11、视频转码与压缩:分辨率缩放、码率控制、H.264/H.265编码参数调优、CRF与CBR

视频转码与压缩,说白了就是「把视频从一种格式变成另一种格式,同时尽量把体积做小」。这活儿看着简单,但坑特别多。我刚开始做音视频处理时,觉得不就是调个参数嘛,结果压出来的视频要么糊成马赛克,要么文件大得离谱。后来踩了无数坑,才慢慢摸清楚这里面的门道。

今天咱们就聊聊视频转码的核心:分辨率缩放、码率控制,还有 H.264 和 H.265 的参数调优。嗯,CRF 和 CBR 这两个概念,我也会重点讲清楚。

核心观点:视频转码不是简单的「压缩」,而是在画质、文件大小、编码速度三者之间找平衡。你不可能同时做到「画质最好、体积最小、速度最快」——这是铁律。

视频转码与压缩核心知识体系 视频转码与压缩 分辨率缩放 码率控制 编码标准 参数调优 保持宽高比 算法选择(最近邻/双线性/双三次) CBR / VBR / CRF 2-Pass 编码 H.264 vs H.265 Profile / Level preset / tune / profile 关键帧间隔 / B帧数量

分辨率缩放:不是简单拉大拉小

分辨率缩放,就是把视频的宽高尺寸改一改。比如 1920x1080 缩到 1280x720。听起来简单?但这里有个关键点:保持宽高比

我见过不少新手直接把宽和高写死,结果画面被压扁了。你想想看,一个圆形的球被压成椭圆,那画面能看吗?

我的习惯:缩放时永远先计算目标宽度对应的正确高度,或者反过来。用代码算一下:

// 保持宽高比缩放
int targetWidth = 1280;
int targetHeight = (int)(originalHeight * (targetWidth / (float)originalWidth));
// 如果高度不是16的倍数,记得对齐
targetHeight = (targetHeight / 16) * 16;

嗯,这里要注意:高度最好对齐到 16 的倍数。为什么?因为大多数编码器在处理 16x16 的宏块时效率最高。不对齐的话,编码器会多做一些 padding 操作,浪费码率。

缩放算法也有讲究。我常用的三种:

  • 最近邻插值:最快,但锯齿明显。适合实时预览或缩略图。
  • 双线性插值:折中方案。大部分场景够用。
  • 双三次插值:画质最好,但慢。适合离线转码。

我在项目中遇到过一个问题:把 4K 视频缩到 1080p 时,用双线性插值总觉得画面有点「糊」。后来换成双三次插值,清晰度明显提升。代价是编码时间多了 30%,但效果值得。

码率控制:CBR、VBR 和 CRF

码率控制,说白了就是「怎么分配比特给每一帧」。这里有三条路:CBR、VBR 和 CRF。

模式 特点 适用场景
CBR(恒定码率) 码率始终不变,画面质量波动大 直播、视频会议、网络带宽受限
VBR(可变码率) 码率动态变化,画面质量稳定 本地存储、点播、高质量存档
CRF(恒定质量) 以质量为基准,自动分配码率 个人存档、追求画质一致性

CBR 是最「死板」的模式。码率锁死,画面复杂时质量下降,简单时又浪费码率。但直播场景必须用 CBR,因为带宽是固定的。我曾经调一个直播项目,CBR 设了 2Mbps,结果画面里出现烟花特效时直接糊成一片。后来把码率提到 3Mbps,才勉强能看。

VBR 就灵活多了。它允许码率在一定范围内波动。我一般用 2-Pass VBR:第一遍分析视频复杂度,第二遍精确分配码率。效果比单遍好很多,但编码时间翻倍。

重点来了:CRF 是我个人最推荐的模式。

CRF 不是直接控制码率,而是控制「质量」。取值范围 0-51,数值越小质量越高。一般用 18-28:

  • CRF 18:视觉无损,适合存档
  • CRF 23:默认值,画质与体积平衡
  • CRF 28:体积小,画质可接受

为什么我喜欢 CRF?因为它省心。你不需要猜码率设多少合适,只需要告诉编码器「我要这个质量」,剩下的它自己搞定。我在处理个人视频存档时,一律用 CRF 20,出来的效果和原片几乎看不出区别,体积却小了一半。

注意:CRF 不适合直播或文件大小有严格要求的场景。因为最终文件大小不可控。我曾经用 CRF 18 压了一段 10 分钟的 4K 视频,结果出来 800MB——比预期大了两倍。

H.264 与 H.265 编码参数调优

H.264 和 H.265,一个是老将,一个是新秀。H.265 在同等画质下体积能比 H.264 小 30%-50%,但编码时间也长得多。

调优参数时,我重点关注这几个:

preset(预设)

preset 控制编码速度和压缩率的平衡。从 ultrafast 到 placebo,速度越来越慢,压缩率越来越高。

  • ultrafast / superfast:实时编码用,画质差
  • medium:默认值,折中
  • slow / slower:离线转码用,效果好
  • placebo:几乎不用,收益极小

我个人的习惯:离线转码用 slow,直播用 veryfast。别用 placebo,它比 slow 慢 10 倍,压缩率只提升不到 1%。

profile(档次)

profile 决定了编码器支持的特性集。H.264 有 baseline、main、high 三个档次。

  • baseline:最基础,兼容性最好,但压缩率低
  • main:折中
  • high:压缩率最高,但解码要求高

嗯,这里要注意:如果目标设备是老旧手机或机顶盒,用 high profile 可能解码不了。我踩过这个坑——压了一批视频给客户,结果他们的设备播不了,最后全部重压成 main profile。

关键帧间隔(GOP size)

关键帧(I帧)是视频的「锚点」。间隔越小,随机寻址越快,但码率越高。一般设 2-5 秒。

直播场景我设 2 秒(60帧的话就是 120),点播场景设 5 秒(250帧)。

实战:用 FFmpeg 调优

说了这么多,来点实际的。下面是我常用的几条 FFmpeg 命令:

# H.264 CRF 模式,slow preset
ffmpeg -i input.mp4 -c:v libx264 -preset slow -crf 20 -c:a aac -b:a 128k output.mp4

# H.265 CRF 模式,medium preset
ffmpeg -i input.mp4 -c:v libx265 -preset medium -crf 22 -c:a aac -b:a 128k output.mp4

# H.264 2-Pass VBR,目标码率 2Mbps
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -pass 1 -an -f mp4 /dev/null
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -pass 2 -c:a aac -b:a 128k output.mp4

一个小技巧:用 H.265 时,CRF 值可以比 H.264 高 2-4。比如 H.264 用 CRF 20,H.265 用 CRF 22 就能达到相近的画质,体积还能再小 20%。

避坑指南

最后分享几个我踩过的坑:

  • 不要盲目追求高码率。我曾经把码率设到 50Mbps,结果画质和 20Mbps 没区别,文件却大了两倍多。码率超过一定阈值后,收益递减。
  • 注意音频也要处理。很多人只压视频,音频还是原始 PCM 或高码率 AAC。视频压到 2Mbps,音频却占了 512Kbps,比例失调。
  • 测试时用真实素材。别用纯色背景或静态画面测试,那测不出编码器的真实水平。用一段运动剧烈、场景切换频繁的视频来测。

视频转码这事儿,说难不难,说简单也不简单。核心就是理解「质量、体积、速度」这个三角关系,然后根据场景选合适的参数。多试几次,你就能找到自己的「黄金参数」了。


公众号:蓝海资料掘金营,微信deep3321