FFmpeg filter过滤器使用详解

article/2025/9/6 10:47:59


1、FFmpeg过滤器简介

FFmpeg filter 提供了很多音视频特效处理功能,比如视频缩放、截取、翻转、叠加等。
FFmpeg有很多已经实现好的滤波器,这些滤波器的实现位于libavfilter目录之下,用户需要可以调用这些滤波器实现滤波。

我们可以通过ffmpeg -filters命令查看FFmpeg支持的过滤器。FFmpeg常用的filter包括:

  • scale:视频/图像的缩放;
  • overlay:视频/图片的叠加;
  • crop:视频/图像的裁剪;
  • trim:截取视频的片段;
  • rotate:以任意⻆度旋转视频
  • movie:加载第三方的视频;
  • yadif:去隔行。

使用示例(对视频的宽和高减半):ffmpeg -i input -vf scale=iw/2:ih/2 output


2、过滤器使用方法

ffmpeg的filter用起来是和Gstreamer的plugin是一样的概念,通过avfilter_link,将各个创建好的filter按自己想要的次序链接到一起,然后avfilter_graph_config之后,就可以正常使用。

FFmpeg的filter包含3个层次:filter -> filterchain -> filtergraph

filtergraph可以用文本形式表示,可以作为ffmpeg中的 -filter/-vf/-af和-filter_complex 选项以及ffplay中的- vf/-af 和libavfilter/avfilter.h中定义的avfilter_graph_parse2()函数的参数。

示例”把视频的上部分镜像到下半部分“ , 流程如下:
在这里插入图片描述
(1)使用 split filter 将输入流分割为两个流 [main] 和 [temp];
(2)其中一个流[temp]通过crop filter把下半部分裁剪掉;
(3)步骤2中的输出再经过vflip filter对视频进行垂直翻转,输出[flip];
(4)把步骤3中输出[flip]叠加到[main]的下半部分。

这个流程可以编程实现,也可以使用命令实现。命令实现如下:ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip[flip]; [main][flip] overlay=0:H/2" OUTPUT

处理结果如下:
在这里插入图片描述


3、过滤器语法

3.1 filter语法

用一个字符串描述filter的组成:
形式:[in_link_1]…[in_link_N]filter_name=parameters[out_link_1]…[out_link_M]

参数:
1)[in_link_N]、[out_link_N]:用来标识输⼊和输出的标签。in_link_N是标签名,可以任意命名,需要使用方括号括起来。在filter_name的前面的标签用于标识输入,在filter_name的后面的标签用于标识输出。一个filter可以有多个输入和多个输出,没有输入的filter称为source filter,没有输出的filter称为sink filter。对于输入或输出打标签是可选的,打上标签是为了连接其他filter时使用。

2)filter_name:filter的名称。

3) “=parameters”:包含初始化filter的参数,是可选的。有以下几种形式:

  • 使用 : 字符分隔的一个“键=值”对列表。如: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


抽取视频Y、U、V分量到不同的文件示例(extractplanes filter指定了三个输出,分别是 [y][u][v],抽取后,将不同的输出保存到不同的文件中):ffmpeg -i input.mp4 -filter_complex "extractplanes=y+u+v[y][u][v]" -map "[y]" input_y.mp4 -map "[u]" input_u.mp4 -map "[v]" input_v.mp4


3.2 filterchain的语法

用一个字符串描述filterchain的组成:
形式:"filter1, filter2, ... filterN-1, filterN"

说明:
1)由1个或多个filter的连接而成,filter之间以逗号“,”分隔。
2)每个filter都连接到序列中的前1个filter,即1个filter的输出是后1个filter的输入。比如示例(crop)


3.3 filtergraph的语法

用一个字符串描述filtergraph的组成:
形式:"filterchain1;filterchain2;...filterchainN-1;fiterchainN"

说明:
1)由1个或多个filter的组合而成,filterchain之间用分号";"分隔。
2)filtergraph是连接filter的有向图。它可以包含循环,一对filter之间可以有多个连接。
3)当在filtergraph中找到两个相同名称的标签时,将创建相应输入和输出之间的连接。
4)如果输出没有被打标签,则默认将其连接到filterchain中下1个filter的第1个未打标签的输入。

例如:以下filterchain中:nullsrc, split[L1], [L2]overlay, nullsink
说明:split filter有两个输出,overlay filter有两个输入。split的第1个输出标记为“L1”,overlay的第1个输入pad标记为“L2”。split的第1个输出将连接到overlay的第1个输入。

5)在一个filter描述中,如果没有指定第1个filter的输入标签,则假定为“In”。如果没有指定最后一个filter的输出标签,则假定为“out”。

6)在一个完整的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]”。它只有1个filter,即 split,它有1个默认的输入,即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]。有1个默认的输出。


4、过滤器主要结构体

(1)AVFilterGraph结构体
定义描述:对filter系统的整体管理;主要用于统合这整个滤波过程。

重点字段:

typedef struct AVFilterGraph {AVFilterContext **filters;unsigned nb_filters;....


(2)AVFilter
定义描述:滤波器的实现是通过AVFilter以及位于其下的结构体/函数来维护的。

重点字段:

typedef struct AVFilter {const char *name;			//overlay, Filter name. Must be non-NULL and unique among filters.const AVFilterPad *inputs;	//List of inputs, terminated by a zeroed element.const AVFilterPad *outputs;	//List of outputs, terminated by a zeroed element....

使用示例:定义filter本身的能力,拥有pads,回调函数接口定义。

AVFilter ff_vf_overlay = {.name = "overlay",.description = NULL_IF_CONFIG_SMALL("Overlay a video source on top of the input."),.preinit = overlay_framesync_preinit,.init = init,.uninit = uninit,.priv_size = sizeof(OverlayContext),.priv_class = &overlay_class,.query_formats = query_formats,.activate = activate,.process_command = process_command,.inputs = avfilter_vf_overlay_inputs,.outputs = avfilter_vf_overlay_outputs,.flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,};


(3)AVFilterContext
定义描述:一个滤波器实例,即使是同一个滤波器,在进行实际的滤波时,也会由于输入的参数不同而有不同的滤波效果,AVFilterContext就是在实际进行滤波时用于维护滤波相关信息的实体。

重点字段:

 struct AVFilterContext {const AVFilter *filter;		///< the AVFilter of which this is an instancechar *name;					///< name of this filter instanceAVFilterPad *input_pads;	///< array of input padsAVFilterLink **inputs;		///< array of pointers to input linksunsigned nb_inputs;			///< number of input padsAVFilterPad *output_pads;	///< array of output padsAVFilterLink **outputs;		///< array of pointers to output linksunsigned nb_outputs;		///< number of output padsstruct AVFilterGraph *graph; ///< filtergraph this filter belongs to 从属于哪个AVFilterGraph...
};


(4)AVFilterLink
定义描述:滤波器链,主要是用于链接相邻的两个AVFilterContext,为了实现一个滤波过程,可能会需要多个滤波器协同完成,即一个滤波器的输出可能会是另一个滤波器输入,AVFilterLink的作用是串联两个相邻的滤波器实例,形成两个滤波器之间的通道。

重点参数:

struct AVFilterLink
{AVFilterContext *src; 			///< source filterAVFilterPad *srcpad;			///< output pad on the source filteAVFilterContext *dst;			///< dest filterAVFilterPad *dstpad;			///< input pad on the dest filterstruct AVFilterGraph *graph;	//Graph the filter belongs to....
};


(5)AVFilterPad
定义描述:滤波器的输入输出端口,一个滤波器可以有多个输入以及多个输出端口,相邻滤波器之间是通过AVFilterLink来串联的,而位于AVFilterLink两端的分别就是前一个滤波器的输出端口以及一个滤波器的输入端口。

重点参数:

struct AVFilterPad
{const char *name;	//Pad name. The name is unique among inputs and among outputs,AVFrame *(*get_video_buffer)(AVFilterLink *link, int w, int h);	// Callback function to get a video buffer. AVFrame *(*get_audio_buffer)(AVFilterLink *link, int nb_samples);	//Callback function to get an audio buffer. Iint (*filter_frame)(AVFilterLink *link, AVFrame *frame);	//Filtering callback. int (*request_frame)(AVFilterLink *link);	//Frame poll callback....
}


(6)AVFilterInOut
定义描述:过滤器链输入/输出的链接列表。

重点参数:

typedef struct AVFilterInOut {/** unique name for this input/output in the list */char *name;/** filter context associated to this input/output */AVFilterContext *filter_ctx;/** index of the filt_ctx pad to use for linking */int pad_idx;/** next input/input in the list, NULL if this is the last */struct AVFilterInOut *next;} AVFilterInOut;

在AVFilter模块中定义了AVFilter结构,每个AVFilter结构都是具有独立功能的节点,如scale filter的作用就是进行图像尺寸变换,overlay filter的作用就是进行图像的叠加。

这里需要重点提的两个特别的filter:buffer和buffersink
(1)buffer:滤波器buffer代表filter graph中的源头,原始数据就往这个filter节点输入的。通过调用该滤波器提供的函数(如av_buffersrc_add_frame)可以把需要滤波的帧传输进入滤波过程。在创建该滤波器实例的时候需要提供一些关于所输入的帧的格式的必要参数(如:time_base、图像的宽高、图像像素格式等)。

(2)buffersink:一个特殊的滤波器,滤波器buffersink代表filter graph中的输出节点,处理完成的数据从这个filter节点输出。通过调用滤波器提供的函数(如av_buffersink_get_frame)可以提供出被滤波过程过滤完成后的帧。


5、主要函数

//进行滤波器注册
avfilter_register_all();// 获取FFmpeg中定义的filter,调用该方法前需要先调用avfilter_register_all();进行滤波器注册
AVFilter avfilter_get_by_name(const char name);// 往源滤波器buffer中输入待处理的数据
int av_buffersrc_add_frame(AVFilterContext ctx, AVFrame frame);// 从目的滤波器buffersink中获取处理完的数据
int av_buffersink_get_frame(AVFilterContext ctx, AVFrame frame);// 创建一个滤波器图filter graph
AVFilterGraph *avfilter_graph_alloc(void);// 创建一个滤波器实例AVFilterContext,并添加到AVFilterGraph中
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt,const char name, const char args, void *opaque,AVFilterGraph *graph_ctx);// 连接两个滤波器节点
int avfilter_link(AVFilterContext *src, unsigned srcpad,AVFilterContext *dst, unsigned dstpad);


6、滤波实例过程

step1:注册过滤器

 avfilter_register_all();//注册



step2:创建统合整个滤波过程的滤波图结构体(AVFilterGraph)

AVFilterGraph* filter_graph = avfilter_graph_alloc();



step3:获取滤波过程需要的滤波器(AVFilter)

const AVFilter *buffersrc = avfilter_get_by_name("buffer");		//AVFilterGraph的输入源
const AVFilter *buffersink = avfilter_get_by_name("buffersink");//输出滤波器
const AVFilter *myfilter = avfilter_get_by_name("myfilter");	//处理业务的滤波器



step4:创建用于维护滤波相关信息的滤波器实例(AVFilterContext)

AVFilterContext *in_video_filter = NULL;
AVFilterContext *out_video_filter = NULL;
AVFilterContext *my_video_filter = NULL;char args[512];sprintf(args,"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",in_width, in_height, AV_PIX_FMT_YUV420P,1, 25, 1, 1);
avfilter_graph_create_filter(&in_video_filter, buffersrc, "in", args,NULL, filter_graph);
avfilter_graph_create_filter(&out_video_filter, buffersink, "out", NULL, NULL, filter_graph);
avfilter_graph_create_filter(&my_video_filter, myfilter, "myfilter",NULL, NULL, filter_graph);



step5:用AVFilterLink把相邻的两个滤波实例连接起来

avfilter_link(in_video_filter, 0, my_video_filter, 0);
avfilter_link(my_video_filter, 0, out_video_filter, 0);



step6:提交整个滤波图

avfilter_graph_config(filter_graph, NULL);

http://chatgpt.dhexx.cn/article/kRF1hwKK.shtml

相关文章

【全面详解】Filter过滤器的使用

一、什么是过滤器 Filter称之为过滤器&#xff0c;是SerlvetAPI提供的一个Filter接口&#xff0c;A类实现了这个接口&#xff0c;那么A类称之为过滤器Filter。主要用户的请求&#xff08;HttpServletRequest&#xff09;进行预处理&#xff0c;也可以对服务器响应后的数据进行处…

Filter过滤器的例子与注解配置

概念 作用 创建 创建web项目 定义类实现Servlet接口&#xff0c;实现其抽象方法 配置Filter 原理 注解配置 过滤器放行 Filter的生命周期 Filter的拦截路径 Filter的拦截方式 Filter的过滤器链 概念 当访问服务器的资源时&#xff0c;过滤器可以将请求拦截下来&…

Filter 过滤器接口详解

目录 1、Filter接口描述 2、如何使用Filter接口定义一个过滤器&#xff1f; 3、Filter接口的工作原理 4、Filter、FilterChain、FilterConfig、FilterRegistration、FilterRegistration.Dynamic 接口综述 &#xff08;1&#xff09;如何使用FilterConfig接口对Filter实例进…

Filter过滤器的作用

Filter过滤器的作用 Filter的作用&#xff1a;过滤器处于客户端和服务器端资源之间&#xff0c;对所有的请求或者响应进行拦截操作Filter过滤器在开发过程中的实际运用&#xff1a;Servlet 开发和Filter开发做对比Servlet开发Filter开发 Filter的作用&#xff1a;过滤器处于客户…

Filter 过滤器的使用

目录 一、Filter简介 二、Filter使用 1、Filter 的初体验 2、Filter 的生命周期 3、FilterConfig类 4、FilterChain过滤器链 5、Filter 的拦截路径 1&#xff09;精确匹配 2&#xff09;目录匹配 3&#xff09;后缀名匹配 一、Filter简介 Filter 过滤器它是 JavaWeb…

Filter过滤器工作原理

Filter过滤器工作原理 Filter简介 Filter也称之为过滤器&#xff0c;它是Servlet技术中最激动人心的技术之一&#xff0c;WEB开发人员通过Filter技术&#xff0c;对web服务器管理的所有web资源&#xff1a;例如Jsp, Servlet, 静态图片文件或静态html文件等进行拦截&#xff0…

Filter过滤器

文章目录 FilterFilter过滤器的简单说明Filter的执行顺序 Eclipse创建简单的Filter过滤器Filter过滤不到指定路径 Filter Filter过滤器的简单说明 1.过滤器是一个驻留在服务器端的web组件&#xff0c;可以截取客户端和服务器端之间的请求与响应的信息 2.过滤器Filter是对客户…

FilterChain 过滤器链和拦截路径

Filter 过滤器 Chain 链&#xff0c;链条 FilterChain 就是过滤器链&#xff08;多个过滤器如何一起工作&#xff09; Filter 的拦截路径 精确匹配&#xff1a; <url-pattern>/target.jsp</url-pattern>以上配置的路径&#xff0c;表示请求地址必须为&#xff1…

Filter 过滤器

一、Filter 过滤器概念 ① Filter 过滤器它是 JavaWeb 的三大组件之一 三大组件分别是&#xff1a;Servlet 程序、 Listener 监听器、 Filter 过滤器 ② 他是 JavaEE 的规范&#xff0c;也就是接口 ③ 作用&#xff1a;拦截请求&#xff0c;过滤响应 拦截请求常见的应用场景有&…

filter过滤器的概念

文章目录 1. 图示2. 什么是Filter3. 代码演示4. 使用场景&#xff1a;事务处理 1. 图示 2. 什么是Filter Filter也属于Servlet规范Filter开发步骤&#xff1a;新建类实现Filter接口&#xff0c;然后实现其中的三个方法&#xff1a;init、doFilter、destroy 配置Filter&#xf…

Filter 过滤器使用

一、什么是Filter过滤器 Filter 过滤器它是 JavaWeb 的三大组件之一。 三大组件分别是&#xff1a;Servlet 程序、Listener 监听器、Filter 过滤器 Filter 过滤器它是 JavaEE 的规范。也就是接口 Filter 过滤器它的作用是&#xff1a;拦截请求&#xff0c;过滤响应。 拦截…

Filter过滤器(超详细)

声明&#xff1a;本文是根据博主学习内容所整理得的笔记&#xff0c;仅作为交流学习使用&#xff0c;需要观看视频的请移步&#xff1a;http://www.atguigu.com/ 1.Filter &#xff1f;什么是过滤器 Filter 过滤器它是 JavaWeb 的三大组件之一。 三大组件分别是&#xff1a;S…

GitHub使用教程(完整教程)

第一步&#xff1a;进入官网 &#xff08;https://github.com/&#xff09; 第二步&#xff1a;新建账号——输入用户名&#xff0c;邮箱&#xff0c; 密码——邮箱确认——登录GitHub 第三步&#xff1a;创建仓库 第三步&#xff1a;查看仓库 第四步&#xff1a;实现本地项目…

Git和Github详细入门教程(别再跟我说你不会Git和Github)

前言&#xff1a;基础差建议先观看B站视频&#xff08;关键字&#xff1a;GitHub&#xff09;&#xff0c;该教程是根据视频教程而制。 文章目录 01.Git概述02.Git的本地仓库操作 Git的版本回退操作 03.远程仓库05.Git的分支操作06.冲突的产生与解决07.Git实用功能08.忽略文件0…

GitHub Actions 入门教程

https://jiangren.com.au/blog/github-actions 一、GitHub Actions 是什么&#xff1f; 大家知道&#xff0c;持续集成由很多操作组成&#xff0c;比如抓取代码、运行测试、登录远程服务器&#xff0c;发布到第三方服务等等。GitHub 把这些操作就称为 actions。 很多操作在不…

小白入门~ GitHub和Git超详细使用教程

https://github.com/ 这是GitHub的官方网站&#xff0c;在官网上可以注册属于自己的GitHub账号&#xff0c;网上是全英文的&#xff0c;对于英语不好的同学建议使用谷歌浏览器&#xff0c;谷歌浏览器可以翻译网页变为中文使用起来十分方便。 通过简单的步骤之后你就会有一个属于…

GitHub使用教程(项目下载)

1.登录GitHub后选择左上角搜索框&#xff08;以点餐系统为例&#xff09; 2.选择合适的项目进入 3.选择合适的项目进入后&#xff0c;点击Code 4.点击Download ZIP即可下载项目代码压缩包

github使用教程图文详解(一)[入门]

git的使用和踩坑 Git的注册下载本地github工具绑定ssh秘钥获取ssh秘钥官网绑定ssh秘钥 创建远程库初始化仓库设置全局签名和单仓库签名的作用单仓库签名全局用户签名 提交到本地仓库git区域的划分提交到缓存区提交本地仓库和备注提交总结注意: 提交到远程仓库克隆远程仓库总结 …

GitHub 的 10 分钟快速入门教程

Hello World 这一篇是 GitHub 的 10 分钟快速入门教程&#xff0c;因为找不到中文版&#xff0c;大橙子自己给大家翻译了一下。 Hello World 项目是计算机编程的一个历史悠久的传统。这一篇我们也通过这个简单的练习让你学习到新的知识。那么就让我们开始 GitHub 的学习旅程吧…

【Github教程】史上最全github使用方法:github入门到精通

【初识Github】 首先让我们大家一起喊一句“Hello Github”。YEAH!就是这样。 Git是一个分布式的版本控制系统,最初由Linus Torvalds编写,用作Linux内核代码的管理。在推出后,Git在其它项目中也取得了很大成功,尤其是在Ruby社区中。目前,包括Rubinius和Merb在内的很多知名…