4、转码核心流程:解封装→解码→滤镜处理→编码→封装

转码这件事,说白了就是让视频「改头换面」。我刚开始接触 FFmpeg 时,以为转码就是一条命令搞定的事。后来踩了不少坑才明白——真正的转码是一条流水线,每个环节都藏着细节。

这一章,咱们就把这条流水线拆开来看。

4.1 转码的五步流水线

FFmpeg 的转码流程,本质上就是五步:

  1. 解封装(Demuxer)—— 把容器拆开,拿到音频流、视频流、字幕流
  2. 解码(Decoder)—— 把压缩的数据解成原始帧(YUV / PCM)
  3. 滤镜处理(Filter)—— 对原始帧做缩放、裁剪、调色、加字幕等操作
  4. 编码(Encoder)—— 把处理后的原始帧重新压缩
  5. 封装(Muxer)—— 把压缩后的流再装进新的容器

我画了一张流程图,帮你直观理解这条线:

FFmpeg 转码流水线 输入文件 解封装 解码 滤镜处理 编码 封装 输出文件 转码流水线:解封装 → 解码 → 滤镜处理 → 编码 → 封装

你看,数据从左边进去,一路经过五个工位,最后从右边出来。每个工位干的事都不一样。

4.2 解封装与解码

解封装,就是把 MP4、MKV、AVI 这些「包装盒」拆开。包装盒里装着视频流(H.264/H.265)、音频流(AAC/MP3)、字幕流等。FFmpeg 的 -f 参数可以指定封装格式,但大多数时候它会自动识别。

解码,是把压缩的视频数据还原成原始帧。比如 H.264 解码成 YUV 像素数据,AAC 解码成 PCM 音频采样。

我个人习惯用这条命令查看流的详细信息:

ffprobe -v error -show_entries stream=index,codec_name,codec_type -of default=noprint_wrappers=1 input.mp4

输出大概长这样:

[STREAM]
index=0
codec_name=h264
codec_type=video
[/STREAM]
[STREAM]
index=1
codec_name=aac
codec_type=audio
[/STREAM]

嗯,这里要注意:解封装和解码是两个独立步骤。你可以只解封装不解码(比如只提取字幕),也可以解封装后直接复制流(-c copy),跳过解码和编码。

小技巧: 如果你只想换容器格式(比如 MP4 转 MKV),用 -c copy 就行,速度极快,画质无损。我经常用这招给视频「换壳」。

4.3 滤镜处理

滤镜处理是转码中最灵活的一环。它工作在解码之后、编码之前,操作的是原始帧数据。

常见的滤镜操作包括:

  • 缩放:scale=1280:720
  • 裁剪:crop=640:480:0:0
  • 旋转:transpose=1
  • 调色:eq=brightness=0.1:saturation=1.5
  • 叠加文字/图片:drawtext / overlay

滤镜的语法是 -vf(视频滤镜)和 -af(音频滤镜)。多个滤镜用逗号分隔:

ffmpeg -i input.mp4 -vf "scale=1280:720,eq=brightness=0.05" -c:a copy output.mp4

我曾经在项目中遇到过一个问题:客户要求把一批 4K 视频压成 1080p,同时要调亮画面。如果先转码再调色,得跑两遍。用滤镜链一步搞定,省了一半时间。

4.4 编码与封装

编码,是把处理后的原始帧重新压缩。这是最吃 CPU/GPU 的环节。编码器的选择直接影响输出质量和文件大小。

封装,是把编码后的流再装进新的容器。这一步基本不消耗性能,但决定了输出文件的兼容性。

来看一个完整的转码命令:

ffmpeg -i input.mp4 \
  -c:v libx264 -b:v 2M \
  -c:a aac -b:a 128k \
  -vf "scale=1280:720" \
  output.mp4

这条命令干了什么?

  1. 解封装 input.mp4
  2. 解码视频流(H.264)和音频流(AAC)
  3. 视频经过 scale 滤镜缩放到 1280x720
  4. 视频用 libx264 编码,码率 2 Mbps
  5. 音频用 AAC 编码,码率 128 kbps
  6. 封装成 MP4

4.5 关键参数详解:-c:v、-c:a、-b:v

这三个参数是转码命令里的「三剑客」。我刚开始用 FFmpeg 时,经常搞混它们的作用。下面这张表帮你理清:

参数 全称 作用 常用值
-c:v codec:video 指定视频编码器 libx264, libx265, h264_nvenc, copy
-c:a codec:audio 指定音频编码器 aac, mp3, libopus, copy
-b:v bitrate:video 设置视频目标码率 1M, 2M, 500k

重点:

  • -c:v copy 表示视频流不重新编码,直接复制。速度快,画质无损。
  • -c:a copy 同理,音频流直接复制。
  • -b:v 只对编码器生效。如果用了 -c:v copy,设置 -b:v 是无效的。

举个例子,我想把视频从 MP4 转成 MKV,同时保持画质不变:

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

这条命令只做解封装和封装,不解码不编码,几秒钟就能搞定一个 10GB 的视频。

但如果我想压缩视频,就得指定编码器和码率:

ffmpeg -i input.mp4 -c:v libx264 -b:v 1M -c:a aac -b:a 96k output.mp4
避坑指南: 我曾经在项目里把 -b:v 写成了 -b,结果 FFmpeg 报错说参数不识别。后来查文档才发现,-b 是全局码率参数,现在已经废弃了。一定要写成 -b:v 和 -b:a。

4.6 转码流水线的实际应用

理解了五步流程和关键参数,你就可以组合出各种转码方案。下面是我总结的几种常见场景:

场景 命令核心 适用情况
格式转换(无损) -c:v copy -c:a copy MP4 → MKV,只换容器
压缩视频 -c:v libx264 -b:v 1M 减小文件体积
缩放+压缩 -vf scale=... -c:v libx264 -b:v 1M 4K 转 1080p 并压缩
提取音频 -vn -c:a copy 只保留音频流
提取视频 -an -c:v copy 只保留视频流

你看,核心就是那五步。你可以在任意步骤插入操作,也可以跳过某些步骤。FFmpeg 的灵活性就在这里。

个人经验: 我建议你在写转码命令时,先加 -an 或 -vn 测试视频或音频部分,确认没问题再合起来跑。这样排查问题快很多。