命令行基础:FFmpeg 结构解析与实战技巧
说实话,我见过太多人一上来就甩一串长长的 FFmpeg 命令,跑通了就欢呼,跑不通就抓瞎。其实 FFmpeg 的命令行结构非常清晰,你只要掌握了它的骨架,剩下的就是往里面填参数而已。
这一章,我们就把它拆开揉碎了讲。嗯,我保证不绕弯子。
1. FFmpeg 命令行核心骨架
任何一个 FFmpeg 命令,本质上都长这样:
ffmpeg [全局参数] [输入文件参数] -i 输入文件 [输出文件参数] 输出文件
就这么简单。你想想看,左边是输入,右边是输出,中间是各种控制开关。我在项目中带新人时,总让他们先把这行结构默写三遍——真的管用。
核心记忆口诀:「全局在前,输入在中,输出在后,-i 是输入的门牌号」
2. 全局参数:控制整个转码过程的开关
全局参数放在最前面,影响的是整个命令的行为,而不是某个具体的流。我个人习惯把全局参数分成三类:
| 类别 | 常用参数 | 说明 |
|---|---|---|
| 日志控制 | -loglevel、-v、-report |
控制控制台输出多少信息,调试时必用 |
| 覆盖/追加 | -y、-n |
-y 直接覆盖输出文件,-n 拒绝覆盖 |
| 基准测试 | -benchmark、-benchmark_all |
输出转码耗时和 CPU 使用情况 |
举个例子,调试时我几乎必加这两项:
ffmpeg -y -loglevel debug -i input.mp4 output.avi
-y 省得每次确认覆盖,-loglevel debug 能把每一帧的处理细节都吐出来。我曾经在排查一个音频同步问题时,就是靠 debug 日志发现容器时间基算错了——这种坑,光看报错信息根本看不出来。
我的习惯:写脚本时用 -loglevel error 只显示错误;手工调试时用 -loglevel info 或 debug。别一上来就开 debug,信息量太大反而眼花。
3. 输入文件指定:-i 不是万能的,但没有 -i 是万万不能的
-i 后面跟的就是输入文件路径。但这里有几个细节,我踩过坑才记住的:
- 路径有空格? 用双引号包起来,比如
-i "my video.mp4" - 多个输入文件? 写多个
-i,比如-i video.mp4 -i audio.mp3 - 输入是设备或网络流? 照样用
-i,比如-i rtsp://...或-i /dev/video0
还有一个容易被忽略的点:输入参数要放在对应的 -i 前面。比如你想强制把输入当成某种格式:
ffmpeg -f rawvideo -pix_fmt yuv420p -s 1920x1080 -i input.yuv output.mp4
这里的 -f rawvideo、-pix_fmt、-s 都是针对后面那个 -i input.yuv 的输入参数。如果你把它们放到 -i 后面,FFmpeg 会当成输出参数处理——那就全乱套了。
注意:输入参数只对紧随其后的 -i 生效。多个输入文件时,每个输入都可以有自己的参数组。我曾经在拼接多段视频时,因为把输入参数顺序搞反了,结果画面花了一整屏——嗯,从那以后我再也不敢乱放参数位置了。
4. 输出文件指定:你想要的格式,写在最后
输出文件没有 -i,直接写路径就行。FFmpeg 会根据文件扩展名自动猜测封装格式。比如:
output.mp4→ MP4 容器output.ts→ MPEG-TS 容器output.mkv→ Matroska 容器
如果你想强制指定格式,用 -f 参数:
ffmpeg -i input.mp4 -f mpegts output.ts
输出参数放在输出文件前面,比如设置视频码率、分辨率、音频采样率等。这些我们后面几章会详细讲,这里先记住位置就行。
5. 帮助文档查阅技巧:别死记硬背,学会查
FFmpeg 的参数成百上千,没人能全记住。我自己的做法是:记住几个关键的查询命令,剩下的现场查。
| 你想查什么 | 命令 |
|---|---|
| 所有可用的封装格式 | ffmpeg -formats |
| 所有可用的编码器 | ffmpeg -encoders |
| 所有可用的解码器 | ffmpeg -decoders |
| 某个编码器的详细参数 | ffmpeg -h encoder=h264_nvenc |
| 某个封装格式的详细参数 | ffmpeg -h muxer=mp4 |
| 所有像素格式 | ffmpeg -pix_fmts |
| 所有滤镜 | ffmpeg -filters |
举个例子,我想查 H.264 的软件编码器 libx264 有哪些可调参数:
ffmpeg -h encoder=libx264
输出会列出所有可用选项,包括 crf、preset、profile 等。你想想看,与其去网上搜一篇可能过时的博客,不如直接查官方帮助——这才是最准的。
一个小技巧:用 ffmpeg -h long 可以显示更详细的帮助信息。如果某个参数看不懂,试试 ffmpeg -h full | grep 参数名 来快速定位。
6. 知识体系总览
下面这张图,是我自己整理 FFmpeg 命令行结构时画的。每次写命令前,我都会在脑子里过一遍这个流程:
你看,从左到右,从上到下,逻辑非常清晰。全局参数控制整体行为,输入参数告诉 FFmpeg 怎么读,输出参数告诉它怎么写。中间那个 -i 就是分水岭。
7. 实战:一个完整的命令拆解
我们来拆一个真实项目中的命令。这是我去年帮一个客户做视频转码时用的:
ffmpeg -y -loglevel warning \
-f rawvideo -pix_fmt yuv420p -s 1920x1080 -r 25 -i input.yuv \
-c:v libx264 -preset medium -crf 23 -c:a aac -b:a 128k \
output.mp4
拆开看:
-y -loglevel warning→ 全局参数:覆盖输出,只显示警告和错误-f rawvideo -pix_fmt yuv420p -s 1920x1080 -r 25→ 输入参数:告诉 FFmpeg 输入是原始 YUV 数据,分辨率 1080p,帧率 25-i input.yuv→ 输入文件-c:v libx264 -preset medium -crf 23→ 输出参数:视频用 H.264 编码,中等编码速度,CRF 23 质量-c:a aac -b:a 128k→ 输出参数:音频用 AAC,码率 128koutput.mp4→ 输出文件
我第一次写这种命令时,把 -f rawvideo 放到了 -i 后面,结果 FFmpeg 死活不认——它以为我要把输出也设成 rawvideo。这种错,犯一次就记住了。
避坑指南:我曾经在生产环境遇到过一个问题——忘记加 -y,结果转码脚本在半夜卡住,因为 FFmpeg 在等用户确认是否覆盖文件。从那以后,所有自动化脚本里我都强制加上 -y。
8. 本章小结
这一章我们只讲了一件事:FFmpeg 命令行的骨架。全局参数、输入参数、-i、输出参数、输出文件,顺序不能乱。再加上几个查询帮助的技巧,你就能自己摸索出 90% 的常用命令了。