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



27 comments:

  1. I have a problem with the second program when I do it simulate it shows me a white window I do not know why

    ReplyDelete
    Replies
    1. I had same problem when I removed form while cycle this piece of program:
      if (waitKey(10) == 27){
      cout << "Esc is presse by user" << endl;
      break;
      }
      so it looks like it is somehow bounded with wait..

      Delete
  2. Thankyou so much for the tutorial bro.

    ReplyDelete
  3. thanks for article! Could you tell how to capture video with sound?

    ReplyDelete
    Replies
    1. Although OpenCV does not support sound in a video, you can use other libraries like ffmpeg to play the sound while OpenCV displays the video frame by frame.

      Delete
  4. i am getting the error unresolved externals.
    this is the error

    Severity Code Description Project File Line Suppression State
    Error LNK1120 2 unresolved externals PLAY_VIDEO c:\users\ashish\documents\visual studio 2015\Projects\PLAY_VIDEO\x64\Debug\PLAY_VIDEO.exe 1
    Error LNK2019 unresolved external symbol "public: virtual bool __cdecl cv::VideoCapture::read(class cv::debug_build_guard::_OutputArray const &)" (?read@VideoCapture@cv@@UEAA_NAEBV_OutputArray@debug_build_guard@2@@Z) referenced in function main PLAY_VIDEO c:\Users\ashish\documents\visual studio 2015\Projects\PLAY_VIDEO\PLAY_VIDEO\Source.obj 1
    Error LNK2019 unresolved external symbol "void __cdecl cv::imshow(class cv::String const &,class cv::debug_build_guard::_InputArray const &)" (?imshow@cv@@YAXAEBVString@1@AEBV_InputArray@debug_build_guard@1@@Z) referenced in function main PLAY_VIDEO c:\Users\ashish\documents\visual studio 2015\Projects\PLAY_VIDEO\PLAY_VIDEO\Source.obj 1

    ReplyDelete
    Replies
    1. You have to give link location to the opencv debug/release libraries in your visual studio properties. Please refer https://opencv-srf.blogspot.com/2017/11/install-opencv-with-visual-studio.html for more information.

      Delete
  5. how to read sequence of images like image1 image2 .....image500 from file saved in a directory...can any one tell please. Thanks

    ReplyDelete
    Replies
    1. You have to rename image1.jpg to image001, image2.jpg to image002.jpg, etc.

      Then try the following code

      VideoCapture cap("Fullpath/image%03d.jpg");

      while (true)
      {
      Mat frame;
      bool bSuccess = cap.read(frame);

      if (bSuccess == false)
      break;

      if (waitKey(10) == 27)
      break;
      }


      Delete
  6. Using eclipse ide and trying "play video from.file or camera"
    Facing build error, undefined reference error:
    Undefined reference to cv:videocapture::videocapture(cv::string const&)
    Undefined reference to cv::videocapture::isopened() const
    Undefined reference to cv::videocapture::get(int)const
    Undefined reference to cv::videocapture::read(cv::outputarray const&)

    ReplyDelete
  7. The error is resolved.
    I am unable to play the video.It is coming false and printing "cannot open video file" on output terminal.

    ReplyDelete
    Replies
    1. Please check whether the given filename exist. If it exists, what is your video file format?

      Delete
  8. The file is existing in the path, the video format is mp4

    ReplyDelete
  9. Yes,d:\\personal\\workspace\\firstvideo.mp4

    ReplyDelete
  10. I tried many options like adding ffmpeg.dll into system path... Videocapture with opencv 3.4.0 is still not working.
    Is any configuration am I still missing with? Can anyone help me out in resolving this issue.

    ReplyDelete
  11. The link to next tutorial is broken in this page. The tutorials are amazing, Just wanted to suggest this.

    ReplyDelete
  12. Simple worked in first attempt..... Thank you..........

    ReplyDelete
  13. Thank you very much for sample of work with camera!

    ReplyDelete
  14. i already confirm my path has correct but it prompt cannot open video file

    ReplyDelete
  15. In second program while compiler throws error:

    Exception thrown at 0x00007FFCB12BA388 (KernelBase.dll) in Open_CV.exe: WinRT originate error - 0xC00D36B3 : 'The stream number provided was invalid.'.

    but it still works

    ReplyDelete
  16. I found useful article in your blog. thank you for sharing nice info
    visit
    web programming tutorial
    welookups.com

    ReplyDelete
  17. This comment has been removed by the author.

    ReplyDelete
  18. Hello.. I tried running the first program but I am getting the following error and the program quits.
    'Open_Video.exe' (Win32): Loaded 'C:\Opencv-3.4.1\opencv\build\x64\vc15\bin\opencv_world341d.dll'. Cannot find or open the PDB file.

    Can someone please help me in resolving this.

    ReplyDelete
  19. GStreamer Plugin: Embedded video playback halted; module v4l2src0 reported: Internal data flow error.
    OpenCV Error: Unspecified error (GStreamer: unable to start pipeline
    ) in cvCaptureFromCAM_GStreamer, file /opt/opencv/modules/videoio/src/cap_gstreamer.cpp, line 818
    terminate called after throwing an instance of 'cv::Exception'
    what(): /opt/opencv/modules/videoio/src/cap_gstreamer.cpp:818: error: (-2) GStreamer: unable to start pipeline
    in function cvCaptureFromCAM_GStreamer


    I am getting this error.

    ReplyDelete