3. FFmpeg命令行基础:命令结构、全局参数、输入输出与编码选择

说实话,我见过不少刚接触FFmpeg的朋友,一上来就复制网上的命令跑,跑通了就觉得自己会了。但一旦遇到报错,或者想改点东西,就完全懵了。这就像你只会按快门,却不懂光圈和快门速度的关系——永远拍不出想要的照片。

所以这一章,咱们把FFmpeg的命令行基础彻底搞明白。我保证,看完这章,你不仅能看懂任何一条FFmpeg命令,还能自己组装出符合需求的命令。

3.1 FFmpeg命令的骨架:一个命令是怎么组成的?

一条完整的FFmpeg命令,其实就五个部分。我习惯把它想象成「流水线」:

ffmpeg [全局参数] [输入文件参数] -i 输入文件 [输出文件参数] 输出文件

咱们拆开看:

  • ffmpeg:就是启动这个工具本身,没啥好说的。
  • [全局参数]:影响整个命令行为的设置,比如日志级别、覆盖文件策略等。它放在最前面。
  • [输入文件参数]:针对输入文件的设置,比如指定视频轨道、设置输入格式等。它紧跟在全局参数后面,在 -i 之前。
  • -i 输入文件:指定输入文件路径。可以写多个 -i,实现多输入。
  • [输出文件参数]:针对输出文件的设置,比如编码器、码率、分辨率等。它放在输出文件之前。

举个例子,这条命令我经常在项目里用来快速转码:

ffmpeg -y -i input.mp4 -c:v libx264 -b:v 2M output.mp4

这里 -y 是全局参数(自动覆盖输出文件),-c:v libx264 -b:v 2M 是输出文件参数,input.mp4 是输入,output.mp4 是输出。结构清晰吧?

3.2 常用全局参数:这些你每天都会用到

全局参数虽然不多,但用错了能让你抓狂。我挑几个最常用的说说:

参数 作用 我的经验
-y 覆盖输出文件,不询问 脚本里必加,否则卡住
-n 不覆盖输出文件,直接跳过 批量处理时防止误覆盖
-loglevel 设置日志级别 调试用 debug,生产用 error
-hide_banner 隐藏编译信息等杂项 让输出更清爽,我必加
-stats 显示编码进度 默认开启,但有时需要显式指定
我的小习惯: 写脚本时,我通常这样开头:ffmpeg -y -hide_banner -loglevel error。这样既安静又不会因为文件存在而中断。

3.3 输入输出文件指定:不只是写个路径那么简单

指定输入输出文件,最基础的就是写路径。但FFmpeg支持很多「花样」,我挑两个实用的:

3.3.1 多个输入文件

比如你要把视频和音频合并:

ffmpeg -i video.mp4 -i audio.wav -c:v copy -c:a aac output.mp4

这里两个 -i,第一个是视频,第二个是音频。FFmpeg会按顺序给它们编号:0:0 是第一个文件的第一个流,1:0 是第二个文件的第一个流。

3.3.2 使用管道(pipe)

我在做实时流处理时经常用这个。从标准输入读取:

cat input.ts | ffmpeg -i pipe:0 -c copy output.mp4

或者输出到标准输出:

ffmpeg -i input.mp4 -c copy -f mpegts pipe:1 | some_other_program
注意: 使用管道时,必须用 -f 指定输出格式,因为FFmpeg无法从管道中自动探测格式。我曾经在这上面栽过跟头,折腾了半天才发现是格式没指定。

3.4 -c copy 与重编码:核心区别在哪?

这是新手最容易混淆的地方。我直接说结论:

  • -c copy:直接复制,不重新编码。速度快,画质无损。
  • 重编码:解码后再编码。速度慢,画质有损(除非用无损编码器)。

为什么会这样?你想想看,-c copy 只是把压缩好的数据从一种容器里「搬」到另一种容器里。而重编码,是把压缩的数据先解压成原始图像/音频,再用另一种方式压缩回去。这中间的解压-再压缩过程,不仅耗时,还会引入画质损失。

我举个例子,你一看就明白:

# 直接复制(秒完成)
ffmpeg -i input.mkv -c copy output.mp4

# 重编码(可能要几分钟)
ffmpeg -i input.mkv -c:v libx264 -c:a aac output.mp4

第一条命令,如果只是改封装格式(比如从MKV到MP4),几秒钟就完事。第二条命令,同样的文件,可能要跑几分钟甚至更久。

什么时候用 -c copy?
  • 只改封装格式(如 MKV → MP4)
  • 只裁剪或拼接(不改变编码)
  • 只提取流(如提取音频)
什么时候必须重编码?
  • 改变分辨率、帧率、码率
  • 改变编码格式(如 H.264 → H.265)
  • 添加滤镜、水印、字幕

我曾经有个项目,需要把一批TS流文件转成MP4。一开始我傻傻地用重编码,一个文件要跑半小时。后来发现只是容器不同,改成 -c copy,一个文件十几秒就搞定。嗯,这就是经验的价值。

3.5 知识体系总览:一张图看懂

说了这么多,咱们用一张SVG图把整个命令结构串起来。这样你以后看到任何FFmpeg命令,都能快速拆解:

FFmpeg命令结构总览 FFmpeg命令结构总览 全局参数 -y, -n, -loglevel 输入文件参数 -ss, -t, -f -i 输入文件 input.mp4 输出文件参数 -c:v, -b:v, -s 输出 核心决策:-c copy 还是 重编码? -c copy(流复制) 不解码,直接复制压缩数据 速度极快,画质无损 适用:改封装、裁剪、提取流 重编码(Transcoding) 解码 → 处理 → 重新编码 速度慢,画质有损 适用:改编码、加滤镜、调参数 选择依据:如果只是「搬家」,用 -c copy;如果要「改造」,必须重编码。 记住:重编码是最后的手段,能用 copy 就别重编码。 FFmpeg封装格式转换全攻略 · 第3章

3.6 实战对比:一个例子看懂所有

咱们用同一个输入文件,做三件事,你感受一下区别:

操作 命令 速度 画质
改封装(MKV→MP4) ffmpeg -i input.mkv -c copy output.mp4 极快(几秒) 无损
改编码(H.264→H.265) ffmpeg -i input.mp4 -c:v libx265 output.mp4 慢(几分钟) 有损(但更小)
加滤镜(调亮度) ffmpeg -i input.mp4 -vf eq=brightness=0.2 output.mp4 慢(需重编码) 有损
我的建议: 拿到一个任务,先问自己「我需要改变视频内容本身吗?」如果只是换容器、剪片段、提音频,直接用 -c copy。如果必须改内容,再考虑重编码。这个习惯能帮你省下大量时间。

好了,这一章的内容就这些。记住命令的骨架结构,分清全局参数和文件参数,理解 -c copy 和重编码的本质区别。这些东西看似基础,但我在工作中见过太多人在这上面翻车。打好这个基础,后面的章节你会走得很顺。