Play Video from File or Camera


In this tutorial, I will show you how to capture and play a video from a file or a camera/webcam with OpenCV. Although OpenCV is not optimized for video processing, it has provided a simple API to play videos. In our OpenCV program, all we have to do is to extract frames (images) from the video file or camera and show it in a continuous loop.

One limitation of OpenCV with video is that it is incapable of capturing any sound in the video. Therefore you have to use another library like FFmpeg to capture the sound from a video file or a microphone.

Play a Video File


In this section, I am going to show you how to play a video file. First, a VideoCapture object should be constructed by passing a valid location to a video file. Then the VideoCapture object should be read frame by frame. Finally those frames should be displayed in a window sequentially. Here is the sample OpenCV code to perform the above tasks.
//Uncomment the following line if you are compiling this code in Visual Studio
//#include "stdafx.h"

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

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
 //open the video file for reading
 VideoCapture cap("D:/My OpenCV Website/A Herd of Deer Running.mp4"); 

 // if not success, exit program
 if (cap.isOpened() == false)  
 {
  cout << "Cannot open the video file" << endl;
  cin.get(); //wait for any key press
  return -1;
 }

 //Uncomment the following line if you want to start the video in the middle
 //cap.set(CAP_PROP_POS_MSEC, 300); 

 //get the frames rate of the video
 double fps = cap.get(CAP_PROP_FPS); 
 cout << "Frames per seconds : " << fps << endl;

 String window_name = "My First Video";

 namedWindow(window_name, WINDOW_NORMAL); //create a window

 while (true)
 {
  Mat frame;
  bool bSuccess = cap.read(frame); // read a new frame from video 

  //Breaking the while loop at the end of the video
  if (bSuccess == false) 
  {
   cout << "Found the end of the video" << endl;
   break;
  }

  //show the frame in the created window
  imshow(window_name, frame);

  //wait for for 10 ms until any key is pressed.  
  //If the 'Esc' key is pressed, break the while loop.
  //If the any other key is pressed, continue the loop 
  //If any key is not pressed withing 10 ms, continue the loop
  if (waitKey(10) == 27)
  {
   cout << "Esc key is pressed by user. Stoppig the video" << endl;
   break;
  }
 }

 return 0;

}

Copy and paste above simple code snippet into your IDE and run it. Please note that you have to replace "D:/My OpenCV Website/A Herd of Deer Running.mp4" in the code with a valid location to a video in your computer. Then you should see a window like in the below image.

Playing a video from a file


Explanation


Let's go through the above code line by line.

//#include "stdafx.h"

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

using namespace cv;
using namespace std;
These are the include files and namespaces used in our program. If you need more explanation, please refer to Load & Display Image.


VideoCapture cap("D:/My OpenCV Website/A Herd of Deer Running.mp4"); 
This is one of few constructors available in VideoCapture class. This constructor will open the video file and initialize the VideoCapture object for reading the video stream from the specified file.

The destructor of this class will de-allocate any associated memory with the opened video file. Therefore you don't need to de-allocate memory explicitly in your program.


if (cap.isOpened() == false)  
{
 cout << "Cannot open the video file" << endl;
 cin.get(); //wait for any key press
 return -1;
}
If the previous call to VideoCapture constructor is successful, cap.isOpened() function will return true. Otherwise it will return false. If the function return false, program will print a message to the console, wait for any key press and exit the program with the exit code of -1.

It is essential to check whether the VideoCapture object is initialized successfully before playing the video to avoid a possible crash.


//cap.set(CAP_PROP_POS_MSEC, 300); 
You may uncomment this line, if you want to start your video in the middle. You can call this function inside the while loop too.

bool VideoCapture::set(int propId, double value)

It is possible to change some properties of VideoCapture object with VideoCapture::set function. For supported properties, this function will return true. Otherwise it will return false.
  1. propID - The property of the VideoCapture object which is to be changed. Most common properties which can be changed are
    • CAP_PROP_POS_MSEC - Current position of the video file in milliseconds
    • CAP_PROP_POS_FRAMES - Relative position of the frame to be captured next (Starting from 0, e.g. - 0, 1, 2, 3, ...)
  2. value - The new value for the specified property


double fps = cap.get(CAP_PROP_FPS); 
cout << "Frames per seconds : " << fps << endl;
These 2 lines will obtain the frame rate of the video and print it in the console. You can call this function inside the while loop too.

double VideoCapture::get(int propId) const

This function returns the value of the specified property of the VideoCapture object. For unsupported properties, this function will return 0.
  1. propId - This argument specify the property of the VideoCapture object which is to be obtained. Most common properties are 
    • CAP_PROP_POS_MSEC - Current position of the video file in milliseconds
    • CAP_PROP_POS_FRAMES - Relative position of the frame to be captured next (Starting from 0, e.g. - 0, 1, 2, 3, ...) 
    • CAP_PROP_FRAME_WIDTH - Width of the frames in the video
    • CAP_PROP_FRAME_HEIGHT - Height of the frames in the video
    • CAP_PROP_FPS - Frame rate of the video 
    • CAP_PROP_FOURCC - 4-character code of the codec 
    • CAP_PROP_FRAME_COUNT - Total number of frames in the video file 


String window_name = "My First Video";
namedWindow(window_name, WINDOW_NORMAL); //create a window
First line specify the name of the window. This name will be used to identify the window in the code later.
Second line will create a window passing the window name and the flag WINDOW_NORMAL. With this flag, created window become re-sizable. More information about this function can be found in Load & Display Image.


Mat frame;
bool bSuccess = cap.read(frame); // read a new frame from video
The 2nd line will read frames from the video file one by one inside the while loop and store it in the frame.


if (bSuccess == false) 
{
 cout << "Video is completed" << endl;
 break;
}
When there are no more frames to be captured from the video file, cap.read(frame) function will return false. This if block is placed to break the while loop at the end of the video file when bSuccess become false.


imshow(window_name, frame);
This line will display each frames of the video file in the window created in a previous step.

This function should be followed by waitKey(int) function in order to provide sufficient time to paint and display the frame in the window for the specified time duration in milliseconds. If you do not call waitKey(int) function, the frame will not be displayed in the window.


if (waitKey(10) == 27)
{
 cout << "Esc key is pressed by user. Stoppig the video" << endl;
 break;
}
waitKey function waits for 10 milliseconds. If a key was pressed before the specified time, it returns the ASCII value of the pressed key. If that value is 27 (ASCII value of Esc key is 27), the program will execute inside the if block and break the while loop. If no key is pressed during the 10 ms, the function will return -1 and program will continue the while loop.



Summary


In the above section, you have learned,
  • How to load a video from a file 
  • How to read each frames of the video one by one and display it in a window in a while loop
  • How to break the while loop at the end of the video
  • How to break the while loop if a specific key is pressed before the end of the video

Video file can be played backwards too. But it is not as simple as you would think. Please refer to Play Video File Backwards, if you need the details.



Capture and Play Video From Camera/Webcam


In this section, you will learn how to capture and play a video from a camera/webcam connected to your personal computer.

The main difference of this program against the above program is the use of the VideoCapture constructor. In this program, you just need to give the index of your camera/webcam to the constructor of the VideoCapture object instead of a video file name. Here is the sample OpenCV code.
//Uncomment the following line if you are compiling this code in Visual Studio
//#include "stdafx.h"

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

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
 //Open the default video camera
 VideoCapture cap(0);

 // if not success, exit program
 if (cap.isOpened() == false)  
 {
  cout << "Cannot open the video camera" << endl;
  cin.get(); //wait for any key press
  return -1;
 } 

 double dWidth = cap.get(CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
 double dHeight = cap.get(CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video

 cout << "Resolution of the video : " << dWidth << " x " << dHeight << endl;

 string window_name = "My Camera Feed";
 namedWindow(window_name); //create a window called "My Camera Feed"
 
 while (true)
 {
  Mat frame;
  bool bSuccess = cap.read(frame); // read a new frame from video 

  //Breaking the while loop if the frames cannot be captured
  if (bSuccess == false) 
  {
   cout << "Video camera is disconnected" << endl;
   cin.get(); //Wait for any key press
   break;
  }

  //show the frame in the created window
  imshow(window_name, frame);

  //wait for for 10 ms until any key is pressed.  
  //If the 'Esc' key is pressed, break the while loop.
  //If the any other key is pressed, continue the loop 
  //If any key is not pressed withing 10 ms, continue the loop 
  if (waitKey(10) == 27)
  {
   cout << "Esc key is pressed by user. Stoppig the video" << endl;
   break;
  }
 }

 return 0;

}

Copy and paste above simple code snippet into your IDE and run it. Then you should see the camera output in an opened window.


Explanation


VideoCapture cap(0);
This line will initialize the VideoCapture object with the default camera and the default back-end.

VideoCapture::VideoCapture(int index)

This is one of few constructors available in VideoCapture class. This constructor initializes and opens the camera specified by the argument index.

You may pass 0 for the argument index to use the default camera connected to your computer. You may use a positive integer as the index, if your computer is attached to more than 1 camera.

The destructor of this class will de-allocated any associated memory with this object. Therefore you don't need to de-allocate memory explicitly in your program.


double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video

cout << "Resolution of the video : " << dWidth << " x " << dHeight << endl;
1st line will obtain the width (in pixels) of frames of the camera output. Next line will obtain the height of the frames of the camera output. Then it prints the resolution of the camera output which is (width x height).


All other code lines are same as in the first program to play a video file.



Next Tutorial : Save Images & Videos to File