Edit
Click here to add content.

Reading and Writing Videos using OpenCV

Reading and writing videos in OpenCV is very similar to reading and writing images. A video is nothing but a series of images that are often referred to as frames. So, all you need to do is loop over all the frames in a video sequence, and then process one frame at a time. In this post, we will demonstrate how to read, display and write videos from a file, an image sequence and a webcam. We will also look into some of the errors that might occur in the process, and help understand how to resolve them.

Let’s go through the code example for reading a video file first.This essentially contains the functions for reading a video from disk and displaying it. As you proceed further, we will discuss the functions in detail used in this implementation.

Python

import cv2 

# Create a video capture object, in this case we are reading the video from a file
vid_capture = cv2.VideoCapture('Resources/Cars.mp4')

if (vid_capture.isOpened() == False):
	print("Error opening the video file")
# Read fps and frame count
else:
	# Get frame rate information
	# You can replace 5 with CAP_PROP_FPS as well, they are enumerations
	fps = vid_capture.get(5)
	print('Frames per second : ', fps,'FPS')

	# Get frame count
	# You can replace 7 with CAP_PROP_FRAME_COUNT as well, they are enumerations
	frame_count = vid_capture.get(7)
	print('Frame count : ', frame_count)

while(vid_capture.isOpened()):
	# vid_capture.read() methods returns a tuple, first element is a bool 
	# and the second is frame
	ret, frame = vid_capture.read()
	if ret == True:
		cv2.imshow('Frame',frame)
		# 20 is in milliseconds, try to increase the value, say 50 and observe
		key = cv2.waitKey(20)
		
		if key == ord('q'):
			break
	else:
		break

# Release the video capture object
vid_capture.release()
cv2.destroyAllWindows()

C++

// Include Libraries
#include<opencv2/opencv.hpp>
#include<iostream>

// Namespace to nullify use of cv::function(); syntax
using namespace std;
using namespace cv;

int main()
{
	// initialize a video capture object
	VideoCapture vid_capture("Resources/Cars.mp4");

	// Print error message if the stream is invalid
	if (!vid_capture.isOpened())
	{
		cout << "Error opening video stream or file" << endl;
	}

	else
	{
		// Obtain fps and frame count by get() method and print
		// You can replace 5 with CAP_PROP_FPS as well, they are enumerations
		int fps = vid_capture.get(5);
		cout << "Frames per second :" << fps;

		// Obtain frame_count using opencv built in frame count reading method
		// You can replace 7 with CAP_PROP_FRAME_COUNT as well, they are enumerations
		int frame_count = vid_capture.get(7);
		cout << "  Frame count :" << frame_count;
	}


	// Read the frames to the last frame
	while (vid_capture.isOpened())
	{
		// Initialise frame matrix
		Mat frame;

	    // Initialize a boolean to check if frames are there or not
		bool isSuccess = vid_capture.read(frame);

		// If frames are present, show it
		if(isSuccess == true)
		{
			//display frames
			imshow("Frame", frame);
		}

		// If frames are not there, close it
		if (isSuccess == false)
		{
			cout << "Video camera is disconnected" << endl;
			break;
		}
		
		//wait 20 ms between successive frames and break the loop if key q is pressed
		int key = waitKey(20);
		if (key == 'q')
		{
			cout << "q key is pressed by the user. Stopping the video" << endl;
			break;
		}


	}
	// Release the video capture object
	vid_capture.release();
	destroyAllWindows();
	return 0;
}
Official OpenCV Courses
Start your exciting journey from an absolute Beginner to Mastery in AI, Computer Vision & Deep Learning!

These are the main functions in OpenCV video I/O that we are going to discuss in this blog post:

  1. cv2.VideoCapture – Creates a video capture object, which would help stream or display the video.
  2. cv2.VideoWriter – Saves the output video to a directory.
  3. In addition, we also discuss other needed functions such as cv2.imshow(), cv2.waitKey() and the get() method which is used to read the video metadata such as frame height, width, fps etc.
GIF showing the input video for the post.

In this example, you will be reading the above video (‘Cars.mp4’) and displaying it.

We assume you already have OpenCV in your system. If you need to install OpenCV, please visit the relevant link below.
  1. Install OpenCV on Windows
  2. Install OpenCV on MacOS
  3. Install OpenCV on Ubuntu

We have provided the codes both in Python and C++ languages for your study and practice.

Now let’s start with it.

First we import the OpenCV library. Please note that for C++, you would normally use cv::function(), but because we choose to use the cv namespace (using namespace cv), we can access the OpenCV functions directly, without pre-pending cv:: to the function name. 

Python

# Import libraries
import cv2
Download Code To easily follow along this tutorial, please download code by clicking on the button below. It's FREE!

C++

// Include Libraries
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;

Reading Video From a File

The next code block below uses the VideoCapture() class to create a VideoCapture object, which we will then use to read the video file. The syntax for using this class is shown below: 

VideoCapture(path, apiPreference)

The first argument is the filename/path to the video file. The second is an optional argument, indicating an API preference. Some of the options associated with this optional argument  will be discussed further below. To learn more about apiPreference, visit the official documentation link VideoCaptureAPIs.

Python

# Create a video capture object, in this case we are reading the video from a file
vid_capture = cv2.VideoCapture('Resources/Cars.mp4')

C++

# Create a video capture object, in this case we are reading the video from a file
VideoCapture vid_capture("Resources/Cars.mp4");

For all the examples given below, you can use the same video file that we have used here, which is available in the Downloadable Code folder, or you can use your own video file.


Now that we have a video capture object we can use the isOpened() method to confirm the video file was opened successfully. The isOpened() method returns a boolean that indicates whether or not the video stream is valid. Otherwise you will get an error message. The error message can imply many things. One of them is that the entire video is corrupted, or some frames are corrupted. Assuming the video file was opened successfully, we can use the get() method to retrieve important metadata associated with the video stream. Note that this method does not apply to web cameras. The get() method takes a single argument from an enumerated list of options documented here. In the example below, we provided the numeric values 5 and 7, which correspond to the frame rate (CAP_PROP_FPS) and frame count (CAP_PROP_FRAME_COUNT). The numeric value or the name can be supplied.

Python

if (vid_capture.isOpened() == False):
	print("Error opening the video file")
else:
	# Get frame rate information

	fps = int(vid_capture.get(5))
	print("Frame Rate : ",fps,"frames per second")	

	# Get frame count
	frame_count = vid_capture.get(7)
	print("Frame count : ", frame_count)

C++

if (!vid_capture.isOpened())
	{
		cout << "Error opening video stream or file" << endl;
	}
else
	{
            // Obtain fps and frame count by get() method and print
		int fps = vid_capture.get(5):
		cout << "Frames per second :" << fps;
		frame_count = vid_capture.get(7);
		cout << "Frame count :" << frame_count;
	}

After retrieving the desired metadata associated with the video file, we are now ready to read each image frame from the file. This is accomplished by creating a loop and reading one frame at a time from the video stream using the vid_capture.read() method. 

The vid_capture.read() method returns a tuple, where the first element is a boolean and the next element is the actual video frame. When the first element is True, it indicates the video stream contains a frame to read. 

If there is a frame to read, you can then use imshow() to display the current frame in a window, otherwise exit the loop. Notice that you also use the waitKey() function to pause for 20ms between video frames. Calling the waitKey() function lets you monitor the keyboard for user input. In this case, for example, if the user presses the ‘q’ key, you exit the loop.

Python

while(vid_capture.isOpened()):
	# vCapture.read() methods returns a tuple, first element is a bool 
	# and the second is frame

	ret, frame = vid_capture.read()
	if ret == True:
		cv2.imshow('Frame',frame)
		k = cv2.waitKey(20)
		# 113 is ASCII code for q key
		if k == 113:
			break
	else:
		break

C++

while (vid_capture.isOpened())
{
        // Initialize frame matrix
        Mat frame;
        // Initialize a boolean to check if frames are there or not
        bool isSuccess = vid_capture.read(frame);
        // If frames are present, show it
        if(isSuccess == true)
        {
            //display frames
            imshow("Frame", frame);
        }

        // If frames are not there, close it
        if (isSuccess == false)
        {
            cout << "Video camera is disconnected" << endl;
            break;
        }        
//wait 20 ms between successive frames and break the loop if key q is pressed
        int key = waitKey(20);
            if (key == 'q')
        {
            cout << "q key is pressed by the user. Stopping the video" << endl;
            break;
        }
    }

Once the video stream is fully processed or the user prematurely exits the loop, you release the video-capture object (vid_capture) and close the window, using the following code:

Python

# Release the objects
vid_capture.release()
cv2.destroyAllWindows()

C++

// Release video capture object
vid_capture.release();
destroyAllWindows();

Reading an Image Sequence

Processing image frames from an image sequence is very similar to processing frames from a video stream. Just specify the image files which are being read. 

In the example below, 

  • You continue using a video-capture object
  • But instead of specifying a video file, you simply specify an image sequence
    • Using the notation shown below (Cars%04d.jpg), where %04d indicates a four-digit sequence-naming convention (e.g. Cars0001.jpg, Cars0002.jpg, Cars0003.jpg, etc).  
    • If you had specified “Race_Cars_%02d.jpg” then you would be looking for files of the form: 

(Race_Cars_01.jpg, Race_Cars_02.jpg, Race_Cars_03.jpg, etc…). 

All other codes described in the first example would be the same. 

Python

vid_capture = cv2.VideoCapture('Resources/Image_sequence/Cars%04d.jpg')

C++

VideoCapture vid_capture("Resources/Image_sequence/Cars%04d.jpg");

Reading Video from a Webcam 

Reading a video stream from a web camera is also very similar to the examples discussed above. How’s that possible? It’s all thanks to the flexibility of the video capture class in OpenCV, which has several overloaded functions for convenience that accept different input arguments. Rather than specifying a source location for a video file or an image sequence, you simply need to give a video capture device index, as shown below. 

  • If your system has a built-in webcam, then the device index for the camera will be ‘0’. 
  • If you have more than one camera connected to your system, then the device index associated with each additional camera is incremented (e.g. 1, 2, etc).

Python

vid_capture = cv2.VideoCapture(0, cv2.CAP_DSHOW)

C++

VideoCapture vid_capture(0);

You might be wondering about the flag CAP_DSHOW. This is an optional argument, and is therefore not required. CAP_DSHOW is just another video-capture API preference, which is short for directshow via video input.

Writing Videos

Let’s now take a look at how to write videos. Just like video reading, we can write videos originating from any source (a video file, an image sequence, or a webcam). To write a video file: 

  • Retrieve the image frame height and width, using the get() method.
  • Initialize a video capture object (as discussed in the previous sections), to read the video stream into memory, using any of the sources previously described.
  • Create a video writer object.
  • Use the video writer object to save the video stream to disk. 

Continuing with our running example, let’s start by using the get() method to obtain the video frame width and height.

Python

# Obtain frame size information using get() method
frame_width = int(vid_capture.get(3))
frame_height = int(vid_capture.get(4))
frame_size = (frame_width,frame_height)
fps = 20

C++

// Obtain frame size information using get() method
Int frame_width = static_cast<int>(vid_capture.get(3));
int frame_height = static_cast<int>(vid_capture.get(4));
Size frame_size(frame_width, frame_height);
int fps = 20;

As previously discussed, the get() method from the VideoCapture() class requires:

  •  A single argument from an enumerated list that allows you to retrieve a variety of metadata associated with the video frames. 

The metadata available is extensive, and can be found here

  • In this case, you are retrieving the frame width and height, by specifying 3 (CAP_PROP_FRAME_WIDTH) and 4 (CAP_PROP_FRAME_HEIGHT). You will use these dimensions further below, when writing the video file to disk.

In order to write a video file, you need to first create a video-writer object from the VideoWriter() class, as shown in the code below. 

Here’s the syntax for VideoWriter():

VideoWriter(filename, apiPreference, fourcc, fps, frameSize[, isColor])

The VideoWriter() class takes the following arguments: 

  • filename: pathname for the output video file
  • apiPreference:  API backends identifier
  • fourcc: 4-character code of codec, used to compress the frames (fourcc)
  • fps: Frame rate of the created video stream
  • frame_size: Size of the video frames
  • isColor: If not zero, the encoder will expect and encode color frames. Else it will work with grayscale frames (the flag is currently supported on Windows only).

The following code creates the video writer object, output from the VideoWriter() class. A special convenience function is used to retrieve the four-character codec, required as the second argument to the video writer object, cv2.

  • VideoWriter_fourcc('M', 'J', 'P', 'G') in Python.
  • VideoWriter::fourcc('M', 'J', 'P', 'G') in C++.

The video codec specifies how the video stream is compressed. It converts uncompressed video to a compressed format or vice versa. To create AVI or MP4 formats, use the following fourcc specifications:

AVI: cv2.VideoWriter_fourcc('M','J','P','G')

MP4: cv2.VideoWriter_fourcc(*'XVID')

The next two input arguments specify the frame rate in FPS, and the frame size (width, height).

Python

# Initialize video writer object
output = cv2.VideoWriter('Resources/output_video_from_file.avi', cv2.VideoWriter_fourcc('M','J','P','G'), 20, frame_size)

C++

//Initialize video writer object
VideoWriter output("Resources/output.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'),frames_per_second, frame_size);

Now that you have created a video writer object, use it to write the video file to disk, one frame at a time, as shown in the code below. Here, you are writing an AVI video file to disk, at 20 frames per second. Note how we have simplified to loop from the previous examples.

Python

while(vid_capture.isOpened()):
    # vid_capture.read() methods returns a tuple, first element is a bool 
    # and the second is frame

    ret, frame = vid_capture.read()
    if ret == True:
           # Write the frame to the output files
           output.write(frame)
    else:
         print(‘Stream disconnected’)
           break

C++

while (vid_capture.isOpened())
{
        // Initialize frame matrix
        Mat frame;

          // Initialize a boolean to check if frames are there or not
        bool isSuccess = vid_capture.read(frame);

        // If frames are not there, close it
        if (isSuccess == false)
        {
            cout << "Stream disconnected" << endl;
            break;
        }


            // If frames are present
        if(isSuccess == true)
        {
            //display frames
            output.write(frame);
                  // display frames
                  imshow("Frame", frame);

                  // wait for 20 ms between successive frames and break        
                  // the loop if key q is pressed
                  int key = waitKey(20);
                  if (key == ‘q’)
                  {
                      cout << "Key q key is pressed by the user. 
                      Stopping the video" << endl;
                      break;
                  }
        }
 }

Finally, in the code below, release the video capture and video-writer objects. 

Python

# Release the objects
vid_capture.release()
output.release()

C++

// Release the objects
vid_capture.release();
output.release();

Errors That One Might Face when Reading or Writing Videos

Video reading

While reading frames it can throw an error if the path is wrong or the file is corrupted or frame is missing.That’s why we are using an if statement inside the while loop. Which can be seen in the line, if ret == True. This way it will process it only when frames are present. Following is an example of an error log that is observed in this case. It is not the full log, only key parameters are included.

cap_gstreamer.cpp:890: error: (-2) GStreamer: unable to start pipeline  in function

For wrong path:

When you provide a wrong path to a video, then it will not show any error or warning using the VideoCapture() class. The issues will arise when you will try to do any operation on the video frames. For this, you can use a simple if block for checking whether you have read a video file or not like we did in our example. That should print the following message.

Error opening the video file

Video writing

In this step various errors can occur. Most common are frame size error and api preference error. If the frame size is not similar to the video, then even though we get a video file at the output directory, it will be blank. If you are using the NumPy shape method to retrieve frame size, remember to reverse the output as OpenCV will return height x width x channels. If it is throwing an api preference error, we might need to pass the CAP_ANY flag in the VideoCapture() argument. It can be seen in the webcam example, where we  are using CAP_DHOW to avoid warnings being generated.

Following are the examples of error logs:

When CAP_DSHOW is not passed:

 [WARN:0]...cap_msmf.cpp(438) …. terminating async callback

When frame size is not correct:

cv2.error: OpenCV(4.5.2) :-1: error: (-5:Bad argument) in function 'VideoWriter'
> Overload resolution failed:
>  - Can't parse 'frameSize'. Sequence item with index 0 has a wrong type
>  - VideoWriter() missing required argument 'frameSize' (pos 5)
>  - VideoWriter() missing required argument 'params' (pos 5)
>  - VideoWriter() missing required argument 'frameSize' (pos 5)

Expand Your Knowledge

Official OpenCV Courses
Start your exciting journey from an absolute Beginner to Mastery in AI, Computer Vision & Deep Learning!

Summary

In this blog, you learned to read and display video streams from three different sources, using a video-capture object. Even saw how to use a video-capture object to retrieve important metadata from the video stream. We also demonstrated how to write video streams to disk, using a video-writer object. You may also find it helpful to resize video frames, or annotate them with shapes and text. For this, just modify the individual image frames.

Now that you know how to read and write videos, and are comfortable using OpenCV,keep up the pace. And keep learning.

Subscribe & Download Code



Subscribe To Receive
We hate SPAM and promise to keep your email address safe.​

Subscribe to receive the download link, receive updates, and be notified of bug fixes

seperator

Almost there! Please complete this form and click the button below to receive the download link.

Subscribe To Receive
We hate SPAM and promise to keep your email address safe.​
Subscribe Now
Disclaimer

All views expressed on this site are my own and do not represent the opinions of OpenCV.org or any entity whatsoever with which I have been, am now, or will be affiliated.

About LearnOpenCV

In 2007, right after finishing my Ph.D., I co-founded TAAZ Inc. with my advisor Dr. David Kriegman and Kevin Barnes. The scalability, and robustness of our computer vision and machine learning algorithms have been put to rigorous test by more than 100M users who have tried our products.

Copyright © 2021 – BIG VISION LLC