🎬 第二章 把控FFmpeg骨架:【八大金刚】核心开发库
📄 一句话概括

468 个滤镜都在这层,滤镜串成链、链拼成图,多进多出要走图。 drawtext、subtitles、ass 本机三个都没有——缺 freetype 与 libass。

📝 本节和前面几节的关系

2.6 讲采集,这一篇讲对画面做的每一个动作。 它是「简单滤镜」与「复杂滤镜」的分界线所在。

一、滤镜、滤镜链、滤镜图

概念 是什么 例子


滤镜 最小处理单元 scale、hflip 滤镜链 一串首尾相连的滤镜 scale,hflip 滤镜图 多条链,可多进多出 overlay 两路输入

链是「一进一出」,图可以多路进、多路出。 命令行 -vf 只能给一条链, -filter_complex 才能给整张图。 这就是「简单滤镜」与「复杂滤镜」的分界:看你需不需要多路输入。 加水印要两路(原图 + 水印图),所以必须用 complex。

二、本机 468 个,常用的十来个

滤镜 干什么 在不在


scale 缩放 在 crop 裁剪 在 overlay 叠加 在 transpose 旋转 在 drawbox 画框 在 gblur 高斯模糊 在 drawtext 写字 不在 subtitles 挂字幕 不在

三个「不在」的共同原因是缺依赖:drawtext 要 freetype 找字体, subtitles 与 ass 要 libass 排版。没编这两样,对应的滤镜根本不会被注册。 「No such filter」的意思是「这个构建没编它」,不是「这个滤镜不存在」。 换一套带 freetype 的构建,那三个滤镜就都有了。

三、命令行与 API 是同一套东西

-vf "scale=1280:720,hflip" 那串字符串,在 API 里就是解析器的输入。 步 函数


1 avfilter_graph_alloc 2 avfilter_graph_create_filter 两次(源与汇) 3 avfilter_graph_parse_ptr 解析那串字符串 4 avfilter_graph_config 校验并生效 5 av_buffersink_get_frame 取结果

第 3 步是理解这件事的关键:那串 scale=1280:720,hflip 不是 FFmpeg 特有的格式, 它就是滤镜图的文本表示法。学会写命令,等于学会写 API 的参数。 第 4 步会失败。 参数写错、格式不匹配(比如往 yuv420p 上套只收 rgb 的滤镜),都在这一步报出来, 而不是等到取帧的时候。

四、为什么滤镜层值得单独学一章

因为水印、跑马灯、九宫格、画中画、美颜,全都是滤镜。 本课后面第十三章的直播美颜, 本质也是一串滤镜加 OpenCV。 而且它跟命令行完全同构:你会在命令行里试出效果,把那串字符串原样搬到 API 里就能用。 试错成本极低。 本机三个常用滤镜缺失这件事,也在这里说清:不是代码写错,是构建没编。 查 filters_available 一眼就知道。

五、动手 Demo:libavfilter——468 个滤镜,一条链子串起来

这一段查十三个常用滤镜在不在,把三个「不在」标出来。 那三个缺的都是字体与字幕库。

import av.filter

fs = set(av.filter.filters_available)
for n in ("scale", "overlay", "gblur", "drawtext", "subtitles", "ass"):
    print(n, n in fs)

实跑输出:

--------------------------------------------------------------------
libavfilter——468 个滤镜,一条链子串起来
--------------------------------------------------------------------

**① 本机这 468 个里,常用的十来个**

  滤镜          干什么          在不在
  ----------------------------------------
  scale         缩放            在
  crop          裁剪            在
  overlay       叠加            在
  hflip         左右翻          在
  vflip         上下翻          在
  transpose     旋转            在
  drawbox       画框            在
  gblur         高斯模糊        在
  eq            调亮度对比      不在
  format        转像素格式      在
  drawtext      写字            不在
  subtitles     挂字幕          不在
  ass           挂 ASS 字幕     不在

**`drawtext`、`subtitles`、`ass` 三个不在。** 它们要 freetype 与 libass,
本机这套构建没编——这就是「同一句命令在别人机器上能用,在我这儿报 No such filter」的真相。

**② 三种东西,别混**

  概念       是什么                   例子
  --------------------------------------------------------
  滤镜       最小的处理单元           scale、hflip
  滤镜链     一串首尾相连的滤镜       scale,hflip
  滤镜图     多条链,可有多进多出     overlay 两路输入

**一条链里的数据是「一进一出」,一张图里可以有多条链。** 命令行 `-vf` 只能给一条链,
`-filter_complex` 才能给整张图——这就是「简单滤镜」与「复杂滤镜」的分界。

**③ 命令行与 API 是同一套东西**

`-vf "scale=1280:720,hflip"` 那串字符串,API 里就是 `avfilter_graph_parse_ptr` 的输入。
**先会用命令,再换成 API,几乎不用重学。**

scale、overlay、gblur 都在,drawtext、subtitles、ass 三个不在。 缺 freetype 与 libass,滤镜压根不会被注册。

30 秒实验

  1. python -c "import av.filter; print(len(av.filter.filters_available))" 数滤镜。
  2. 命令行 ffmpeg -filters | grep drawtext,看有没有那一行。
  3. 把 scale=640:360,hflip 用 API 跑一遍,看输出帧的宽高。

常见误区

  1. 以为「No such filter」是用法错。 实际是构建没编这个滤镜。
  2. 拿 -vf 去做两路输入的事。 加水印必须用 -filter_complex。
  3. 跳过 avfilter_graph_config。 参数错要到这一步才报,跳过就等崩溃。
自测三问(点开对答案) 1. 滤镜、滤镜链、滤镜图的区别是什么? —— 滤镜是最小单元,链是一串一进一出,图可以多进多出。命令行 -vf 只能给链。 2. 本机为什么没有 drawtext? —— 它要 freetype 找字体,这套构建没编。没有依赖的滤镜不会被注册。 3. 为什么说学会写命令行等于学会写 API? —— `-vf` 那串字符串就是滤镜图的文本表示,API 里由同一个解析器吃进去。

相关笔记