3. 编码器选型与调优:H.264 vs H.265 编码对比、x264 参数调优、硬件编码器(NVENC/VAAPI)配置
编码器选型,说白了就是你在「画质」、「码率」、「延迟」和「计算成本」之间做权衡。我见过太多团队一上来就上 H.265,结果解码端卡成幻灯片,或者为了省带宽把画质压到没法看。这一章,咱们把 H.264 和 H.265 的底裤扒干净,再聊聊 x264 的调优套路,最后说说 NVENC 和 VAAPI 怎么配才不翻车。
核心观点:没有最好的编码器,只有最适合你场景的编码器。直播推流场景下,H.264 依然是兼容性之王,H.265 更适合带宽极度受限或存储成本敏感的场景。
3.1 H.264 vs H.265:到底差在哪?
先看一张对比表,把核心差异说清楚。
| 对比维度 | H.264 (AVC) | H.265 (HEVC) |
|---|---|---|
| 编码标准 | 2003 年发布,MPEG-4 Part 10 | 2013 年发布,ITU-T H.265 |
| 压缩效率 | 基准 | 同等画质下码率降低 30%~50% |
| 计算复杂度 | 较低,适合软编码 | 高,约 2~4 倍于 H.264 |
| 编码单元 | 宏块 (16x16) | 编码树单元 (CTU, 最大 64x64) |
| 运动补偿 | 1/4 像素精度,最多 16 个参考帧 | 1/8 像素精度,最多 16 个参考帧,支持更多预测方向 |
| 帧内预测 | 9 种模式 | 35 种模式 |
| 熵编码 | CAVLC / CABAC | CABAC (改进版) |
| 硬件支持 | 几乎所有设备 | 较新设备,部分老旧设备不支持 |
| 专利许可 | 成熟,专利池复杂但已稳定 | 专利授权费用较高,存在不确定性 |
我个人习惯在推流场景下这样选:如果目标客户端覆盖 iOS 9 以上、Android 7 以上,且带宽低于 2Mbps,我会优先考虑 H.265。否则,老老实实用 H.264。我在项目中遇到过用 H.265 推流,结果某品牌电视盒子解码花屏的坑,排查了三天才发现是固件 HEVC 解码器有 bug。
3.2 x264 参数调优:软编码的终极武器
x264 是软件编码器里的老大哥,调好了画质能打硬件编码器,调不好就是 CPU 烧火棍。下面是我常用的调优套路。
3.2.1 预设(Preset)与调优(Tune)
预设控制编码速度和压缩率的平衡。从 ultrafast 到 placebo,速度越来越慢,画质越来越好。但注意,placebo 的收益微乎其微,我一般只用到 slow 或 slower。
# 直播推流推荐:中等预设 + 低延迟调优
ffmpeg -i input.mp4 -c:v libx264 -preset medium -tune zerolatency -b:v 2000k -g 60 output.ts
# 点播录制推荐:慢速预设 + 胶片调优(保留细节)
ffmpeg -i input.mp4 -c:v libx264 -preset slow -tune film -crf 18 output.mp4
我的经验:直播场景用 zerolatency 调优,可以大幅降低编码延迟。但注意,它会禁用部分 lookahead 功能,码率控制会稍微粗糙一点。如果对画质要求高,可以试试 fastdecode 调优,解码端压力更小。
3.2.2 码率控制模式
x264 支持三种码率控制模式,我分别说说适用场景。
- CRF(恒定质量): 最推荐。设置
-crf 23,数值越小画质越好。直播场景建议 18~23,点播场景 16~20。注意 CRF 不保证码率上限,需要配合-maxrate和-bufsize使用。 - ABR(平均码率): 用
-b:v指定目标码率。适合直播推流,码率可控。但画质波动较大,我一般配合-maxrate和-minrate做约束。 - CBR(恒定码率): 严格固定码率,适合对带宽要求苛刻的场景。但画质最差,不推荐。
# CRF 模式 + 码率上限约束(直播推荐)
ffmpeg -i input.mp4 -c:v libx264 -preset medium -tune zerolatency -crf 20 -maxrate 2500k -bufsize 5000k output.ts
# ABR 模式(带宽受限场景)
ffmpeg -i input.mp4 -c:v libx264 -preset fast -b:v 1500k -maxrate 2000k -minrate 1000k -bufsize 3000k output.ts
3.2.3 关键帧与 GOP 设置
关键帧间隔(GOP)直接影响推流的延迟和随机访问能力。我习惯这样设:
- 直播场景:
-g 60(60 帧一个关键帧,约 2 秒)。如果延迟要求更高,可以设-g 30(1 秒)。 - 点播场景:
-g 250(10 秒左右),压缩率更好。 - 强制关键帧: 配合
-force_key_frames "expr:gte(t,n_forced*2)"每 2 秒强制一个关键帧,适合切片场景。
避坑指南:我曾经把 GOP 设成 250 用于直播,结果推流端网络抖动导致关键帧丢失,客户端花了 10 秒才恢复画面。后来我强制每 2 秒一个关键帧,问题解决。记住:直播场景下,GOP 越大,丢帧恢复时间越长。
3.3 硬件编码器配置:NVENC 与 VAAPI
硬件编码器最大的优势是「快」,但画质和码率控制通常不如 x264。不过,对于高并发推流场景,硬件编码是唯一的选择。
3.3.1 NVENC(NVIDIA 显卡)
NVENC 从 Kepler 架构开始支持,但真正好用是从 Maxwell 2.0 开始。我目前主力是 Turing 架构的 NVENC,画质已经接近 x264 medium 预设。
# NVENC 推流示例(H.264)
ffmpeg -i input.mp4 -c:v h264_nvenc -preset p4 -tune hq -b:v 2000k -maxrate 2500k -bufsize 5000k -g 60 -rc vbr_hq output.ts
# NVENC 推流示例(H.265)
ffmpeg -i input.mp4 -c:v hevc_nvenc -preset p5 -tune hq -b:v 1500k -maxrate 2000k -bufsize 4000k -g 60 -rc vbr_hq output.ts
参数说明:
-preset:p1~p7,p1 最快但画质最差,p7 最慢但画质最好。我一般用 p4 或 p5。-tune hq:高质量模式。还有ll(低延迟)和ull(超低延迟)可选。-rc vbr_hq:高质量 VBR 模式。还有cbr(恒定码率)和vbr(普通 VBR)。
我的经验:NVENC 的 vbr_hq 模式配合 -maxrate 和 -bufsize,码率控制比默认的 vbr 好很多。另外,如果显卡支持 B 帧(Turing 及以上),可以加 -b_ref_mode middle 提升压缩率。
3.3.2 VAAPI(Intel/AMD 显卡)
VAAPI 是 Linux 上主流的硬件编码接口。Intel 的 Quick Sync 和 AMD 的 VCE 都通过 VAAPI 暴露。配置起来比 NVENC 稍微麻烦一点。
# 检查 VAAPI 设备
vainfo
# VAAPI H.264 编码示例
ffmpeg -vaapi_device /dev/dri/renderD128 -i input.mp4 -vf 'format=nv12,hwupload' -c:v h264_vaapi -b:v 2000k -maxrate 2500k -bufsize 5000k -g 60 -rc_mode VBR output.ts
# VAAPI H.265 编码示例
ffmpeg -vaapi_device /dev/dri/renderD128 -i input.mp4 -vf 'format=nv12,hwupload' -c:v hevc_vaapi -b:v 1500k -maxrate 2000k -bufsize 4000k -g 60 -rc_mode VBR output.ts
关键点:
-vaapi_device:指定 VAAPI 设备节点,通常是/dev/dri/renderD128。-vf 'format=nv12,hwupload':将帧格式转为 NV12 并上传到显存。注意,VAAPI 只支持 NV12 格式。-rc_mode VBR:码率控制模式。还有CBR、CQP(恒定质量)可选。
避坑指南:我曾经在 Intel 核显上跑 VAAPI 编码,发现画质比 NVENC 差一截。后来排查发现是 -rc_mode 默认用了 CBR,改成 VBR 后画质明显提升。另外,VAAPI 的 H.265 编码在部分旧驱动上有 bug,建议先升级驱动到最新版。
3.4 编码器选型决策流程
下面这张图是我自己总结的编码器选型决策流程,帮你快速定位该用哪种编码器。
3.5 实战调优 checklist
最后,我把自己常用的调优 checklist 列出来,你照着做基本不会翻车。
- 确定场景:直播还是点播?延迟要求多少?客户端覆盖哪些设备?
- 选择编码器:CPU 充足用 x264,否则用 NVENC/VAAPI。带宽受限优先 H.265。
- 设置预设:直播用
medium+zerolatency,点播用slow+film。 - 配置码率:CRF 模式优先,直播场景配合
-maxrate和-bufsize做约束。 - 调整 GOP:直播 1~2 秒一个关键帧,点播 5~10 秒。
- 测试兼容性:至少覆盖主流浏览器、手机、电视盒子。H.265 要特别注意。
- 监控资源:推流过程中监控 CPU/GPU 占用、编码延迟、码率波动。
我的习惯:每次调优后,我都会用 ffmpeg -i output.ts -f null - 快速检查编码质量,再用 ffprobe 查看码率分布。如果发现码率波动过大,就调整 -bufsize 和 -maxrate 的比例,一般 bufsize = 2 * maxrate 是个不错的起点。