刘歧:FFmpeg Filter深度应用

简介: 本文来自OnVideo视频创作云平台联合创始人刘歧在LiveVideoStackCon的讲师热身分享,刘歧分享了FFmpeg的基本原理、使用方法及开发方法。在10月19-20日的LiveVideoStackCon 2018上,刘歧还将分享如何通过FFmpeg实现视频版权保护的方法。

640?wx_fmt=png


本文来自OnVideo视频创作云平台联合创始人刘歧在LiveVideoStackCon的讲师热身分享,刘歧分享了FFmpeg的基本原理、使用方法及开发方法。在10月19-20日的LiveVideoStackCon 2018上,刘歧还将分享如何通过FFmpeg实现视频版权保护的方法。


文 / 刘歧

整理 / LiveVideoStack

直播回放:

https://www.baijiayun.com/web/playback/index?classid=18081550127330&session_id=201808160&token=UpmOXagOUwZt681rrJ0J_fi3uef2YslR9xPZowdmKaIVnKE7ZcXWwkkNnUrZm8So4_FWYYdehfAKp0fXMnVKLQ


大家好我是刘歧,目前和几个朋友一起创办了视频云创作平台OnVideo,主要负责做一些新功能预研和整体方向把控。


今天主要从四个方面来介绍一下FFmpeg的滤镜深度应用:


1.  Filter基本原理

2.  Filter使用方法

3.  Filter开发基础

4.  Filter开发


一.  Filter基本原理


基本原理的理解可以从以下六点出发:


  1. 线性属性:滤镜是一个线性的属性,是一步接着一步的往下走的,当然也可以有多线程的,但是多线程的实现不是特别好,一般的实现都是通过单线程来线性处理的。

  2. 输入输出标签:滤镜都有输入和输出的标签。

  3. 滤镜名

  4. 滤镜参数:当我们在使用某一类滤镜时,需要知道对应的参数大小,如位置,宽高等。

  5. 内置变量:在使用滤镜时,可以用到它的很多内置变量,如帧率,PTS等,这些变量可以在命令行中使用,在调用API时也会用到。

  6. 压缩前、解压后的YUV/RGB/PCM数据:对数据进行滤镜处理时使用的都是原始数据,也就是未压缩的数据。


640?wx_fmt=png


线性处理图解

 

如上图所示,从滤镜线性处理图中可以看出,对每一个的滤镜处理过程必须要有输入和输出,比如在最后滤镜8的位置没有输出1来承接它的结果,则会报错。另外,如从滤镜1到滤镜2的过程,滤镜1的输出Out可以作为滤镜2的输入In,从滤镜2再往后,滤镜2的输出Out可以分为两部分,分别作为其它滤镜处理的输入。


640?wx_fmt=png


原始数据处理

 

滤镜的处理都是基于原始数据来进行的,比如视频图像的每一帧,当然也包括音频。如上图所示,每一帧可以有前后的多个层,一般情况下是两层,当有多层时,如Frame1是三层,则可以先处理前两层,处理之后合并成一层,再跟另一层一起去做处理。当处理完Frame1后送到编码器进行编码,再依次处理Frame2、Frame3、Frame4,处理完后均送到编码器进行压缩编码为另一个格式,比如H.264。


二.  Filter使用方法


1.  常用滤镜


常用的滤镜中重点的是:scale、trim、overlay、yadif、rotate、movie

比如常用的scale 可以用来做缩放,trim可以做比较精确的帧级的剪切,overlay可以来实现视频混流,画中画或多画面等叠加处理,rotate来做旋转,movie可以加载第三方的视频等等,yadif可以在摄像机上做隔行扫描,在PC端的播放器可以做去交错。另外,还有delogo、crop、colorkey、chromakey、zoompan; delogo可以用来模糊化某一区域,crop用于图像区域剪切,colorkey和chromakey是用于抠图的,chromakey以YUV输入为主,colorkey以RGB输入为主,zoompan可以将图像放大。


2.  命令行


ffmpeg -filters


640?wx_fmt=png


通过这一命令,可以列出所有的滤镜,但需要弄清楚每一个滤镜的作用,比如上图的adelay,它的作用是音频转音频,延缓一个或更多的音频通道。在滤镜参数里面还包括timeline support、slice threading、command support,等在后面也会有介绍。


ffmpeg -h filters=rotate


640?wx_fmt=png


当某个滤镜不知道它里面都有什么参数或者参数怎么用时,那么可以通过上面这条help命令去查看滤镜的内容。比如在上图,查看旋转(rotate)滤镜,可以看出它支持slice threading,而在最下面可以看到还支持timeline操作,并且输入和输出都是Video格式,再下面就是rotate的一些参数,值得注意的是,在FFmpeg里面,尤其滤镜这部分,为了让大家在输入参数时候更简单,它会把很长的参数提供一个简化的名称。


命令行的使用开头都是:filter_complex,然后再在后面接一些字符串,如下:


下面列出几个例子的命令行使用:


1.  跑马灯


 

[0:v][1:v]overlay=x='if(gte(t,0), -w+(mod(n, W+w))+5, NAN)':y=0[out]


应用场景如新闻播放时画面下方的小栏预告,从右跑到左。


2.  图像旋转


 

[1:v]rotate=a=60*PI/180:ow=180:oh=180[v1];[0:v][v1]overlay=x=-20:y=-20[o]


3.  delogo(模糊化某一区域)


 

delogo=x=72:y=32:w=168:h=86:band=1:show=1


下图为以上三条命令行处理后的展示效果:

 

640?wx_fmt=png


在FFmpeg的ffplay里可以通过dumpgraph对滤镜的处理过程增加更深的了解,可以看看下面这个例子:


 

./ffplay -dumpgraph 1 -f lavfi "movie=a.flv[l];movie=logo.png[r];[l][r]overlay=x=0:y=0"


640?wx_fmt=png


在滤镜处理的过程中是先加载第一个电影,然后再加载一张PNG图片,为了叠加处理比较方便会先将它们转换成YUV,再进行叠加运算,最后输出到一个buffersink中。


3.  API


滤镜Filter的API结构包括:

  • AVFilterContext:滤镜的上下文
  • AVFilterInOut:滤镜的输入、输出
  • AVFilterGraph:滤镜的图结构
  • AVFilter:滤镜的具体处理类
  • AVFilterPad:包括输入的Pad和输出的Pad


调用API的分为两个大的步骤:


第一步,滤镜的初始化


640?wx_fmt=png


初始化部分首先要确定In的Buffer和Out的Buffersink,接下来就是创建一个滤镜的Graph,再就是做一个滤镜的解析,最后就是通用配置。


第二步,滤镜处理


640?wx_fmt=png


滤镜处理过程是先解码,解码之后将帧加入到Buffer,再调用滤镜处理模块,处理之后输出到Buffersink。


滤镜API的使用方法跟之前命令行的使用方法是一样的,只是略微有一点差别。如果我们不会使用多输入多输出的方式,对于API的使用实际上它的输入也可以用字符串处理的方式,就是命令行里边的处理方式,如以下官方demo的代码:


跑马灯


 

[0:v][1:v]overlay=x='if(gte(t,0), -w+(mod(n, W+w))+5, NAN)':y=0[out]


640?wx_fmt=png


图像旋转


 

[1:v]rotate=a=60*PI/180:ow=180:oh=180[v1];[0:v][v1]overlay=x=-20:y=-20[o]


640?wx_fmt=png


Delogo(模糊化某一区域)

 

 

delogo=x=72:y=32:w=168:h=86:band=1:show=1


640?wx_fmt=png


从上面的介绍可以看出,命令行与API实质上并没有太大的区别。


三.  Filter开发基础


1.  Module结构


640?wx_fmt=png


在上面的Module结构里面,可以很清晰的看出步骤流程,先要在滤镜的类里面注册它所对应的所有信息,如滤镜名,上下文等等;下一步就是对Input和Output的处理,对帧的滤镜处理正常都是在一个Input里面处理的;


640?wx_fmt=png


再就是要看滤镜是否支持Timeline,比如做一些动态的变量,跑马灯之类的,也要有时间线的概念。在这个里面也有一些对应的内置函数,可以把他们理解为一些数字运算的接口。以及下面还有一些变量名的定义。


640?wx_fmt=png


2.  加入到FFmpeg中


添加滤镜的时候,主要是往下面两个里面添加:


640?wx_fmt=png  


四.  Filter开发


在这一部分,为大家做了FFMPEG添加新滤镜的过程的录像,录像地址为http://bbs.chinaffmpeg.com/add_filter.mp4,有兴趣的同学可以看一下


640?wx_fmt=png


首先建立了一个zoomscale的滤镜文件,建立完这个文件之后,创建对应的context,然后把刚才讲到的那些接口都写进来,定义zoomscale公共的类,下面我们实现了一个filter _frame,它会把里面的input给释放掉,让它变成一个NULL,此时显示的前景图像就会变成一个纯绿色的图像,如果说这里有process commode,那么就可以在做zmq的时候用,如果没有的话,可以留空。关键是filter_frame,可以当作滤镜处理的一个入口,而get_video_buffer可以把它理解为我们看到的很多demo里面写到的get_video_buffer,即创建一个帧的对应Buffer,将其添加至Makefile之后,继续添加一个avfilter。这是FFmpeg4.0之前的版本,在后面新版本里面,采用的是数组的形式,也就没有列表那么麻烦,速度会更快一些,添加完之后,可以通过config进行查看配置,每次config完之后,会有整体的一个输出。添加完成后,进行编译,之后可以在avfilter库里直接查看滤镜是否已经加到FFmpeg的应用程序里,然后调用API部分,直接把字符串传进来就可以使用了。


Q&A:


Q1:直播实时应用滤镜怎么处理?


A:只要性能跟的上就可以,比如说通过滤镜里可以添加OpenCV,或者OpenGL的方式。如果原来是直接调用OpenGL,想更加方便,在FFmpeg里进行处理的话,可以把它添加到FFmpeg的滤镜里面,实现对应的OpenGL方法,再调方法即可。


Q2:在FFmpeg里面滤镜处理都是线性的吗?


A:介绍是这样的,通过代码的演示可以看到滤镜的处理是一步一步进行的,处理完一帧,再处理下一帧。接口的调用也是如此。

相关文章
|
25天前
|
设计模式 编解码 C++
【ffmpeg 视频播放】深入探索:ffmpeg视频播放优化策略与设计模式的实践应用(一)
【ffmpeg 视频播放】深入探索:ffmpeg视频播放优化策略与设计模式的实践应用
46 0
|
25天前
|
设计模式 存储 缓存
【ffmpeg 视频播放】深入探索:ffmpeg视频播放优化策略与设计模式的实践应用(二)
【ffmpeg 视频播放】深入探索:ffmpeg视频播放优化策略与设计模式的实践应用
27 0
|
25天前
|
设计模式 编解码 算法
【ffmpeg 视频播放】深入探索:ffmpeg视频播放优化策略与设计模式的实践应用(三)
【ffmpeg 视频播放】深入探索:ffmpeg视频播放优化策略与设计模式的实践应用
28 0
|
29天前
|
人工智能 算法 物联网
声音的变奏:深入理解ffmpeg音频格式转换的奥秘与应用(二)
声音的变奏:深入理解ffmpeg音频格式转换的奥秘与应用
33 0
|
29天前
|
存储 编解码 算法
声音的变奏:深入理解ffmpeg音频格式转换的奥秘与应用(一)
声音的变奏:深入理解ffmpeg音频格式转换的奥秘与应用
45 0
案例分享:Qt+FFmpeg录屏应用(支持帧率、清晰度设置)
案例分享:Qt+FFmpeg录屏应用(支持帧率、清晰度设置)
案例分享:Qt+FFmpeg录屏应用(支持帧率、清晰度设置)
|
编解码
LiveVideoStackCon讲师热身分享 ( 八 ) —— FFmpeg的滤镜在视频编辑场景中的应用
LiveVideoStackCon 2018音视频技术大会是每年的多媒体技术人的盛宴,为了让参会者与大会讲师更多互动交流,我们推出了LiveVideoStackCon讲师热身分享第一季,在每周四晚19:30,邀请1名大会讲师进行线上分享技术干货,解答热点问题。
1393 0
|
编解码 测试技术 PHP
多媒体工具ffmpeg(音乐格式应用)
前言: 今天来了个新需求要将用户上传的高品质,无损格式的音乐转换为低码率的mp3格式。来达到试听时播放低品质mp3,下载时下载高品质的无损格式的目的。 目录: 安装ffmpeg 再服务器中测试转码 php中应用ffmpeg 1. 安装ffmpeg FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。
1305 0
ffmpeg一些filter用法、以及一些功能命令
1、加字幕          命令:ffmpeg -i  -filter_complex subtitles=filename=-y          说明:利用libass来为视频嵌入字幕,字幕是直接嵌入到视频里的硬字幕。
1600 0
|
数据安全/隐私保护 编解码
FFMPEG 最简滤镜filter使用实例(实现视频缩放,裁剪,水印等)
FFMPEG官网给出了FFMPEG 滤镜使用的实例,它是将视频中的像素点替换成字符,然后从终端输出。我在该实例的基础上稍微的做了修改,使它能够保存滤镜处理过后的文件。在上代码之前先明白几个概念:     Filter:代表单个filter     FilterPad:代表一个filter的输入或...
2679 0