FFmpeg实现叠加图片无限横向滚动(无背景露出)及overlay参数表达式解析
FFmpeg实现叠加图片无限横向滚动(无背景露出)及overlay参数表达式解析
嘿,我来帮你搞定这个无限滚动的问题,顺便把你提到的overlay参数表达式给讲明白~
一、修改代码实现无背景露出的无限滚动
你的原代码问题在于图片只会向左移动一次,完全移出画面后就会露出红色的nullsrc背景。要实现无限循环滚动且不露出背景,我们可以用mod函数让图片位置循环重置,修改后的命令如下:
-y -i "storage/0000-0000/Android/data/com.silentlexx.ffmpeggui/Sub/cybercity_3840_h1080.png" -filter_complex "nullsrc=d=96:size=1920x1080,drawbox=c=red:t=fill[bg];[bg][0:v]overlay=x='mod(-t*40, -w)':y=0" -r 30 -c:v libx264 -crf 10 "storage/0000-0000/Android/data/com.silentlexx.ffmpeggui/Sub/slide_b.mp4"
为什么这样能实现无限滚动?
你的图片宽度是3840px,刚好是输出分辨率1920px的2倍。mod(-t*40, -w)这个表达式的作用逻辑:
-t*40:计算图片随时间向左移动的总像素偏移量(40px/秒,负号代表向左移动)mod(..., -w):对偏移量取-w(图片宽度的负数)的余数,当偏移量达到-w(即图片完全移出画面左侧)时,余数会重置为0,相当于图片从右侧重新开始向左滑动,完美衔接之前的画面,永远不会露出背景。
如果你的图片宽度不是输出分辨率的整数倍,只需要先给图片做横向平铺处理,比如用tile滤镜把图片拼成长条:
-y -i "你的图片路径.png" -filter_complex "nullsrc=d=96:size=1920x1080,drawbox=c=red:t=fill[bg];[0:v]tile=5x1[tiled];[bg][tiled]overlay=x='mod(-t*40, -w)':y=0" -r 30 -c:v libx264 -crf 10 "输出路径.mp4"
这里tile=5x1是把图片横向拼5张,足够覆盖长时间的滚动需求。
二、原overlay表达式min(0,-(t-0)*40)解析
咱们拆解一下这个表达式的作用和局限性:
-(t-0)*40部分:t是FFmpeg滤镜中的时间变量,代表当前视频播放的秒数(从0开始计时,所以t-0就是t)- 乘以40表示图片每秒向左移动40像素,前面的负号代表向左(FFmpeg中overlay的x参数,正数是向右偏移,负数是向左偏移)
- 比如t=1秒时,这个值是-40,图片向左挪了40px;t=10秒时,值是-400,挪了400px。
min(0, ...)部分:min(a,b)是取两个值中较小的那个。t=0时,-(t-0)*40等于0,min(0,0)结果是0,图片在初始位置(x=0)- 当t>0时,
-(t-0)*40变成负数,负数比0小,所以min的结果就是这个负数,图片开始持续向左移动 - 但问题来了:当这个偏移量小于图片的负宽度(比如你的图片宽3840,当x<-3840时),整个图片就完全移出了画面,之后x会继续变小,红色的nullsrc背景就露出来了——这就是原代码无法实现无限滚动的原因。
备注:内容来源于stack exchange,提问作者MayK
相关产品推荐
相关产品推荐

