使用 python opencv 编写 mp4视频

我想捕捉视频从一个网络摄像头,并保存到一个 mp4文件使用 opencv。我发现堆栈溢出(下面)的示例代码工作得很好。唯一的问题是我想把它保存为 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()
202079 次浏览

这招对我很管用。

self._name = name + '.mp4'
self._cap = VideoCapture(0)
self._fourcc = VideoWriter_fourcc(*'MP4V')
self._out = VideoWriter(self._name, self._fourcc, 20.0, (640,480))

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/' ???'这样的问题可能是您的输出视频大小与原始视频不一样。你可以先查看视频的帧大小。

在代码中有一些需要更改的地方:

  1. 将输出名称更改为‘ output.mp4’(更改为. mp4)
  2. 我有同样的问题,人们在评论中有,所以我改为 0x7634706d: out = cv2.VideoWriter('output.mp4',0x7634706d , 20.0, (640,480))的 fourcc

对于那些还在为这个问题而挣扎的人来说,根据 这篇文章,我使用了这个样本,它对我很有效:

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')编解码器。

对我来说,有效的方法是确保输入“帧”大小等于输出视频的大小(在本例中为(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

fourcc = cv2.VideoWriter_fourcc(*'mp4v')

与在 fourcc 中定义的 MP4V 不同,‘ MP4V’不返回任何错误

对于错误:

”OpenCV: FFMPEG: tag 0x5634504d/‘ MP4V’不支持编解码器 id 13和格式‘ MP4/MP4(MPEG-4 Part 14)’OpenCV: FFMPEG: 回退到 使用标签0x00000020/’? ? ?’”

这是用来保存摄像机拍摄的视频的 默认代码

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来减小保存的文件的大小,在 30MB60MB之间根据视频的质量需要改变,使用 crf降低的 crf 更好的视频质量和更大的文件大小生成。您也可以改变格式 avimp4mkv

然后我找到了 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

这对我很有用,我添加了 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()

任何想用 OpenCV 或 FFmpeg 编写 MP4文件的人,都可以看到我最先进的 VidGear Video-Processing Python 库的 WriteGear API,它可以同时使用 OpenCV 后端FFmpeg 后端,甚至 支持 GPU 编码器。下面是一个在 WriteGear 中使用 H264编码器和 FFmpeg 后端进行编码的例子:

# 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()

只需将编解码器改为 "DIVX"即可。该编解码器适用于所有格式。

fourcc = cv2.VideoWriter_fourcc(*'DIVX')

我希望这对你有用!

您需要将编解码器设置为 'mp4v'(小写)。如果设置为大写,将抛出一个错误,表示使用 不支持,建议改为使用小写: OpenCV:FFMPEG:fallback to use tag 0x7634706d/'mp4v'。您可能还想了解一下 录像作家的文档,以及给出的 OpenCV:0示例。此外,请确保您的输出视频的大小等于您的输入 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)))

OpenCV 的文档对于 VideoWriter 来说并不是很丰富,但是我通过以下方式(通过查看堆栈跟踪)让它工作起来:

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 做同样的事情。