使用 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 08:33:25  来源:igfitidea点击:

Writing an mp4 video using python opencv

pythonopencvvideo

提问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:

您的代码中有一些需要更改的内容:

  1. Change the name of your output to 'output.mp4' (change to .mp4)
  2. 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))
  1. 将输出名称更改为“output.mp4”(更改为 .mp4)
  2. 我遇到了人们在评论中遇到的相同问题,因此我将 Fourcc 更改为0x7634706dout = 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 ffmpegto reduce the size of the file saved, between 30MBto 60MBbased on the quality of the video that is required changed using crflower 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降低保存的文件的大小,之间30MB60MB根据所需使用改变了视频质量crf下产生的慢性肾功能衰竭的视频更好的质量和更大的文件大小。您也可以更改格式avimp4mkv,等

Then i found ffmpeg-python

然后我找到了ffmpeg-python

Here a code to save numpy arrayof 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()