1. 转码基础:理解视频编码原理、封装格式与编码格式的区别、FFmpeg转码基本流程

各位好,欢迎来到这门课。我是老张,在音视频这行摸爬滚打了十几年。今天咱们聊转码,但别急着敲命令——先把地基打牢。

很多人一上来就问我:“张哥,FFmpeg 转个码是不是就一行命令?” 嗯,是也不是。你确实能用一行命令把 MP4 转成 H.264,但如果你不懂背后发生了什么,遇到花屏、音画不同步、文件体积爆炸这些问题时,你连从哪下手都不知道。

所以第一章,咱们先把概念理清楚。说白了,就是搞明白三件事:视频是怎么编码的、封装和编码到底是不是一回事、FFmpeg 转码时内部到底干了什么。

1.1 视频编码原理:为什么原始视频那么大?

先问个问题:一段 1080p、30fps、时长 10 秒的原始视频,有多大?

算一下:每帧 1920×1080 像素,每个像素用 YUV420 格式存储,每个像素平均 12 bit(1.5 字节)。一帧就是 1920×1080×1.5 ≈ 3.1 MB。30fps 就是 93 MB/s。10 秒就是 930 MB。

一个 10 秒的视频就快 1GB 了,这谁受得了?所以必须压缩。

视频编码的核心思想就两个:

  • 空间冗余:同一帧里,相邻像素颜色差不多。比如蓝天背景,没必要每个像素都存一遍,存一块区域+一个颜色值就行。
  • 时间冗余:相邻帧之间,大部分内容没变。比如新闻主播,背景不动,只有嘴在动。那我只存变化的部分,没变的直接复用上一帧。

我刚开始做编码优化时,犯过一个低级错误:用最高质量参数压了一个监控视频,结果文件比原始还大。后来才发现,监控场景静态区域太多,编码器反而花了大量 bit 去保留那些根本没人看的细节。这就是没理解“时间冗余”的典型反面教材。

现代编码标准(H.264、H.265、AV1)都是基于混合编码框架的:

  1. 帧内预测:利用空间冗余,压缩单帧内部数据。
  2. 帧间预测:利用时间冗余,只编码运动部分。
  3. 变换量化:把像素数据转到频域,丢掉人眼不敏感的高频细节。
  4. 熵编码:用更短的码字表示出现频率高的数据。

一句话总结:编码的本质就是“找规律+丢细节”。找得越准,丢得越聪明,压缩率就越高。

1.2 封装格式 vs 编码格式:别再搞混了

这是新手最容易踩的坑。我面试过不少人,问“MP4 和 H.264 有什么区别”,十个有八个答不上来。

咱们打个比方:

  • 编码格式(Codec) = 你写的内容。比如 H.264、H.265、VP9、AV1。它决定了视频怎么压缩、质量怎么样。
  • 封装格式(Container) = 装内容的信封。比如 MP4、MKV、AVI、TS。它决定了怎么把视频流、音频流、字幕、元数据打包在一起。

同一个 MP4 文件,里面可以装 H.264 视频,也可以装 H.265 视频。同一个 H.264 视频流,可以放进 MP4,也可以放进 MKV。两者没有必然绑定关系。

我遇到过最离谱的事:一个合作方发来的视频,后缀是 .mp4,但 FFmpeg 死活打不开。一查,里面封装的是原始 YUV 数据。这就是典型的“信封写对了,内容放错了”。

下面这张表帮你快速区分:

维度 编码格式 封装格式
作用 压缩视频/音频数据 组织、存储、同步多路流
常见例子 H.264, H.265, AV1, AAC MP4, MKV, AVI, TS, MOV
文件后缀 通常不直接作为后缀 直接决定文件后缀
关注点 压缩率、画质、解码性能 兼容性、功能(字幕、章节)

避坑指南:我曾经把一个 H.265 编码的视频直接改了后缀为 .mp4,结果播放器全挂。记住:改后缀不等于转封装,更不等于转编码。

1.3 FFmpeg 转码基本流程:内部到底发生了什么?

好,现在咱们看看 FFmpeg 执行一条转码命令时,内部是怎么跑的。

一条典型的转码命令:

ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -c:a aac -b:a 128k output.mp4

这条命令背后,FFmpeg 做了这么几件事:

  1. 解封装(Demuxing):读取 input.mp4,分离出视频流(H.264 原始码流)和音频流(可能是 AAC 或别的)。
  2. 解码(Decoding):把压缩的视频流解码成原始 YUV 帧,音频流解码成原始 PCM 采样。
  3. 滤镜处理(Filtering):可选。比如缩放、裁剪、加水印。这一步在原始数据上操作。
  4. 编码(Encoding):把原始 YUV 帧重新压缩成新的编码格式(这里指定了 libx264)。
  5. 封装(Muxing):把新的视频流和音频流打包进 output.mp4。

整个过程可以画成下面这张图:

FFmpeg 转码内部流程 输入文件 解封装 解码 滤镜处理 编码 封装 输出文件 注意:滤镜步骤是可选的。如果不需要缩放、裁剪、水印,这一步直接跳过。 解码后的原始数据是 YUV/PCM,编码器重新压缩后才变成新的码流。

这里有个关键点很多人会忽略:解码再编码是有损的。哪怕你用了“无损”参数,只要经过了 YUV 转换和量化,信息就丢了。所以如果你只是想换个封装格式(比如 MP4 转 MKV),千万别用上面的命令——那等于把视频解压再压缩一遍,质量损失不说,还慢得要命。

正确的做法是直接流复制:

ffmpeg -i input.mp4 -c:v copy -c:a copy output.mkv

这条命令只做解封装和封装,不解码也不编码。速度飞快,质量零损失。

警告:流复制只适用于同一种编码格式。如果你想把 H.264 转成 H.265,必须走完整的解码→编码流程。别想着用 copy 参数“偷懒”,那只会得到一个没转码的假结果。

1.4 本章小结

咱们把这一章的核心点串一下:

  • 视频编码靠的是消除空间冗余和时间冗余,核心是“找规律+丢细节”。
  • 封装格式和编码格式是两码事。编码管压缩,封装管打包。别搞混。
  • FFmpeg 转码流程是:解封装→解码→(滤镜)→编码→封装。每一步都有代价。
  • 如果只是换封装,用 -c:v copy -c:a copy,别傻傻地重新编码。

这些概念看着简单,但我在实际项目中见过太多人栽在上面。尤其是封装和编码的区别,几乎每周都有人问。记住今天这张图、这张表,后面咱们聊参数调优、质量评估、效率优化时,你才不会晕头转向。