How do I write a video using H.264 compression with the VideoWriter class in OpenCV? I basically want to get a video from the webcam and save it after a character is pressed. The ouput video file is huge when using MPEG4 Part 2 compression.
2 Answers
You can certainly use the VideoWriter
class, but you need to use the correct FourCC code that represents the the H264 standard. FourCC stands for Four Character Code, which is an identifier for a video codec, compression format, colour or pixel format used in media files.
Specifically, when you create a VideoWriter
object, you specify the FourCC code when constructing it. Consult the OpenCV docs for more details: http://docs.opencv.org/trunk/modules/highgui/doc/reading_and_writing_images_and_video.html#videowriter-videowriter
I'm assuming you're using C++, and so the definition of the VideoWriter
constructor is:
VideoWriter::VideoWriter(const String& filename, int fourcc,
double fps, Size frameSize, bool isColor=true)
filename
is the output of the video file, fourcc
is the FourCC code for the code you wish to use, fps
is the desired frame rate, frameSize
is the desired dimensions of the video, and isColor
specifies whether or not you want the video to be in colour. Even though FourCC uses four characters, OpenCV has a utility that parses FourCC and outputs a single integer ID which is used as a lookup to be able to write the correct video format to file. You use the CV_FOURCC
function, and specify four single characters - each corresponding to a single character in the FourCC code of the codec you want. Note that CV_FOURCC
is for OpenCV 2.x. It is recommended you use cv::Videowriter::fourcc
for OpenCV 3.x and beyond.
Specifically, you would call it like this:
int fourcc = CV_FOURCC('X', 'X', 'X', 'X');
int fourcc = VideoWriter::fourcc('X', 'X', 'X', 'X');
Replace X
with each character that belongs to the FourCC (in order). Because you want the H264 standard, you would create a VideoWriter
object like so:
#include <iostream> // for standard I/O
#include <string> // for strings
#include <opencv2/core/core.hpp> // Basic OpenCV structures (cv::Mat)
#include <opencv2/highgui/highgui.hpp> // Video write
using namespace std;
using namespace cv;
int main()
{
VideoWriter outputVideo; // For writing the video
int width = ...; // Declare width here
int height = ...; // Declare height here
Size S = Size(width, height); // Declare Size structure
// Open up the video for writing
const string filename = ...; // Declare name of file here
// Declare FourCC code - OpenCV 2.x
// int fourcc = CV_FOURCC('H','2','6','4');
// Declare FourCC code - OpenCV 3.x and beyond
int fourcc = VideoWriter::fourcc('H','2','6','4');
// Declare FPS here
double fps = ...;
outputVideo.open(filename, fourcc, fps, S);
// Put your processing code here
// ...
// Logic to write frames here... see below for more details
// ...
return 0;
}
Alternatively, you could simply do this when declaring your VideoWriter
object:
VideoWriter outputVideo(filename, fourcc, fps, S);
If you use the above, it's not required that you call open
as this will automatically open up the writer for writing frames to file.
If you're not sure if H.264 is supported on your computer, specify -1
as the FourCC code, and a window should pop up when you run the code that displays all of the available video codecs that are on your computer. I'd like to mention that this only works for Windows. Linux or Mac OS doesn't have this window popping out when you specify -1
. In other words:
VideoWriter outputVideo(filename, -1, fps, S);
You can choose which one is most suitable should H.264 not exist on your computer. Once that is done, OpenCV will create the right FourCC code to be input into the VideoWriter
constructor so that you will get a VideoWriter instance that represents a VideoWriter
that will write that type of video to file.
Once you have a frame ready, stored in frm
for writing to the file, you can do either:
outputVideo << frm;
OR
outputVideo.write(frm);
As a bonus, here's a tutorial on how to read/write videos in OpenCV: http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_gui/py_video_display/py_video_display.html - However, it's written for Python, but what is good to know is near the bottom of the link, there is a list of FourCC codes that are known to work for each operating system. BTW, the FourCC code they specify for the H264 standard is actually 'X','2','6','4'
, so if 'H','2','6','4'
doesn't work, replace H
with X
.
Another small note. If you are using Mac OS, then what you need to use is 'A','V','C','1'
or 'M','P','4','V'
. From experience, 'H','2','6','4'
or 'X','2','6','4'
when trying to specify the FourCC code doesn't seem to work.

- 102,964
- 22
- 184
- 193
-
I tried the program. First when I tried to use the Fourcc parameter as -1 no window popped up. When I tried using x264 as you mentioned I got " could not open codec: libx264" error and some other errors like "broken ffmpeg default settings detected".. what should I do BTW I use ubuntu 14.04 – kauDaOtha Jan 29 '15 at 12:45
-
1That means you don't have the H264 libraries.... That is another post all together. When I get to work, I'll give you a link. Btw the -1 only works in Windows. Forgot to mention that too. Oops! – rayryeng Jan 29 '15 at 13:23
-
Thank you .. do let me know when you work on the h264 lib installation. . I need to know deperately – kauDaOtha Jan 29 '15 at 14:02
-
@KausicGunasekkar - Try updating to the latest `libx264` library. Check out this post here - it helped me: http://stackoverflow.com/questions/9764740/unknown-encoder-libx264 . Try the accepted answer. If that doesn't work, try the answer by Scott Stensland in the same post: http://stackoverflow.com/a/15105901/325082. Scott's answer is the one I used to ultimately get it working. – rayryeng Jan 29 '15 at 14:46
-
for me it was also case sensitive; had to use lowercase for my python implementation – stanley Jul 31 '16 at 16:18
-
@stanley That I didn't know. Thanks for your comment... and an upvote would be welcome :) – rayryeng Jul 31 '16 at 16:18
-
@rayryeng do you know if there is a way to control the bitrate the video writer uses to write the new file? when i use video writer to make new files the bit rate goes up by over 5x resulting file sizes that are too large. i created a new question regarding this: http://stackoverflow.com/questions/38686359/opencv-videowriter-control-bitrate – stanley Jul 31 '16 at 16:59
-
@stanley Unfortunately from experience it isn't possible. I had to use FFMPEG to downconvert the bitrate so that I could control it. OpenCV has a tendency to blow up the file size because the bitrate is uncontrolled. – rayryeng Jul 31 '16 at 17:00
-
@rayryeng ok. maybe you could show me an example of how to do that here: http://stackoverflow.com/questions/38686359/opencv-videowriter-control-bitrate – stanley Jul 31 '16 at 17:02
-
@rayryeng i've only ever used ffmpeg from the command line. not sure how i'd do that within a file. c++ example is fine. – stanley Jul 31 '16 at 17:04
-
@stanley I've only used FFMPEG through the command-line. What I did was I wrote a shell script that would call my C++ or Python code that uses OpenCV to create a video, then called FFMPEG separately after. This post on Super User should help for controlling the bitrate: http://superuser.com/questions/319542/how-to-specify-audio-and-video-bitrate. Read the highest voted answer (17 at the time of this writing). – rayryeng Jul 31 '16 at 17:07
-
Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/118753/discussion-between-stanley-and-rayryeng). – stanley Jul 31 '16 at 17:10
-
@stanley can't chat now sorry. I'm not at home. – rayryeng Jul 31 '16 at 17:11
-
ok my email is stanchiang23@gmail.com maybe we can continue talking when you have more time – stanley Jul 31 '16 at 17:12
-
@stanley You can get in touch with me in the MATLAB chat room. You can find a link on my profile page. I'll be there later today. Just ping me using my handle. – rayryeng Jul 31 '16 at 17:13
-
Note that in the newer versions of opencv (4.2, for sure), `CV_FOURCC` has changed to `cv::VideoWriter::fourcc`. – user14717 Feb 03 '20 at 17:39
-
@user14717 thanks! I'll update my answer when I have a moment. – rayryeng Feb 03 '20 at 21:07
-
1If you do, also note the `fps` is now a `double`. – user14717 Feb 03 '20 at 23:52
-
Hi @rayryeng what about image compression ? I want to compress image instead video ? Should I use this way again ? – Yunus Temurlenk Mar 29 '21 at 06:38
-
1@YunusTemurlenk You can use `cv::imwrite` and specify different image formats and different compression options. The above approach is only applicable to videos so you should definitely not use this. See https://stackoverflow.com/questions/7237144/compressing-images-on-opencv-imwrite-how-to-explicitly-set-the-compression-fa for an example. – rayryeng Mar 29 '21 at 17:19
As rayryeng states, you need to pass the correct FourCC code to VideoWriter
.
For H.264 most people use AVC, which would look like this:
cv2.VideoWriter_fourcc('a','v','c','1')
mp4v
also seems to work for many. If they both don't, check your list of available codecs.

- 1,771
- 18
- 18