2、基础命令结构:ffmpeg命令格式解析、全局选项、输入文件选项、输出文件选项
说实话,我见过不少刚接触 FFmpeg 的朋友,第一反应就是去网上复制一段命令。跑通了还好,跑不通就完全懵了。其实 FFmpeg 的命令结构非常规整,你只要搞懂它的骨架,剩下的就是往里面填东西而已。
今天我们就来拆开这个骨架看看。说白了,FFmpeg 的命令就一个套路:
ffmpeg [全局选项] [输入文件选项] -i 输入文件 [输出文件选项] 输出文件
嗯,就这么简单。但简单归简单,里面每个部分都有讲究。我一个个说。
2.1 命令格式总览
先看一个最典型的例子:
ffmpeg -y -i input.mp4 -c:v libx264 -b:v 2M output.mp4
这里面:
-y是全局选项,表示覆盖输出文件时不询问-i input.mp4是输入文件及其选项-c:v libx264 -b:v 2M是输出文件选项output.mp4是输出文件路径
你可能会问:为什么全局选项要放在最前面?其实这是 FFmpeg 解析器的习惯——它先处理全局设置,再处理输入,最后处理输出。顺序错了,有时候选项就不生效了。我在项目中就踩过这个坑,把 -y 写在 -i 后面,结果某些旧版本 FFmpeg 直接报错。
核心原则:全局选项 → 输入选项 + -i 输入文件 → 输出选项 + 输出文件。这个顺序不要乱。
2.2 全局选项
全局选项影响的是整个命令的行为,不针对某个具体的流。常用的就这几个:
| 选项 | 作用 | 我的使用频率 |
|---|---|---|
-y |
覆盖输出文件,不询问 | 几乎每次都用 |
-n |
不覆盖输出文件,直接退出 | 偶尔,批量处理时用 |
-loglevel |
控制日志输出级别 | 调试时必用 |
-hide_banner |
隐藏编译信息、库版本等 | 脚本中常用,保持输出干净 |
-stats |
显示编码进度统计 | 默认开启,一般不用管 |
举个例子,我写自动化脚本时,通常会这样:
ffmpeg -y -hide_banner -loglevel error -i input.mp4 output.mp4
这样只有出错时才打印信息,平时干干净净。你想想看,如果脚本跑几百个文件,日志里全是库版本信息,那得多烦人。
小技巧:调试时用 -loglevel debug,FFmpeg 会把每一步的决策都打印出来。我曾经靠这个定位过一个音频采样率不匹配的问题,省了大半天时间。
2.3 输入文件选项
输入选项写在 -i 前面,告诉 FFmpeg 怎么读取这个文件。常见的场景:
- 指定输入格式:
-f mp4,强制按某种格式解析 - 选择输入流:
-map 0:v:0,只取第一个视频流 - 设置输入参数:
-ss 00:01:00,从第1分钟开始读取 - 处理输入编码参数:
-hwaccel cuda,启用硬件加速解码
看个实际例子:
ffmpeg -ss 00:00:30 -t 10 -i input.mp4 output.mp4
这个命令从第30秒开始,截取10秒的视频。注意 -ss 写在 -i 前面,这叫「快速定位」模式。FFmpeg 会先跳转到指定时间点,再开始解码,速度很快。如果写在 -i 后面,它会从头解码到那个时间点再开始,慢很多。
注意:输入选项只对紧随其后的 -i 生效。如果你有多个输入文件,每个输入都要单独写选项。我曾经犯过这个错,以为写一次就能作用于所有输入,结果第二个输入完全没按预期走。
2.4 输出文件选项
输出选项是最灵活的部分,也是你真正干活的地方。它控制编码器、码率、分辨率、帧率、封装格式等等。
常用的输出选项分组:
| 类别 | 选项示例 | 说明 |
|---|---|---|
| 视频编码器 | -c:v libx264 |
指定视频编码器 |
| 音频编码器 | -c:a aac |
指定音频编码器 |
| 视频码率 | -b:v 1M |
目标视频码率 |
| 音频码率 | -b:a 128k |
目标音频码率 |
| 分辨率 | -s 1920x1080 |
缩放输出分辨率 |
| 帧率 | -r 30 |
输出帧率 |
| 封装格式 | -f mp4 |
强制输出格式 |
一个完整的例子:
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -c:a aac -b:a 128k -s 1280x720 -r 30 output.mp4
这个命令把输入视频转成 H.264 + AAC,码率分别是 2Mbps 和 128kbps,分辨率缩到 720p,帧率 30fps。很典型的转码场景。
我的习惯:输出选项我一般按「视频编码→视频参数→音频编码→音频参数→其他参数」的顺序写。这样别人看你的命令,一眼就能找到关键信息。团队协作时,这个习惯特别有用。
2.5 知识结构图
下面这张图把 FFmpeg 命令的骨架画出来了。你以后写命令时,就照着这个结构填空:
2.6 多输入多输出
FFmpeg 支持多个输入和多个输出,这在处理复杂任务时特别有用。比如合并视频和音频:
ffmpeg -i video.mp4 -i audio.mp3 -c:v copy -c:a aac output.mp4
这里两个 -i,第一个是视频,第二个是音频。输出选项 -c:v copy -c:a aac 同时作用于输出文件。
再看一个多输出的例子:
ffmpeg -i input.mp4 \
-c:v libx264 -b:v 1M output_1M.mp4 \
-c:v libx264 -b:v 2M output_2M.mp4 \
-c:v libx264 -b:v 4M output_4M.mp4
这个命令一次生成三个不同码率的版本。我经常在给客户准备多码率素材时这么干,一条命令搞定,省得反复跑。
注意:多输出时,每个输出文件前面都要写完整的输出选项。不要想着「共用选项」,FFmpeg 不会帮你继承。我曾经偷懒少写了一组参数,结果第三个输出用了默认编码器,文件大了一倍。
2.7 流映射基础
默认情况下,FFmpeg 会从每个输入中选择「最好的」一个视频流和一个音频流。但有时候你需要手动指定。这时候就用 -map:
ffmpeg -i input.mp4 -map 0:v:0 -map 0:a:1 -c copy output.mp4
这个命令只取第一个视频流和第二个音频流。为什么会有这种需求?我遇到过一种情况:一个视频文件里有两条音轨,一条是中文,一条是英文。客户只要英文的,那就用 -map 0:a:1 精确选择。
流映射的格式是 输入索引:流类型:流索引。输入索引从0开始,流类型是 v(视频)、a(音频)、s(字幕)。
小技巧:先用 ffprobe input.mp4 查看文件里的流信息,确认每个流的索引,再写 -map。我每次处理不熟悉的文件都会先跑一下 ffprobe,避免选错流。
2.8 总结一下
FFmpeg 的命令结构其实就一句话:全局选项管全局,输入选项管读取,输出选项管编码。你只要记住这个顺序,剩下的就是查参数、填参数的事。
我个人建议,刚开始不要背参数,而是理解结构。结构对了,参数可以随时查。我到现在也经常翻文档,但命令的骨架从来没变过。