Writing an mp4 video using python opencv
I want to capture video from a webcam and save it to an mp4 file using opencv. I found example code on stackoverflow (below) that works great. The only hitch is that I'm trying to save it as mp4, not avi. Part of what I don't get is that the 'XVID' argument passed to the FOURCC writer is supposed to be, I think, an mp4 codec (from this link). If I change the filename to 'output.mp4' it tells me that the tag is invalid, so I have to believe that the XVID codec is actually making an avi file. Is this a stupid question? How do I write to an mp4?
I have found links showing how to convert an avi to an mp4 after the fact but that seems inefficient. Seems like I should be able to do it during the initial write.
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
# Define the codec and create VideoWriter object
fourcc = cv2.cv.CV_FOURCC(*'XVID')
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))
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()
Solution 1:
This worked for me.
self._name = name + '.mp4'
self._cap = VideoCapture(0)
self._fourcc = VideoWriter_fourcc(*'MP4V')
self._out = VideoWriter(self._name, self._fourcc, 20.0, (640,480))
Solution 2:
What worked for me was to make sure the input 'frame' size is equal to output video's size (in this case, (680, 480) ).
http://answers.opencv.org/question/27902/how-to-record-video-using-opencv-and-python/
Here is my working code (Mac OSX Sierra 10.12.6):
cap = cv2.VideoCapture(0)
cap.set(3,640)
cap.set(4,480)
fourcc = cv2.VideoWriter_fourcc(*'MP4V')
out = cv2.VideoWriter('output.mp4', fourcc, 20.0, (640,480))
while(True):
ret, frame = cap.read()
out.write(frame)
cv2.imshow('frame', frame)
c = cv2.waitKey(1)
if c & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()
Note: I installed openh264 as suggested by @10SecTom but I'm not sure if that was relevant to the problem.
Just in case:
brew install openh264
Solution 3:
There are some things to change in your code:
- Change the name of your output to 'output.mp4' (change to .mp4)
- I had the the same issues that people have in the comments, so I changed the fourcc to
0x7634706d
:out = cv2.VideoWriter('output.mp4',0x7634706d , 20.0, (640,480))
Solution 4:
This is the default code given to save a video captured by camera
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))
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()
For about two minutes of a clip captured that FULL HD
Using
cap = cv2.VideoCapture(0,cv2.CAP_DSHOW)
cap.set(3,1920)
cap.set(4,1080)
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (1920,1080))
The file saved was more than 150MB
Then had to use ffmpeg
to reduce the size of the file saved, between 30MB
to 60MB
based on the quality of the video that is required changed using crf
lower the crf better the quality of the video and larger the file size generated. You can also change the format avi
,mp4
,mkv
,etc
Then i found ffmpeg-python
Here a code to save numpy array
of each frame as video using ffmpeg-python
import numpy as np
import cv2
import ffmpeg
def save_video(cap,saving_file_name,fps=33.0):
while cap.isOpened():
ret, frame = cap.read()
if ret:
i_width,i_height = frame.shape[1],frame.shape[0]
break
process = (
ffmpeg
.input('pipe:',format='rawvideo', pix_fmt='rgb24',s='{}x{}'.format(i_width,i_height))
.output(saved_video_file_name,pix_fmt='yuv420p',vcodec='libx264',r=fps,crf=37)
.overwrite_output()
.run_async(pipe_stdin=True)
)
return process
if __name__=='__main__':
cap = cv2.VideoCapture(0,cv2.CAP_DSHOW)
cap.set(3,1920)
cap.set(4,1080)
saved_video_file_name = 'output.avi'
process = save_video(cap,saved_video_file_name)
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
frame = cv2.flip(frame,0)
process.stdin.write(
cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
.astype(np.uint8)
.tobytes()
)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
process.stdin.close()
process.wait()
cap.release()
cv2.destroyAllWindows()
break
else:
process.stdin.close()
process.wait()
cap.release()
cv2.destroyAllWindows()
break