在 OpenCV 的视频处理流程里,cv2.VideoWriter_fourcc 是我见过最像“咒语”的一行代码。它读起来差不多是乱码,但 VideoWriter 能不能把视频正常写进文件,绝大多数情况下都由这串四个字符决定。我早期刚接触 OpenCV 的时候踩过好几次坑:摄像头画面明明能正常弹窗,writer.write() 也一路执行完不报错,最后生成的视频却只有几百字节,甚至根本没有文件生成。折腾一圈后才发现,问题全出在我对 fourcc 的理解太浅——只知道“抄别人代码里的字符串”,不知道它背后的编码机制、容器匹配和安装包差异。
这篇文章我打算用自己的项目经历,把 cv2.VideoWriter_fourcc 这个函数彻底聊透:它到底是什么、不同编码格式怎么选、常见失败场景怎么排查,以及我在实际录制摄像头、批量合成图片视频时总结的稳定方案。无论你是刚开始学 OpenCV,还是已经在做视觉项目但被视频输出折磨过,这篇文章应该都能给你省下不少时间。
1. 拆开四个字符:fourcc 到底在告诉 OpenCV 什么
1.1 Four Character Code 的由来和本质
fourcc 的全称是 Four Character Code,直译就是“四字符代码”。这个设计最早可以追溯到老一代多媒体系统,后来在视频容器和编码领域被广泛沿用。它的本质非常简单:用四个可打印的 ASCII 字符,比如 M、J、P、G,拼成一个唯一的标识,用来告诉媒体库“我想用哪一种编码器”。
在 OpenCV 里,cv2.VideoWriter_fourcc 的返回值并不是字符串,而是一个 32 位整数。VideoWriter 构造函数拿到这个整数后,会把它翻译成底层视频后端能识别的编码器编号。所以你可以打印一下看看:
python复制import cv2
code = cv2.VideoWriter_fourcc(*"MJPG")
print(type(code))
print(code)
输出会是一个 int 类型,而不是 "MJPG" 字符串。理解了这一点,很多初学者的疑惑就解开了:为什么明明传了一个看起来正常的四个字母,视频却写不出来?因为你的 OpenCV 环境里,
根本没注册这个四个字符对应的编码器,或者这个编码器根本不能被写进你指定的容器文件。
1.2 Python 里那个容易被忽略的星号
Python 接口使用 cv2.VideoWriter_fourcc(*"MJPG") 这种写法,其中 *"MJPG" 是把字符串拆成四个单字符参数,等价于:
python复制cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
这是很多从 C++ 转 Python 的开发者最容易忽视的细节。C++ 里的写法本来就是四个参数:
cpp复制int fourcc = VideoWriter::fourcc('M', 'J', 'P', 'G');
Python 里如果漏掉星号,写成 cv2.VideoWriter_fourcc("MJPG"),解释器会直接抛出类型错误,因为它期望 4 个参数,而你只给了 1 个。这个报错还算友好,怕的是你把一个字符串变量传进去,报错的时机又很靠后,容易被误判成编码器问题。
我见过不少人在循环里反复创建 VideoWriter,每次都用字符串拼接来生成不同文件名。这里有个大坑:如果文件名后缀、容器格式和 fourcc 编码器不匹配,VideoWriter 构造函数不会立刻抛异常,而是默默创建一个写不进去的“僵尸对象”,直到你调用 isOpened() 才发现返回 False。所以代码里每创建一次 writer,都应该立刻检查一次打开结果,否则后面排查成本会成倍增加。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 编码格式选型:为什么同样叫 mp4,输出文件差别这么大
2.1 常用编码器对照表
我在不同项目里轮流用过 MJPG、XVID、mp4v、avc1 这些 fourcc,它们的生产环境表现差异很大。下面这张表是我根据自己的使用经验整理的,不代表所有环境,但作为选型参考已经够用:
| FourCC | 实际编码 | 常见容器 | 压缩效率 | 兼容性特征 |
|---|---|---|---|---|
| MJPG | Motion JPEG | AVI | 很低 | 几乎万能播放,文件体积非常大 |
| XVID | MPEG-4 Part 2 | AVI | 中等 | 老式播放器和系统兼容性较好 |
| DIVX | DivX MPEG-4 | AVI | 中等 | 与 XVID 类似,不同设备解码器需求不同 |
| mp4v | MPEG-4 Part 2 | MP4 | 中等 | MP4 基础兼容,部分新播放器支持一般 |
| avc1 / H264 | H.264/AVC | MP4 | 很高 | 当前平台兼容性最好,但编码器不一定内置 |
| hvc1 / HEVC | H.265/HEVC | MP4 | 非常高 | 高压缩率,但老旧设备和部分播放器打不开 |
| VP90 | VP9 | WebM | 很高 | 浏览器生态好,OpenCV 默认支持不稳定 |
先从我自己最常用的几个说。MJPG 是将每一帧图像单独压缩成 JPEG 再封装进视频流,帧内编码,没有利用时间上的冗余,所以同样一段画面,它的文件体积可能比 mp4v 大出好几倍,画面内容一旦复杂,差距还会继续拉大。优点是什么设备几乎都能解码,编码速度也快,非常适合做视觉算法的中间过程采集,例如保存检测结果视频用于后续调试。
mp4v 是我早期做成品项目时的默认选项,因为它写进 .mp4 后缀文件时,很多普通播放器都能打开。但后来我遇到过会议演示现场打不开的情况,换了播放器又是正常的。这是因为 mp4v 对应的实际编码是 MPEG-4 Part 2,不是大家默认以为的 H.264,部分软件
