0

I am trying to move a shape (an image) over a background image to each corner. Here is the video example I generated with ffmpeg.

As you can see from the example, at the end of the video the shape is not positioned on the top right corner as it should be:

last frame shape positionning issue

Here is the ffmpeg command I use:

ffmpeg -i background.jpeg -loop 1 -i logo.png -filter_complex "[0]scale=300:250[s0];[1]format=gbrap[s4];[s0][s4]overlay=x=if(between(t\\,0.0\\,0.8)\\,lerp(0.0\\,240.0\\,round((t-0.0)/0.8*100)/100)\\,if(between(t\\,0.8\\,2.2)\\,lerp(240.0\\,0.0\\,round((t-0.8)/1.4*100)/100)\\,if(between(t\\,2.2\\,3.0)\\,lerp(0.0\\,240.0\\,round((t-2.2)/0.8*100)/100)))):y=if(between(t\\,0.0\\,0.8)\\,lerp(0.0\\,200.0\\,round((t-0.0)/0.8*100)/100)\\,if(between(t\\,0.8\\,2.2)\\,lerp(200.0\\,200.0\\,round((t-0.8)/1.4*100)/100)\\,if(between(t\\,2.2\\,3.0)\\,lerp(200.0\\,0.0\\,round((t-2.2)/0.8*100)/100))))[s5]" -map "[s5]" -c:v libx264 -crf 0 -pix_fmt yuv420p -t 3.0 video.mp4 
  • video is 300x250
  • logo.png is the blue shape (width=60px, height=50px)
  • the coordinates are set as follow: 0s: x=0,y=0 / 0.8s: x=240px,y=200px / 2.2s: x=0,y=200px / 3s: x=240px,y=0

I am using lerp to retrieve the right position depending on the current time t. It seems like the last frames are not played.

I tried to:

  • set a framerate (30 & 100) to the logo.png input,
  • round the value given by lerp,
  • use setpts to define a number of frames.

But I do not understand the problem I am facing, could you help me?

UPDATE 1: If I extend the video duration to 4s, the shape position at 3s is the right one

UPDATE 2: I added -framerate 100 as option the logo.png input and fps=24 just after the scale filter. The problem is still present. I extracted every frame as png (as expected there are 72 frames) & 17 were generated between 2.2s & 3s.

UPDATE 3: The problem is resolved by settings a fps of 100. However the generated video file is too big. Is there any other way to get it to work at 24fps?

1 Answer 1

0

Since your total duration is 3 seconds, there is no frame at 3 seconds. The last frame is at 3 seconds - 1/framerate seconds.

The default framerate of image inputs is 25, so you should interpolate to the final position at 2.96 seconds.

i.e.

if(between(t\\,2.2\\,3.0)\\, lerp(200.0\\,0.0\\,round((t-2.2)/0.76*100)/100))

3
  • Thank you, that's working. Can you tell me why "The last frame is at 3 seconds - 1/framerate seconds"? (Is this a FFmpeg limitation?)
    – antoox
    Nov 2, 2023 at 18:41
  • 2
    No. Each frame has a presentation time and a duration. For 25 fps videos, duration is 1/25 = 40ms. If there was a frame at 3s, then total video duration would be 3s40ms.
    – Gyan
    Nov 3, 2023 at 3:47
  • oh that makes perfect sense! thank you
    – antoox
    Nov 3, 2023 at 8:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.