(音视频学习笔记):FFmpeg 滤镜

目录

FFmpeg 滤镜

视频裁剪

文字水印

图片水印

FFmpeg 生成画中画

FFmpeg 视频多宫格处理

FFmpeg 滤镜

视频裁剪

  • 视频过滤器(滤镜) :裁剪

  • 将输入视频帧的宽度和高度从 x 和 y 值表示的位置裁剪到指定的宽度和高度。
  • x 和 y 是输出的左上角坐标,协调系统的中心是输入视频帧的左上角。
    • 对 x 的计算值(从左上角水平方向的像素个数)和 y(垂直像素的数量),对每个帧进行评估, x的默认值为(iw - ow)/2, y 的默认值为(ih - oh)/2
  • 如果使用了可选的 keep_aspect 参数,将会改变输出 SAR(样本宽比)以补偿新的 DAR(显示长宽比)
  • ow 的值可以从 oh 得到,反之亦然,但不能从 x 和 y 中得到,因为这些值是在 ow 和 oh 之后进行的。
  • x 的值可以从 y 的值中得到,反之亦然。
    • 例如,在输入框的左三、中三和右三,我们可以使用命令:
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
(1) 裁剪 100x100 的区域,起点为(12,34).
crop=100:100:12:34
相同效果:
crop=w=100:h=100:x=12:y=34

(2)裁剪中心区域,大小为 100x100
crop=100:100

(3)裁剪中心区域,大小为输入视频的 2/3
crop=2/3*in_w:2/3*in_h

(4)裁剪中心区域的正方形,高度为输入视频的高
crop=out_w=in_h
crop=in_h

(5) 裁剪偏移左上角 100 像素
crop=in_w-100:in_h-100:100:100

(6)裁剪掉左右 10 像素,上下 20 像素
crop=in_w-2*10:in_h-2*20

(7)裁剪右下角区域
crop=in_w/2:in_h/2:in_w/2:in_h/2
  • 技巧:使用ffplay查看效果,最后使用ffmpeg进行裁剪
ffplay-i input -vf crop=iw/3:ih:0:0 output
  • 在使用 FFmpeg 的 Filter 时可以使用 Filter 的时间相关的内置变量
    • FFmpeg 滤镜 filter 基本内置变量
      • t             以秒表示的时间戳,如果输入的时间是未知的则是 NAN
      • n            输入帧的顺序编号,从 0 开始
      • pos        输入帧的位置,如果未知的则是 NAN
      • w           输入视频帧的宽度
      • h            输入视频帧的高度

文字水印

  • 在视频中增加文字水印需要准备的条件比较多:
    • 需要有文字字库处理的相关文件。
    • 在编译 FFmpeg 时需要支持 FreeType、FontConfig、iconv。
    • 系统中需要有相关的字库。
  • 在 FFmpeg 中增加纯字母水印可以使用 drawtext 滤镜进行支持,下面就来看一下 drawtext 的滤镜参数,

  • 将文字的水印加在视频的左上角
ffplay -i input.mp4 -vf "drawtext=fontsize=100:fontfile=FreeSerif.ttf:text='hello world':x=20:y=20"
  • 将字体的颜色设置为绿色:fontcolor=green
ffplay -i input.mp4 -vf "drawtext=fontsize=100:fontfile=FreeSerif.ttf:text='hello world':fontcolor=green"
  • 如果想调整文字水印显示的位置,调整 x 与 y 参数的数值即可:x=400:y=200
ffplay -i input.mp4 -vf "drawtext=fontsize=100:fontfile=FreeSerif.ttf:text='hello world':fontcolor=green:x=400:y=200"
  • 修改透明度:alpha
ffplay -i input.mp4 -vf "drawtext=fontsize=100:fontfile=FreeSerif.ttf:text='hello world':fontcolor=green:x=400:y=200:alpha=0.5
  • 文字水印还可以增加一个框,然后给框加上背景颜色:box=1:boxcolor=yellow
fplay -i input.mp4 -vf "drawtext=fontsize=100:fontfile=FreeSerif.ttf:text='hello world':fontcolor=green:box=1:boxcolor=yellow"
  • 希望文字水印以本地时间作为水印内容,可以在 drawtext 滤镜中配合一些特殊用法来完成,在 text 中显示本地当前时间,格式为年月日时分秒的方式
    • text='%{localtime\:%Y\-%m\-%d %H-%M-%S}'
ffplay -i input.mp4 -vf "drawtext=fontsize=60:fontfile=FreeSerif.ttf:text='%{localtime\:%Y\-%m\-%d %H-%M-%S}':fontcolor=gree n:box=1:boxcolor=yellow"
  • 在使用 ffmpeg 转码存储到文件时需要加上 -re,否则时间不对
ffmpeg -re -i input.mp4 -vf "drawtext=fontsize=60:fontfile=FreeSerif.ttf:text='%{localtime\:%Y\-%m\-%d %H-%M-%S}':fontcolor=green:box=1:boxcolor=yellow" out.mp4
  • 在个别场景中,需要定时显示水印,定时不显示水印:enable=lt(mod(t\,3)\,1)
    • 这种方式同样可以配合 drawtext 滤镜进行处理,使用 drawtext 与 enable 配合即可,例如每 3 秒钟显示一次文字水印:
ffplay -i input.mp4 -vf "drawtext=fontsize=60:fontfile=FreeSerif.ttf:text='test':fontcolor=green:box=1:boxcolor=yellow:enable=lt(mod(t\,3)\,1)
  • 在使用 ffmpeg 转码存储到文件时需要加上-re,否则时间不对。
  • 表达式参考: http://www.ffmpeg.org/ffmpeg-utils.html 3 Expression Evaluation
    • lt(x, y) Return 1 if x is lesser than y, 0 otherwise.
    • mod(x, y) Compute the remainder of division of x by y.
  • 跑马灯效果
    • x=mod(100*t\,w):y=abs(sin(t))*h*0.7
ffplay -i input.mp4 -vf "drawtext=fontsize=100:fontfile=FreeSerif.ttf:text='helloworld':x=mod(100*t\,w):y=abs(sin(t))*h*0.7"
  • 修改字体透明度,修改字体颜色:enable=lt(mod(t\,3)\,1)
ffplay -i input.mp4 -vf "drawtext=fontsize=40:fontfile=FreeSerif.ttf:text='liaoqingfu':
x=mod(50*t\,w):y=abs(sin(t))*h*0.7:alpha=0.5:fontcolor=white:enable=lt(mod(t\,3)\,1)"

图片水印

  • 为视频添加图片水印可以使用 movie 滤镜
  • FFmpeg movie 滤镜的参数
参数 类型 说明
filename 字符串 输入的文件名,可以是文件,协议,设备
format_name, f 字符串 输入的封装格式
stream_index, si 整数 输入的流索引编号
seek_point, sp 浮点数 Seek 输入流的时间位置
streams, s 字符串 输入的多个流的流信息
loop 整数 循环次数
discontinuity 时间差值 支持跳动的时间戳差值
  • 案例:
ffmpeg -i input.mp4 -vf "movie=logo.png[watermark];[in][watermark]overlay=x=10:y=10[out]" output.mp4
  • 原始视频文件路径: input.mp4
  • 水印图片路径: logo.png
  • 水印位置: (x,y)=(10,10)<=(left,top)距离左侧、顶部各 10 像素;
  • 输出文件路径: output.mp4
    • main_w            视频单帧图像宽度
    • main_h             视频单帧图像高度
    • overlay_w        水印图片的宽度
    • overlay_h         水印图片的高度
  • 对应地可以将 overlay 参数设置成如下值来改变水印图片的位置:
    • 水印图片位置           overlay 值
    • 左上角                     10:10
    • 右上角                     main_w-overlay_w-10:10
    • 左下角                    10:main_h-overlay_h-10
    • 右下角                     main_w-overlay_w-10:main_h-overlay_h-10

  • 在 FFmpeg 中加入图片水印有两种方式:
    • 一种是通过 movie 指定水印文件路径
    • 一种方式是通过filter 读取输入文件的流并指定为水印,这里重点介绍如何读取 movie 图片文件作为水印
  • 图片 logo.png 将会打入到 input.mp4 视频中, 显示在 x 坐标 50、 y 坐标 20 的位置
ffplay -i input.mp4 -vf "movie=logo.png[logo];[in][logo]overlay=50:10[out]"
  • 由于 logo.png 图片的背景色是白色,所以显示起来比较生硬,如果水印图片是透明背景的,效果会更好,下面找一张透明背景色的图片试一下
ffplay -i input.mp4 -vf "movie=logo2.png[watermark];[in][watermark]overlay=50:10[out]"
  • 显示位置
ffplay -i input.mp4 -vf "movie=logo.png[watermark];[in][watermark]overlay=10:10[out]"

ffplay -i input.mp4 -vf "movie=logo.png[watermark];[in][watermark]overlay=main_w-overlay_w-10:10[out]"

ffplay -i input.mp4 -vf "movie=logo.png[watermark];[in][watermark]overlay=10:main_h-overlay_h-10[out]"

ffplay -i input.mp4 -vf "movie=logo.png[watermark];[in][watermark]overlay=main_w-overlay_w-10:main_hoverlay_h-10[out]"
  • 跑马灯效果:overlay=x=mod(50*t\,main_w):y=abs(sin(t))*h*0.7[out]
ffplay -i input.mp4 -vf "movie=logo.png[watermark];[in][watermark]overlay=x=mod(50*t\,main_w):y=abs(sin(t))*h*0.7[out]"

FFmpeg 生成画中画

  • 使用 FFmpeg 处理流媒体文件时,有时需要使用画中画的效果。
  • 在 FFmpeg 中,可以通过 overlay 将多个视频流、多个多媒体采集设备、多个视频文件合并到一个界面中,生成画中画的效果。
  • 在前面的滤镜使用中,以至于以后的滤镜使用中,与视频操作相关的处理,大多数都会与 overlay 滤镜配合使用,尤其是用在图层处理与合并场景中,下面就来了解一下 overlay 的参数,
参数 类型 说明
x 字符串 坐标
y 字符串 坐标
eof_action 整数
  • 遇到 eof 表示时的处理方式,默认为重复
    • repeat(值为 0):重复前一帧
    • endcall(值为 1):停止所有的流
    • pass(值为 2):保留主图层
shortest 布尔 终止最短的视频时全部终止(默认 false)
format 整数
  • 设置 output 的像素格式,默认为 yuv420
    • yuv420 (值为 0)
    • yuv422 (值为 1)
    • yuv444 (值为 2)
    • rgb (值为 3)
  • 从参数列表中可以看到,主要参数并不多,但实际上在 overlay 滤镜使用中,还有很多组合的参数可以使用,可以使用一些内部变量,例如 overlay 图层的宽、高、坐标等。

  • 显示画中画效果
ffplay -i input.mp4 -vf "movie=sub_320x240.mp4[sub];[in][sub]overlay=x=20:y=20[out]"

ffplay -i input.mp4 -vf "movie=sub_320x240.mp4[sub];[in][sub]overlay=x=20:y=20:eof_action=1[out]"

ffplay -i input.mp4 -vf "movie=sub_320x240.mp4[sub];[in][sub]overlay=x=20:y=20:shortest =1[out]
  • 缩放子画面尺寸:scale=640x480
ffplay -i input.mp4 -vf "movie=sub_320x240.mp4,scale=640x480[sub];[in][sub]overlay=x=20:y=20[out]"
  • 跑马灯
ffplay -i input.mp4 -vf "movie=sub_320x240.mp4[test];[in][test]overlay=x=mod(50*t\,main_w):y=abs(sin(t))*main_h*0.7[out]"

FFmpeg 视频多宫格处理

  • 视频除了画中画显示,还有一种场景为以多宫格的方式呈现出来,除了可以输入视频文件,还可以输入视频流、采集设备等。
  • 从前文中可以看出进行视频图像处理时, overlay 滤镜为关键画布,可以通过 FFmpeg建立一个画布,也可以使用默认的画布。
  • 如果想以多宫格的方式展现,则可以自己建立一个足够大的画布,下面就来看一下多宫格展示的例子:
ffmpeg -i 1.mp4 -i 2.mp4 -i 3.mp4 -i 4.mp4 -filter_complex "nullsrc=size=640x480[base];
[0:v] setpts=PTS-STARTPTS,scale=320x240[upperleft];
[1:v]setpts=PTS-STARTPTS,scale=320x240[upperright];
[2:v]setpts=PTS-STARTPTS, scale=320x240[lowerleft];
[3:v]setpts=PTS-STARTPTS,scale=320x240[lowerright];
[base][upperleft]overlay=shortest=1[tmp1];
[tmp1][upperright]overlay=shortest=1:x=320[tmp2];
[tmp2][lowerleft]overlay=shortest=1:y=240[tmp3];
[tmp3][lowerright]overlay=shortest=1:x=320:y=240" out.mp4
  • 1.2.3.4.mp4 为文件路径, out.MP4 为输出文件路径,通过 nullsrc 创建 overlay 画布,画布大小 640:480,使用[0:v][1:v][2:v][3:v]将输入的 4 个视频流去除,分别进行缩放处理,然后基于 nullsrc 生成的画布进行视频平铺,命令中自定义 upperleft,upperright,lowerleft,lowerright 进行不同位置平铺。

  • 只叠加左上右上的命令:
ffmpeg -i 1.mp4 -i 2.mp4 -i 3.mp4 -i 4.mp4 -filter_complex "nullsrc=size=640x480[base];[0:v]setpts=PTSSTARTPTS,scale=320x240[upperleft];[1:v]setpts=PTSSTARTPTS,scale=320x240[upperright];[base][upperleft]overlay=shortest=1[tmp1];[tmp1][upperright]overlay=sho
rtest=1:x=320" out2.mp4

猜你喜欢

转载自blog.csdn.net/baidu_41388533/article/details/112402753