2021-03-16

ffmpeg gl-transitions 图片合成视频 转场特效

参考 https://github.com/transitive-bullshit/ffmpeg-gl-transition

插件本身支持 GPU 加速功能,需要用到 EGL 安装模式,本案例没有使用 EGL,部署环境为 Ubuntu 18.04

注意0:按照 git 教程来反正我的 Ubuntu 是死活启动失败,报如下错误,最后按照 Dockerfile 来安装才可以正常运行,花费了好长时间,告诫需要的朋友们。
 

[AVFilterGraph @ 0x55c5007bc180] Error initializing filter 'gltransition'
Error initializing complex filters.
Operation not permitted

注意1:如果是在没有显示设备的服务器上安装运行,需要安装xvfb,然后在 ffmpeg 的执行命令前加xvfb-run -a -s '+iglx -screen 0 1920x1080x24',该命令的具体含义参考四、docker 环境下的开发

一、安装环境

$ sudo apt-get -y update && apt-get -y upgrade
$ sudo apt-get -y install gcc g++ make xorg-dev pkg-config \
libglew2.0 libglew-dev libglfw3-dev \
nasm yasm libx264-dev libx265-dev libvpx-dev libglu1-mesa-dev \
libmp3lame-dev libopus-dev libfdk-aac-dev

二、安装 ffmpeg 和转场特效过滤器 ffmpeg-gl-transition

$ cd ~
$ git clone https://github.com/transitive-bullshit/ffmpeg-gl-transition.git
$ cd ffmpeg-gl-transition
$ git clone https://github.com/gl-transitions/gl-transitions.git
$ cd ..
$ wget https://www.ffmpeg.org/releases/ffmpeg-4.2.2.tar.gz
$ tar -zxvf ffmpeg-4.2.2.tar.gz
$ grep -v "define GL_TRANSITION_USING_EGL" \
ffmpeg-gl-transition/vf_gltransition.c > \
ffmpeg-4.2.2/libavfilter/vf_gltransition.c
$ cd ffmpeg-4.2.2/
$ git apply ../ffmpeg-gl-transition/ffmpeg.diff
$ ./configure \
--enable-libx264 \
--enable-libx265 \
--enable-libvpx  \
--enable-libfdk-aac \
--enable-libmp3lame \
--enable-libopus \
--enable-nonfree \
--enable-gpl \
--enable-opengl \
--enable-filter=gltransition \
--extra-libs='-lGLEW -lglfw -ldl'
$ make -j
$ sudo make install
$ sudo apt-get -y install xvfb

查看 ffmpeg 是否安装成功:

ffmpeg

三、图片合成带转场效果视频

1、图片合成视频,指定转场时间和转场特效

$ ffmpeg \
-t 1 -loop 1 -i input0.jpg \
-t 1 -loop 1 -i input1.jpg \
-filter_complex \
"gltransition=offset=0.5:duration=0.5:source=/home/jl/ffmpeg-gl-transition/gl-transitions/transitions/crosswarp.glsl" \
-y out.mp4

参数:

-t
图片转为视频的持续时间
-loop
图片循环,如果设置为1,则循环输入,预设值为0。
-i
输入图片
-t 1 -loop 1 -i input0.jpg
整体意思即为图片循环生成持续1秒的视频
-filter_complex
过滤器
gltransition
指定使用 ffmpeg-gl-transitions 的过滤器
offset
(浮点型,默认 0)指定转场效果在 0.5s 开始
duration
(浮点型,默认 1)转场效果持续时间
source
转场效果指定的文件的路径,注意一定要使用全路径,~ 路径识别不了,转场文件可以从 gl-transitions 获取,如果不指定 source,则转场效果为默认的淡入淡出效果。
-y
如果输出文件已存在则覆盖
注意: 该表达式只是一个简单的事例,合成视频的时长为第二个视频的时长。

 

2、多图片合成带音乐的、时长叠加的视频

$ ffmpeg -hide_banner \
-t 3 -loop 1 -i input0.jpg \
-t 3 -loop 1 -i input1.jpg \
-t 2 -loop 1 -i input2.jpg \
-stream_loop -1 -i music.mp3 -acodec aac \
-filter_complex "\
[0]split[v_sp_0_0][v_sp_0_1];[v_sp_0_0]trim=0:2[v_tr_0_0];[v_sp_0_1]trim=2:3[v_tr_0_1];[v_tr_0_1]setpts=PTS-STARTPTS[v_st_0];\
[1]split[v_sp_1_0][v_sp_1_1];[v_sp_1_0]trim=0:2[v_tr_1_0];[v_sp_1_1]trim=2:3[v_tr_1_1];[v_tr_1_1]setpts=PTS-STARTPTS[v_st_1];\
[v_st_0][v_tr_1_0]gltransition=duration=1:source=/home/jl/ffmpeg-gl-transition/gl-transitions/transitions/SimpleZoom.glsl[v0];\
[v_st_1][2]gltransition=duration=1:source=/home/jl/ffmpeg-gl-transition/gl-transitions/transitions/CrossZoom.glsl[v1];\
[v_tr_0_0][v0][v1]concat=n=3[v];\
afade=t=out:st=5:d=2" \
-map "[v]" \
-map "3:a" \
-t 7 \
-shortest \
-c:v libx264 \
-profile:v main \
-pix_fmt yuv420p \
-preset fast \
-y \
out.mp4

参数:

-hide_banner
所有 FFmpeg 工具通常都会显示版权声明,构建选项和库版本,此选项可用于禁止打印此信息。
-stream_loop
输入流循环的次数,0 表示无循环,-1 表示无限循环,即音乐循环播放。
-acodec aac
设置音频编解码为 acc 模式
[0]split[v_sp_0_0][v_sp_0_1];[v_sp_0_0]trim=0:2.0[v_tr_0_0];[v_sp_0_1]trim=2.0:3[v_tr_0_1];[v_tr_0_1]setpts=PTS-STARTPTS[v_st_0]
将第一个视频拆分为 0-2s 和 2s-3s 两个视频;帧是从每个输入视频按时间戳顺序获取的,因此,如果它们的初始时间戳不同,则最好将两个输入通过 setpts = PTS-STARTPTS 过滤器传递,以使它们以相同的0时间戳开始,即为了让 2s-3s 的视频和第二个视频合并作为转场视频,需要将 2s-3s 视频的初始时间戳设为 0。
[v_st_0][v_tr_1_0]gltransition=duration=1:source=/home/jl/ffmpeg-gl-transition/gl-transitions/transitions/SimpleZoom.glsl[v0]
将第一个视频拆分出来的 2s-3s 的视频与第二个视频的初始视频合并生成时长 1s 的转场视频。
[v_tr_0_0][v0][v1]concat=n=3[v]
合并视频为一个完整的输出视频
afade=t=out:st=5:d=2
设置从 5s 开始,持续 2s 的音乐淡出效果。转场时间会合并到下一个视频的初始时间中,所以合成视频的时长为 2+2+2=6s,视频在播放时最后 1-2s 通常就黑屏了,所以视频时长加 1s。
-map "[v]"
将合成的视频输入流 v 指定为输出文件的源
-map "3:a"
将第四个文件作为视频音频文件
-t 7
输出视频时长为 7s
shortest
最短的输入流结束时,完成编码。
-c:v libx264
输出视频编码格式
-profile:v main
指定视频画质,baseline:基本画质,extended:进阶画质,main:主流化之,high:高级画质。
-pix_fmt yuv420p
设置像素格式为 yuv420p
-preset fast
调节编码速度和质量的平衡,有ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow、placebo这10个选项,编码速度从快到慢,视频质量越来越好。

3、合成带背景图的视频

如上背景图为 1080x1920 尺寸的,中间的透明区域为 1080x720 的,当我们需要将上面的图片合成的视频以如下背景图作为背景的时候,那么我们的视频尺寸就必须缩放为 1080x720 的视频,我们当然可以通过 -s 1080x720 来缩放上面生成的视频,但是会存在视频变形的情况,我们可以通过如下命令来等比例缩放图片从而一步到位生成带背景的视频。
 

$ ffmpeg -hide_banner \
-t 3 -loop 1 -i input0.jpg \
-t 3 -loop 1 -i input1.jpg \
-t 2 -loop 1 -i input2.jpg \
-i bg.png \
-stream_loop -1 -i music.mp3 -acodec aac \
-filter_complex "\
[0]scale=min(iw*720/ih\,1080):min(720\,ih*1080/iw),pad=1080:720:(1080-iw)/2:(720-ih)/2[p0];\
[1]scale=min(iw*720/ih\,1080):min(720\,ih*1080/iw),pad=1080:720:(1080-iw)/2:(720-ih)/2[p1];\
[2]scale=min(iw*720/ih\,1080):min(720\,ih*1080/iw),pad=1080:720:(1080-iw)/2:(720-ih)/2[p2];\
[p0]split[v_sp_0_0][v_sp_0_1];[v_sp_0_0]trim=0:2[v_tr_0_0];[v_sp_0_1]trim=2:3[v_tr_0_1];[v_tr_0_1]setpts=PTS-STARTPTS[v_st_0];\
[p1]split[v_sp_1_0][v_sp_1_1];[v_sp_1_0]trim=0:2[v_tr_1_0];[v_sp_1_1]trim=2:3[v_tr_1_1];[v_tr_1_1]setpts=PTS-STARTPTS[v_st_1];\
[v_st_0][v_tr_1_0]gltransition=duration=1:source=/home/jl/ffmpeg-gl-transition/gl-transitions/transitions/SimpleZoom.glsl[v0];\
[v_st_1][p2]gltransition=duration=1:source=/home/jl/ffmpeg-gl-transition/gl-transitions/transitions/CrossZoom.glsl[v1];\
[v_tr_0_0][v0][v1]concat=n=3[out];\
[3][out]overlay=0:600[v];\
afade=t=out:st=5:d=2" \
-map "[v]" \
-map "4:a" \
-t 7 \
-shortest \
-c:v libx264 \
-profile:v main \
-pix_fmt yuv420p \
-preset fast \
-y \
out.mp4

参数:

-i bg.png
指定背景图
[0]scale=min(iw*720/ih\,1080):min(720\,ih*1080/iw),pad=1080:720:(1080-iw)/2:(720-ih)/2[p0]
等比例缩放为 1080x720 的居中图片,pad指定尺寸不足的地方以黑色背景填充。
缩放扩展:scale=1080:720:force_original_aspect_ratio=decrease,pad=1080:720:(ow-iw)/2:(oh-ih)/2
force_original_aspect_ratio参数,decrease指定图片缩小,increase扩大。
[3][out]overlay=0:600[v]
将合成的视频覆盖到第四个输入文件(即背景图)上,x 轴位移 0,y 轴位移 600((1920-720)/2=600)。


合成视频效果如下

[0]scale=min(iw*720/ih\,1080):min(720\,ih*1080/iw),setsar=1/1,pad=1080:720:(1080-iw)/2:(720-ih)/2[p0];\
[1]scale=min(iw*720/ih\,1080):min(720\,ih*1080/iw),setsar=1/1,pad=1080:720:(1080-iw)/2:(720-ih)/2[p1];\
[2]scale=min(iw*720/ih\,1080):min(720\,ih*1080/iw),setsar=1/1,pad=1080:720:(1080-iw)/2:(720-ih)/2[p2];\

注意:有时候会因为生成视频的采样纵横比不同而报如下错误

[Parsed_concat_16 @ 0x55f8751e47c0] Input link in2:v0 parameters (size 1080x720, SAR 0:1) do not match the corresponding output link in0:v0 parameters (1080x720, SAR 1214:1215)
[Parsed_concat_16 @ 0x55f8751e47c0] Failed to configure output pad on Parsed_concat_16
Error reinitializing filters!
Failed to inject frame into filter network: Invalid argument
Error while processing the decoded data for stream #4:0
Conversion failed!

SAR :Sample aspect ratio,采样纵横比。
concat 滤波器要求它的所有视频输入具有相同的分辨率和采样纵横比,报错信息显示SAR 1214:1215,近乎正方形1:1,所以我们可以在图片缩放生成视频的时候指定采样纵横比为正方形setsar=1/1从而解决该问题。

4、合成带高斯模糊背景图的视频

思路为先将图片合成高斯模糊背景视频,然后将生成的视频覆盖到背景视频上。原图为 1200x800,要想生成 3 的效果,就要将当前视频的图片缩放为 2880x1920,然后截取中间的 1080x1920 部分。下面命令前 3 个输入图片是作为高斯背景合成视频使用的。

$ ffmpeg -hide_banner \
-t 2 -loop 1 -i input0.jpg \
-t 2 -loop 1 -i input1.jpg \
-t 2 -loop 1 -i input2.jpg \
-t 3 -loop 1 -i input0.jpg \
-t 3 -loop 1 -i input1.jpg \
-t 2 -loop 1 -i input2.jpg \
-stream_loop -1 -i music.mp3 -acodec aac \
-filter_complex "\
[0][1][2]concat=n=3[bout];\
[bout]scale=2880:1920[bv0];\
[bv0]crop=1080:1920:900:0[bv1];\
[bv1]avgblur=sizeX=90[bv2];\
[bv2]eq=contrast=1:brightness=-0.1[bv];\
[3]scale=min(iw*720/ih\,1080):min(720\,ih*1080/iw),pad=1080:720:(1080-iw)/2:(720-ih)/2[p0];\
[4]scale=min(iw*720/ih\,1080):min(720\,ih*1080/iw),pad=1080:720:(1080-iw)/2:(720-ih)/2[p1];\
[5]scale=min(iw*720/ih\,1080):min(720\,ih*1080/iw),pad=1080:720:(1080-iw)/2:(720-ih)/2[p2];\
[p0]split[v_sp_0_0][v_sp_0_1];[v_sp_0_0]trim=0:2[v_tr_0_0];[v_sp_0_1]trim=2:3[v_tr_0_1];[v_tr_0_1]setpts=PTS-STARTPTS[v_st_0];\
[p1]split[v_sp_1_0][v_sp_1_1];[v_sp_1_0]trim=0:2[v_tr_1_0];[v_sp_1_1]trim=2:3[v_tr_1_1];[v_tr_1_1]setpts=PTS-STARTPTS[v_st_1];\
[v_st_0][v_tr_1_0]gltransition=duration=1:source=/home/jl/ffmpeg-gl-transition/gl-transitions/transitions/SimpleZoom.glsl[v0];\
[v_st_1][p2]gltransition=duration=1:source=/home/jl/ffmpeg-gl-transition/gl-transitions/transitions/LinearBlur.glsl[v1];\
[v_tr_0_0][v0][v1]concat=n=3[out];\
[bv][out]overlay=0:600[v];\
afade=t=out:st=5:d=2" \
-map "[v]" \
-map "6:a" \
-t 7.0 \
-shortest \
-c:v libx264 \
-profile:v main \
-pix_fmt yuv420p \
-preset fast \
-y \
out.mp4

参数:

[bout]scale=2880:1920[bv0]
将前三个视频合成的视频缩放为 2880x1920
[bv0]crop=1080:1920:900:0[bv1]
2880x1920 的视频截取 x 轴位移 900,y 轴位移 0 的中间的 1080x1920 部分。
[bv1]avgblur=sizeX=90[bv2]
均值模糊,sizeX 的值越大越模糊,即产生高斯模糊效果,默认值 0。
[bv2]eq=contrast=1:brightness=-0.1[bv]
降低高斯模糊背景亮度,突出中间的视频。
 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值