How to write mp4 video file with H264 codec?

2019-08-04 06:02发布

On OSX I can record from my webcam and write a video file with the following simple script:

import cv2
camera = cv2.VideoCapture(0)

# Define the codec and create VideoWriter object to save the video
fourcc = cv2.VideoWriter_fourcc(*'XVID')
video_writer = cv2.VideoWriter('output.avi', fourcc, 25.0, (640, 480))

while True:
    try:
        (grabbed, frame) = camera.read()  # grab the current frame
        frame = cv2.resize(frame, (640, 480))  # resize the frame
        video_writer.write(frame)  # Write the video to the file system

    except KeyboardInterrupt:
        camera.release()
        break

The resulting avi file is quite big though. I want a smaller file, preferably an mp4. So I changed the filename to output.mp4 and the fourcc codec to H264. That writes a video file which works, but gives me the following error:

$ python write_video_file.py 
OpenCV: FFMPEG: tag 0x34363248/'H264' is not supported with codec id 28 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x00000021/'!???'

Since I thought I'm missing the H264 codec in ffmpeg I decided to uninstall ffmpeg and opencv and reinstall them again with H264 support. For this I used the following commands:

# First ffmpeg
brew install ffmpeg --with-fdk-aac --with-libvidstab --with-openh264 \
      --with-openjpeg  --with-openssl --with-tools --with-webp --with-x265 --with-zeromq
# then opencv3
brew tap homebrew/science
brew install opencv3 --with-contrib --with-ffmpeg --with-tbb

After this I ran the script again, using the following combinations:

  • output.mp4 with H264
  • output.mp4 with X264

Unfortunately I still get the OpenCV warnings/errors. The file is readable, but it still annoys me that I get these errors. Does anybody have any idea how I can make OpenCV write mp4 video file with the H264 codec?

All tips are welcome!

1条回答
仙女界的扛把子
2楼-- · 2019-08-04 06:46

I spent ages trying to find a list of video codecs on macOS, and finding which codecs work with which containers, and then if QuickTime can actually read the resulting files.

I can summarise my findings as follows:

.mov container and fourcc('m','p','4','v') work and QuickTime can read it
.mov container and fourcc('a','v','c','1') work and QuickTime can read it
.avi container and fourcc('F','M','P','4') works but QuickTime cannot read it without conversion

I did manage to write h264 video in an mp4 container, as you wanted, just not using OpenCV's VideoWriter module. Instead I changed the code (mine happens to be C++) to just output raw bgr24 format data - which is how OpenCV likes to store pixels anyway:

So the output of a frame of video stored in a Mat called Frame becomes:

cout.write(reinterpret_cast<const char *>(Frame.data),width*height*3);

and then you pipe the output of your program into ffmpeg like this:

./yourProgram | ffmpeg -y -f rawvideo -pixel_format bgr24 -video_size 1024x768 -i - -c:v h264 -pix_fmt yuv420p video.mp4

Yes, I know I have made some assumptions:

  • that the data are CV8_UC3,
  • that the sizes match in OpenCV and ffmpeg, and
  • that there is no padding or mad stride in the OpenCV data,

but the basic technique works and you can adapt it for other sizes and situations.

查看更多
登录 后发表回答