Need to burn a company logo or copyright notice into a video? FFmpeg’s overlay filter lets you place a transparent PNG watermark at any position, opacity, and time range — all from the command line, no GUI required. Time to complete: 10 minutes.
Tested with: FFmpeg 6.1 (ubuntu-latest / GitHub Actions CI-validated)
What You Will Learn
- How the
overlayfilter works and why-filter_complexis required - Position variables (
main_w,overlay_w, etc.) for resolution-independent placement - Transparent PNG (alpha channel) compositing
- Semi-transparent watermarks with opacity control
- Time-limited display — show the logo only during intro or outro
- Scrolling animated watermark
- Compositing multiple logos simultaneously
- Five common errors and fixes
- Five frequently asked questions
Command Examples
1. Basic: Logo in the Top-Left Corner
ffmpeg -i input.mp4 -i logo.png -filter_complex "overlay=10:10" output.mp4
-i input.mp4— main video-i logo.png— watermark imageoverlay=X:Y— place the logo’s top-left corner at (X, Y); origin is the video’s top-left
2. Bottom-Right Placement (Most Common)
ffmpeg -i input.mp4 -i logo.png \
-filter_complex "overlay=main_w-overlay_w-20:main_h-overlay_h-20" \
output.mp4
main_w-overlay_w-20— X: 20px margin from the right edgemain_h-overlay_h-20— Y: 20px margin from the bottom edge
3. Resize Logo Before Compositing (Transparent PNG)
Resize the logo to 150px wide before placing it bottom-right:
ffmpeg -i input.mp4 -i logo.png \
-filter_complex "[1:v]scale=150:-1[wm];[0:v][wm]overlay=main_w-overlay_w-20:main_h-overlay_h-20" \
output.mp4
Filter graph breakdown:
[1:v]scale=150:-1[wm]— resize logo (second input) to 150px wide (aspect-ratio preserved), label it[wm][0:v][wm]overlay=...— composite main video with the resized logo
FFmpeg handles alpha-channel transparency in PNGs automatically. No extra options needed.
4. Semi-Transparent Watermark (Opacity Control)
Use colorchannelmixer to adjust the alpha channel (0.5 = 50% opacity):
ffmpeg -i input.mp4 -i logo.png \
-filter_complex "[1:v]scale=150:-1,colorchannelmixer=aa=0.5[wm];[0:v][wm]overlay=main_w-overlay_w-20:main_h-overlay_h-20" \
output.mp4
aa=0.5— alpha multiplier (0.0=fully transparent,1.0=fully opaque)
5. Time-Limited Display (Show Only During Intro)
# Show logo only during seconds 0–5
ffmpeg -i input.mp4 -i logo.png \
-filter_complex "overlay=main_w-overlay_w-20:main_h-overlay_h-20:enable='between(t,0,5)'" \
output.mp4
# Show logo from 10s to 30s
ffmpeg -i input.mp4 -i logo.png \
-filter_complex "overlay=10:10:enable='between(t,10,30)'" \
output.mp4
t— current timestamp in secondsbetween(t, start, end)— returns 1 (active) within the range
6. Scrolling Watermark (Left to Right)
Logo scrolls across the bottom of the frame:
ffmpeg -i input.mp4 -i logo.png \
-filter_complex "[1:v]scale=200:-1[wm];[0:v][wm]overlay=x='mod(t*100,main_w+overlay_w)-overlay_w':y=main_h-overlay_h-20" \
output.mp4
mod(t*100, main_w+overlay_w)-overlay_w— moves 100px/second; loops from off-left to off-right
7. Multiple Logos Simultaneously
Place two logos (top-left and bottom-right) at the same time:
ffmpeg -i input.mp4 -i logo1.png -i logo2.png \
-filter_complex "[1:v]scale=100:-1[wm1];[2:v]scale=150:-1[wm2];[0:v][wm1]overlay=10:10[tmp];[tmp][wm2]overlay=main_w-overlay_w-20:main_h-overlay_h-20" \
output.mp4
Position Variable Reference
| Variable | Meaning |
|---|---|
main_w / W | Main video width |
main_h / H | Main video height |
overlay_w | Logo width |
overlay_h | Logo height |
t | Current time in seconds (for animation) |
Common Position Formulas
| Position | X Expression | Y Expression |
|---|---|---|
| Top-left | 10 | 10 |
| Top-right | main_w-overlay_w-10 | 10 |
| Bottom-left | 10 | main_h-overlay_h-10 |
| Bottom-right (recommended) | main_w-overlay_w-20 | main_h-overlay_h-20 |
| Center | (main_w-overlay_w)/2 | (main_h-overlay_h)/2 |
Option Reference
| Option | Meaning | Example |
|---|---|---|
overlay=X:Y | Logo placement (top-left origin) | overlay=10:10 |
enable='between(t,S,E)' | Time-limited display (S to E seconds) | enable='between(t,0,5)' |
[N:v]scale=W:-1 | Resize N-th input to W px wide | [1:v]scale=150:-1 |
colorchannelmixer=aa=A | Alpha multiplier (0.0–1.0) | aa=0.5 (50% opacity) |
x='mod(t*speed,...)' | Scrolling animation | x='mod(t*100,main_w+overlay_w)-overlay_w' |
Troubleshooting
Problem 1: Too many inputs for overlay filter
Cause: Using -vf instead of -filter_complex. The overlay filter requires two inputs and doesn’t work with -vf.
Fix:
# Wrong
ffmpeg -i input.mp4 -i logo.png -vf "overlay=10:10" output.mp4
# Correct
ffmpeg -i input.mp4 -i logo.png -filter_complex "overlay=10:10" output.mp4
Problem 2: Logo Is Invisible (Fully Transparent)
Cause: The PNG’s alpha channel is fully transparent, or the logo is too small.
Fix:
# Inspect logo dimensions and pixel format
ffprobe -v quiet -show_streams logo.png | grep -E "width|height|pix_fmt"
Problem 3: Output file #0 does not contain any stream
Cause: The filter graph labels don’t match (e.g., [wm] defined but referenced as [logo]).
Fix: Verify that every label you define ([wm]) is used exactly once on both sides of the graph.
Problem 4: Logo Appears Stretched or Distorted
Cause: scale=W:H was used with both width and height specified explicitly.
Fix: Use scale=150:-1 (set height to -1 for automatic aspect-ratio preservation).
Problem 5: Output File Is Much Larger Than Expected
Cause: overlay always triggers re-encoding of the video stream (this is by design).
Fix: Set CRF to maintain quality:
ffmpeg -i input.mp4 -i logo.png \
-filter_complex "overlay=main_w-overlay_w-20:main_h-overlay_h-20" \
-c:v libx264 -crf 18 -preset fast -c:a copy output.mp4
FAQ
Q1. Can I use a JPEG logo?
A. Yes, but JPEG has no alpha channel (no transparency). For a transparent logo you need PNG or WebP. A solid-color rectangular logo in JPEG will composite fine.
Q2. Does using overlay always re-encode the video?
A. Yes. The overlay filter composites frames pixel-by-pixel, which requires re-encoding the video stream. Audio can still be copied losslessly with -c:a copy.
Q3. Will the logo position adjust automatically for different video resolutions?
A. Yes — that’s exactly what expressions like main_w-overlay_w-20:main_h-overlay_h-20 are for. They adapt to any resolution.
Q4. Can the logo fade in and out over time?
A. It requires a complex filter graph. The simpler approach is enable='between(t,0,5)' to switch display on/off. A smooth fade requires animating colorchannelmixer=aa= with a time expression.
Q5. How do I add the same logo to all videos in a folder?
for f in *.mp4; do
ffmpeg -i "$f" -i logo.png \
-filter_complex "[1:v]scale=150:-1[wm];[0:v][wm]overlay=main_w-overlay_w-20:main_h-overlay_h-20" \
-c:v libx264 -crf 18 -c:a copy "watermarked_${f}" -y
done
Related Articles
- Scaling and Resizing Video — scale Filter Guide
- FFmpeg Basic Syntax and Options
- Creating Optimized GIFs from Video
- Video Compression — CRF, Bitrate, and Preset Guide
Tested with: ffmpeg 6.1.1 / Ubuntu 24.04 (GitHub Actions runner)
Primary sources: ffmpeg.org/ffmpeg.html / ffmpeg.org/ffmpeg-filters.html / trac.ffmpeg.org