How to Zoom Images and Videos using FFmpeg

22 October 2022 | 5 min read
Casper Kloppenburg

Prerequisites

FFmpeg is a free and open-source video editing tool capable of trimming, cropping, concatenating, muxing, and transcoding almost any type of media file you throw at it.

It's also a very robust solution for implementing video automation, as we use it extensively in our own video editing API. For this tutorial we'll use FFmpeg 5.1.2, but any recent version will do.

Zooming an image

Use the zoompan filter to create a zoom effect on an image: $ ffmpeg -loop 1 -framerate 60 -i image.jpg -vf "scale=8000:-1,zoompan=z='zoom+0.001':x=iw/2-(iw/zoom/2):y=ih/2-(ih/zoom/2):d=5*60:s=1920x1280:fps=60" -t 5 -c:v libx264 -pix_fmt yuv420p output.mp4

  • We begin by scaling the image to 8.000 pixels wide. This gives us a higher resolution for the zoompan filter to produce a smooth zoom effect.
  • The zoompan filter accepts an expression of the form of z='zoom+0.001' that is evaluated every frame. In this case, we're increasing the zoom factor every frame, creating the zoom-in effect we're looking for.
  • The x=iw/2-(iw/zoom/2) and y=ih/2-(ih/zoom/2) expressions define the top-left corner of the zoom window within the input image. Keeping the zoom window centered using the iw, ih and zoom variables gives the appearance that the image is zoomed-in to the center.
  • In order to zoom for 5 seconds at 60 fps with the expression being evaluated each frame, we are setting d=5*60. When this is set to a shorter duration than the total video duration, the zoom effect simply repeats.
  • s=1920x1280 is the output resolution. It defaults to 1280x720 if we don't specify it.
  • fps=60 is the output frame rate. It defaults to 25 if we don't specify it.
  • With -t 5, we specify the total length of the video.
  • With -c:v libx264 -pix_fmt yuv420p, the video codec is set to H.264 and the pixel format to 4:2:0 subsampling, which is widely supported and makes the video playable on most devices.
Zooming in an image.

Zooming to another point

Using x and y expressions, you can specify where the image zooms in. To get the input width, input height, and zoom factor, we use iw, ih, and zoom, respectively. Here are some examples of zooming into different locations, while keeping everything else the same.

Zooming to the top-left corner:

$ ffmpeg -loop 1 -framerate 60 -i image.jpg -vf "scale=8000:-1,zoompan=z='zoom+0.001':x=0:y=0:d=5*60:s=1920x1280:fps=60" -t 5 -c:v libx264 -pix_fmt yuv420p output.mp4

Zooming to the top-right corner:

$ ffmpeg -loop 1 -framerate 60 -i image.jpg -vf "scale=8000:-1,zoompan=z='zoom+0.001':x=iw-(iw/zoom):y=0:d=5*60:s=1920x1280:fps=60" -t 5 -c:v libx264 -pix_fmt yuv420p output.mp4

Zooming to the bottom-left corner:

$ ffmpeg -loop 1 -framerate 60 -i image.jpg -vf "scale=8000:-1,zoompan=z='zoom+0.001':x=0:y=ih-(ih/zoom):d=5*60:s=1920x1280:fps=60" -t 5 -c:v libx264 -pix_fmt yuv420p output.mp4

Zooming to the bottom-right corner:

$ ffmpeg -loop 1 -framerate 60 -i image.jpg -vf "scale=8000:-1,zoompan=z='zoom+0.001':x=iw-(iw/zoom):y=ih-(ih/zoom):d=5*60:s=1920x1280:fps=60" -t 5 -c:v libx264 -pix_fmt yuv420p output.mp4

Zooming out

We need a slightly different approach if we want to zoom out instead of in. Rather than starting with a zoom factor of 1.0, we need to set the zoom to a high value and decrease it with each frame. Unfortunately, FFmpeg doesn't let us change the initial zoom factor. There is, however, a way around this:

$ ffmpeg -loop 1 -framerate 60 -i image.jpg -vf "scale=8000:-1,zoompan=z='if(lte(zoom,1.0),1.5,max(1.001,zoom-0.0015))':x=iw/2-(iw/zoom/2):y=ih/2-(ih/zoom/2):d=5*60:s=1920x1280:fps=60" -t 5 -c:v libx264 -pix_fmt yuv420p output.mp4

Here's what's happening. With an if statement, we're changing the initial zoom factor to 1.5 from 1.0 at the first frame. Next, the value decreases as each subsequent frame passes, but never below 1.001 to keep it from being reset. This causes the zoom factor to decrease from 1.5 to 1.001, giving the impression that the image is zooming out.

Zooming out an image.

Zooming in a video

By default, zoompan only works on still images. If you were using one of the previous examples with a video as input, you will see that only the first frame is being used. We can make zoompan work with videos by doing this:

$ ffmpeg -i video.mp4 -vf "fps=60,scale=8000:-1,zoompan=z='pzoom+0.001':x=iw/2-(iw/zoom/2):y=ih/2-(ih/zoom/2):d=1:s=1920x1280:fps=60" -t 5 -c:v libx264 -pix_fmt yuv420p output.mp4
  • Using fps=60, we make sure the video is converted to the specified frame rate.
  • Next, scale=8000:-1 increases the resolution of each frame to increase the smoothness of the zoom effect.
  • As compared to zooming a still image, the d=1 is the main difference. It tells the zoompan effect to apply to all frames of the video instead of just the first frame. This requires using pzoom instead of zoom in the z='pzoom+0.001' expression in order to work.
Zooming in a video.

Start automating today

Start with a full-featured trial with 50 credits, no credit card required.
Get started for free