命令变长以后,先找到每个 -i 和输出文件名,再判断选项作用于哪里。本篇接着说明 Filter、编码质量和容器选项怎样配合。

按输入和输出拆开命令

官方骨架:

ffmpeg [全局选项] [输入选项] -i 输入 ... [输出选项] 输出 ...

多数非全局选项作用于紧随其后的输入或输出文件,并在下一个文件处重新设置。先按文件划分:

ffmpeg -hide_banner -ss 00:01:00 -i input.mp4 -t 30 -c:v libx264 output.mp4
└ 全局 ─┘ └ 输入选项 ─┘ └ 输入 ─┘ └ 输出选项 ──────┘ └ 输出 ┘
Terminal window
ffmpeg -hide_banner -ss 00:01:00 -i input.mp4 -map 0:v:0 -map 0:a:0? -t 00:00:30 -c:v libx264 -crf 23 -c:a aac output.mp4
片段作用范围
-hide_banner全局,隐藏版本横幅
-ss ... -i input.mp4这个输入的定位
-map ...当前输出挑选哪些流
-t ...当前输出写多久
-c:v、-crf、-c:a当前输出各流怎么处理
output.mp4这组输出选项到此结束

多输入、多输出时,选项要贴着对应的 -i 或输出文件。不要把一组输出参数写在两个输出文件之间,然后假设两边都会生效。

-ss、-t 和 -to

第 03 篇给出了切片命令,这里对照选项位置:

写法官方行为适合
-ss 在 -i 前 + -c copy输入 seek 到目标前最近的 seek point,多出来的数据会保留快速粗切
-ss 在 -i 前 + 转码默认 -accurate_seek 会把多出来的那段解码后丢掉较快且切点较准
-ss 在 -i 后 + 转码输出选项:解码并丢弃到目标时间戳未做输入定位时,需解码前面的内容
-t持续时长(输入或输出选项,看写在 -i 哪一侧)切 30 秒
-to停在时间轴的某个位置(同样分输入/输出)切到 1:30

官方规定 -t 和 -to 互斥,且 -t 优先;实践中只选一个。

Terminal window
ffmpeg -ss 00:01:00 -i input.mp4 -t 30 -c copy fast-clip.mp4
ffmpeg -i input.mp4 -ss 00:01:00 -t 30 -c:v libx264 -c:a aac accurate-clip.mp4

Filter 为什么需要解码和重新编码

flowchart LR
A[输入] --> B[Demuxer]
B --> C[Packet]
C -->|copy| E[Muxer]
C -->|Filter 或重新编码| F[Decode]
F --> G[Frame]
G --> H[Filter 可选]
H --> I[Encode]
I --> E
E --> J[输出]
  • -c copy 走 Packet → Muxer,不经过 Decoder 和 Filter;
  • 改编码、缩放、裁剪、水印、调音量或改采样率时,相关流走 Decode → Filter(可选)→ Encode;
  • 一个输出可以两条路混用,例如视频重编码、音频复制。

Filter 处理的是 Decode 之后的 Frame。所以同一条视频一旦进了 scale,就不能再 -c:v copy。这就是常见报错 Filtering and streamcopy cannot be used together 的原因。

常用视频参数

参数用途入门记法
-c:v视频编码器或 copylibx264 是常见 H.264 软件编码器,先查本机构建
-vf单路 Video Filterchain-vf "scale=1280:-2"
-crf编码器相关的恒定质量数值越小通常质量越高、文件越大
-preset速度和压缩效率慢一些通常更省体积,不直接等于画质
-b:v目标视频码率适合有带宽或体积上限的任务
-pix_fmt输出像素格式yuv420p 常见,但不是所有任务的最佳选择
-r输出帧率相关处理会影响丢帧/补帧,先理解 fps Filter 再使用

下面沿用教程中的 libx264 -crf 23 -preset medium 作为演示配置。CRF 控制质量与体积的取舍,preset 控制编码速度与压缩效率,实际效果需要用自己的素材比较:

Terminal window
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output.mp4

保持输入和其他参数相同时,对 libx264 降低 CRF 通常会提高质量并增大文件;提高 CRF 则相反。某个数值不能保证“接近原片”,也不能跨编码器直接比较。CRF 23 不是 23% 画质。

有明确带宽上限时,给编码器码率约束:

Terminal window
ffmpeg -i input.mp4 -c:v libx264 -b:v 2500k -maxrate 3000k -bufsize 6000k -c:a aac -b:a 128k output.mp4

-maxrate 和 -bufsize 描述缓冲约束,不保证每一秒比特数完全相同。最终体积还受音频、容器和内容影响。-fs 达到文件大小限制后会停止继续写入,实际文件可能略大于该值;它不会自动调整质量来保留完整时长。

常用音频参数

参数用途示例
-c:a音频编码器或 copy-c:a aac
-b:a音频码率-b:a 128k
-ar输出采样率-ar 48000
-ac输出声道数-ac 2
-af单路 Audio Filterchain-af "volume=1.5"
-an禁止输出音频只生成无声视频

改变音量、采样率或声道会改变音频采样,不能再对该音频使用 -c:a copy。

Filter:从 Filterchain 到 Filtergraph

单输入、单输出的常见 Filter:

Terminal window
ffmpeg -i input.mp4 -vf "scale=1280:-2,fps=25" -c:v libx264 -c:a copy output.mkv

逗号表示从左到右:先 scale,再 fps。视频经过 Filter 后必须编码;没改的音频仍可复制。

多个输入或多个输出用 -filter_complex,并给中间结果起名字(Label):

Terminal window
ffmpeg -i input.mp4 -i logo.png -filter_complex "[1:v]scale=160:-1[logo];[0:v][logo]overlay=W-w-24:H-h-24[outv]" -map "[outv]" -map 0:a:0? -c:v libx264 -c:a copy output.mkv
[1:v] 第二个输入的视频
[logo] Filtergraph 内部的 Label,不是文件名
[outv] 合成结果,必须再 -map 才能进输出文件
flowchart LR
V[0:v 主视频] --> OV[overlay]
L[1:v Logo] --> S[scale=160:-1]
S --> LB[logo]
LB --> OV
OV --> OUTV[outv]
OUTV --> MAP["-map outv"]
MAP --> ENC[-c:v libx264]
ENC --> FILE[output.mkv]

这里的 [outv] 是带标签输出,必须映射一次且只能一次。无标签的复杂 Filtergraph 输出会自动加入第一个输出文件,即使该文件已写了其他 -map。显式命名并映射更便于检查连接关系,详见 FFmpeg Filters。

输出容器和兼容性

网页渐进下载常见的 MP4 写法:

Terminal window
ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p -c:a aac -b:a 128k -movflags +faststart output.mp4

+faststart 把 MP4 的索引(moov)移到文件前面,方便普通文件边下边播;它不会把文件变成直播协议,也不会把 H.265 自动变成 H.264。yuv420p 常见于 8-bit SDR 兼容场景,HDR / 10-bit 不能机械套用。

普通 MP4 / MKV 通常让 FFmpeg 按扩展名选择容器。需要原始数据、管道或无扩展名 URL 时,再显式写 -f。

程序调用时的两个实用选项

禁止后台任务等待标准输入:

Terminal window
ffmpeg -nostdin -i input.mp4 -c copy output.mkv

输出机器可读进度(不要去解析人类日志里的 frame=):

Terminal window
ffmpeg -nostdin -i input.mp4 -c:v libx264 -c:a aac -progress pipe:1 -nostats output.mp4

程序仍要读退出码和 stderr,设置超时,取消时清理进程。-progress 不是任务成功的替代证明。

需要时再查的高级参数

-copyts、-fps_mode、硬件编解码、原始视频输入和协议私有选项都依赖具体任务。遇到它们时,先问当前构建:

Terminal window
ffmpeg -hide_banner -h encoder=libx264
ffmpeg -hide_banner -h filter=scale
ffmpeg -hide_banner -h demuxer=rtsp

不要把某个硬件编码器、协议选项或旧式 -vsync 当成所有 FFmpeg 构建都通用的参数。

依据:FFmpeg 选项与命令结构、Filter 官方文档、libx264 编码选项、MP4 封装与 faststart。