I get a stream of cv2
images from my webcam and want to save it to a video file. After playing a bit with cv2.VideoWriter()
it turned out that using ffmpeg
would provide more options and – apparently, following a few threads here on SO – lead to better results. So I gave the VidGear Python library a try, and it seems to work fine.
There is one catch though: My webcam provides a variable framerate, most of the time between 10 and 30 FPS. When saving these frames the video file becomes way too fast, like watching in fast-forward. One real-time minute becomes only a few seconds in the video.
I tried to play with various combinations of the ffmpeg’s -framerate
and/or -r
parameters, but without luck. Here is the command I am using right now:
ffmpeg -y -f rawvideo -vcodec rawvideo -s 1920x1080 -pix_fmt bgra -framerate 25.0 -i - -vcodec libx265 -crf 25 -r 25 -preset fast <output_video_file>
For the records, I am creating the WriteGear
class from the VidGear library like this:
video_params = { "-vcodec": "libx265", "-crf": 25, "-input_framerate": 25, "-r": 25, } WriteGear(output_filename=video_file, logging=True, **video_params)
Any ideas what I am doing wrong here and how I need to call ffmpeg?
Advertisement
Answer
Ok, I solved my issue now by using cv2.VideoWriter()
instead of the VidGear library. Don’t know why, but I was not able to get the latter working in a proper way – either it was me not using it correctly, or the library is broken (for my use case).
Either way, after playing around with the OpenCV solution, it turned out that using the VideoWriter
class and providing the FPS value from the web cam everything works quite well now.
For the records, one thing to note though: Even after finding a correct codec for my platform and double-checking the dimensions of the images to be saved, I still ended up with an “empty” (1k) .mp4 video file. The reason was that all frames from my webcam came with 4 channels, but the VideoWriter
class apparently expects frames with 3 channels instead, silently dropping all other, “invalid” frames. With the following code I was able to convert my 4-channel images:
if len(image.shape) > 2 and image.shape[2] == 4: image = cv2.cvtColor(image, cv2.COLOR_BGRA2BGR)