[英]Writing an mp4 video using python opencv
我想从网络摄像头捕获视频并使用 opencv 将其保存到 mp4 文件。 我在stackoverflow(下)上找到了很好的示例代码。 唯一的问题是我试图将其保存为 mp4,而不是 avi。 我不明白的部分是传递给 FOURCC 编写器的“XVID”参数应该是,我认为,一个 mp4 编解码器(来自这个链接)。 如果我将文件名更改为“output.mp4”,它会告诉我标签无效,所以我必须相信 XVID 编解码器实际上是在制作 avi 文件。 这是一个愚蠢的问题吗? 如何写入 mp4?
我找到了显示如何将 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()
这对我有用。
self._name = name + '.mp4'
self._cap = VideoCapture(0)
self._fourcc = VideoWriter_fourcc(*'MP4V')
self._out = VideoWriter(self._name, self._fourcc, 20.0, (640,480))
对我有用的是确保输入的“帧”大小等于输出视频的大小(在本例中为 (680, 480) )。
http://answers.opencv.org/question/27902/how-to-record-video-using-opencv-and-python/
这是我的工作代码(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()
注意:我按照@10SecTom 的建议安装了 openh264,但我不确定这是否与问题有关。
以防万一:
brew install openh264
您的代码中有一些需要更改的地方:
0x7634706d
: out = cv2.VideoWriter('output.mp4',0x7634706d , 20.0, (640,480))
这是保存相机拍摄的视频的默认代码
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()
大约两分钟的剪辑捕捉到了FULL HD
使用
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))
保存的文件超过150MB
然后不得不使用ffmpeg
来减小保存的文件大小,根据需要更改的视频质量在30MB
到60MB
之间使用crf
降低 crf 更好的视频质量并生成更大的文件大小。 您还可以更改格式avi
、 mp4
、 mkv
等
然后我找到了ffmpeg-python
这是使用ffmpeg-python
将每帧的numpy array
保存为视频的代码
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
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
'mp4v' 不返回错误,这与在fourcc 中定义的'MP4V' 不同
对于错误:
“OpenCV:FFMPEG:标签 0x5634504d/'MP4V' 不支持编解码器 id 13 和格式'mp4 / MP4(MPEG-4 第 14 部分)' OpenCV:FFMPEG:回退使用标签 0x00000020/'???'”
这对我有用,我添加了 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()
对于仍在为问题苦苦挣扎的人。 根据这篇文章,我使用了这个示例,它对我有用:
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()
所以我不得不使用cv2.VideoWriter_fourcc(*'X264')
编解码器。 使用从源代码编译的 OpenCV 3.4.3 进行测试。
任何正在寻找使用 OpenCV 或 FFmpeg 编写 MP4 文件的最方便和最强大的方法的人,都可以查看我最先进的VidGear视频处理 Python 库的WriteGear API ,它可与OpenCV 后端和FFmpeg 后端一起使用,甚至支持 GPU 编码器. 这是一个在带有 FFmpeg 后端的 WriteGear 中使用 H264 编码器进行编码的示例:
# import required libraries
from vidgear.gears import WriteGear
import cv2
# define suitable (Codec,CRF,preset) FFmpeg parameters for writer
output_params = {"-vcodec":"libx264", "-crf": 0, "-preset": "fast"}
# Open suitable video stream, such as webcam on first index(i.e. 0)
stream = cv2.VideoCapture(0)
# Define writer with defined parameters and suitable output filename for e.g. `Output.mp4`
writer = WriteGear(output_filename = 'Output.mp4', logging = True, **output_params)
# loop over
while True:
# read frames from stream
(grabbed, frame) = stream.read()
# check for frame if not grabbed
if not grabbed:
break
# {do something with the frame here}
# lets convert frame to gray for this example
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# write gray frame to writer
writer.write(gray)
# Show output window
cv2.imshow("Output Gray Frame", gray)
# check for 'q' key if pressed
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
# close output window
cv2.destroyAllWindows()
# safely close video stream
stream.release()
# safely close writer
writer.close()
诸如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/' ???'
也许您的输出视频大小与原始视频不同。 您可以先查看视频的帧大小。
您需要将编解码器设置为'mp4v'
(小写)。 如果设置为大写,则会抛出一个错误,说不支持,建议改用小写: OpenCV:
FFMPEG
:fallback to use tag 0x7634706d/'mp4v'
。 您可能还想查看VideoWriter的文档以及此处给出的示例。 另外,请确保您的输出视频的大小等于您的输入frame
大小(下面使用VideoCapture
对象的尺寸来处理这个问题)。
cap = cv2.VideoCapture(0)
w = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
h = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = cap.get(cv2.CAP_PROP_FPS)
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output.mp4', fourcc, fps, (int(w),int(h)))
您可以通过设置fourcc=-1
来获取可用于mp4
等的编解码器的完整列表。 例如:
out = cv2.VideoWriter('output.mp4', -1, fps, (int(w),int(h)))
关于 VideoWriter,OpenCV 文档不是很丰富,但是我设法通过以下方式使其工作(通过查看堆栈跟踪):
import cv2
HEIGHT = 480
WIDTH = 640
FPS = 30.0
cap = cv2.VideoCapture(0, cv2.CAP_ANY)
cap.set(cv2.CAP_PROP_FPS, FPS)
cap.set(cv2.CAP_PROP_CONVERT_RGB , 1)
cap.set(cv2.CAP_PROP_BUFFERSIZE, 100)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, WIDTH)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, HEIGHT)
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
# output parameters such as fps and size can be changed
output = cv2.VideoWriter("output.mp4", fourcc, FPS, (WIDTH, HEIGHT))
while True:
if cap.isOpened():
(ret, frame) = cap.read()
if ret:
output.write(frame)
cv2.imshow("frame", frame)
if cv2.waitKey(10) == ord('q'):
break
output.release()
cap.release()
cv2.destroyAllWindows()
堆栈跟踪错误是:
OpenCV: FFMPEG: tag 0x5634504d/'MP4V' is not supported with codec id 12 and
format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x7634706d/'mp4v'
不幸的是,很难找到 OpenCV 使用的官方编解码器列表,或者至少我找不到它们。 无论如何,您似乎必须输入以小写形式编写的编解码器“mp4v”。
https://docs.opencv.org/3.4/dd/d01/group__videoio__c.html#gac005718f121379beffdbdbfb44f2646a
我注意到的一件重要的事情是帧和输出视频的纵横比必须相同,这就是为什么我使用两个变量来表示高度和宽度。 如果这两个不同,则创建文件,但不保存帧(您总是得到一个 1KB 的 mp4 文件)。 为避免任何问题,您可以对 FPS 执行相同操作。
只需将编解码器更改为"DIVX"
。 此编解码器适用于所有格式。
fourcc = cv2.VideoWriter_fourcc(*'DIVX')
我希望这对你有用!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.