[时间:2016-08] [状态:Open]
[关键词:FFmpeg, filter, filter graph,命令行]
FFmpeg中的libavfilter提供了一整套的基于filter的机制。filter本身是一个插件的形式,可以快速的组装需要的效果。
比如下面的filter,可以实现视频的水平镜像效果。
ffplay.exe sample.rmvb -vf hflip
FFmpeg定义的libavcodec接口已经成为在编解码领域的事实上的行业标准。但音视频filter并没有类似的标准,多个不同的多媒体项目(比如MPlayer、Xine、GStreamer等)都实现了自定义的filter系统。为了统一filter库API接口,FFmpeg提出了参考DirectDraw实现了高质量、高效、灵活的音视频filter接口。详细的文档资料可以参考FFmpeg filter。
本部分资料参考filter-def
filter可以翻译成过滤器,滤波器。物理概念上,常见的过滤器跟净化器概念重复,比如滤水器、空气净化器等。
按照处理数据的类型,通常多媒体的filter分为:
另一种按照处于编解码器的位置划分:
FFmpeg中filter分为:
除了source和sink filter,其他filter都至少有一个输入、至少一个输出。
介绍了这么多,下面也是一个例子,使用filter实现宽高减半显示:
ffplay.exe sample.rmvb -vf scale=iw/2:ih/2
下面是使用mptestsrc
的source filter作为ffplay输入,直接显示:
ffplay -f lavfi mptestsrc=t=dc_luma
ffplay -f lavfi life=s=300x200:mold=10:r=60:ratio=0.1:death_color=#C83232:life_color=#00ff00,scale=1200:800:flags=16
FFmpeg filter可以认为是一些预定义的范式,可以实现类似积木的多种功能的自由组合。每个filter都有固定数目的输入和输出,而且实际使用中不允许有空悬的输入输出端。使用文本描述时我们可以通过标识符指定输入和输出端口,将不同filter串联起来,构成更复杂的filter。这就形成了嵌套的filter。当然每个filter可以通过ffmpeg/ffplay命令行实现,但通常filter更方便。
ffmpeg.exe、ffplay.exe能够通过filter处理原始的音视频数据。ffmpeg将filtergraph分为simple filtergraph和complex filtergraph。通常simple filtergraph只有一个输入和输出,ffmpeg命令行中使用-vf
、-af
识别,基本原理图如下:
_________ ______________ | | | | | decoded | | encoded data | | frames |\ _ | packets | |_________| \ /||______________| \ __________ / simple _\|| | / encoder filtergraph | filtered |/ | frames | |__________|
complex filtergraph,通常是具有多个输入输出文件,并有多条执行路径;ffmpeg命令行中使用-lavfi
、-filter_complex
,基本原理图如下:
_________| || input 0 |\ __________|_________| \ | | \ _________ /| output 0 | \ | | / |__________| _________ \| complex | /| | | |/| input 1 |---->| filter ||_________| | | \ __________ /| graph | \ | | / | | \| output 1 | _________ / |_________| |__________|| | /| input 2 |/|_________|
第三部分会介绍filtergraph的基本语法和构成。
在libavfilter, 一个filter可以包含多个输入、多个输出。下图是一个filtergraph的示例:
[main]input --> split ---------------------> overlay --> output | ^ |[tmp] [flip]| +-----> crop --> vflip -------+
上图中filtergraph将输入流分成两个流,其中一个通过crop filter和vflip filter,然后通过overlay filter将这两个流合成一个流输出。这个filtergraph可以用下面命令行表示:
ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT
FFmpeg中filter包含三个层次,filter->filterchain->filtergraph。具体可以参考下图:
filter是ffmpeg的libavfilter提供的基础单元。在同一个线性链中的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处于同一个线性链,split、overlay位于另一个线性链。二者连接通过命名的label实现(位于中括号中的是label的名字)。在上例中split filter有两个输出,依次命名为[main]和[tmp];[tmp]作为crop filter输入,之后通过vflip filter输出[flip];overlay的输入是[main]和[flilp]。如果filter需要输入参数,多个参数使用冒号分割。
对于没有音频、视频输入的filter称为source filter,没有音频、视频输出的filter称为sink filter。
FFmpeg支持的所有filter可以通过filters查看。
这里选几个相对经典的filter。
adelay
filteradelay=1500|0|500
,这个例子中实现第一个声道的延迟1.5s,第三个声道延迟0.5s,第二个声道不做调整。aecho
filteramerge
filterashowinfo
filterpan
filterpan=1c|c0=0.9*c0+0.1*c1
,实现立体声到单声道的变换;pan="5.1| c0=c1 | c1=c0 | c2=c2 | c3=c3 | c4=c4 | c5=c5"
。silencedetect
和silenceremove
filtervolume
和volumedetect
filteraevalsrc
filter按照特定表达式生成音频信号。anullsrc
filter生成特定的原始音频数据,用于模板或测试。anoisesrc
filter生成噪声音频信号。sine
filter生成正弦波音频信号。abuffersink
filter和anullsink
filter,这些filter只是用于特定情况下结束filter chain。blend
和tblend
filtercrop
filterdrawbox
、drawgrid
、drawtext
filteredgedetect
filterfps
filterhflip
、vflip
filterhistogram
filternoise
filteroverlay
filterpad
filterrotate
filterscale
filtershowinfo
filtersubtitles
filterthumbnail
filtertranspose
filtercellatuo
、coreimagesrc
、mptestsrc
、life
等filter,具体效果建议参考ffmpeg用户手册。buffersink
、nullsink
两个filter。ahistogram
filterconcat
filtermetadata
、ametadata
filtersetpts
、asetpts
filtershowfreqs
、showspectrum
、showspertrumpic
、showvolume
、showwaves
filtersplit
、asplit
filtermovie
、amovie
filter。从movie容器中读取音频或者视频帧。FFmpeg提供了很多有趣的filter实例,详见Fancy Filtering Examples。
我们这里先从几个简单的实例开始。
将输入缩小宽度缩小一半,并保持宽高比。
ffmpeg -i input.jpg -vf scale=iw/2:-1 output.jpg
先将输入去交织,然后减半显示。
以下三个命令是等价的。
# 2 chains form, one filter per chain, chains linked by the [middle] pad
ffmpeg -i input -vf [in]yadif=0:0:0
[middle];[middle]scale=iw/2:-1[out] output# 1 chain form, with 2 filters in the chain, linking implied
ffmpeg -i input -vf [in]yadif=0:0:0
,scale=iw/2:-1[out] output# the input and output are implied without ambiguity
ffmpeg -i input -vf yadif=0:0:0
,scale=iw/2:-1 output
这个实例主要说明下filtergraph使用。命令行如下:
./ffmpeg -f lavfi -i testsrc -f lavfi -i testsrc -f lavfi -i testsrc -f lavfi -i testsrc -filter_complex "[0:v]pad=iw*2:ih*2[a]; [1:v]negate[b]; [2:v]hflip[c]; [3:v]edgedetect[d]; [a][b]overlay=w[x]; [x][c]overlay=0:h[y]; [y][d]overlay=w:h[out]" -map "[out]" -c:v ffv1 -t 5 multiple_input_grid.avi
联系客服