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后面跟的是输入文件,它属于输入文件参数的一部分。

我个人习惯把命令行结构画成一张图,这样更直观:

FFmpeg 命令行结构 ffmpeg 全局参数 输入参数 输出参数 示例: ffmpeg -y -i input.mp4 -c:v libx264 -b:v 2M output.mp4 程序名 全局参数 输入参数 输出参数 参数顺序:ffmpeg [全局参数] [输入参数] [输出参数]

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的命令行其实没那么可怕。


公众号:蓝海资料掘金营,微信deep3321