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 秒实验
python -c "import av.filter; print(len(av.filter.filters_available))"数滤镜。- 命令行
ffmpeg -filters | grep drawtext,看有没有那一行。 - 把
scale=640:360,hflip用 API 跑一遍,看输出帧的宽高。
常见误区
- 以为「No such filter」是用法错。 实际是构建没编这个滤镜。
- 拿
-vf去做两路输入的事。 加水印必须用-filter_complex。 - 跳过
avfilter_graph_config。 参数错要到这一步才报,跳过就等崩溃。
自测三问(点开对答案)
1. 滤镜、滤镜链、滤镜图的区别是什么? —— 滤镜是最小单元,链是一串一进一出,图可以多进多出。命令行 -vf 只能给链。 2. 本机为什么没有 drawtext? —— 它要 freetype 找字体,这套构建没编。没有依赖的滤镜不会被注册。 3. 为什么说学会写命令行等于学会写 API? —— `-vf` 那串字符串就是滤镜图的文本表示,API 里由同一个解析器吃进去。- ☐ (本节完,下一节 2.8 libswresample 库简介)