Picture-in-picture with FFmpeg overlay
Scale the second video down, overlay it at a corner, decide whose audio you keep. Each command was run with a 1280x720 main video and a 640x360 inset; every output was 360 frames at 1280x720.
Verified with FFmpeg 9.0.1 on 26 August 2026. Search intent: ffmpeg picture in picture.
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex "[1:v]scale=360:-2[pip];[0:v][pip]overlay=W-w-24:H-h-24[out]" -map "[out]" -map 0:a -c:v libx264 -preset veryfast -crf 20 -c:a copy output.mp4Scales the second input to 360 px wide, places it 24 px from the bottom-right corner and keeps the audio of the main video untouched. Output: 1280x720, 360 frames, 3.4 MB.
Flags, explained
- [1:v]scale=360:-2[pip]
- Take the video of the second input, scale it to 360 px wide with an even height, name the result pip.
- overlay=W-w-24:H-h-24
- Place the inset. Capital W and H are the main frame size, lower-case w and h the inset size.
- -map "[out]"
- Send the filter graph result to the output. Required once -map is used at all.
- -map 0:a
- Keep the audio of the first input. -map 1:a takes the second.
- pad=iw+8:ih+8:4:4:color=white
- Add a 4 px border on each side of the inset.
- amix=inputs=2:duration=first
- Mix two audio streams, stopping when the first ends.
- enable='between(t,2,8)'
- Apply the overlay only between 2 s and 8 s.
Variants
Top-left corner
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex "[1:v]scale=360:-2[pip];[0:v][pip]overlay=24:24[out]" -map "[out]" -map 0:a -c:v libx264 -preset veryfast -crf 20 -c:a copy output.mp4x and y are the position of the inset from the top-left of the main frame. W-w-24 means right edge minus inset width minus margin; 24:24 is the opposite corner.
White border around the inset
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex "[1:v]scale=360:-2,pad=iw+8:ih+8:4:4:color=white[pip];[0:v][pip]overlay=W-w-24:H-h-24[out]" -map "[out]" -map 0:a -c:v libx264 -preset veryfast -crf 20 -c:a copy output.mp4pad adds 4 px on each side of the scaled inset before it is overlaid, which draws a 4 px frame.
Mix both audio tracks
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex "[1:v]scale=360:-2[pip];[0:v][pip]overlay=W-w-24:H-h-24[out];[0:a][1:a]amix=inputs=2:duration=first[aout]" -map "[out]" -map "[aout]" -c:v libx264 -preset veryfast -crf 20 -c:a aac -b:a 128k output.mp4amix sums the two tracks (each attenuated so the sum does not clip) and stops with the first input. The mixed track has to be re-encoded, hence -c:a aac.
Show the inset between 2 s and 8 s and take its audio
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex "[1:v]scale=360:-2[pip];[0:v][pip]overlay=W-w-24:H-h-24:enable='between(t,2,8)'[out]" -map "[out]" -map 1:a -c:v libx264 -preset veryfast -crf 20 -c:a aac -b:a 128k output.mp4enable turns the overlay on only for that time range; -map 1:a picks the audio of the second input instead of the first.
Pitfalls we hit
- Without any -map FFmpeg picks one audio stream by its own rules and does not say which. With two inputs that both carry audio, always map the track you want.
- The overlay ends when the inset ends unless you set eof_action=repeat or pass on the overlay filter, or cut the main video with -shortest.
- Capital W/H are the main video, lower-case w/h the inset. Swapping them puts the inset off-screen.
- scale=360:-1 can give an odd height and fail with yuv420p; -2 keeps it even.
- Video always needs a re-encode here; -c:v copy cannot apply a filter. Only the audio can be copied.
How we verified it
Run with FFmpeg 9.0.1 on 26 August 2026 with a 12 s 1280x720 H.264/AAC main video and a 12 s 640x360 H.264/AAC inset. Primary command: 1280x720, 360 frames, main audio copied (564 AAC frames), 3,373,744 bytes. Top-left, border, amix and enable variants: 360 frames each, 1280x720. Without -map, FFmpeg kept a single 48 kHz mono track of its own choosing.
The same edit as a typed operation
create_picture_in_picture_video takes a corner keyword and an inset width, keeps the main audio, and renders the composite in one pass. Inputs are probed and validated before the render, and the result comes back as a signed URL.
{
"inputs": [
{ "id": "main", "url": "https://example.com/screen.mp4" },
{ "id": "pip", "url": "https://example.com/facecam.mp4" }
],
"options": { "position": "bottom-right", "width": 360 }
}FAQ
How do I move the inset to another corner?
Change the overlay position: 24:24 for top-left, W-w-24:24 for top-right, 24:H-h-24 for bottom-left, W-w-24:H-h-24 for bottom-right. The number is the margin in pixels.
Can I keep the audio of both videos?
Yes, mix them with amix as in the variant above. Each input is attenuated so the sum does not clip; add volume filters before amix if one should dominate.
What happens when the inset is shorter than the main video?
By default the overlay stops when the inset runs out and the main video continues. Set eof_action=repeat on the overlay to freeze the last frame, or enable to control when it shows.
Why can I not use -c copy?
Compositing changes the pixels, so the video must be decoded, filtered and encoded again. Audio that is not mixed can still be copied.
Related commands
- ffmpeg resize videoResize a video with FFmpegRead
- ffmpeg image to videoTurn an image into a video with FFmpegRead
- ffmpeg compress videoCompress a video with FFmpegRead