The Ken Burns effect is a slow zoom or pan across a still image that makes it feel like moving footage. It takes its name from the American documentary maker who used it heavily on archive photographs. You can create it in any editor with keyframes, or reproducibly from the command line with FFmpeg's zoompan filter, which this guide explains in detail.
Why it still works
Documentary editors have used slow moves on photographs for decades because they solve a real problem: a still image on screen for more than a couple of seconds feels dead, but cutting too fast makes it hard to take anything in. A gentle move keeps the eye engaged and can direct attention: push in towards a face, pan across a crowd, pull out to reveal a location.
For creators working with AI-generated images, it is also a practical alternative to AI video. A well-composed still with a controlled camera move often looks cleaner than a generated clip, and it never changes the character's face halfway through. It pairs well with the techniques in our guide to character consistency in AI images.
The basic moves
| Move | What it does | Typical use |
|---|---|---|
| Push in (zoom in) | Moves towards a point of interest | Emphasis, tension, focus on a face |
| Pull out (zoom out) | Reveals more of the scene | Context, endings, reveals |
| Pan | Slides across the image at a fixed zoom | Wide landscapes, group photos, reading a document |
| Pan and zoom | Combines both | Moving attention from one detail to another |
Keep moves slow and subtle. A zoom from 100% to about 110–120% over five seconds is usually plenty. Faster moves draw attention to themselves and can look like a slideshow template.
A working FFmpeg zoompan example
This command takes one image and makes a five-second, 1920×1080, 25 fps clip that pushes in slowly towards the centre:
ffmpeg -i photo.jpg -vf "scale=7680:4320:force_original_aspect_ratio=increase,crop=7680:4320,zoompan=z='1+0.2*on/125':x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':d=125:s=1920x1080:fps=25,format=yuv420p" -c:v libx264 -crf 18 -preset slow push_in.mp4
Let us take it apart.
The input
-i photo.jpg reads a single image. Note that we do not use -loop 1. The zoompan filter generates multiple output frames from each input frame, so one image in produces a whole clip out. If you loop the input, zoompan would produce a clip for every repeated frame, and your video would be far longer than intended.
Scale and crop first
scale=7680:4320:force_original_aspect_ratio=increase,crop=7680:4320 does two things:
- It makes the image match the output's 16:9 shape, by scaling until it covers 7680×4320 and cropping the excess. Without this, a portrait or square image would be stretched.
- It upscales to four times the output resolution. This is the fix for the most common zoompan problem: jitter. The filter positions its crop window in whole input pixels, so on a small image each step of a slow move is visibly jerky. With a much larger input, each whole-pixel step becomes a tiny fraction of an output pixel, and the move looks smooth.
Upscaling this much uses more memory and time, but for a five-second clip from a single image it is modest. If you are processing many images and speed matters, try 3840:2160 first and check the result.
The zoompan parameters
z(zoom): the zoom factor for each output frame, where 1 means the full image and 2 means half the width and height is shown.1+0.2*on/125starts at 1 and rises in a straight line to about 1.2 by the last frame. The variableonis the output frame number, counting from 0.xandy: the top-left corner of the visible window, measured in input pixels.iwandihare the input width and height, andzoomis the current zoom. The visible window isiw/zoomwide, soiw/2-(iw/zoom/2)places it in the centre. Change these to aim the push at a different point.d(duration): how many output frames to produce for each input frame. With one image, 125 frames at 25 fps gives exactly five seconds.s(size): the output resolution. It defaults to 1280×720 (hd720), so always set it.fps: the output frame rate, which defaults to 25. Set it to match your project; our guide to frame rates explains the choice.
The encode
format=yuv420p converts to the pixel format most players and YouTube expect. -c:v libx264 -crf 18 -preset slow gives high-quality H.264 suitable for editing or upload. For the rest of an upload chain, see our YouTube export settings.
Variations you can copy
Pull out instead of push in
Reverse the zoom so it starts close and ends wide:
zoompan=z='1.2-0.2*on/125':x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':d=125:s=1920x1080:fps=25
Pan left to right at a fixed zoom
Hold the zoom at 1.2 and slide x from the left edge to the right edge:
zoompan=z=1.2:x='(iw-iw/zoom)*on/124':y='ih/2-(ih/zoom/2)':d=125:s=1920x1080:fps=25
iw-iw/zoom is the largest value x can take without running off the image. Dividing by 124 (the last frame number, one less than d) means the pan reaches the right edge exactly on the final frame.
Push in towards a specific point
To zoom towards a face at, say, 70% across and 35% down the image, centre the window on that point instead of the middle:
zoompan=z='1+0.25*on/125':x='iw*0.70-(iw/zoom/2)':y='ih*0.35-(ih/zoom/2)':d=125:s=1920x1080:fps=25
Keep the target away from the edges, or the window will try to go outside the image. FFmpeg clamps it, which shows up as a sudden change in direction.
Ease in and out
A linear move starts and stops abruptly. A cosine curve makes it accelerate gently and settle at the end:
zoompan=z='1+0.2*(1-cos(PI*on/124))/2':x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':d=125:s=1920x1080:fps=25
Joining several stills
Once you have a clip per image, join them. If they share the same resolution, frame rate and encoding, a simple list and the concat demuxer does it without re-encoding:
printf "file 'shot_01.mp4'\nfile 'shot_02.mp4'\nfile 'shot_03.mp4'\n" > list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy sequence.mp4
For a crossfade between two clips, use xfade. With a five-second first clip and a one-second fade, the fade starts at four seconds:
ffmpeg -i shot_01.mp4 -i shot_02.mp4 -filter_complex "xfade=transition=fade:duration=1:offset=4,format=yuv420p" -c:v libx264 -crf 18 fade.mp4
The official documentation for all these filters is at ffmpeg.org/ffmpeg-filters.html. Our guide to FFmpeg commands for creators covers the basics if the syntax is new to you.
Good practice
- Match the move to the narration. Push in when the voice focuses on something; pull out when it widens the context. Planning this in a storyboard helps (see storyboarding AI video).
- Vary direction. Alternate push-ins, pull-outs and pans so the sequence does not feel mechanical.
- Start with a good image. A move reveals compression artefacts and soft focus. Use the highest-resolution source you have.
- Leave room. Compose AI images with some space around the subject, so a push-in does not crop off heads.
- Keep it slow. If you notice the move, it is probably too fast.
Quick checklist
- Crop the image to your output aspect ratio before zooming.
- Upscale well beyond the output size to avoid jitter.
- Use a single image input without
-loop, and setdto frames = seconds × fps. - Always set
sandfpsexplicitly. - Keep zoom changes to roughly 10–25% over a shot.
- Use easing for moves that start or end on screen.
- Encode to
yuv420pfor compatibility.
FAQ
Why is my zoompan video shaky?
The filter moves in whole input pixels, so a small source makes each step visible. Upscale the image to several times the output resolution before zoompan, as in the example above.
Why is my clip much longer than expected?
You probably used -loop 1 on the input. Zoompan already produces d frames per input frame, so looping multiplies the length. Remove -loop 1 for single images.
Can I do the Ken Burns effect without FFmpeg?
Yes. Any editor with position and scale keyframes can do it, and many have a built-in pan-and-zoom option. FFmpeg is useful when you want identical, repeatable moves across many images.
What zoom amount looks natural?
For a shot of four to eight seconds, something between 10% and 25% usually feels natural. Larger zooms suit dramatic moments but lose resolution quickly.