目录
- 参考
- FFmpeg filter简介
- filter的使用方法
1. 参考
- [1] ffmpeg.org/libavfilter documentation
- [2] ffmpeg.org/Filters Documentation
- [3] 北雨南萍/FFmpeg-4.0 的filter机制的架构与实现.之一 Filter原理
2. FFmpeg filter简介
FFmpeg filter提供了很多音视频特效处理的功能,比如视频缩放、截取、翻转、叠加等。
其中定义了很多的filter,例如以下常用的一些filter。
- scale:视频/图像的缩放
- overlay:视频/图像的叠加
- crop:视频/图像的裁剪
- trim:截取视频的片段
- rotate:以任意角度旋转视频
支持的filter的列表可以通过以下命令获得。
ffmpeg -filters
也可以查看文档[2],具体某个版本的支持情况以命令行获取到的结果为准。
以下是filter的一个简单的应用示例,对视频的宽和高减半。
ffmpeg -i input -vf scale=iw/2:ih/2 output
3. filter的使用方法
学习filter的使用,先需要了解一下filter的语法。
FFmpeg中filter包含三个层次,filter->filterchain->filtergraph。
具体参考下图:
说明:
- 第一层是 filter 的语法。
- 第二层是 filterchain的语法。
- 第三层是 filtergraph的语法。
filtergraph可以用文本形式表示,可以作为ffmpeg中的-filter/-vf/-af和-filter_complex选项以及ffplay中的-vf/-af和libavfilter/avfilter.h中定义的avfilter_graph_parse_ptr()函数的参数。
为了说明可能的情况,我们考虑下面的例子“把视频的上部分镜像到下半部分”。
处理流程如下:
- 使用split filter将输入流分割为两个流[main]和[temp]。
- 其中一个流[temp]通过crop filter把下半部分裁剪掉。
- 步骤2中的输出再经过vflip filter对视频进行和垂直翻转,输出[flip]。
- 把步骤3中输出[flip]叠加到[main]的下半部分。
以下整个处理过程的一个图示,也就是对filtergraph的一个描述[2]。
[main]
input --> split ---------------------> overlay --> output
| ^
|[tmp] [flip]|
+-----> crop --> vflip -------+
可以用以下的命令来实现这个流程。
ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT
处理结果如下图所示。
下面具体了解每一层的语法,从而理解上面这个命令的含义。
3.1 filter的语法
用一个字符串描述filter的组成,形式如下
[in_link_1]…[in_link_N]filter_name=parameters[out_link_1]…[out_link_M]
参数说明:
- [in_link_N]、[out_link_N]:用来标识输入和输出的标签。in_link_N是标签名,标签名可以任意命名,需使用方括号括起来。在filter_name的前面的标签用于标识输入,在filter_name后面的用于标识输出。一个filter可以有多个输入和多个输出,没有输入的filter称为source filter,没有输出的filter称为sink filter。对输入或输出打标签是可选的,打上标签是为了连接其他filter时使用。
- filter_name:filter的名称。
- “=parameters”:包含初始化filter的参数,是可选的。
“=parameters”有以下几种形式
- 使用':'字符分隔的一个“键=值”对列表。如下所示。
ffmpeg -i input -vf scale=w=iw/2:h=ih/2 output
- 使用':'字符分割的“值”的列表。在这种情况下,键按照声明的顺序被假定为选项名。例如,scale filter的前两个选项分别是w和h,当参数列表为“iw/2:ih/2”时,iw/2的值赋给w,ih/2的值赋给h。如下所示。
ffmpeg -i input -vf scale=iw/2:ih/2 output
- 使用':' 字符分隔混合“值”和“键=值”对的列表。“值”必须位于“键=值”对之前,并遵循与前一点相同的约束顺序。之后的“键=值”对的顺序不受约束。如下所示。
ffmpeg -i input -vf scale=iw/2:h=ih/2 output
filter类定义了filter的特性以及输入和输出的数量,某个filter的使用方式可以通过以下命令获知。
ffmpeg -h filter=filter_name
也可以查看文档[2],但具体某个版本的参数形式以命令行获取到的结果为准。
以下是rotate filter的使用方式
- 可以看出它支持slice threading。
- Inputs下面定义的是输入。可以看出rotate filter有一个输入,格式为Video。
- Outputs下面定义的是输出。可以看出rotate filter有有一个输出,格式为video。
- AVOptions下面定义了支持的参数,后面有默认值描述。为了简化输入参数,对长的参数名提供一个简化的名称。比如rotate filter中,“angle”的简化名称是“a”。
以下是使用到fiter的标签名的一个示例:抽取视频Y、U、V分量到不同的文件
ffmpeg -i jack.mp4 -filter_complex "extractplanes=y+u+v[y][u][v]" -map "[y]" jack_y.mp4 -map "[u]" jack_u.mp4 -map "[v]" jack_v.mp4
extractplanes filter指定了三个输出,分别是 [y][u][v],抽取后,将不同的输出保存到不同的文件中。
3.2 filterchain的语法
用一个字符串描述filterchain的组成,形式如下
"filter1, filter2, ... filterN-1, filterN"
说明:
- 由一个或多个filter的连接而成,filter之间以逗号“,”分隔。
- 每个filter都连接到序列中的前一个filter,即前一个filter的输出是后一个filter的输入。
比如示例
ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT
示例说明:
- crop、vflip在同一个filterchain中,
3.3 filtergraph的语法
用一个字符串描述filtergraph的组成,形式如下
"filterchain1;filterchain2;...filterchainN-1;fiterchainN"
说明:
- 由一个或多个filter的组合而成,filterchain之间用分号";"分隔。
- filtergraph是连接filter的有向图。它可以包含循环,一对filter之间可以有多个连接。
- 当在filtergraph中找到两个相同名称的标签时,将创建相应输入和输出之间的连接。
- 如果输出没有被打标签,则默认将其连接到filterchain中下一个filter的第一个未打标签的输入。例如以下filterchain中。
nullsrc, split[L1], [L2]overlay, nullsink
说明:split filter有两个输出,overlay filter有两个输入。split的第一个输出标记为“L1”,overlay的第一个输入pad标记为“L2”。split的第二个输出将连接到overlay的第二个输入。
- 在一个filter描述中,如果没有指定第一个filter的输入标签,则假定为“In”。如果没有指定最后一个filter的输出标签,则假定为“out”。
- 在一个完整的filterchain中,所有没有打标签的filter输入和输出必须是连接的。如果所有filterchain的所有filter输入和输出pad都是连接的,则认为filtergraph是有效的[2]。
比如示例
ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT
其中有三个filterchain, 分别是:
- "split [main][tmp]"。它只有一个filter,即 split,它有一个默认的输入,即INPUT解码后的frame。有两个输出, 以 [main], [tmp] 标识。
- "[tmp] crop=iw:ih/2:0:0, vflip [flip]"。它由两个filter组成,crop和vflip,crop的输入 为[tmp],vflip的输出标识为[flip]。
- "[main][flip] overlay=0:H/2"。它由一个filter组成,即overlay。有两个输入,[main]和[flip]。有一个默认的输出。