FFmpeg 命令行核心结构:搞懂格式、输入、输出与参数

说实话,我见过不少刚接触 FFmpeg 的朋友,第一反应就是去网上复制一段命令,跑通了就完事。但一旦遇到点小问题——比如转码出来的视频没声音,或者拼接时画面卡顿——就完全不知道从哪下手。

为什么会这样?说白了,就是没搞懂 FFmpeg 命令行的骨架长什么样。

这一章,我就带你把这个骨架拆开来看。你只要掌握了这个结构,以后不管多复杂的命令,你都能一眼看穿它在干什么。

2.1 FFmpeg 命令行的通用格式

先记住这个最核心的公式:

ffmpeg [全局参数] [输入文件参数] -i 输入文件 [输出文件参数] 输出文件

嗯,就这么简单。但这里有几个关键点,我得跟你强调一下:

  • 顺序是固定的:全局参数在最前面,然后是输入相关的参数,接着是 -i 指定输入文件,最后是输出参数和输出文件。
  • 可以有多个输入:你可以写多个 -i,每个前面都可以带自己的参数。
  • 输出文件也可以有多个:FFmpeg 支持一次输出多个文件,每个输出可以有不同的参数。

核心要点:FFmpeg 的命令行结构本质上是一个「参数 + 文件」的流水线。参数控制行为,文件提供数据。搞懂这个顺序,你就掌握了 80% 的命令行阅读能力。

2.2 输入文件(-i)与输出文件

咱们先聊聊输入文件。你可能会想:「不就是指定一个文件路径吗?有什么好说的?」

其实不然。我在项目中遇到过好几次,有人把 -i 的位置放错了,结果 FFmpeg 把参数当成了输出文件,直接报错。所以记住:-i 后面紧跟的,就是输入文件路径。

来看个最简单的例子:

ffmpeg -i input.mp4 output.avi

这条命令的意思是:读取 input.mp4,然后输出成 output.avi。FFmpeg 会自动根据输出文件的后缀名,选择合适的编码器和封装格式。

但如果你有多个输入呢?比如你要把两个视频拼在一起:

ffmpeg -i part1.mp4 -i part2.mp4 -filter_complex concat output.mp4

这里有两个 -i,分别指定了两个输入文件。FFmpeg 会按顺序把它们编号为 0 和 1,后面的参数可以通过这个编号来引用它们。

我的小习惯:我一般会在每个 -i 前面都加上对应的输入参数,比如 -c:v libx264 或 -r 30。这样即使后面改了输入顺序,参数也不会乱套。你想想看,如果所有参数都堆在最后,一旦输入文件多了,你根本分不清哪个参数对应哪个文件。

2.3 全局参数与流参数的区别

这是很多人容易搞混的地方。我刚开始用 FFmpeg 的时候,也踩过这个坑。

全局参数:影响整个命令的行为,跟具体的输入输出文件无关。它们必须放在 -i 之前。

流参数:只影响特定的输入流或输出流。它们可以放在 -i 前面(影响输入流),也可以放在输出文件前面(影响输出流)。

我画了一张图,帮你理清这个关系:

FFmpeg 命令行结构图 全局参数 输入流参数 -i 输入文件 (可多个) 输出流参数 输出文件 说明: 1. 全局参数:影响整个命令,如 -y(覆盖输出文件)、-loglevel(日志级别) 2. 输入流参数:只影响对应的输入文件,如 -ss(跳转到指定时间点) 3. 输出流参数:只影响对应的输出文件,如 -b:v(视频码率)、-s(分辨率) 4. 多个输入时,每个 -i 前面都可以有自己的输入参数 5. 多个输出时,每个输出文件前面都可以有自己的输出参数

2.4 实战:用表格看懂参数归属

光说理论不够,咱们直接上例子。下面这个命令,我拆开给你看:

ffmpeg -y -ss 30 -i input.mp4 -c:v libx264 -b:v 2M output.mp4

咱们用表格把每个参数归类:

参数 类型 作用
-y 全局参数 覆盖输出文件,不询问
-ss 30 输入流参数 从输入文件的第 30 秒开始读取
-i input.mp4 输入文件 指定输入源
-c:v libx264 输出流参数 视频编码器设为 H.264
-b:v 2M 输出流参数 视频码率设为 2 Mbps
output.mp4 输出文件 最终生成的文件

你看,这样一拆,是不是清晰多了?

我曾经踩过的坑:有一次我把 -ss 30 放在了输出文件前面,结果 FFmpeg 先解码了整段视频,再跳转到第 30 秒。本来几秒就能完成的任务,硬是跑了十几分钟。所以记住:输入参数放 -i 前面,输出参数放输出文件前面。这个顺序直接影响性能。

2.5 流选择器:精准控制每个流

一个视频文件里通常有多个流:视频流、音频流、字幕流。FFmpeg 默认会处理所有流,但有时候你只想处理其中某一个。

这时候就需要流选择器了。它的格式是:

-map [输入文件编号]:[流类型]:[流编号]

举个例子:

ffmpeg -i input.mp4 -map 0:v:0 -map 0:a:1 output.mp4

这条命令的意思是:

  • 0:v:0:取第 0 个输入文件的第 0 个视频流
  • 0:a:1:取第 0 个输入文件的第 1 个音频流

为什么要这么干?我遇到过一种情况:一个视频文件里有两条音轨,一条是中文,一条是英文。我只想要中文音轨,这时候 -map 0:a:0 就派上用场了。

我的建议:刚开始用 -map 的时候,可以先不加任何选择,让 FFmpeg 默认处理。等你看懂了输出日志里的流信息,再慢慢尝试精确控制。别一上来就搞复杂的映射,容易把自己绕晕。

2.6 常见参数速查表

我把最常用的参数整理了一下,方便你随时查阅:

参数 类型 说明 示例
-y 全局 覆盖输出文件 -y
-n 全局 不覆盖输出文件 -n
-loglevel 全局 设置日志级别 -loglevel debug
-ss 输入/输出 跳转到指定时间 -ss 00:01:30
-t 输入/输出 限制处理时长 -t 10
-c:v 输出 视频编码器 -c:v libx264
-c:a 输出 音频编码器 -c:a aac
-b:v 输出 视频码率 -b:v 1M
-s 输出 视频分辨率 -s 1920x1080
-r 输出 帧率 -r 30
-map 输出 流选择 -map 0:v:0

2.7 小结:记住这三句话

这一章的内容,其实就三句话:

  1. 全局参数在最前面,影响整个命令。
  2. 输入参数紧挨着 -i,只影响对应的输入文件。
  3. 输出参数放在输出文件前面,只影响对应的输出文件。