3. FFmpeg 命令行基础:三大工具与核心参数

说实话,很多初学者一上来就问我:“FFmpeg 到底怎么用?” 我的回答永远是:先把三个工具搞清楚——ffmpeg、ffprobe、ffplay。它们就像瑞士军刀的三把主刃,各管一摊,但配合起来能解决 90% 的日常问题。

我个人习惯把这三兄弟比作:厨师、质检员和试吃员。ffmpeg 负责加工处理,ffprobe 负责检查原料成分,ffplay 负责快速预览成品。你想想看,如果连工具分工都不清楚,后面那些复杂的封装解析工作根本没法下手。

核心观点: 学 FFmpeg 命令行,先别急着背参数。先把三个工具的定位刻在脑子里——ffmpeg 是主力处理工具,ffprobe 是分析诊断工具,ffplay 是快速预览工具。

3.1 三大工具的分工与定位

咱们一个一个说。

3.1.1 ffmpeg:主力处理工具

这是最核心的。转格式、裁剪、拼接、滤镜、封装解封装…… 几乎所有操作都靠它。我在项目中遇到过最典型的场景:客户给了一个 TS 流,要求转成 MP4 并保留所有字幕轨道。没有 ffmpeg,这活根本没法干。

基本调用方式很简单:

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

嗯,这里要注意:参数顺序是有讲究的。写在 -i 前面的是输入参数,只对当前输入生效;写在 -i 后面、下一个 -i 前面的是输出参数。我见过太多人把参数放错位置,结果死活不出想要的效果。

3.1.2 ffprobe:分析诊断工具

这个工具很多人低估了。说白了,它就是多媒体文件的“CT 机”。能告诉你文件里有多少流、编码格式是什么、码率多少、关键帧间隔多长…… 所有元数据一览无余。

我记得有一次排查一个直播推流卡顿问题,就是靠 ffprobe 发现推流端的关键帧间隔设置成了 10 秒,导致拉流端首屏加载慢得离谱。

最常用的命令:

ffprobe -v quiet -print_format json -show_format -show_streams input.mp4

输出 JSON 格式,方便程序解析。我个人习惯先跑这条命令,看看文件“底细”再动手处理。

3.1.3 ffplay:快速预览工具

这个更简单——就是一个基于 FFmpeg 的播放器。但它比普通播放器强在哪?能直接看原始流。比如你想看某个视频的原始 YUV 数据,或者单独听某个音频轨道,ffplay 都能干。

我曾经用它来调试一个 H.264 码流问题:

ffplay -v debug -i input.h264

加上 -v debug 能看到解码过程中的详细信息,对排查编码参数问题特别有用。

小技巧: 用 ffplay -f lavfi -i "color=c=red:size=1280x720:d=5" 可以生成一个纯色测试画面,调试显示设备时特别好用。

3.2 核心参数详解

参数很多,但真正高频使用的就四个:-i、-c、-f、-map。把这四个吃透,基本就能应付 80% 的工作了。

3.2.1 -i:指定输入文件

这个最简单,但也最容易踩坑。-i 后面跟的是输入文件路径。但注意:FFmpeg 支持多个输入。比如你要拼接两个视频:

ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1" output.mp4

这里两个 -i 分别指定了两个输入文件。我曾经在项目里同时处理过 8 个输入流,参数顺序一旦搞错,后面的 -map 就全乱了。

3.2.2 -c:指定编解码器

-c 是 -codec 的缩写,用来指定用哪个编解码器处理流。-c:v 指定视频编解码器,-c:a 指定音频,-c:s 指定字幕。

最常用的场景是“复制流”而不重新编码:

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

这里 copy 是个特殊值,意思是“直接复制,不重新编码”。速度极快,而且画质无损。我在做封装格式转换时几乎必用这个参数。

如果要重新编码,就指定具体的编码器名称:

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

注意: -c:v copy 虽然快,但并不是所有格式都支持直接复制。比如把 H.264 视频复制到 MP4 没问题,但复制到某些老旧的 AVI 容器就可能失败。原因在于容器格式对编码数据的组织方式有要求。

3.2.3 -f:强制指定格式

-f 用来强制指定输入或输出的封装格式。正常情况下 FFmpeg 会根据文件扩展名自动判断格式,但有时候需要手动指定。

我遇到过最典型的场景:从标准输入读取裸 H.264 流:

cat stream.h264 | ffmpeg -f h264 -i - -c:v copy output.mp4

这里 -f h264 告诉 FFmpeg:输入是裸 H.264 流,别猜了。如果不加这个参数,FFmpeg 会尝试从文件头判断格式,但管道输入没有文件头,就会报错。

输出时也常用:

ffmpeg -i input.mp4 -f flv output.flv

虽然扩展名已经暗示了格式,但显式指定 -f flv 可以避免某些边界情况下的格式误判。

3.2.4 -map:精确选择流

这个参数是很多人的噩梦,但一旦搞懂,你会爱上它。-map 用来精确控制哪些输入流进入输出文件。

默认情况下,FFmpeg 会从每个输入文件里选“最好”的一个视频流、一个音频流和一个字幕流。但实际需求往往更复杂。比如:

ffmpeg -i input.mp4 -map 0:v:0 -map 0:a:2 -c copy output.mp4

这里 0:v:0 的意思是:第一个输入文件的第一个视频流。0:a:2 是第一个输入文件的第三个音频流(索引从 0 开始)。

我曾经处理过一个多语言视频:

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

这样输出文件里包含视频流、英语音轨和法语音轨,完美保留多语言。

记住这个公式: -map 输入文件索引:流类型:流索引。流类型:v 视频、a 音频、s 字幕、d 数据。

3.3 知识体系总览

下面这张图把三大工具和四个核心参数的关系梳理清楚了。我建议你把它存下来,以后遇到命令行问题先回来看看这张图。

FFmpeg 命令行知识体系 ffmpeg(主力处理) ffprobe(分析诊断) ffplay(快速预览) 四大核心参数 -i 指定输入文件 -c 指定编解码器 -f 强制指定格式 -map 精确选择流 典型应用场景 格式转换(-i + -c + -f) 流选择与映射(-i + -map) 流分析(ffprobe + -show_*) 快速预览(ffplay + -v debug) 多输入拼接(多个 -i + -map) 裸流处理(-f 指定格式)

3.4 参数组合实战

光说不练假把式。咱们看几个真实场景下的参数组合。

场景一:MP4 转 TS 并保持编码不变

ffmpeg -i input.mp4 -c:v copy -c:a copy -f mpegts output.ts

这里 -c:v copy -c:a copy 保证不重新编码,-f mpegts 强制输出 TS 格式。速度极快,适合在封装格式之间切换。

场景二:提取视频中的某个音频轨道

ffmpeg -i input.mp4 -map 0:a:1 -c:a copy audio.aac

只提取第二个音频轨道(索引 1),直接复制编码,不重新压缩。

场景三:查看文件详细信息

ffprobe -v quiet -print_format json -show_format -show_streams input.mp4 | jq .

配合 jq 工具格式化输出,一目了然。我每次拿到陌生文件第一件事就是跑这条命令。

调试利器: 如果某个命令没达到预期效果,先加 -v debug 看看 FFmpeg 内部是怎么处理的。它会打印出每一步的决策过程,比如“选择了哪个流”、“用了什么编码器”。

3.5 常见误区与避坑

  • 参数顺序搞反: 输入参数必须写在 -i 前面,输出参数写在 -i 后面。我曾经见过有人把 -c:v copy 写在 -i 前面,结果 FFmpeg 把它当成了输入参数,直接忽略。
  • 滥用 -c copy: 不是所有容器都支持所有编码格式的直接复制。比如把 HEVC 视频复制到 MP4 没问题,但复制到 AVI 就可能失败。先用 ffprobe 确认容器兼容性。
  • 忽略 -map 的默认行为: 不加 -map 时,FFmpeg 会自作主张选“最好”的流。如果你有多个音频轨道,不加 -map 可能只保留一个。我踩过这个坑,后来养成了显式 -map 的习惯。
  • 管道输入忘记 -f: 从标准输入读取裸流时,必须用 -f 指定格式,否则 FFmpeg 无法识别。

重要提醒: 处理重要文件前,先用 ffprobe 摸清文件底细。我见过太多人直接上手转码,结果发现源文件有问题,白白浪费时间。先分析,再动手——这是专业工程师的习惯。

好了,三大工具和四个核心参数就讲到这里。这些是 FFmpeg 命令行的基石,后面的章节会反复用到。你可以在自己的机器上多敲几遍,感受一下参数变化带来的效果差异。实践出真知,命令行这东西,敲多了自然就熟了。