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
withH264
output.mp4
withX264
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!
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:
I did manage to write
h264
video in anmp4
container, as you wanted, just not using OpenCV's VideoWriter module. Instead I changed the code (mine happens to be C++) to just output rawbgr24
format data - which is how OpenCV likes to store pixels anyway:So the output of a frame of video stored in a
Mat
calledFrame
becomes:and then you pipe the output of your program into
ffmpeg
like this:Yes, I know I have made some assumptions:
but the basic technique works and you can adapt it for other sizes and situations.