如何使用FFmpeg垂直滚动图像并同时检测到图像的结尾(EOI)?

6
我需要垂直滚动图像,从图像的顶部滚动到底部,然后停止创建输出视频,直到图像的最后一个底部位于屏幕顶部时停止。

1
自从最近回答了这个问题,ffmpeg添加了一个滚动过滤器,但我似乎无法弄清楚如何设置此命令中的v(在此处找到:https://twitter.com/FFmpeg/status/1180179571456372737),使其每秒滚动一次图像(将命令适应为垂直滚动):`ffmpeg -loop 1 -framerate 30 -i input.png -vf“scroll=v=0.001,crop=640:360:0:ih,format=yuv420p”-preset veryslow -crf 18 -t 10 output.mp4`--我发现如果图像被裁剪到自己的高度,则为0.03333,但如果它比裁剪区域更高,则会改变。? - Alex Hall
@AlexHall 很有趣。你解决了吗?这个滚动选项在功能上与其他列出的选项(包括运行时)相比如何? - Roel Van de Paar
我还没有想通。 - Alex Hall
2个回答

12

要一条命令完成此操作,请使用

ffmpeg -f lavfi -i color=s=1920x1080 -loop 1 -t 0.08 -i "input.png" -filter_complex "[1:v]scale=1920:-2,setpts=if(eq(N,0),0,1+1/0.02/TB),fps=25[fg]; [0:v][fg]overlay=y=-'t*h*0.02':eof_action=endall[v]" -map "[v]" output.mp4

请注意,在某些Shell(例如Bash)中,需要转义逗号:

ffmpeg -f lavfi -i color=s=1920x1080 -loop 1 -t 0.08 -i "input.png" -filter_complex "[1:v]scale=1920:-2,setpts=if(eq(N\,0)\,0\,1+1/0.02/TB),fps=25[fg]; [0:v][fg]overlay=y=-'t*h*0.02':eof_action=endall[v]" -map "[v]" output.mp4

添加-t是为了使图像具有2帧流。 (25 fps x 0.08 = 2)。 setpts将第二个帧的时间戳设置为滚动速率的倒数,该速率表示高度的分数。 fps过滤器使用克隆帧填充时间戳间隙。

覆盖叠加功能会在图像输入结束时停止。


1
看起来你的shell需要你在表达式中转义逗号,所以if(eq(N,0),0,1+1/0.02/TB) --> if(eq(N\,0)\,0\,1+1/0.02/TB) - Gyan
1
在叠加之后插入这个 setpts,setpts=if(eq(N\,0)\,0\,PTS+2/TB) - Gyan
嘿,你的解决方案很完美,但是我在处理ffmpeg方面还是个新手,有一些问题: 1)如何增加fps?我尝试设置fps = 50和-t 0.04,以便保持您使用的相同帧比率,但失败了。 2)我应该如何在视频开头和结尾添加1秒暂停?感谢您的所有帮助。 - Julien FEGER
在开始时有两秒的暂停,很容易更改为一秒。我希望结束时的暂停也是类似的。不确定FPS,请查看FFmpeg文档。 - Roel Van de Paar
1
太好了!当底部图像到达视频底部时,我该如何立即停止它? - eivindml
显示剩余9条评论

3

我找到了一个解决方案:

最初的回答:

ffmpeg -f lavfi -i color=s=1920x1080 -loop 1 -i "input.png" -filter_complex "[1:v]scale=1920:-2[fg]; [0:v][fg]overlay=y=-'t*h*0.02'[v]" -map "[v]" -t 00:03:00 output.mp4

请注意滚动速率为0.02。将其设置得更低,例如0.01以减慢滚动速度,或者设置得更高,例如0.03,以加快滚动速度。
请注意,我将最长时间设置为3分钟。不幸的是,在您的特定设置中,这个时间需要比任何图像滚动输出所需的时间更长。
作为参考,一个1920x7043像素的图像需要49.88秒。您可以使用以下代码以编程方式获取图像的高度;
file input.png | sed 's|.*1920 x \([0-9]\+\).*|\1|'
output: 7043

如果有更好的方法来“检测图像滚动结束 - 即图像最后一行/底部从屏幕顶部滚动出去”的能力,并能基于此缩放时间/持续时间,那将非常方便。
目前,这是我拥有的最佳解决方案;扫描上面最后一个ffmpeg命令的输出,寻找类似以下内容的东西;
[blackdetect @ 0x559298835480] black_start:49.88

例如,使用这个命令;
Original Answer翻译成"最初的回答"。
ffmpeg -i output.mp4 -vf blackdetect=d=0.1:pix_th=.1 -f rawvideo -y /dev/null 2>&1 | grep -o "black_start:[\.0-9]\+ "
output: black_start:49.88

And crop accordingly;

ffmpeg -i output.mp4 -t 49.88 -c copy finaloutput.mp4
vlc finaloutput.mp4  # Assuming you have vlc installed

另一种可能修复此问题的方法是通过某种方式在ffmpeg命令中计算所需的确切秒数/帧数或类似值,并在达到该值后终止。我不确定ffmpeg是否支持这样(复杂)的语法。欢迎提出想法。 - Roel Van de Paar
1
如果您以高度的X%滚动,则图像底部从顶部滚过的时间为1 / X秒,如果您从y = 0的初始位置开始。 - Gyan
1
@Roel 另一种获取高度的方法:ffprobe -v error -show_entries stream=height -of csv=p=0 input.png - llogan
@Gyan 有没有在ffmpeg中以编程方式实现这个的方法? - Roel Van de Paar
1
@Roel 已添加回答。 - Gyan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接