python-3.x - 如何使用 cv2.VideoWriter 输出 x265 压缩视频

标签 python-3.x opencv rendering codec

我正在对 45 分钟的 1.2GB 视频进行一些渲染,每个 80,0000 帧大小为 1344x756,视频为 mp4 格式,我正在尝试输出具有 x265 压缩的视频问题是当我使用cv2.VideoWriter 10 分钟视频的输出大小超过 2GB,这不是我想要的结果,所以我在 mac osx 和 ubuntu 18 上尝试了以下操作:

codec = cv2.VideoWriter_fourcc(*'HEVC')
out = cv2.VideoWriter('output.mp4', 'HEVC', fps, (width, height))

我得到的只是运行时警告:
OpenCV: FFMPEG: tag 0x43564548/'HEVC' is not found (format 'mp4 / MP4 (MPEG-4 Part 14)')'

我想要实现的不一定是最高质量的输出,而应该是高质量和尽可能小的尺寸。

最佳答案

据我所知,OpenCV VideoWriter不支持 HEVC 编码(目前)。
我建议您使用 FFmpeg作为子进程,并将渲染的帧通过管道传输到 stdin ffmpeg 的输入流.
您可以使用 Python 绑定(bind) ffmpeg喜欢 ffmpeg-python , 或执行 ffmpeg使用 Python subprocess .
使用 ffmpeg ,与 cv2.VideoWriter 相比,您可以更好地控制视频编码参数(cv2.VideoWriter 旨在简化和扩展灵 active )。
这是一个渲染 50 帧的示例代码,将帧流式传输到 ffmpeg使用 HEVC 视频编解码器对 MP4 视频文件进行编码:

import cv2
import numpy as np
import subprocess as sp
import shlex

width, height, n_frames, fps = 1344, 756, 50, 25  # 50 frames, resolution 1344x756, and 25 fps

output_filename = 'output.mp4'

# Open ffmpeg application as sub-process
# FFmpeg input PIPE: RAW images in BGR color format
# FFmpeg output MP4 file encoded with HEVC codec.
# Arguments list:
# -y                   Overwrite output file without asking
# -s {width}x{height}  Input resolution width x height (1344x756)
# -pixel_format bgr24  Input frame color format is BGR with 8 bits per color component
# -f rawvideo          Input format: raw video
# -r {fps}             Frame rate: fps (25fps)
# -i pipe:             ffmpeg input is a PIPE
# -vcodec libx265      Video codec: H.265 (HEVC)
# -pix_fmt yuv420p     Output video color space YUV420 (saving space compared to YUV444)
# -crf 24              Constant quality encoding (lower value for higher quality and larger output file).
# {output_filename}    Output file name: output_filename (output.mp4)
process = sp.Popen(shlex.split(f'ffmpeg -y -s {width}x{height} -pixel_format bgr24 -f rawvideo -r {fps} -i pipe: -vcodec libx265 -pix_fmt yuv420p -crf 24 {output_filename}'), stdin=sp.PIPE)

# Build synthetic video frames and write them to ffmpeg input stream.
for i in range(n_frames):
    # Build synthetic image for testing ("render" a video frame).
    img = np.full((height, width, 3), 60, np.uint8)
    cv2.putText(img, str(i+1), (width//2-100*len(str(i+1)), height//2+100), cv2.FONT_HERSHEY_DUPLEX, 10, (255, 30, 30), 20)  # Blue number

    # Write raw video frame to input stream of ffmpeg sub-process.
    process.stdin.write(img.tobytes())

# Close and flush stdin
process.stdin.close()

# Wait for sub-process to finish
process.wait()

# Terminate the sub-process
process.terminate()
笔记:
  • ffmpeg可执行文件必须在 Python 脚本的执行路径中。
  • 对于 Linux,如果 ffmpeg不在执行路径中,您可以使用完整路径:
     process = sp.Popen(shlex.split(f'/usr/bin/ffmpeg -y -s {width}x{height} -pixel_format bgr24 -f rawvideo -r {fps} -i pipe: -vcodec libx265 -pix_fmt yuv420p -crf 24 {output_filename}'), stdin=sp.PIPE)
    
    (假设 ffmpeg 可执行文件位于 /usr/bin/ 中)。
  • Python 3's f-Strings语法需要 Python 3.6 或更高版本。
  • 关于python-3.x - 如何使用 cv2.VideoWriter 输出 x265 压缩视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61260182/

    相关文章:

    c# - C++ AMP计算与WPF渲染显卡双用性能

    python - PyQuery Python 不支持 for 循环

    python - 通过QFileDialog下载/保存图像

    python - python中列表列表之间的叉积

    c++ - Opencv从多个摄像机捕获视频

    javascript - 如何将外部 HTML 文件导入 TypeScript 类

    python - 即使在 pip 安装后也找不到模块

    python - 如何将累加器 [Hough 变换] 的值转换回 Canvas 上的一条线?

    python - 如何将 tesseract 添加到我的 Docker 容器中以便我可以使用 pytesseract

    opengl - 什么样的几何体适合渲染 Twig