【问题标题】:Writing an mp4 video using python opencv使用 python opencv 编写 mp4 视频
【发布时间】:2015-08-11 03:20:30
【问题描述】:

我想从网络摄像头捕获视频并使用 opencv 将其保存为 mp4 文件。我在stackoverflow(下)上找到了很好的示例代码。唯一的问题是我试图将其保存为 mp4,而不是 avi。我不明白的部分是传递给 FOURCC 编写器的“XVID”参数应该是,我认为,一个 mp4 编解码器(来自this link)。如果我将文件名更改为“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()

【问题讨论】:

  • 尝试使用->fourcc = cv2.cv.CV_FOURCC(*'H264')
  • 不过你需要 ffmpeg
  • 尝试使用 CV_FOURCC('m', 'p', '4', 'v')。这是一个例子:stackoverflow.com/a/28904970/4481702
  • @Ha Dang:不。该示例与我所看到的完全相同。该文件仍保存为 avi。
  • 您是否将输出文件名更改为 .mp4 扩展名?你怎么知道它仍然保存为 avi?

标签: python opencv video


【解决方案1】:

这对我有用。

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

【讨论】:

  • 两年了!你没想到会有这样的投票,对吧? :P 我正在使用 H264 写入 mp4 文件。它在搜索时创建了滞后的视频,这个建议帮助了我。 MP4V编解码器解决了这个问题! :)
  • @varun ha no didn't see it come :) .. 很高兴它帮助你萌芽。
  • 它不起作用,并显示以下错误: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/' ???'
  • @BahramdunAdil 输出文件的名称必须以.mp4 结尾,这就是您遇到该错误的原因
  • 我有错误编解码器 id 12 而不是 @BahramdunAdil 的 13 并将编解码器更改为 *'mp4v'*'MP4V' 为我修复了它。
【解决方案2】:

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

  1. 将输出名称更改为“output.mp4”(更改为 .mp4)
  2. 我遇到了和cmets一样的问题,所以我把fourcc改成了0x7634706d:out = cv2.VideoWriter('output.mp4',0x7634706d , 20.0, (640,480))

【讨论】:

  • 0x7634706d 与使用fourcc的mp4v(小写)相同
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    这是default code,用于保存相机拍摄的视频

    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更好的质量视频和更大的文件大小生成。您也可以更改格式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
    

    【讨论】:

    • '在大约两分钟的时间内捕捉到 FULL HD' 你在代码中哪里指定了 2 分钟?
    【解决方案5】:

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

    【讨论】:

      【解决方案6】:

      fourcc = cv2.VideoWriter_fourcc(*'mp4v')

      'mp4v' 与fourcc 中定义的'MP4V' 不同,不会返回任何错误

      对于错误:

      "OpenCV: FFMPEG: tag 0x5634504d/'MP4V' is not supported with codec id 13 和格式 'mp4 / MP4 (MPEG-4 Part 14)' OpenCV: FFMPEG: fallback to 使用标签 0x00000020/' ???'"

      【讨论】:

        【解决方案7】:

        任何正在寻找使用 OpenCV 或 FFmpeg 编写 MP4 文件的最方便和最可靠的方法的人,可以查看我最先进的 VidGear Video-Processing Python 库的 WriteGear API,它适用于 OpenCV backendFFmpeg backend 甚至 supports GPU encoders。这是一个在带有 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 作为后端的情况:由于 OpenCV 的视频编写器本身是 a wrapper 围绕 ffmpeg 和其他库(根据 OS 平台),我想知道使用这个库是否真的有特别的优势与使用 OpenCV 本身相比,使用 OpenCV 作为其后端。很高兴学习。
        • 是的,它不仅在 OpenCV 后端的情况下提供对 OpenCV 编写器的直接访问,而且还自动处理输出文件路径、simplifies assigning FOURCC Codecs 名称并在编码文件时处理任何错误。
        【解决方案8】:

        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,则输出文件必须以.mp4 结尾。与XVID 相同,输出文件名应以.avi 结尾
        • 如果对swiftlane.com/eng/…987654321@ 有帮助,我会深入研究并在这篇博文中记录我的解决方案
        【解决方案9】:

        对于仍在为问题苦苦挣扎的人。根据this article,我使用了这个示例,它对我有用:

        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 进行测试。

        【讨论】:

        【解决方案10】:

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

        【讨论】:

          【解决方案11】:

          只需将编解码器更改为"DIVX"。此编解码器适用于所有格式。

          fourcc = cv2.VideoWriter_fourcc(*'DIVX')
          

          我希望这对你有用!

          【讨论】:

            猜你喜欢
            • 2018-03-10
            • 2011-07-22
            • 1970-01-01
            • 2020-03-15
            • 1970-01-01
            • 2020-09-24
            • 2014-04-20
            • 1970-01-01
            相关资源
            最近更新 更多