2、命令行基础:FFmpeg命令行结构解析、常用全局参数、输入文件参数、输出文件参数
说实话,很多初学者一看到FFmpeg的命令行就头大。一长串字符,各种参数堆在一起,看着像天书。我当年刚接触时也是这样,总觉得这东西太复杂了。但后来我发现,只要搞懂了它的基本结构,一切就豁然开朗了。
FFmpeg的命令行,说白了就四个部分:程序名 + 全局参数 + 输入参数 + 输出参数。就这么简单。你想想看,就像写一封信,有收件人、有内容、有签名,每个部分各司其职。
2.1 命令行基本结构
先看一个最典型的例子:
ffmpeg -y -i input.mp4 -c:v libx264 -b:v 2M output.mp4
这个命令里,ffmpeg是程序名,-y是全局参数,-i input.mp4是输入参数,剩下的都是输出参数。嗯,这里要注意,-i后面跟的是输入文件,它属于输入文件参数的一部分。
我个人习惯把命令行结构画成一张图,这样更直观:
2.2 全局参数
全局参数,顾名思义,影响整个命令的行为。它们放在程序名后面,输入文件参数之前。我常用的全局参数不多,但个个都很关键。
| 参数 | 说明 | 示例 |
|---|---|---|
-y |
覆盖输出文件,不询问 | ffmpeg -y -i in.mp4 out.mp4 |
-n |
不覆盖输出文件,直接退出 | ffmpeg -n -i in.mp4 out.mp4 |
-loglevel |
设置日志级别(quiet/panic/fatal/error/warning/info/verbose/debug/trace) | ffmpeg -loglevel error -i in.mp4 out.mp4 |
-hide_banner |
隐藏编译信息、库版本等横幅 | ffmpeg -hide_banner -i in.mp4 out.mp4 |
-version |
显示版本信息 | ffmpeg -version |
-loglevel debug 可以看到每一步的详细信息。生产环境我一般用 -loglevel error 或 -hide_banner,避免日志刷屏。
我曾经在一个自动化脚本里忘了加 -y,结果程序卡在「是否覆盖文件?」的提示上,整个流水线都停了。从那以后,只要确定要覆盖,我一定加上 -y。
2.3 输入文件参数
输入文件参数,就是告诉FFmpeg「你要处理哪个文件,以及怎么读它」。最基本的输入参数就是 -i 后面跟文件名。
但实际项目中,输入参数远不止这么简单。你想想看,有时候输入文件是网络流,有时候是摄像头设备,有时候需要指定格式、帧率、编码器……
| 参数 | 说明 | 示例 |
|---|---|---|
-i |
指定输入文件或URL | -i input.mp4 |
-f |
强制指定输入格式 | -f rawvideo -i input.yuv |
-ss |
从指定时间开始读取(定位) | -ss 00:01:30 -i input.mp4 |
-t |
读取指定时长 | -t 10 -i input.mp4 |
-to |
读取到指定时间结束 | -to 00:02:00 -i input.mp4 |
-codec |
指定输入的解码器 | -c:v h264_cuvid -i input.mp4 |
-ss 放在 -i 前面还是后面,效果完全不同。放在前面是「快速定位」,放在后面是「逐帧解码到指定位置」。前者快但不精确,后者慢但精确。我一般用前者做预览,用后者做精确截取。
2.4 输出文件参数
输出参数是最灵活、最复杂的部分。说白了,就是告诉FFmpeg「你想要什么样的输出」。视频编码、音频编码、比特率、分辨率、帧率……都在这里设置。
| 参数 | 说明 | 示例 |
|---|---|---|
-c:v / -codec:v |
指定视频编码器 | -c:v libx264 |
-c:a / -codec:a |
指定音频编码器 | -c:a aac |
-b:v |
视频比特率 | -b:v 2M |
-b:a |
音频比特率 | -b:a 128k |
-s |
视频分辨率(宽x高) | -s 1920x1080 |
-r |
视频帧率 | -r 30 |
-an |
禁用音频输出 | -an |
-vn |
禁用视频输出 | -vn |
-sn |
禁用字幕输出 | -sn |
-map |
选择要输出的流 | -map 0:v -map 1:a |
-f |
强制指定输出格式 | -f mp4 |
-c:a,结果FFmpeg用了默认的音频编码器,导致输出文件在某些播放器上没声音。所以,输出参数一定要显式指定,不要依赖默认值。
2.5 实战:一个完整的例子
说了这么多,我们来个完整的实战。假设我有一个 input.mp4,我想把它转成H.264编码、AAC音频、分辨率1920x1080、视频比特率2Mbps、音频比特率128kbps,只取前30秒的内容。
ffmpeg -y -hide_banner \
-i input.mp4 \
-c:v libx264 -b:v 2M \
-c:a aac -b:a 128k \
-s 1920x1080 \
-t 30 \
output.mp4
这个命令里:
-y -hide_banner是全局参数,覆盖文件且不显示横幅-i input.mp4是输入参数- 剩下的都是输出参数
你可能会问,为什么 -t 30 放在输出参数里?因为 -t 既可以做输入参数,也可以做输出参数。放在输入侧是「读取30秒」,放在输出侧是「输出30秒」。效果一样,但语义不同。我个人习惯放在输出侧,这样更清晰。
2.6 参数顺序的潜规则
嗯,这里有个很重要的点:参数顺序是有讲究的。虽然FFmpeg对大部分参数不要求严格顺序,但有些参数必须放在正确的位置。
- 全局参数:必须放在
-i之前 - 输入参数:必须放在对应的
-i之前 - 输出参数:必须放在所有
-i之后
举个例子,下面这个命令是错的:
ffmpeg -i input.mp4 -y output.mp4 # 错误!-y 应该在 -i 之前
正确的写法:
ffmpeg -y -i input.mp4 output.mp4 # 正确
2.7 多输入多输出
FFmpeg支持多个输入文件和多个输出文件。这在做视频拼接、画中画、音频混音时非常有用。
ffmpeg -i video.mp4 -i audio.mp3 \
-c:v copy -c:a aac \
-map 0:v -map 1:a \
output.mp4
这个命令把 video.mp4 的视频和 audio.mp3 的音频合并到一起。注意 -map 参数,它告诉FFmpeg「从第一个输入取视频流,从第二个输入取音频流」。
多输出也很简单:
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
这个命令一次生成三个不同码率的文件。我在做自适应码率打包时经常这么用,省得写三个命令。
2.8 总结一下
FFmpeg的命令行结构,说白了就是「程序名 + 全局参数 + 输入参数 + 输出参数」。全局参数控制整体行为,输入参数告诉FFmpeg读什么、怎么读,输出参数告诉它写什么、怎么写。
我个人觉得,掌握这个结构比背参数更重要。因为参数可以查文档,但结构搞错了,命令就跑不起来。你想想看,是不是这个道理?
好了,这一章就到这里。记住:多动手,多试错,FFmpeg的命令行其实没那么可怕。