Bounce an Image in FFmpeg with Overlay Filter
This article explains how to use the FFmpeg overlay
filter to create a bouncing image effect over a video. By applying
mathematical expressions to the X and Y coordinates of the overlay, you
can make any image bounce off the edges of the screen, mimicking the
classic DVD screensaver effect.
The Bouncing Equation
To achieve a constant-speed, linear bouncing motion, you must use a
triangle wave formula. In FFmpeg, this is achieved using the
mod (modulo) and abs (absolute value)
functions.
The standard formula for a bouncing coordinate is:
Position = (Boundary - Element_Size) - abs(mod(t * Speed, 2 * (Boundary - Element_Size)) - (Boundary - Element_Size))
In FFmpeg’s overlay filter, the variables are defined
as: * W: Width of the main background video *
H: Height of the main background video * w:
Width of the overlay image * h: Height of the overlay image
* t: Current timestamp in seconds
The FFmpeg Command
To apply this to both the horizontal (x) and vertical
(y) axes with different speeds (to ensure it bounces
dynamically rather than in a straight diagonal line), use the following
command:
ffmpeg -i background.mp4 -i logo.png -filter_complex \
"[0:v][1:v]overlay=x='(W-w)-abs(mod(t*200,2*(W-w))-(W-w))':y='(H-h)-abs(mod(t*150,2*(H-h))-(H-h))'" \
output.mp4How the Math Works
W-w: This calculates the maximum travel distance. The image cannot move further than the background width minus the image’s own width.t*200: This sets the speed. In this case, the image moves at a rate of 200 pixels per second along the X-axis. Change200(X-axis speed) and150(Y-axis speed) to adjust how fast the image moves.mod(t*Speed, 2*Distance): This creates a continuous ramp that climbs from0to twice the maximum distance, then resets to0.abs(... - Distance): This offsets the ramp and folds the upper half backward, turning the saw-tooth motion into a continuous triangle wave (up and down, or left and right).(W-w) - ...: This final subtraction ensures the image starts moving in the correct direction and stays within the visible boundaries of the video.