首页 / FFmpeg 入门教程 / 滤镜链基础语法

FFmpeg 入门教程

滤镜链基础语法

本教程共 32 篇 · 第 23 篇 · 更新于 2026-08-09 · 约 5 分钟阅读

FFmpeg滤镜filtergraphfilter_complex-vf-af语法

本节目标:彻底搞懂 FFmpeg 滤镜的语法规则。看完这章,任何 -vf-af-filter_complex 命令你都能读懂、能自己拼。

FFmpeg 的滤镜(filter)是处理音视频画面的核心。缩放、裁剪、加水印、调速、混音,全靠滤镜。但很多人看到 -filter_complex "[0:v][1:v]overlay=...[v]" 就头大,其实它的语法只有三层,搞懂就不慌。

一、三层结构

从简到繁,三个概念:

  1. filter(滤镜):一个最小操作单元,比如 scale=1280:720crop=640:480volume=2.0
  2. filterchain(滤镜链):一串用逗号 , 连接的滤镜,前一个的输出是后一个的输入。
  3. filtergraph(滤镜图):多条滤镜链用分号 ; 隔开,可以有分支、汇合、多输入多输出。
filter1,filter2,filter3              ← 一条 filterchain
filterchain1;filterchain2;filterchain3  ← 一个 filtergraph

二、简单滤镜:-vf 和 -af

只处理一个视频流或一个音频流时,用 -vf(video filter)或 -af(audio filter):

ffmpeg -i input.mp4 -vf "scale=1280:720,fps=30" output.mp4

这条命令做了两件事:先缩放,再改帧率。逗号表示串联,数据从左往右流。

input → scale → fps → output

音频同理:

ffmpeg -i input.mp4 -af "volume=2.0,atempo=1.5" output.mp4

先加大音量,再变速。

选项里有冒号和逗号怎么办

滤镜的参数用冒号 : 分隔,比如 scale=宽:高。如果参数值里本身有特殊字符(空格、冒号、逗号),要用引号或转义:

ffmpeg -i input.mp4 -vf "drawtext=text='Hello World':fontsize=24:x=10:y=10" output.mp4

整个 -vf 的值用双引号包住,内部文字用单引号,这是最常见的写法。

三、缓冲标签:[name]

当滤镜图需要分支或合流时,用方括号标签给中间结果命名:

[输入标签]滤镜链[输出标签]

标签可以随便起,比如 [v0][scaled][a_mix]。输入标签从输入文件取流([0:v] 表示第一个输入的视频流),输出标签要么喂给下一条链,要么在命令末尾用 -map 引用。

举个最简单的例子——把视频缩小后再加水印:

ffmpeg -i input.mp4 -i logo.png -filter_complex \
  "[0:v]scale=1280:720[bg];[bg][1:v]overlay=10:10[v]" \
  -map "[v]" output.mp4

拆解:

  1. [0:v]scale=1280:720[bg]:取第 0 个输入的视频流,缩放后命名为 [bg]
  2. [bg][1:v]overlay=10:10[v]:把 [bg] 作为底图,第 1 个输入(logo)叠在 (10,10),结果命名为 [v]
  3. 两条链用分号 ; 隔开。
  4. -map "[v]" 把最终结果输出。
[0:v] → scale → [bg] ──┐
                        ├→ overlay → [v] → output
[1:v] ──────────────────┘

四、为什么需要 -filter_complex

-vf-af 只能处理一个输入流、输出一个流的简单情况。一旦涉及:

  • 多个输入文件叠加(水印、画中画)
  • 分流:同一个视频要走两条不同处理路径
  • 合流:把两个视频拼在一起、把两路音频混在一起
  • 视频和音频在同一条滤镜图里处理(比如调速要同时改 setpts 和 atempo)

就必须用 -filter_complex。它支持任意复杂的有向无环图。

同一个流分两路

比如既要原始视频,又要缩小版做画中画:

ffmpeg -i input.mp4 -filter_complex \
  "[0:v]split=2[v1][v2];[v2]scale=320:240[pip];[v1][pip]overlay=W-w-10:H-h-10[v]" \
  -map "[v]" output.mp4

split=2 把输入复制成两路 [v1][v2],第二路缩小后叠回第一路。

视频音频一起调速

ffmpeg -i input.mp4 -filter_complex \
  "[0:v]setpts=2.0*PTS[v];[0:a]atempo=0.5[a]" \
  -map "[v]" -map "[a]" output.mp4

视频慢动作(setpts 改时间戳)和音频减速(atempo=0.5)必须在同一个 filtergraph 里,否则只能用 -vf-af 分开写,效果一样但没法用标签引用。

五、常用流引用写法

写法含义
[0:v]第 0 个输入的视频流(v=video)
[0:a]第 0 个输入的音频流(a=audio)
[0:s]第 0 个输入的字幕流
[0:v:0]第 0 个输入的第 0 条视频流
[1:v]第 1 个输入的视频流
[label]自己命名的中间结果

六、避坑清单

  1. 逗号和分号别搞混:逗号是串行连接,分号是并行链。绝大多数报错都是把分号写成逗号。
  2. 标签要闭合:每条输入标签必须有来源,每条输出标签要么被下游引用,要么被 -map 引用,否则报错”Output with label … does not exist”或”Some filters were not used”。
  3. 引号要配对:Windows PowerShell 里用双引号包住整个 filtergraph,内部用单引号或转义;bash 里同理。
  4. 视频滤镜不能处理音频,音频滤镜不能处理视频。如果滤镜收到类型不匹配的流,会报”Cannot find a matching input pad”。
  5. 顺序很重要:滤镜从左到右执行,scale,cropcrop,scale 结果不同。先想清楚数据流方向。
Tip

看不懂复杂滤镜图时,拿笔按分号拆成一条链子,再按逗号拆成单个滤镜,画出标签的流向,就跟看流程图一样。后续四章会反复用这套语法,每次只加一两个新滤镜,不会一下子堆满。