我迫切想弄清楚为什么 ffmpeg 覆盖过滤器会出现问题
我有以下 ffmpeg 命令
ffmpeg -loop 1 -r 60 -i ./tmp/tmp0.jpg -loop 1 -r 60 -i ./tmp/tmp1.jpg -y -filter_complex
[0]trim=duration=5[0_trim0];
[0_trim0]scale=width=1280:height=-1[0_scale1];
[0_scale1]setsar=sar=1[0_setsar2];
[0_setsar2]crop=out_w=1280:out_h=720:x=0:y=(in_h - 720) / 2[0_setsar2_crop0];
[0_setsar2_crop0]setsar=sar=1[0_setsar3];
[0_setsar3]split=2[fl0_r0][fl0_r1];
[1]trim=duration=2[1_trim0];
[1_trim0]scale=width=1280:height=-1[1_scale1];
[1_scale1]setsar=sar=1[1_setsar2];
[1_setsar2]crop=out_w=1280:out_h=720:x=0:y=(in_h - 720) / 2[1_setsar2_crop0];
[1_setsar2_crop0]setsar=sar=1[1_setsar3];
[1_setsar3]split=2[fl1_r0][fl1_r1];
[fl0_r0]setpts=PTS-STARTPTS[fl0_r0_];
[fl1_r0]setpts=PTS-STARTPTS[fl1_r0_];
[fl0_r0_][fl1_r0_]overlay=x='if(lte(x, (main_w - overlay_w) / 2), -overlay_w + t / 5 * (overlay_w + (main_w - overlay_w) / 2), (main_w - overlay_w) / 2)'[tr0_overlay];
[tr0_overlay]trim=duration=5[tr0];
[fl0_r1][tr0][fl1_r1]concat=n=3:v=1[vt]
-map [vt] -acodec libmp3lame -r 60 -vcodec libx264 -f mp4 -pix_fmt yuv420p -preset fast -crf 20 ./tmp/output.mp4
(为了更好的可见度,它有衬垫)
我想要做什么?
- 显示第一张图片 5 秒(任意数字)
- 将第二幅图像从左向右滑动到第一幅图像上,持续 5 秒(任意数字,可以是 1,可以是 10 - 不应取决于第一和第二个输入流的长度)
- 显示第二张图片 2 秒(任意数字)
我能得到什么?
我尝试了各种解决方案,但这个方案只会在第一秒内将第二幅图像移动到第一幅图像上方,然后在接下来的 4 秒内突然停止,之后立即跳转到动画的结尾
而 ffmpeg 会发出大量警告
frame= 98 fps=8.1 q=28.0 size= 144kB time=00:00:01.08 bitrate=1087.8kbits/
[Parsed_overlay_14 @ 0x30d6400] [framesync @ 0x30d64e8] Buffer queue overflow, d ropping
我怀疑帧时间线存在一些问题,但到目前为止我还没有成功。如果我添加 setpts 过滤器 5*PTS - 它运行完美,但我观察到 5 倍帧下降(从 60 fps 下降到 12 fps)取自:https://ffmpeg.org/ffmpeg-filters.html#Examples-88 (慢动作)
由于某种原因,无论我尝试做什么,叠加滤镜仅适用于视频的第一秒
我还尝试将 fps 和 setpts 过滤器结合起来作为一种奇怪的 hack - 没有成功
ffmpeg 版本:
ffmpeg version N-76045-g97be5d4 Copyright (c) 2000-2015 the FFmpeg developers
built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04)
我可能忽略了一些显而易见的东西!请帮忙...
答案1
经过大约 8 小时在 ffmpeg、google 和文档中苦苦寻找之后,我终于找到了解决办法(适用于任何滑动持续时间):
setpts
筛选PTS*5-STARTPTS
fps
setpts
使用过滤器“拉伸”流后,将 fps 校正为所需值- 将两个流都传递给
fifo
过滤器,这可以防止 ffmpeg 丢帧
由于某种原因,ffmpeg 会丢弃给予overlay
过滤器的 FRAME_RATE 以上的任何帧,除非您手动将它们通过fifo
...即,您最多可以每秒传递 60 帧(如果您的 fps 为 60)或每秒 12 帧持续 5 秒(总共 60 帧 = 与视频的 fps 相同)
哎...我希望文档能更好地处理这些事情
答案2
因此,如果我理解正确的话,您希望图像在一段时间后滑过前一张图像。
你可以这样做:
ffmpeg -loop 1 -i img01.png -loop 1 -i img02.png -loop 1 -i img03.png -loop 1 -i img04.png -i watermark_logo.png -filter_complex \ "[0:v]scale=412x684,setpts=PTS-STARTPTS[v0];\ [0:v]trim=duration=3,scale=412x684,setpts=PTS-STARTPTS,split[v1a][v1b];\ [1:v]trim=duration=3,scale=412x684,setpts=PTS-STARTPTS,split[v2a][v2b];\ [2:v]trim=duration=3,scale=412x684,setpts=PTS-STARTPTS,split[v3a][v3b];\ [3:v]trim=duration=3,scale=412x684,setpts=PTS-STARTPTS[v4];\ [4:v]setpts=PTS-STARTPTS[v5];\ [v0][v1a] overlay=x='0':shortest=1[vv0];\ [v1b][v2a] overlay=x='max(w-(tw/0.5),0)':最短=1[vv1];\ [v2b][v3a] 覆盖=x='max(w-(tw/0.5),0)':shortest=1[vv2];\ [v3b][v4] overlay=x='max(w-(t*w/0.5),0)':shortest=1[vv3];\ [vv0][vv1][vv2][vv3] concat=n=4:v=1:a=0 [video];\ [video][v5] overlay=main_w-80:main_h-80 [finalvid]" -i audio.mp3 -map "[finalvid]" -map 5:0 -t 20 output.mp4
过滤器分解:
- 从输入图像创建 v0、v1a、v1b...
- 在 v0 上叠加 v1a,在 v1b 上叠加 v2a... 等等
- 连接所有叠加并生成视频
- 用水印叠加视频
- 用 finalVid 映射音频