FFmpeg滤镜使用

  滤镜(filter)详细介绍参考官方文档主要使用了libavfilter库进行音视频处理。

  常用的滤镜功能,像图像加水印/字幕、去logo、图形旋转缩放等,但滤镜不仅仅包括视频部分,还包括音频处理的,像变声变调、声场控制(重低音/留声机/摇滚等效果)。

  下面介绍滤镜类中常用命令,该博文长期更新。

Key1. 去除水印

  该需求实现分为两步:step1.确认水印位置和效果;step2.位置和效果反复调整合适了,再转码。

  step1. ffplay -i Tuesday00.mp4 -vf delogo=x=30:y=40:w=350:h=60:show=1,scale=640x480

  其中,参数"-vf"指视频的滤镜处理(video filter),后面跟参数(水印区域:x/y/w/h,是否圈住区域:show,缩放处理:scale),注意各子处理模块间(delogo与scale)用"逗号"分隔,子处理模块内的各参数用“冒号”分割。

   如果不想缩放处理,但是视频w/h太大了,以至于超出了显示器显示区域的范围,可以控制播放窗口的大小。使用-x或-y指定播放窗口的宽或高。

  step2. ffmpeg -i Tuesday00.mp4 -vf delogo=x=30:y=40:w=350:h=60:show=0,scale=640x480 -c:v libx264 -c:a copy output.mp4

  尝试了多次,确定好区域后,可以进行转码了。注意一点,show要关掉(show=0,否则delogo区域出现绿框),video转码参数(-c:v libx264)可以不带,系统默认使用x264编码。

Key2. 去除某个时间段的水印

  在上面Key2.step2命令中增加时间控制信息: -ss 5 -t 10(从第5秒开始,持续10s,共10秒钟长的视频)

       ffmpeg -i Tuesday00.mp4 -ss 5 -t 10 -vf delogo=x=30:y=40:w=350:h=60:show=0,scale=640x480 -c:v libx264 -c:a copy output.mp4

  注意:“-ss 5 -t 10”参数,对于ffmpeg来说,放在input_file前和后貌似没什么差别,都是转成10秒钟长度的视频文件。

  另外一点增强型需求:假如有多个时间段需要去除水印,例如,第0-15秒之间某个区域需要去除,还有20-30秒之间的另外一个区域水印去除。

  这个需求的方法还没找到,有知道的同学们麻烦告知一下。目前我使用了比较笨的方法,就是多次转码。

Key3.  同时去除多个区域的水印

  在Key1中的step1命令中再增加一个delogo参数,即命令为:ffplay -i Tuesday00.mp4 -vf delogo=x=30:y=40:w=350:h=60:show=1,delogo=x=230:y=240:w=350:h=60:show=1 -y 300

  确定好位置后,再用ffmpeg转码:ffmpeg -i Tuesday00.mp4 -vf delogo=x=30:y=40:w=350:h=60:show=1,delogo=x=230:y=240:w=350:h=60:show=1 output.mp4

Key4.  添加文字水印

  与Key1类型,先用ffplay确认位置和效果,再用ffmpeg进行滤镜+转码。

       step1. ffplay -i Tuesday00.mp4 -vf "drawtext=fontfile=msyh.ttc:text='Hello,world':x=30:y=60:fontsize=120:fontcolor=yellow"

  注意,本地的字体文件(fontfile=msyh.ttc)可以不指定,找不到了用系统使用默认的。

  step2. ffmpeg -i Tuesday00.mp4 -vf "drawtext=fontfile=msyh.ttc:text='Hello,world':x=30:y=60:fontsize=120:fontcolor=yellow" output.mp4

Key5. 给视频添加封面

  其实是将指定图片作为视频的前几帧(只指定为第一帧时,有的平台可能不使用首帧作为缩略图则达不到效果)。核心思想是,图片转为包含若干帧图像的视频流,再跟主视频合并。

  step1. ffmpeg.exe -r 25 -loop 1 -i img.jpg -vcodec libx264 -s 720x1280 -frames 25 -r 25 img_25f.mp4

  其中,参数"-r 25 -loop 1"代表以25fps速度反复读取输入文件。参数"-frames 25"指只编码25帧,"-r 25"指定输出文件帧率为25fps。那么命令结果是,生成了1秒钟的视频文件(用工具分析文件,会发现:第一帧的关键帧size较大,后面的B/P帧非常小,只有几十Bytes大小,因为h264编码p或b帧时,使用的帧间编码技术,参考了第一帧I帧内容编码而来)。

  step2. ffmpeg -f concat -i concat.txt -c copy output.mp4

  其中,参数"-f concat"指视频合并;参数"-i concat.txt"指定输入文件列表,如下格式:

file input1.mp4

file input2.mp4

  注意:如果合并时出现如下异常:[concat @ 0x2690e00] DTS 4079 < 8156 out of order0:02:43.12 bitrate= 676.2kbits/s

  可以这样做:把两个mp4视频分别抽取出裸流,保存为两个独立的h264文件,再合并,这样就不会出现合并时的dts异常问题了(因为裸码流根本没有pts/dts)。

  抽取出裸码流命令为:命令为:ffmpeg -i input.mp4 -c:v copy -an output.mp4

Key6. 将视频放在黑板上

  另外一种说法是,将视频放在幕布上。

  ffmpeg -i input.mp4 -vf pad=720:1280:100:200:black output.mp4

  其中,参数"pad=720:1280:100:200"指定了幕布的宽/高以及视频(左上角)放置在该幕布中的位置(如果放在幕布左上角,参数为pad=720:1280:0:0),参数"black"指定了幕布的颜色。

  另外一点需注意,输入视频size不能超过了幕布size,否则出错(Padded dimensions cannot be smaller than input dimensions.),但允许视频(经过变换后)右下角坐标超过幕布右下角坐标。

Key7. 视频等比例缩放后置于幕布上

  目标与上面的类似,但有一些差异:Key6中的视频宽度和高度可能都小于幕布size,导致使用滤镜后得到的视频,四个周边都有黑框,而本条目标是将视频宽度缩放到幕布的宽度,再贴到幕布上,留下只有上面和下面是黑色的电影效果。

  ffmpeg -i input.mp4 -vf "scale=720:(ih*720/iw),pad=720:1280:0:(1280-(ih*720/iw))/2:black" -y output.mp4  // 将视频等比例缩放到720的宽度,再贴到幕布(720x1280)中央。

  ffmpeg -i input.mp4 -vf "scale=720:(ih*ow/iw),pad=720:1280:0:(oh-(ih*ow/iw))/2:black" -y output.mp4       //上条命令的简写,其中iw、ih指输入(input.mp4文件)的宽高,ow、oh指(pad——幕布)输出的宽高。

  注意一点,如果在视频在幕布上超出了幕布的宽或高,则视频在宽(x轴、水平方向)或高(y轴、垂直方向)方向上会自动居中对齐,因此参数"(oh-(ih*ow/iw))/2"用来手动指定垂直方向上居中对齐略有些复杂,可以也不用写这么复杂,例如直接写成"oh"或"-1",就会自动上下居中了。

Key8. 滚动的字幕

  类似于点视台放的电视剧下面的流动广告或通知。

  ffmpeg -i input.mp4 -vf "drawtext=text='李公公给老佛爷讲段子': y=10:x=(mod(5*n\,w+tw)-tw):fontsize=60:fontcolor=yellow:shadowy=10" -y output.mp4

  其中,drawtext的参数"y=10:x=(mod(5*n\,w+tw)-tw)"为字幕(的首字)的位置:始终固定在同一个高度上,但水平方向上是移动的,n指第几帧图像,5*n指移动速度(5pix/f),符号“”用于指示后面的特殊符号“,”,w/h指输入视频的宽高,tw指总字宽(fontsize控制,即字数x字体宽fontsize),mod指数学上的求余。因此,经计算后该position范围为[-tw, w],效果为:一排字从视频左端开始显现,到视频右边消失,之后再从左边显现,呈现出循环显示的特点。

  参数"shadowy=10"指阴影在垂直方向上的偏移距离。

  注意一点,中文字体的fontsize跟视频size是匹配的,但是英文字体不是匹配的。简单说来,如果视频宽为600,字体fontsize=60,那么中文字符串如果有10个字,则恰好铺满视频宽度,如果是英文字符串,则需要更多字才能铺满视频宽度。

Key9. 视频裁剪(crop)处理

  该需求类似于,一张纸片或布,只需要中间的一部分(矩形区域),其他区域都裁掉不要。

  ffmpeg -i input.mp4 -vf crop=1280:720:0:0 output.mp4

  其中,crop的参数格式为w:h:x:y,w、h为输出视频的宽和高,x、y标记输入视频中的某点,将该点作为基准点,向右下进行裁剪得到输出视频。如果x y不写的话,默认居中剪切。

Key10. 添加居中字幕,字体缩小后再放大

  先用ffplay验证效果,再使用ffmpeg转码(转码命令略,后续只给出ffplay的命令)。  

  ffplay -i input.mp4 -vf drawtext=text='hello\,world':x=(w-text_w)/2:y=(h-text_h)/2:fontsize=abs((300-2*n)):fontcolor=yellow:fix_bounds=1

Key11. 四窗口画面,只使用两个窗口显示视频

  ffplay -i Tuesday02.mp4 -vf "split [main][tmp]; [main] scale=iw/2:ih/2 [a]; [tmp] scale=iw/2:ih/2, pad=iw*2:ih*2:iw:0:black [b]; [b][a] overlay=0:H/2"

  注意:参数"overlay=0:H/2",由于两个输入视频,不能使用iw或ih,因为不知道使用哪个的,而用大写的W/H表示第一个(主)的宽/高,小写的w/h表示第二个(次)的宽/高。

  显示效果如下:

  

原文地址:https://www.cnblogs.com/Dreaming-in-Gottingen/p/13894450.html