欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【冬察冬见】FFmpeg系列学习笔记二  

程序员文章站 2022-03-04 10:09:20
...

近期处理视频时需要剪切视频右侧的聊天区,于是对这个场景下的命令进行了深入学习,笔记如下。

FFmpeg filter简介

FFmpeg filter提供了很多音视频特效处理的功能,比如视频缩放、截取、翻转、叠加等。

其中定义了很多的filter,例如以下常用的一些filter。

scale:视频/图像的缩放
overlay:视频/图像的叠加
crop:视频/图像的裁剪
trim:截取视频的片段
rotate:以任意角度旋转视频
支持的filter的列表可以通过以下命令获得。

ffmpeg -filters

以下是filter的一个简单的应用示例,对视频的宽和高减半。
ffmpeg -i input -vf scale=iw/2:ih/2 output

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()函数的参数。

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

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中,

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]。有一个默认的输出。

视频的画面大小的剪切(crop filter)

将输入的视频的帧,以左上角为坐标的原点,剪切成x,y坐标开始的指定大小。
语法:

[]包裹的选项是可选的

crop= ow[:oh[:x[:y[:keep_aspect]]]]
​#example
​ffmpeg -i input -vf crop=iw/3:ih:0:0 output
ffmpeg -i input -vf crop=iw/3:ih:iw/3:0 output
ffmpeg -i input -vf crop=iw/3:ih:iw/3*2:0 output
简单的解释:

x,y :是偏移量。
ow,oh :是输出的宽和高。
iw ih :还可以使用来表示输入的宽和高
a: 表示比例 ,和 iw/ih 一样
如果想从中间开始剪切,命令就编程了

ffmpeg -i input_file -vf crop=w:h output_file
视频的Padding(应该是增加内边距)(pad filter)

给视频添加一个内边距。通常是视频需要在不同显示比例的画面中显示时,需要的命令。
语法:

#[]中的同样是可选的#坐标系与之前相同pad=width[:height[:x[:y[:color]]]]​
#example
ffmpeg -i photo.jpg -vf pad=860:660:30:30:pink frame_photo.jpg

进一步举例:
ffmpeg -i C:\files\11.mp4 -vf crop=iw/2:ih/2 C:\files\111.mp4
将视频中间区域截取

ffmpeg -i C:\files\11.mp4 -vf crop=iw/5*4:ih:0:0 C:\files\112.mp4
将视频右侧20%部分处理掉

更常用的是将4:3的画面转换成16:9

如果不给color的话。默认将会是黑色的背景

将画面从4:3 切换成16:9

ffmpeg -i input -vf pad=ih*16/9:ih:(ow-iw)/2:0:color output

16:9 转换成 4:3

ffmpeg -i input -vf pad=iw:iw*3/4:0:(oh-ih)/2:color output
其实标准的公式如下

ar是画面的比例。如果是增加画面的宽度,则是

ffmpeg -i input -vf pad=ih*ar:ih:(ow-iw)/2:0:color output

如果是增加画面的高度,则是

ffmpeg -i input -vf pad=iw:iw*ar:0:(oh-ih)/2:color output
翻转和旋转视频(flip filter)

对视频进行翻转和旋转
语法:

#水平翻转(Horizontal flip)
-vf hfilp
#竖直翻转(Vertical flip)
-vf vfilp

旋转

#0 - 逆时针旋转+竖直翻转
#1- 顺时针旋转 90
#2- 逆时针旋转 90
#3- 顺时针旋转90 + 竖直的翻转
transpose={0,1,2,3}
模糊、锐化和其他添加噪点的滤镜

模糊滤镜

boxblur
语法:

r=radius p=powerboxblur=luma_r:luma_p[:chroma_r:chroma_p[:alpha_r:alpha_p]]

#example
ffmpeg -i input.mpg -vf boxblur = 1.5:1 output.mp4
smartblur
#t = threashold
smartblur = luma_r:luma_s:luma_t[:chroma_r:chroma_s:chroma_t]
#example
ffmpeg -i halftone.jpg -vf smartblur= 5:0.8:0 blurred_halftone.png

锐化

滤镜的名称竟然是 unsharp

语法:

l_msize_x:l_msize_y:l_amount:c_msize_x:c_msize_y:c_amount
#all parameters are optional, if not set, the default is 5:5:1.0:5:5:0.0
默认的明亮度矩阵是5x5 而明亮度(luma)的效果强度是1.0.如果想创造高斯模糊的效果的话,可以使用一个负数的明亮度或者是浓度(chroma)

#高斯模糊的效果
ffmpeg -i input -vf unsharp= 6:6:-2 output.mp4

覆盖(Overlay)

可以实现画中画的功能。这里只是简单的覆盖的实例,更加复杂的例子需要在后面的进阶单元里看到。
语法:

overlay[=x:y[[:rgb={0,1}]]

x,y是可选的。默认参数是0 # rgb 也是可选的。它的值是 0或者1

命令行的构成

ffmpeg -i input1 -i input2 -filter_complex overlay=x:y output
这里需要注意是的 filter_complex 来替代-vf,因为有两个输入源。但是如果使用flitergraph和 link labels.这样我们就可以使用 movie 视频源,囊括第二输入和使用-vf

使用 movie 和 -vf

ffmpeg -i input1 -vf movie=input2[logo];[in][logo] overlay=x:y output​#Logo in top-left corner
ffmpeg -i pair.mp4 -i logo.png -filter_complex overlay pair1.mp4

添加文字到视频上

video filter:drawtext
语法:

drawtext=fontfile = font_f:text=text1[:p3=v3[:p3=v4[…]]]​
#最简单的example就是。 此时需要注意的是,这个字体文件必须在当前目录下
ffmpeg -i input -vf drawtext=fontfile=arial.ttf:text=Welcome output
混音

amerge

ffmpeg -y -i video_bgm.mp4 -i src2.aac -filter_complex [0:a][1:a]amerge=inputs=2[a] -map 0:v -map [a] -c:v copy -c:a aac -ac 2 -shortest after_compose3.mp4
amix

ffmpeg -i test.aac -i test.mp3 -filter_complex amix=inputs=2:duration=first:dropout_transition=2 mix.aac

参数

-shortest 取最短的时长

-shortest : duration = MIN(inputs)
实例:
ffmpeg -i test.mp4 -i test.mp3 -vcodec copy -acodec aac -map 0✌️0 -map 1