10

I am trying to use the openCV VideoWriter class to generate a video from numpy arrays. I am using the following code:

import numpy as np
import cv2
size = 720*16//9, 720
duration = 2
fps = 25
out = cv2.VideoWriter('output.avi', cv2.VideoWriter_fourcc(*'X264'), fps, size)
for _ in range(fps * duration):
    data = np.random.randint(0, 256, size, dtype='uint8')
    out.write(data)
out.release()

The codec seems to be installed as ffmpeg can do conversions to the x264 codec and libx264 is installed. The code runs without warnings, however the videos generated seem to contain no data since I always get the following message when trying to read them with mpv:

[ffmpeg/demuxer] avi: Could not find codec parameters for stream 0 (Video: h264 (X264 / 0x34363258), none, 1280x720): unspecified pixel format

What could be the cause of this issue?

daVinci
  • 103
  • 1
  • 1
  • 6

1 Answers1

16

The first issue is that you are trying to create a video using black and white frames while VideoWriter assumes color by default. VideoWriter has a 5th boolean parameter where you can pass False to specify that the video is to be black and white.

The second issue is that the dimensions that cv2 expects are the opposite of numpy. Thus, size should be (size[1], size[0]).

A possible further problem is the codec being used. I have never been able to get "X264" to work on my machine and instead have been using "mp4v" as the codec and ".mp4" for the container type in order to get an H.264 encoded output.

After all of these issues are fixed, this is the result. Please try this and see if it works for you:

import numpy as np
import cv2
size = 720*16//9, 720
duration = 2
fps = 25
out = cv2.VideoWriter('output.mp4', cv2.VideoWriter_fourcc(*'mp4v'), fps, (size[1], size[0]), False)
for _ in range(fps * duration):
    data = np.random.randint(0, 256, size, dtype='uint8')
    out.write(data)
out.release()
Tyson
  • 592
  • 4
  • 13
  • This works, I just wanted to add that the X264 codec does also work, but generates a much lower quality video than mp4v – daVinci Jul 14 '20 at 12:44
  • 1
    Great! Maybe X264 doesn't work for me because I don't have libx264 installed? Anyway, I'm glad to hear that it worked for you :) – Tyson Jul 15 '20 at 00:06
  • Update: I have since found that the video is not being H264 encoded with the method in the above code. I found a solution using one of Cisco's OpenH264 binaries. It must be downloaded and placed in the same working directory. OpenCV seems to find it automatically as long as the binary version is 1.8 and the name is unchanged (newer versions don't work as of the date of this comment). https://github.com/cisco/openh264/releases – Tyson May 17 '21 at 08:13