FFmpeg如何使用动画scale滤镜实现视频尺寸动态缩放效果
FFmpeg实现指定时序视频缩放动画方案
实现逻辑
整个动画按时间拆分为4个阶段,通过滤镜的表达式动态计算每帧的缩放尺寸、叠加位置,实现无硬切的平滑过渡:
- 0~1秒(缩小阶段):视频从1280x720全尺寸,线性缩小到480x270的PIP尺寸,同时位置从全屏对齐平滑移动到画布右上角
- 1~11秒(保持阶段):视频固定为480x270尺寸,停在右上角位置,总保持时长10秒
- 11~12秒(放大阶段):视频从480x270线性放大回1280x720全尺寸,位置从右上角平滑回到全屏对齐
- 12秒之后:视频保持1280x720全尺寸播放直到结束
可直接使用的命令
默认输出1280x720分辨率、30fps,音频直接复制原流不需要重编码:
ffmpeg -i input.mp4 -filter_complex " color=c=black@0:s=1280x720:r=30[bg]; [0:v]scale= w='if(lte(t,1),1280-800*t/1,if(lte(t,11),480,if(lte(t,12),480+800*(t-11)/1,1280)))': h='if(lte(t,1),720-450*t/1,if(lte(t,11),270,if(lte(t,12),270+450*(t-11)/1,720)))': flags=lanczos[scaled]; [bg][scaled]overlay= x='if(lte(t,1),0,if(lte(t,11),800,if(lte(t,12),800-800*(t-11)/1,0)))': y=0: shortest=1[v] " -map "[v]" -map 0:a? -c:v libx264 -crf 23 -c:a copy output.mp4
参数自定义调整方法
所有参数都可以直接修改表达式里的对应值,不需要改动整体结构:
- 时长调整:如果要修改各阶段时长,直接替换表达式里的时间阈值即可。比如要把PIP保持时间改成15秒、放大时长改成2秒,就把所有判断里的
11替换为16(1秒缩小+15秒保持)、12替换为18,同时把放大阶段的除数从1改成2,对应线性变化的时长。 - 尺寸调整:如果要修改PIP尺寸,比如改成320x180,就把保持阶段的w/h值替换为320、180,同时重新计算各阶段的尺寸差值:全宽减PIP宽为缩小阶段宽度总变化量,除以缩小时长得到每秒变化值,高度、放大阶段计算逻辑相同。
- 位置调整:如果要把PIP放到其他位置,只需要修改overlay的x/y表达式即可。比如放右下角就把保持阶段的y值设为
450(720-270),同时补全缩小、放大阶段y值的线性过渡逻辑;放左上角就把保持阶段的x值设为0。 - 动画效果调整:默认是匀速线性动画,如果需要缓入缓出效果,把表达式里的线性比例(比如
t/1)替换成对应的缓动函数即可,比如用sin(t/1*PI/2)实现正弦缓动。 - 帧率匹配:把color滤镜里的
r=30改成原视频的实际帧率,避免动画时长和实际播放进度不匹配。
注意事项
- 缩放参数加了
flags=lanczos,用兰索斯算法采样,缩放后的画面清晰度比默认算法高,不需要可以直接删除该参数。 - 命令里的
-map 0:a?会自动检测原视频的音频流,存在就直接复制,不会做二次编码。 - 如果使用的FFmpeg版本低于4.4,scale滤镜不支持时间维度的表达式,可以替换为zoompan滤镜实现,核心的阶段判断逻辑完全一致,只需要对应调整坐标系换算即可。
内容的提问来源于stack exchange,提问作者nimda
相关产品推荐
相关产品推荐

