【冬察冬见】FFmpeg系列学习笔记二
近期处理视频时需要剪切视频右侧的聊天区,于是对这个场景下的命令进行了深入学习,笔记如下。
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