FFmpeg Overlay Filter: Picture-in-Picture and Compositing

You need to put one video on top of another, and FFmpeg's documentation reads like a math textbook. The overlay filter is one of the most used filters in FFmpeg, but getting the positioning, scaling, and timing right takes more trial and error than it should.
This guide covers the overlay filter from basic image-on-video compositing to timed picture-in-picture with multiple streams.
How the FFmpeg Overlay Filter Works
The overlay filter takes two video inputs and stacks one on top of the other. The first input is the background (main video), and the second is the foreground (the overlay). You control placement with x and y coordinates.
The basic syntax inside filter_complex:
ffmpeg -i main.mp4 -i logo.png -filter_complex "[0:v][1:v]overlay=10:10" output.mp4
This places logo.png at 10 pixels from the left and 10 pixels from the top of main.mp4. Two inputs, one filter, x and y coordinates.
You need -filter_complex instead of -vf whenever you're working with multiple inputs. The [0:v] and [1:v] labels reference the first and second input streams by index.
Position Variables for Dynamic Placement
Hardcoding pixel values breaks the moment your input resolution changes. FFmpeg gives you position variables that reference the dimensions of each stream at runtime:
WandHrefer to the main (background) video's width and heightwandhrefer to the overlay's width and height
To pin a watermark to the bottom-right corner with 10px padding:
ffmpeg -i main.mp4 -i watermark.png -filter_complex "[0:v][1:v]overlay=W-w-10:H-h-10" output.mp4
Center the overlay on the background:
ffmpeg -i main.mp4 -i overlay.png -filter_complex "[0:v][1:v]overlay=(W-w)/2:(H-h)/2" output.mp4
These expressions get evaluated per-frame, so they adapt to any input resolution without changes to your command.
FFmpeg Picture-in-Picture with Scaling
A picture-in-picture layout means shrinking one video and placing it over another. The overlay filter doesn't handle scaling on its own. You need to chain a scale filter before the overlay.
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex \
"[1:v]scale=320:180[pip];[0:v][pip]overlay=W-w-20:20" \
output.mp4
This scales the second input to 320x180, labels it [pip], then overlays it in the top-right corner of the main video. The label syntax is how you route streams through a filter graph. You scale first, then overlay the result.
For maintaining aspect ratio while scaling, use -1 for one dimension:
[1:v]scale=320:-1[pip]
FFmpeg will calculate the height automatically.
Video-on-Video vs. Image-on-Video Compositing
When you overlay a static image (PNG, JPEG) on video, FFmpeg treats the image as a single-frame video stream. It just works. The image stays visible for the full duration.
Video-on-video compositing works the same way syntactically, but you need to think about duration. By default, the output ends when the shortest input ends. If your overlay clip is 5 seconds but your main video is 60 seconds, the output will be 5 seconds unless you set eof_action:
ffmpeg -i main.mp4 -i overlay.mp4 -filter_complex \
"[0:v][1:v]overlay=10:10:eof_action=pass" output.mp4
eof_action=pass tells FFmpeg to keep outputting the main video after the overlay stream ends. Other options are repeat (loop the last overlay frame) and endall (stop everything).
Timed Overlays with Enable Expressions
Sometimes you only want the overlay visible during a specific time window. The enable parameter controls this:
ffmpeg -i main.mp4 -i lower_third.png -filter_complex \
"[0:v][1:v]overlay=0:H-h:enable='between(t,5,15)'" output.mp4
This shows the lower-third graphic only between seconds 5 and 15. The t variable represents the timestamp in seconds.
You can combine multiple timed overlays by chaining filters. Each overlay adds one layer:
ffmpeg -i main.mp4 -i intro.png -i cta.png -filter_complex \
"[0:v][1:v]overlay=0:0:enable='between(t,0,5)'[tmp];[tmp][2:v]overlay=(W-w)/2:H-h-50:enable='between(t,30,40)'" \
output.mp4
This shows intro.png for the first 5 seconds, then cta.png centered near the bottom from 30 to 40 seconds.
Running Overlay Commands with FFmpeg Micro API
Building these commands locally is fine for testing. Running them in production means provisioning servers, managing FFmpeg installations, and handling job queues. FFmpeg Micro runs your overlay commands as API calls.
curl -X POST https://api.ffmpeg-micro.com/v1/transcodes \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputs": [
{"url": "https://storage.example.com/main.mp4"},
{"url": "https://storage.example.com/overlay.png"}
],
"outputFormat": "mp4",
"options": [
{"option": "-filter_complex", "argument": "[0:v][1:v]overlay=W-w-10:H-h-10"}
]
}'
The inputs array maps to FFmpeg's -i flags in order. The options array passes any FFmpeg flags you'd use on the CLI. Same filter syntax, no infrastructure.
Common Pitfalls
Pixel format mismatches. If your overlay has transparency (PNG with alpha), you may need format=yuva420p on the overlay or format=yuv420p on the output to avoid color issues. Adding format=auto to the overlay filter can help: overlay=10:10:format=auto.
Forgetting to map audio. The examples above only handle video. Your output will be silent unless you map the audio stream explicitly. Add -map 0:a -c:a copy to carry the main video's audio through.
Using -vf instead of -filter_complex. The -vf flag only works with a single input. The moment you have two -i flags and need to combine them, you must switch to -filter_complex. This trips up nearly everyone the first time.
FAQ
How do I put a logo in the corner of a video with FFmpeg?
Use the overlay filter with position variables. For bottom-right placement: ffmpeg -i video.mp4 -i logo.png -filter_complex "[0:v][1:v]overlay=W-w-10:H-h-10" output.mp4. The W and H variables reference the main video dimensions, while w and h reference the overlay dimensions.
Can I overlay a video on top of another video in FFmpeg?
Yes. The syntax is identical to image overlays. Use two -i inputs and the overlay filter: ffmpeg -i background.mp4 -i foreground.mp4 -filter_complex "[0:v][1:v]overlay=x:y" output.mp4. Set eof_action=pass if the overlay video is shorter than the background.
How do I make a picture-in-picture effect in FFmpeg?
Chain the scale and overlay filters. Scale the PiP stream first, then overlay it: [1:v]scale=320:180[pip];[0:v][pip]overlay=W-w-20:20. This scales the second input to 320x180 and positions it in the top-right corner.
Why is my FFmpeg overlay output missing audio?
The overlay filter only processes video streams. You need to explicitly map the audio: add -map 0:a -c:a copy to your command to copy the main video's audio track to the output.
How do I show an overlay only during a specific time range?
Use the enable parameter with a between expression: overlay=0:0:enable='between(t,5,15)'. This shows the overlay only between 5 and 15 seconds. The t variable is the current timestamp in seconds.
Every overlay command you can run locally works the same way through the FFmpeg Micro API. Skip the server setup and run filter_complex pipelines as HTTP requests.
About Javid Jamae
Founder & CEO at FFmpeg Micro
Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.
You might also like

How to Add a Watermark to Video with FFmpeg (CLI + API)
Add image or text watermarks to video with FFmpeg overlay filter. Covers positioning, transparency, scaling, and cloud API watermarking.

FFmpeg Scale Filter: Resize Video and Keep Aspect Ratio
Learn how to use FFmpeg's scale filter to resize video without distortion. Covers -2 auto-scaling, force_original_aspect_ratio, pad for letterboxing, and API examples.

How to Add Text to Video with FFmpeg (CLI and API)
Learn two ways to add text overlays to video: FFmpeg drawtext filter for CLI and FFmpeg Micro @text-overlay API for automation.
Ready to process videos at scale?
Start using FFmpeg Micro's simple API today. No infrastructure required.
Get Started Free