26

I am trying to create a video from the python wrapper for OpenCV under OSX. I am using python 2.7.1, opencv 2.3.1a, and the python wrappers from willowgarage that come with that version of opencv. I have:

import cv,cv2
w = cv2.VideoWriter('foo.avi', cv.FOURCC('M','J','P','G'), 25, (100,100))
for i in range(100):
    w.write(np.ones((100,100,3), np.uint8))

OpenCV says

WARNING: Could not create empty movie file container.
Didn't successfully update movie file.
... [ 100 repetitions]

I'm not sure what to try next

Robert Kern
  • 13,118
  • 3
  • 35
  • 32
Alex Flint
  • 6,040
  • 8
  • 41
  • 80

11 Answers11

55

There are many outdated and incorrect online guides on this topic-- I think I tried almost every one. After looking at the source QTKit-based implementation of VideoWriter on Mac OSX, I was finally able to get VideoWriter to output valid video files using the following code:

fps = 15
capSize = (1028,720) # this is the size of my source video
fourcc = cv2.cv.CV_FOURCC('m', 'p', '4', 'v') # note the lower case
self.vout = cv2.VideoWriter()
success = self.vout.open('output.mov',fourcc,fps,capSize,True) 

To write an image frame (note that the imgFrame must be the same size as capSize above or updates will fail):

self.vout.write(imgFrame) 

When done be sure to:

vout.release() 
self.vout = None

This works for me on Mac OS X 10.8.5 (Mountain Lion): No guarantees about other platforms. I hope this snippet saves someone else hours of experimentation!

Todd Stellanova
  • 901
  • 1
  • 9
  • 13
12

I am on macOS High Sierra 10.13.4, Python 3.6.5, OpenCV 3.4.1.

The below code (source: https://www.learnopencv.com/read-write-and-display-a-video-using-opencv-cpp-python/) opens the camera, closes the window successfully upon pressing 'q', and saves the video in .avi format.

Note that you need to run this as a .py file. If you run it in Jupyter Notebook, the window hangs when closing and you need to force quit Python to close the window.

import cv2
import numpy as np
 
# Create a VideoCapture object
cap = cv2.VideoCapture(0)
 
# Check if camera opened successfully
if not cap.isOpened(): 
  print("Unable to read camera feed")
 
# Default resolutions of the frame are obtained.The default resolutions are system dependent.
# We convert the resolutions from float to integer.
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
 
# Define the codec and create VideoWriter object.The output is stored in 'outpy.avi' file.
out = cv2.VideoWriter('outpy.avi',cv2.VideoWriter_fourcc('M','J','P','G'), 10, (frame_width,frame_height))
 
while True:
  ret, frame = cap.read()
 
  if ret: 
     
    # Write the frame into the file 'output.avi'
    out.write(frame)
 
    # Display the resulting frame    
    cv2.imshow('frame',frame)
 
    # Press Q on keyboard to stop recording
    if cv2.waitKey(1) & 0xFF == ord('q'):
      break
 
  # Break the loop
  else:
    break 
 
# When everything done, release the video capture and video write objects
cap.release()
out.release()
 
# Closes all the frames
cv2.destroyAllWindows() 
yl_low
  • 1,209
  • 2
  • 17
  • 26
4

After trying various options, I found that the frame.size that I was using did not fit the size specified in the VideoWriter: So setting it to the default of my iMac 1280x720 made things work!

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
out = cv2.VideoWriter()
succes = out.open('output.mp4v',fourcc, 15.0, (1280,720),True)
while(cap.isOpened()):
    ret, frame = cap.read()
    if ret==True:
        frame = cv2.flip(frame,0)
        # write the flipped frame
        out.write(frame)
        cv2.imshow('frame',frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break

# Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()
Hans van Schaick
  • 112
  • 1
  • 1
  • 7
3

Here's a version that works with:

  • Python 3.6.3
  • OpenCV 3.3.1
  • macOS 10.13.1

Installed with brew install opencv.

#!/usr/bin/env python3

import cv2

def main():
    vc = cv2.VideoCapture()
    if not vc.open('input.mp4'):
        print('failed to open video capture')
        return

    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    # Match source video features.
    fps = vc.get(cv2.CAP_PROP_FPS)
    size = (
        int(vc.get(cv2.CAP_PROP_FRAME_WIDTH)),
        int(vc.get(cv2.CAP_PROP_FRAME_HEIGHT)),
    )

    vw = cv2.VideoWriter()
    if not vw.open('output.mp4', fourcc, fps, size):
        print('failed to open video writer')
        return

    while True:
        ok, frame = vc.read()
        if not ok:
            break

        # Flip upside down.
        frame = cv2.flip(frame, 0)

        # Write processed frame.
        vw.write(frame)

        cv2.imshow('frame', frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    vc.release()
    vw.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()
425nesp
  • 6,936
  • 9
  • 50
  • 61
2

It's the "size" problem.

import cv2
import time

filename = time.strftime("%m-%d-%H-%M-%S") + '.avi'
fps = 16

cap = cv2.VideoCapture(0)

#in this way it always works, because your get the right "size"
size = (int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH)),
        int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT)))
fourcc = cv2.cv.FOURCC('8', 'B', 'P', 'S')     #works, large
out = cv2.VideoWriter(filename, fourcc, fps, size, True)

#in this way, you must set the "size" to your size, 
#because you don't know the default "size" is right or not
#cap.set(3, 640)
#cap.set(4, 480)
#out = cv2.VideoWriter(filename, fourcc, fps, (640, 480), True)

while(cap.isOpened()):
    ret, frame = cap.read()
    if ret == True:
        out.write(frame)
        cv2.imshow('frame', frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break;

else:
    print 'Error...'
    break;

cap.release()
out.release()
cv2.destroyAllWindows()
lch0821
  • 61
  • 4
1

It's possible that your version of ffmpeg is out of date. I encountered a similar problem with ffmpeg 0.8 and it worked fine after I upgraded to ffmpeg 0.11.

John Zhang
  • 518
  • 1
  • 5
  • 12
1

Here's a variation of @ToddStellanova's answer that worked for me:

def write_video(image_dir):
  '''
  Writes a video from a set of images in `image_dir`
  '''
  target = join('data/labelled-videos',
                basename(image_dir) + '.mp4v')
  codec = cv2.cv.CV_FOURCC('m', 'p', '4', 'v')
  size = (256, 256)
  v = cv2.VideoWriter(target, codec, 16, size)
  for image_name in listdir(image_dir):
    image_filename = join(image_dir, image_name)
    arr = np.asarray(Image.open(image_filename))
    assert arr.shape[:2] == size
    v.write(arr)
Rose Perrone
  • 61,572
  • 58
  • 208
  • 243
1

The problem in my case was with the frame_width and frame_height. Try the following:

import cv2

cap = cv2.VideoCapture(0)

# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
size = (frame_width, frame_height)
fps = 10
out = cv2.VideoWriter("output.avi", fourcc, fps, size)

while(cap.isOpened()):
    ret, frame = cap.read()

    if ret:
        out.write(frame)  # write the frame
        cv2.imshow('frame', frame)
    else:
        break
    if cv2.waitKey(1) == 27:  # Esc
        break

# Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()
walter
  • 539
  • 5
  • 5
0

It's not good idea

You must create a VideoWriter structure and use method WriteFrame:

import cv
cv.NamedWindow('cap', 1)
w = cv.CreateVideoWriter('test.avi',cv.CV_FOURCC('X','V','I','D'),25,(640,480))
cap = cv.CaptureFromCAM(0)
while(1):
    img = cv.QueryFrame(cap)
    cv.ShowImage('cap', img)
    cv.WriteFrame(w, img)
    if cv.WaitKey(1) == 27:
        break
cv.DestroyWindow('cap')
ronalchn
  • 12,225
  • 10
  • 51
  • 61
Shoot
  • 9
  • 1
0

Thanks to @TeddStellanova

Here XCode C++ Version:

int fWidth = capture.get(CV_CAP_PROP_FRAME_WIDTH);
int fHeight = capture.get(CV_CAP_PROP_FRAME_HEIGHT);
string vid_path = path + "frames.mov";
VideoWriter vid(vid_path,CV_FOURCC('m','p','4','v'),30,Size(fWidth,fHeight),true);
Ahmet
  • 7,527
  • 3
  • 23
  • 47
0

This code will save the recorded video from the webcam (press q key to exit :)

Specifications:

  • ProductName: macOS
  • ProductVersion: 13.4.1
  • numpy: 1.25.1
  • opencv-python: 4.8.0.74

Code:

import cv2 as cv


# video capture
vc = cv.VideoCapture(0)
# video writer
video_filename = 'webcam.avi'
frame_rate = 30
frame_size = (int(vc.get(3)), int(vc.get(4)))
fourcc = cv.VideoWriter.fourcc('M', 'J', 'P', 'G')
vw = cv.VideoWriter(
  video_filename,
  fourcc,
  frame_rate,
  frame_size
)

while True:
    _, frame = vc.read()
    vw.write(frame)
    cv.imshow('', frame)
    if cv.waitKey(1) == ord('q'):
        break


vc.release()
vw.release()
cv.destroyAllWindows()
Yas
  • 4,957
  • 2
  • 41
  • 24