使用 python opencv 编写 mp4 视频
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30509573/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Writing an mp4 video using python opencv
提问by Gadzooks34
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?
我想从网络摄像头捕获视频并使用 opencv 将其保存到 mp4 文件中。我在 stackoverflow(如下)上找到了很好用的示例代码。唯一的问题是我试图将它保存为 mp4,而不是 avi。我不明白的部分原因是,我认为传递给 FOURCC 编写器的“XVID”参数应该是 mp4 编解码器(来自此链接)。如果我将文件名更改为“output.mp4”,它会告诉我该标签无效,因此我必须相信 XVID 编解码器实际上正在制作一个 avi 文件。这是一个愚蠢的问题吗?如何写入 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.
我找到了显示如何在事后将 avi 转换为 mp4 的链接,但这似乎效率低下。似乎我应该能够在初始写入期间做到这一点。
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()
回答by 10SecTom
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))
回答by TanLingxiao
The problem such as OpenCV: FFMPEG: tag 0x5634504d/'MP4V' is not supported with codec id 13 and format 'mp4 / MP4 (MPEG-4 Part 14)' OpenCV: FFMPEG: fallback to use tag 0x00000020/' ???'
maybe that your output video size is not the same as original video. You can look over the frame size of video first.
问题,例如OpenCV: FFMPEG: tag 0x5634504d/'MP4V' is not supported with codec id 13 and format 'mp4 / MP4 (MPEG-4 Part 14)' OpenCV: FFMPEG: fallback to use tag 0x00000020/' ???'
您的输出视频大小可能与原始视频不同。您可以先查看视频的帧大小。
回答by Alan Soder
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))
- 将输出名称更改为“output.mp4”(更改为 .mp4)
- 我遇到了人们在评论中遇到的相同问题,因此我将 Fourcc 更改为
0x7634706d
:out = cv2.VideoWriter('output.mp4',0x7634706d , 20.0, (640,480))
回答by Ivan Talalaev
For someone whoe still struggle with the problem. According this articleI used this sample and it works for me:
对于仍在与问题作斗争的人。根据这篇文章,我使用了这个示例,它对我有用:
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'X264')
out = cv2.VideoWriter('output.mp4',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()
So I had to use cv2.VideoWriter_fourcc(*'X264')
codec. Tested with OpenCV 3.4.3 compiled from sources.
所以我不得不使用cv2.VideoWriter_fourcc(*'X264')
编解码器。使用从源代码编译的 OpenCV 3.4.3 进行测试。
回答by ling
What worked for me was to make sure the input 'frame' size is equal to output video's size (in this case, (680, 480) ).
对我有用的是确保输入“帧”大小等于输出视频的大小(在这种情况下, (680, 480) )。
http://answers.opencv.org/question/27902/how-to-record-video-using-opencv-and-python/
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):
这是我的工作代码(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.
注意:我按照@10SecTom 的建议安装了 openh264,但我不确定这是否与问题有关。
Just in case:
以防万一:
brew install openh264
回答by Harish vardhana
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
Fourcc = cv2.VideoWriter_fourcc(*' mp4v')
'mp4v' returns no errors unlike 'MP4V' which is defined inside fourcc
与在fourcc 中定义的“MP4V”不同,“mp4v”不会返回任何错误
for the error "OpenCV: FFMPEG: tag 0x5634504d/'MP4V' is not supported with codec id 13 and format 'mp4 / MP4 (MPEG-4 Part 14)' OpenCV: FFMPEG: fallback to use tag 0x00000020/' ???'"
对于错误“OpenCV: FFMPEG: tag 0x5634504d/'MP4V' is not supported with codec id 13 and format 'mp4 / MP4 (MPEG-4 Part 14)' OpenCV: FFMPEG: fallback to use tag 0x00000020/' ???' ”
回答by Santhosh Dhaipule Chandrakanth
This is the default codegiven 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
大约两分钟的剪辑捕捉到了 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
保存的文件超过 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
然后不得不用ffmpeg
降低保存的文件的大小,之间30MB
要60MB
根据所需使用改变了视频质量crf
下产生的慢性肾功能衰竭的视频更好的质量和更大的文件大小。您也可以更改格式avi
,mp4
,mkv
,等
Then i found ffmpeg-python
然后我找到了ffmpeg-python
Here a code to save numpy array
of each frame as video using ffmpeg-python
这里有一个使用代码将numpy array
每一帧保存为视频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
回答by Abdelaziz Khajour
This worked for me, I added images.sort() to keep the sequence order:
这对我有用,我添加了 images.sort() 以保持序列顺序:
import cv2
import numpy as np
import os
image_folder = 'data-set-race-01'
video_file = 'race-01.mp4'
image_size = (160, 120)
fps = 24
images = [img for img in os.listdir(image_folder) if img.endswith(".jpg")]
images.sort()
out = cv2.VideoWriter(video_file, cv2.VideoWriter_fourcc(*'MP4V'), fps, image_size)
img_array = []
for filename in images:
img = cv2.imread(os.path.join(image_folder, filename))
img_array.append(img)
out.write(img)
out.release()