FFmpeg zoompan 动画产生锯齿状图案

FFmpeg zoompan 动画产生锯齿状图案

目标是让用户在视频中指定 zoomPoint,然后我们使用 FFmpeg 渲染该 zoomPoint。将有一个放大和缩小的动画。以下是一些示例值:

"scale":4,        # Scale factor, here x4
"offset":0,       # Start zooming in after 0ms
"duration":5000,  # Stay zoomed in for 5000ms
"marginX":80,     # Zoom x to 80% of video width 
"marginY":10      # Zoom y to 10% of video height

根据该输入,我正在运行以下简化的 FFmpeg 命令:

ffmpeg -i "/tmp/input.mp4" -c:v libx264 -r 30 -vf "scale=iw*2:ih*2,zoompan=fps=30:z='if(gte(it,0.0)*lt(it,5.0), min(pzoom+0.2, 4),if(gte(it,5.0)*lt(it,5.5), max(pzoom-0.2, 1), 1))':d=1:s=1512x982:x='(iw - iw/4)*(80/100)':y='(ih - ih/4)*(10/100)'" /tmp/output.mp4

动画时长为0.5s,视频帧率为30fps,因此0.5 / (1/30) = 15动画帧数为 。

在这种情况下,变焦距离scale - 1 = 3会使变焦增量增加3 / 15 = 0.2

结果如下示例视频点击这里

虽然缩放动画在正确的位置结束,但您会注意到它到达该位置时锯齿状图案,它首先放大右上角,然后改变方向朝向正确的位置。

我似乎无法弄清楚如何让它以直线方式动画缩放到指定的 x/y 位置。

欢迎提供任何建议,谢谢!

答案1

在扣除缩放区域的宽度/高度后,缩放 x 和 y 百分比值将应用于输入的宽度/高度。

当 x = 100% 时,输入宽度为 1000 像素,在 4 倍缩放时,缩放区域的 x 轴将位于 ​​750 像素,而不是 1000 像素。

 iw-(iw/zoom)

 1000-(1000/4) = 750

这并不重要,除了我们不能假设百分比输入值代表输入的真实百分比满的输入宽度/高度。

如果我们需要放大到特定的 x 轴像素位置,则以下公式将确定所需的百分比值。

 (x*100)/(iw-(iw/zoom)) = %

举例来说,使用上述公式,我们可以计算出 4 倍缩放比例下 x = 275 像素的百分比。

 (275x100)/(1000-(1000/4)) = 36.66%

脚本

Zoompan 过滤器计算是基于帧的。为了能够输入基于时间的值(仅限秒和毫秒),并且由于需要多次输入相同的值,以下脚本使用设置变量以清晰易懂。

30fps 的帧速率在主脚本中出现了三次。如果经常使用不同的帧速率,建议额外设置一个变量。

  • set R=变焦倍数
  • set Z=缩放开始时间
  • set D=缩放时长
  • set X=X 百分比坐标(水平)
  • set Y=Y 百分比坐标(垂直)
 set R=4
 set Z=0
 set D=0.5
 set X=80
 set Y=20

 ffmpeg -i input.mkv -filter_complex "[0:v]scale=10*iw:-2,zoompan=z='if(gte(in,(%Z%*30)+1),min(pzoom+(%R%-1)/(%D%*30),%R%))':d=1:fps=30\:x='iw*(%X%/100)-(iw/zoom*(%X%/100))':y='ih*(%Y%/100)-(ih/zoom*(%Y%/100))'" -s 1512x982 out.mkv

要对框架的中心、四个角或边缘之一进行缩放和平移,需要以下 x 和 y 值。

  • x=0 y=0 左上方
  • x=100 y=0 右上
  • x=0 y=100 左下方
  • x=100 y=100 右下角
  • x=50 y=0 顶部
  • x=0 y=50 左边
  • x=50 y=100 底部
  • x=100 y=50 正确的
  • x=50 y=50 中心

相关内容