Windows下cv2.VideoWriter使用HEVC编码写入MP4报错解决方案问询
问题原因
几个核心错误对应的根因如下:
HEVC tag not supported警告:MP4封装标准中HEVC对应的FourCC编码为hev1,你使用的HEVC是非标准标识,FFmpeg自动降级后仍可能触发兼容性问题COM must not be in STA mode报错:Windows Media Foundation 编码器要求运行在多线程单元(MTA)模式,而PyCharm默认启动Python脚本时使用单线程单元(STA)模式- 最终初始化失败:当前环境的OpenCV FFmpeg后端没有可用的HEVC编码器,要么是系统缺少HEVC编码组件,要么是你安装的
opencv-pythonPyPI预编译包因专利授权问题未编译HEVC支持
可行解决方案
按优先级排序:
方案1:修复现有代码+环境基础配置
- 先安装Windows HEVC编码扩展:打开Microsoft Store搜索「HEVC 视频扩展」,安装官方提供的免费扩展包
- 在脚本最开头加入线程模式初始化代码,切换为MTA模式;同时修正FourCC编码为标准
hev1,创建VideoWriter时强制指定FFmpeg后端
对应代码示例:
import pythoncom from cv2 import cv2 # 初始化线程模式为MTA,必须放在所有cv2操作之前 pythoncom.CoInitializeEx(pythoncom.COINIT_MULTITHREADED) video = cv2.VideoCapture(0) frame_width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)) videoFileName = "test_output.mp4" # 改用标准hev1标识,强制指定FFmpeg后端 fourcc = cv2.VideoWriter_fourcc(*'hev1') out1 = cv2.VideoWriter( videoFileName, apiPreference=cv2.CAP_FFMPEG, fourcc=fourcc, fps=30.0, frameSize=(frame_width, frame_height) )
如果提示没有pythoncom包,先执行pip install pywin32安装依赖。
方案2:更换OpenCV安装源
PyPI官方的opencv-python预编译包因专利授权限制,默认未开启HEVC编码支持,可改用conda-forge源的OpenCV包,该版本编译时已开启全编码支持:
- 先卸载现有OpenCV包:
pip uninstall opencv-python opencv-python-headless - 如果你用Anaconda/miniconda环境,执行:
conda install -c conda-forge opencv - 再配合方案1的代码修改使用即可。
方案3:绕过cv2.VideoWriter,直接使用FFmpeg编码
如果上述方案都不生效,可直接调用FFmpeg进行HEVC编码,兼容性更高:
- 先安装依赖:
pip install ffmpeg-python,同时提前将FFmpeg预编译包的bin目录加入系统环境变量PATH - 代码示例:
import ffmpeg from cv2 import cv2 video = cv2.VideoCapture(0) frame_width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)) videoFileName = "test_output.mp4" # 初始化FFmpeg进程,指定HEVC编码 process = ( ffmpeg .input('pipe:', format='rawvideo', pix_fmt='bgr24', s=f'{frame_width}x{frame_height}', r=30) .output(videoFileName, vcodec='libx265', pix_fmt='yuv420p', crf=28) .overwrite_output() .run_async(pipe_stdin=True) ) # 写入帧的逻辑 while True: ret, frame = video.read() if not ret: break process.stdin.write(frame.tobytes()) # 可自行添加显示、退出逻辑 cv2.imshow('frame', frame) if cv2.waitKey(1) == ord('q'): break # 资源释放 process.stdin.close() process.wait() video.release() cv2.destroyAllWindows()
内容的提问来源于stack exchange,提问作者anelson
相关产品推荐
相关产品推荐

