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 前面(影响输入流),也可以放在输出文件前面(影响输出流)。
我画了一张图,帮你理清这个关系:
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 小结:记住这三句话
这一章的内容,其实就三句话:
- 全局参数在最前面,影响整个命令。
- 输入参数紧挨着
-i,只影响对应的输入文件。 - 输出参数放在输出文件前面,只影响对应的输出文件。