How to Add a Transparent Overlay on a Video using FFmpeg

15 October 2022 | 4 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.

Overlaying an image on top of a video

You can merge a video and overlay image using the following command:

$ ffmpeg -i video.mp4 -i overlay.png -filter_complex [0][1]overlay=x=0:y=0 output.mp4
  • The -i video.mp4 and -i overlay.png arguments tell FFmpeg to use these files as input.
  • We then use the -filter_complex [0][1]overlay=x=0:y=0 argument to apply the overlay filter. The [0][1] part specifies that the filter should use the first (0, the video file) and second (1, the overlay file) inputs that we have provided above. We then specify a position for the overlay, in this case the top-left corner (x=0, y=0).

Tip: You can convert any image into a transparent PNG with a service like Remove.bg. If you just want to overlay an opaque image, you don't need to do this.

Specifying the location

These variables can be used to instruct FFmpeg where to place the overlay:

  • main_w The video's width
  • main_h The video's height
  • overlay_w The overlay's width
  • overlay_h The overlay's height

To place the overlay in the bottom-left corner: $ ffmpeg -i video.mp4 -i overlay.png -filter_complex [0][1]overlay=x=0:y=(main_h-overlay_h) output.mp4

To place the overlay in the bottom-right corner: $ ffmpeg -i video.mp4 -i overlay.png -filter_complex [0][1]overlay=x=(main_w-overlay_w):y=(main_h-overlay_h) output.mp4

To place the overlay in the top-left corner: $ ffmpeg -i video.mp4 -i overlay.png -filter_complex [0][1]overlay=x=0:y=0 output.mp4

To place the overlay in the top-right corner: $ ffmpeg -i video.mp4 -i overlay.png -filter_complex [0][1]overlay=x=(main_w-overlay_w):y=0 output.mp4

To place the overlay in the center: $ ffmpeg -i video.mp4 -i overlay.png -filter_complex [0][1]overlay=x=(main_w-overlay_w)/2:y=(main_h-overlay_h)/2 output.mp4

Padding

An overlay can be padded by adding or subtracting pixels from its position, as illustrated in the following example. Here, the overlay is placed in the top-right corner, but with a padding of 100 pixels: $ ffmpeg -i video.mp4 -i overlay.png -filter_complex [0][1]overlay=x=(main_w-overlay_w-100):y=100 output.mp4

Overlaying a sequence of images

FFmpeg also allows us to make an overlay image that changes over time. We can do this by using multiple overlay filters for every image we want to display, and enabling those filters at the right timestamps. Here is how three images can be displayed sequentially over a video:

$ ffmpeg -i video.mp4 -i overlay1.png -i overlay2.png -i overlay3.png -filter_complex [0][1]overlay=enable='between(t,0,4)':x=0:y=0[out];[out][2]overlay=enable='between(t,4,8)':x=0:y=0[out];[out][3]overlay=enable='between(t,8,12)':x=0:y=0 output.mp4
  • Using the -i argument, we tell FFmpeg to import 4 files: the video and 3 overlay images.
  • We then apply multiple filters with the -filter_complex argument. In each filter, we are instructing FFmpeg to use two inputs ([0][1]) only at a specific time, specified by enable='between(t,0,4)'. This allows the overlay to be only shown at a specific time (0 to 4 seconds), rather than during the entire video. Then it is passed through the next filter using [out], which then uses the passed through input with the next input ([out][2]) and so on.

Overlaying a GIF or video

If you want to overlay an animated image on top of a video, simply replace the PNG input from the previous examples. For example, if we want to add a GIF in the top-left corner, we can use the following command:

$ ffmpeg -i video.mp4 -stream_loop -1 -i overlay.gif -filter_complex [0][1]overlay=x=0:y=0:shortest=1 output.mp4
  • The -stream_loop -1 argument tells FFmpeg that we want to loop the GIF.
  • Additionally, we use shortest=1 in our filter. The reason for this is because -stream_loop -1 results in an infinitely long video if we do not tell FFmpeg to stop the video at the end of the input video. This basically states that the resulting video should never be longer than the shortest input we specified, in this case the input video.

Start automating today

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