事情的起点是一个很普通的客户问题:"为什么你们转出来的 1080p 电影是 800M,隔壁服务商是 4G?是不是你们偷偷降了码率?"
我第一反应是"没降啊,我们一直用
-crf 23"。但话到嘴边又咽回去了——因为我发现自己其实也说不清-crf 23到底意味着多大的码率、多大的文件。后来我花了一周,把 ffmpeg 里几种码率控制模式从头捋了一遍,又拿同一段素材跑了十几组对比。结论是:
CRF不是万能的,CQ不是CRF,CBR和VBR是两回事,2-pass才是精确控制大小的终极手段。用错模式,轻则浪费带宽,重则画质崩坏。TL;DR:
CRF是"定画质、不定大小",适合离线分发,-crf 23是 x264 的默认甜点;硬件编码器的CQ看着像 CRF,但量纲不同、同数值画质更低,而且 NVENC 用 CQ 必须加-b:v 0;CBR固定码率、靠maxrate/bufsize压住峰值,是直播刚需;VBR在总码率不变的前提下按复杂度分配;2-pass先分析再编码,在指定码率下画质最接近最优,代价是接近两倍耗时。先想清楚你要"定大小"还是"定画质",再选模式。
目录
- 一、先分清"码率"和"画质"的关系
- 二、CRF:单遍编码的默认选择
- 三、CQ:硬件编码器的"伪 CRF"
- 四、CBR 与 VBR:直播和固定带宽的刚需
- 五、两遍编码 2-pass:离线归档的终极质量
- 六、码率分配:分辨率和码率的匹配
- 七、同一素材的实测对比
- 八、坑清单
- 九、选型速查表
一、先分清"码率"和"画质"的关系
在聊模式之前,得先把两个概念掰开。
码率(bitrate)是每秒消耗的比特数,单位一般是 kbps 或 Mbps。它直接决定文件大小:
文件大小 ≈ 码率 × 时长
一段 10 分钟、平均 5Mbps 的视频,大小约 5Mbps × 600s ÷ 8 ≈ 375MB。所以客户问的"为什么 800M 和 4G",本质就是码率差了五倍。
画质取决于"码率够不够",而不是"码率多不多"。同一个画面,码率给到一定程度之后再加码率,肉眼已经看不出区别——这就是收益递减。真正决定画质的是"码率 × 编码效率":同样的码率,x265 通常比 x264 画质好(效率高),但更慢。
所以"转 1080p 用多少码率"这个问题,永远不能脱离两个前提回答:用什么编码器、分辨率是多少。这也是为什么网上那些"万能码率表"十有八九会翻车。
二、CRF:单遍编码的默认选择
CRF(Constant Rate Factor)是 x264/x265 的默认码率控制模式,也是大多数人天天在用的那个。
它的目标不是固定码率,而是固定"感知画质"。编码器会根据画面复杂度实时分配码率:静止画面给少,运动、复杂纹理的画面给多。所以在同一段视频里,码率是浮动的,但观感质量基本稳定。
CRF 的取值是 0–51(x264),0 是无损,23 是默认,51 最差。数值越低画质越好、文件越大:
| CRF(x264) | 大致画质 | 1080p 典型码率 | 适合场景 |
|---|---|---|---|
| 18 | 视觉无损 | 8–12 Mbps | 归档、母片 |
| 23 | 很好 | 3–6 Mbps | 默认分发 |
| 28 | 可接受 | 1.5–3 Mbps | 快速预览、带宽紧张 |
命令很简单:
ffmpeg -i input.mp4 -c:v libx264 -preset medium -crf 23 -c:a aac -b:a 128k output.mp4
这里有两个容易混淆的点,先说清楚:
CRF不是码率。-crf 23绝不等于 23Mbps,它只是一个质量因子,最终码率由内容复杂度决定。所以同样-crf 23,一部动作片可能是 6Mbps,一部访谈可能只有 2Mbps。- x265 的 CRF 和 x264 不可直接对比。x265 的默认 CRF 是 28,大致对应 x264 的 23,两个数字不能互换套用。
CRF 最大的缺点也在这里:你无法预知最终文件大小。它适合"我只要画质好,大小无所谓"的离线分发场景;一旦要精确控制大小(比如压进 700M、控制在某个码率上限),CRF 就抓瞎了,这时候得上 2-pass,后面会讲。
三、CQ:硬件编码器的"伪 CRF"
GPU 编码器(NVENC、QSV、VAAPI)也提供"类似 CRF"的参数:NVENC 叫 CQ(Constant Quantizer),QSV 叫 ICQ,VAAPI 叫 global_quality。很多教程直接说"CQ 就是硬件版的 CRF,把 -crf 换成 -cq 就行"——这句话错得离谱。
关键差异在量纲:软编 CRF 是基于心理视觉的 rate factor,而硬件 CQ 本质是 quantizer(量化参数)。两者不是一回事,同样写 23,硬件 CQ 出来的画质通常不如软编 CRF。原因也很现实:硬件编码器为了实时性,在运动估计、模式决策这些环节做了大幅简化。
NVENC 的正确用法:
ffmpeg -i input.mp4 -c:v h264_nvenc -preset p4 -cq 23 -b:v 0 -c:a aac -b:a 128k output.mp4
注意那个 -b:v 0:NVENC 默认是 VBR 模式,必须显式把码率置 0,才会真正进入 CQ 模式。漏了它,-cq 直接失效,退化成 VBR,你会得到一堆忽大忽小的文件还以为 CQ 在起作用。
一个粗略的经验换算:NVENC 的 CQ 要画质达到 x264 CRF 23 的水平,大概要压到 -cq 19–21 甚至更低,代价是文件更大。所以硬件 CQ 的正确姿势不是"省码率",而是"用码率换速度"——同样的画质,它比软编快一个数量级,但文件更大。
四、CBR 与 VBR:直播和固定带宽的刚需
CBR(Constant Bit Rate)固定码率,VBR(Variable Bit Rate)可变码率,这是另一对概念。
- CBR:每一秒的码率都尽量恒定。适合直播、RTC、以及 CDN 或协议要求"带宽可预测"的场景。缺点是在复杂画面会画质下降,简单画面又浪费带宽。
- VBR:总码率不变的前提下,把码率往复杂画面集中。适合离线编码,画质利用率更高。
直播场景的标准 CBR 写法:
ffmpeg -i input.mp4 \
-c:v libx264 -preset veryfast \
-b:v 2500k -maxrate 2500k -bufsize 5000k \
-g 50 -keyint_min 50 -sc_threshold 0 \
-c:a aac -b:a 128k \
-f flv rtmp://your-server/live/stream
这里 maxrate 和 bufsize 是 CBR 的灵魂:
maxrate限制输出码率峰值,超过这个值的帧会被压缩或丢。bufsize是 VBV 缓冲区大小,决定了码率允许波动的幅度。
两者要成对设置,配比经验是 bufsize 取 maxrate 的 1–2 倍:bufsize 太小,码率波动被掐得太死、画质变差;太大,峰值就压不住了。只写 -b:v 不写 maxrate/bufsize,那它其实是在按 VBR 跑,峰值照样会飙。
五、两遍编码 2-pass:离线归档的终极质量
2-pass 是最"重"但最"稳"的模式,专门解决"我要精确控制大小/码率,又不想损失画质"的问题。
原理分两步:
- 第一遍:完整扫一遍内容,记录每一帧、每个片段的复杂度,输出一个统计文件,不产出最终视频。
- 第二遍:拿着统计文件重新编码,把目标码率"聪明地"分配到各个片段——复杂画面多给,简单画面少给,总码率卡死在目标值。
命令:
# 第一遍:只分析,不编码音频
ffmpeg -y -i input.mp4 -c:v libx264 -preset slow -b:v 4000k -pass 1 -an -f mp4 NUL
# 第二遍:正式编码
ffmpeg -y -i input.mp4 -c:v libx264 -preset slow -b:v 4000k -pass 2 -c:a aac -b:a 128k output.mp4
(Linux/macOS 下把 NUL 换成 /dev/null。)
两个容易踩的坑:
- 第一遍漏了
-an,音频被白白编了一遍,纯属浪费。 - 两遍的
-b:v必须一致,-preset也要一致,否则统计信息和实际编码对不上。
对比记忆:CRF 是"定画质、不定大小",2-pass 是"定大小、最优化画质"。什么时候值得花两倍时间去跑 2-pass?就是"压进 700M""控制在 4Mbps 以下"这种硬性大小约束出现的时候。
六、码率分配:分辨率和码率的匹配
模式选对了,还要给对码率。分辨率越高需要的码率越高,但关系不是线性的——4K 的像素是 1080p 的四倍,但码率并不需要四倍,因为编码效率随分辨率提升也更好。
下面是 x264 的经验参考值,不是金科玉律,但能帮你快速定位"是不是给多了/给少了":
| 分辨率 | 帧率 | 最低可用码率 | 推荐码率 |
|---|---|---|---|
| 360p | 24–30 | 600k | 1M |
| 720p | 24–30 | 1.5M | 2.5–4M |
| 1080p | 24–30 | 2.5M | 4–8M |
| 4K | 24–30 | 8M | 15–25M |
判断码率是否给够,别靠肉眼硬看,用工具量化:ffmpeg 自带的 libvmaf 能输出 VMAF 分数(0–100,越高越好),或者更轻量的 SSIM。VMAF 低于 85 基本就能看出明显瑕疵了。
七、同一素材的实测对比
拿一段 2 分钟、含大量运动的 1080p30 素材,同一台机器(软编用 8 核 CPU,硬编用一块消费级 NVIDIA)各跑一遍:
| 模式 | 参数 | 文件大小 | 平均码率 | VMAF | 耗时 |
|---|---|---|---|---|---|
| CRF 18 | libx264 | 210M | 14M | 97.1 | 3m |
| CRF 23 | libx264 | 84M | 5.6M | 93.8 | 2.4m |
| CRF 28 | libx264 | 40M | 2.7M | 87.5 | 2m |
| CQ 23 | h264_nvenc | 120M | 8M | 90.2 | 20s |
| 2-pass 4M | libx264 | 60M | 4M | 92.9 | 4.8m |
从这张表能读出几个结论:
- CRF 23 是甜点:画质 93.8 已经很好,大小也克制。
- 硬件 CQ 是拿码率换速度:同样写 23,它比软编 CRF 23 大了 43%,画质反而低,但快了 7 倍。
- 2-pass 的价值在"稳":锁定 4M 上限的同时,VMAF 还能干到 92.9,接近 CRF 23 的水平。
八、坑清单
- 硬件 CQ 忘加
-b:v 0,静默退化成 VBR,CQ 白设。 - 直播用 CBR 只写
-b:v不写maxrate/bufsize,峰值压不住、卡顿断流。 -crf和-b:v同时写,ffmpeg 会报错或忽略其中一个,别混用。- 2-pass 第一遍漏
-an,白编一遍音频;两遍参数不一致,统计作废。 - 拿 x265 的 CRF 数字套 x264(或反过来),画质/大小完全对不上。
- 把硬件
-cq当软编-crf的等价值,以为 23 = 23。 - 给 720p 配 4M 是浪费,给 1080p 配 1M 是灾难——先对表再动手。
九、选型速查表
| 场景 | 推荐模式 | 关键参数 |
|---|---|---|
| 离线分发、画质优先 | CRF | -crf 23 |
| 精确控制大小 | 2-pass | -b:v 目标码率 -pass 2 |
| 直播、固定带宽 | CBR | -b:v -maxrate -bufsize |
| GPU 实时转码 | CQ | -cq 23 -b:v 0 |
| 归档母片 | CRF 低值 | -crf 18 -preset slow |
最后回到开头那个客户问题:800M 和 4G 的差别,从来不是"谁降了码率",而是两边选了不同的模式、不同的质量目标。CRF 23 没问题,有问题的是"拿 CRF 去应付所有场景"——想清楚要"定大小"还是"定画质",码率控制这一关才算真正过了。