第三章 命令行核心语法:ffmpeg 命令结构解析

说实话,我见过不少刚接触 FFmpeg 的同事,上来就复制粘贴网上的命令。能跑通还好,一旦报错就完全懵了。为什么?因为根本不知道这条命令在说什么。

这一章,我们就来彻底拆解 ffmpeg 的命令结构。你搞懂了骨架,以后不管多复杂的命令,在你眼里都是一块块积木。

3.1 命令的“骨架”:一个公式搞定

FFmpeg 的命令行,本质上就一个公式:

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

嗯,就这么简单。你仔细看,它只有四个核心部分:

  • ffmpeg:调用程序本身
  • [全局参数]:影响整个命令行为的开关
  • [输入文件参数]:针对输入文件的设置
  • [输出文件参数]:针对输出文件的设置

我刚开始用的时候,总喜欢把所有参数堆在一起。后来踩了几次坑才发现,参数放错位置,结果天差地别。

核心原则:参数的位置决定了它的作用范围。放在 -i 前面,影响输入;放在 -i 后面、输出文件前面,影响输出。

3.2 输入文件(-i):告诉 FFmpeg 读什么

-i 是 input 的缩写。它的后面跟着你要处理的文件路径或 URL。

ffmpeg -i input.mp4 output.avi

这条命令很简单:读取 input.mp4,输出成 output.avi。

但实际项目中,输入往往不止一个。比如你要给视频加字幕、混音,就需要多个输入:

ffmpeg -i video.mp4 -i subtitle.srt -i audio.mp3 output.mkv

这里我用了三个 -i。FFmpeg 会按顺序给它们编号:0:0 是第一个文件的第一个流,1:0 是第二个文件的第一个流,以此类推。

我的习惯:在复杂命令里,我会在注释里写明每个输入文件的用途。虽然命令行不支持注释,但我会在笔记里记清楚,避免搞混流索引。

3.3 输出文件:不止是文件名

输出文件写在命令的最后。FFmpeg 会根据文件扩展名自动猜测封装格式。比如 .mp4 就是 MP4,.mkv 就是 Matroska。

但输出文件前面可以跟一堆参数,用来控制编码器、码率、分辨率等等。这些就是输出文件参数。

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

这条命令里:

  • -c:v libx264:视频编码器用 H.264
  • -b:v 2M:视频码率设为 2 Mbps
  • -c:a aac:音频编码器用 AAC

这些参数只作用于输出文件,不会影响输入文件的读取方式。

3.4 全局参数 vs 流参数:别放错位置

这是新手最容易搞混的地方。我当年也犯过这个错。

全局参数:放在最前面,影响整个命令。比如日志级别、覆盖输出文件等。

ffmpeg -y -loglevel debug -i input.mp4 output.avi

-y 表示覆盖输出文件而不询问,-loglevel debug 表示输出调试信息。这两个都是全局的。

流参数:针对某个特定的流。比如只处理视频流,或者只处理音频流。

ffmpeg -i input.mp4 -c:v libx264 -an output.mp4

-an 表示禁用音频流。它属于输出文件参数,只影响输出。

参数类型 位置 作用范围 示例
全局参数 所有 -i 之前 整个命令 -y, -loglevel, -stats
输入文件参数 紧跟对应的 -i 之后 该输入文件 -ss, -t, -f
输出文件参数 输出文件之前 该输出文件 -c:v, -b:a, -s

我曾经踩过的坑:有一次我想裁剪视频的前 10 秒,把 -ss 10 放在了输出参数的位置。结果 FFmpeg 先解码再裁剪,速度慢得要命。后来我才知道,-ss 放在输入参数位置是“快进”模式,效率高得多。

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

有时候你只想处理视频里的某一条流。比如一个文件里有两条音轨,你只想保留第二条。

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

-c:a:1 表示只复制第二个音频流。流选择器的语法是 流类型:索引。

常用的流类型:

  • v:视频
  • a:音频
  • s:字幕
  • d:数据

索引从 0 开始。所以 v:0 是第一个视频流,a:1 是第二个音频流。

3.6 知识体系总览

下面这张图,是我自己整理的命令结构。每次写复杂命令前,我都会在脑子里过一遍这个流程。

FFmpeg 命令结构总览 全局参数 输入文件参数 -i 输入文件 (可多个) 输出文件参数 输出文件 💡 执行顺序: FFmpeg 先解析全局参数 → 读取输入文件(应用输入参数)→ 应用输出参数 → 写入输出文件 参数位置决定作用范围,放错位置会导致完全不同的结果。

3.7 实战:从命令到理解

我们来看一个真实项目中的命令。这是我去年帮一个客户处理视频时写的:

ffmpeg -y -ss 00:01:00 -i source.mp4 -t 30 -c:v libx264 -preset fast -crf 23 -c:a aac -b:a 128k output.mp4

我们来逐段拆解:

  1. -y:全局参数,自动覆盖已有文件。
  2. -ss 00:01:00:输入参数,从第 1 分钟开始读取。放在 -i 前面,是快速定位模式。
  3. -i source.mp4:输入文件。
  4. -t 30:输出参数,只输出 30 秒。
  5. -c:v libx264:输出参数,视频编码器。
  6. -preset fast:输出参数,编码速度预设。
  7. -crf 23:输出参数,视频质量。
  8. -c:a aac:输出参数,音频编码器。
  9. -b:a 128k:输出参数,音频码率。
  10. output.mp4:输出文件。

你看,一旦你掌握了骨架,再长的命令也能一眼看穿。

我的建议:刚开始练习时,每次写完命令,都手动标注一下每个参数属于哪一类。坚持两周,你就能形成条件反射。

3.8 常见误区

最后,我总结几个我见过最多的错误:

  • 参数顺序搞反:把输出参数写在 -i 前面,导致参数被忽略。
  • 忘记 -i:直接写文件名,FFmpeg 会把它当成输出文件。
  • 流索引搞错:多输入时,流索引从 0 开始,不是从 1 开始。
  • 全局参数放错位置:比如把 -y 放在 -i 后面,虽然有时也能用,但不符合规范。

嗯,这一章的内容就到这里。你把这些基础打牢了,后面学滤镜、学复杂转码,都会轻松很多。