3、命令行基础:ffmpeg命令结构、全局选项与流选项、输入输出文件指定、常用参数速查
说实话,很多人学FFmpeg第一步就卡在命令行上。我见过不少同事,拿着网上抄来的一长串命令,跑通了就欢呼,跑不通就抓瞎。其实FFmpeg的命令行结构非常清晰,你只要搞懂它的骨架,剩下的就是往上面填参数而已。
这一章,我就带你把这个骨架彻底拆开看一遍。
3.1 命令的骨架:ffmpeg到底在干什么?
先看一个最典型的命令:
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M output.mp4
这个命令的结构,说白了就是三部分:
- ffmpeg —— 调用程序本身
- 全局选项 + 输入文件 —— 告诉它从哪读、怎么读
- 输出选项 + 输出文件 —— 告诉它往哪写、怎么写
嗯,这里要注意:输入文件必须紧跟 -i 参数,输出文件放在最后。顺序错了,FFmpeg会直接报错。我在项目中遇到过好几次,同事把输出文件写在了中间,结果FFmpeg把它当成了输入文件,然后一脸懵地告诉你“找不到这个文件”。
核心公式:
ffmpeg [全局选项] -i [输入文件] [输出选项] [输出文件]
记住这个顺序,你就能看懂90%的FFmpeg命令。
3.2 全局选项 vs 流选项:别搞混了
很多新手分不清全局选项和流选项的区别。我打个比方:全局选项就像你给整个厨房下的指令,比如“今天做中餐”;流选项则是针对每个灶台的具体要求,比如“一号灶台做红烧肉,二号灶台做清蒸鱼”。
常见的全局选项有这些:
| 选项 | 作用 | 我的经验 |
|---|---|---|
-y |
覆盖输出文件,不询问 | 脚本里必加,否则卡住 |
-n |
不覆盖,直接跳过 | 批量处理时防止误覆盖 |
-loglevel |
控制日志输出级别 | 调试用 debug,生产用 error |
-stats |
显示编码进度 | 默认开启,关掉用 -nostats |
流选项则更细,它要指定作用于哪一路流。比如:
ffmpeg -i input.mp4 -c:v libx264 -c:a aac output.mp4
这里的 -c:v 只作用于视频流,-c:a 只作用于音频流。你想想看,如果我想让视频用H.264、音频用AAC、字幕保持原样,就得分别指定。
小技巧: 用 -c copy 可以“透传”某个流,不做任何编解码。我经常用这个来快速分离音视频,速度极快。
3.3 输入输出文件:你指定对了吗?
输入文件用 -i 指定,这个大家都知道。但有几个坑,我踩过不止一次。
第一个坑:多个输入文件。 比如你要把视频和音频合并:
ffmpeg -i video.mp4 -i audio.mp3 -c:v copy -c:a aac output.mp4
这里有两个 -i,FFmpeg会按顺序给它们编号:0:0 是第一个文件的视频流,1:0 是第二个文件的音频流。如果你搞混了顺序,出来的画面和声音就对不上。
第二个坑:输出文件格式。 FFmpeg会根据文件扩展名自动判断封装格式。你写 .mp4 它就封装成MP4,写 .mkv 就封装成MKV。但如果你写错了扩展名,比如明明是H.264视频却给了 .avi,FFmpeg会尝试用AVI容器去装,结果往往不兼容。
我曾经有一次,批量转码时脚本里写死了 .mp4,结果有个源文件是HEVC的,转出来播放器死活打不开。后来才发现,HEVC用MP4容器没问题,但我的播放器版本太老……嗯,从那以后我养成了先查兼容性的习惯。
3.4 常用参数速查:一张表搞定
下面这张表,是我自己整理的高频参数。你把它存下来,写命令时直接翻,比去查文档快得多。
| 分类 | 参数 | 说明 | 示例 |
|---|---|---|---|
| 视频编码 | -c:v libx264 |
H.264软件编码 | 最通用,兼容性最好 |
-c:v libx265 |
H.265/HEVC编码 | 压缩率更高,但编码慢 | |
-c:v h264_nvenc |
NVIDIA硬件编码 | 速度快,画质略差 | |
| 音频编码 | -c:a aac |
AAC音频编码 | MP4标配 |
-c:a libmp3lame |
MP3编码 | 老格式,但仍有需求 | |
| 码率控制 | -b:v 2M |
视频目标码率 | 2Mbps,适合1080p |
-b:a 128k |
音频目标码率 | 128kbps,音质不错 | |
-crf 23 |
质量恒定模式 | 数值越小质量越高,18-28常用 | |
| 分辨率 | -s 1920x1080 |
强制缩放 | 注意保持宽高比 |
-vf scale=1280:720 |
滤镜缩放 | 更灵活,可配合其他滤镜 | |
| 帧率 | -r 30 |
输出帧率 | 会丢帧或插帧 |
-vsync cfr |
恒定帧率模式 | 直播推流常用 |
注意: -crf 和 -b:v 不要同时使用。CRF是质量优先,码率是大小优先,两者会打架。我见过有人两个都写上,结果FFmpeg以最后一个为准,前面的等于白写。
3.5 知识体系:一张SVG图看懂
下面这张图,把FFmpeg命令行的整体结构画出来了。你对照着看,思路会清晰很多。
3.6 实战:从零写一个完整的命令
光说不练假把式。我们拿一个真实场景来走一遍。
需求: 把一个1080p、30fps的MP4视频,转成720p、25fps的H.264视频,音频转成128kbps的AAC,输出到当前目录。
按照我们刚才学的结构,一步步来:
- 全局选项: 加个
-y防止卡住 - 输入文件:
-i input.mp4 - 输出选项:
- 视频编码:
-c:v libx264 - 分辨率:
-vf scale=1280:720 - 帧率:
-r 25 - 音频编码:
-c:a aac - 音频码率:
-b:a 128k
- 视频编码:
- 输出文件:
output_720p.mp4
组合起来就是:
ffmpeg -y -i input.mp4 -c:v libx264 -vf scale=1280:720 -r 25 -c:a aac -b:a 128k output_720p.mp4
你看,是不是很清晰?我建议你每次写命令前,先在脑子里过一遍这个结构,养成习惯后,再复杂的命令也不会乱。
我的习惯: 写长命令时,我会用反斜杠 \ 换行,每行放一类参数。这样既好读,又方便调试。
ffmpeg -y \
-i input.mp4 \
-c:v libx264 \
-vf scale=1280:720 \
-r 25 \
-c:a aac \
-b:a 128k \
output_720p.mp4
3.7 避坑指南:我踩过的那些坑
最后,分享几个我实际工作中遇到的坑,你遇到了能少走弯路。
- 坑1: 忘记加
-y,在脚本里运行时卡住等待用户输入。解决方案:脚本里永远加-y。 - 坑2: 多个输入文件时,流索引搞混。解决方案:先用
ffprobe查看流信息,确认0:0、1:0分别是什么。 - 坑3:
-vf和-filter_complex混用。解决方案:简单滤镜用-vf,复杂多流处理用-filter_complex,不要混在一个命令里。 - 坑4: 输出文件路径包含空格。解决方案:用引号包起来,比如
"my video.mp4"。
我曾经有一次,在服务器上跑批量转码,脚本里忘了加引号,结果有个文件名带空格,FFmpeg把它当成了两个参数,直接报错退出。那次跑了三个小时的任务,全废了。嗯,从那以后我写脚本都会检查文件名里有没有空格。