FFmpeg’s overlay filter burns a logo or a copyright notice into a video. You can set where it sits, how transparent it is and when it shows.

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: the main video
  • -i logo.png: the watermark image
  • overlay=X:Y: puts the logo’s top-left corner at (X, Y), counted in pixels from the video’s top-left corner

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, leaving 20px to the right edge
  • main_h-overlay_h-20: Y, leaving 20px to the bottom edge

3. Resize Logo Before Compositing (Transparent PNG)

This shrinks the logo to 150px wide, then places 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

How the filter graph works:

  1. [1:v]scale=150:-1[wm]: resizes the logo (the second input) to 150px wide, keeps its aspect ratio, and names the result [wm]
  2. [0:v][wm]overlay=...: places [wm] on the main video

FFmpeg reads a PNG’s transparency (its alpha channel) automatically. No extra options are needed.

4. Semi-Transparent Watermark (Opacity Control)

colorchannelmixer scales the alpha channel: 0.5 means 50% opacity. On a logo without an alpha channel (an RGB PNG or a JPEG), aa does nothing, so format=rgba adds one first:

ffmpeg -i input.mp4 -i logo.png \
  -filter_complex "[1:v]scale=150:-1,format=rgba,colorchannelmixer=aa=0.5[wm];[0:v][wm]overlay=main_w-overlay_w-20:main_h-overlay_h-20" \
  output.mp4
  • aa=0.5: the alpha multiplier (0.0 = fully transparent, 1.0 = unchanged, so transparent areas stay transparent)

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: the current time in seconds
  • between(t, start, end): 1 (logo shown) while t is inside the range

6. Scrolling Watermark (Left to Right)

The logo moves 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 per second. The logo enters from the left edge, leaves at the right edge, then starts again.

7. Multiple Logos Simultaneously

Two logos at once, one top-left and one bottom-right. The result of the first overlay is named [tmp], and the second overlay draws on top of it:

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: Simple filtergraph ... was expected to have exactly 1 input and 1 output

Cause: the command uses -vf instead of -filter_complex. overlay takes two inputs, and -vf allows only one.
Fix: use -filter_complex:

# 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 is fully transparent, or the logo is too small to see.
Fix: check the logo’s size and pixel format:

# Inspect logo dimensions and pixel format
ffprobe -v quiet -show_streams logo.png | grep -E "width|height|pix_fmt"

Problem 3: Error binding filtergraph inputs/outputs

Cause: the labels in the filter graph do not match. For example, the graph creates [wm] but the overlay asks for [logo]. The line above the error, Filter 'scale:default' has output 0 (wm) unconnected, names the label that leads nowhere.
Fix: make sure every label you create, such as [wm], is used exactly once as an output and once as an input.

Problem 4: Logo Appears Stretched or Distorted

Cause: scale=W:H set both the width and the height, so the shape changed.
Fix: set only the width, as in scale=150:-1. With -1 as the height, FFmpeg keeps the aspect ratio.

Problem 5: Output File Is Much Larger Than Expected

Cause: overlay always re-encodes the video stream.
Fix: raise the CRF value. The file gets smaller and the quality drops a little (libx264 uses 23 by default):

ffmpeg -i input.mp4 -i logo.png \
  -filter_complex "overlay=main_w-overlay_w-20:main_h-overlay_h-20" \
  -c:v libx264 -crf 26 -preset fast -c:a copy output.mp4

FAQ

Q1. Can I use a JPEG logo?
A. Yes, but JPEG cannot store transparency. For a logo with a transparent background, use PNG or WebP. A rectangular logo on a solid-color background works fine as a JPEG.

Q2. Does using overlay always re-encode the video?
A. Yes. overlay changes the pixels of every frame, so the video must be re-encoded. The audio can still be copied unchanged with -c:a copy.

Q3. Will the logo position adjust automatically for different video resolutions?
A. Yes, if you use expressions such as main_w-overlay_w-20:main_h-overlay_h-20. FFmpeg works them out from each video’s size.

Q4. Can the logo fade in and out over time?
A. Yes, but not with colorchannelmixer=aa=. It takes a fixed number, not a time expression, so adding enable only switches the logo on or off. For a fade, read the logo with -loop 1 -i logo.png and fade its alpha, as in [1:v]fade=t=in:st=0:d=2:alpha=1[wm];[0:v][wm]overlay=10:10:shortest=1. To show or hide the logo without a fade, enable='between(t,0,5)' is the easiest way.

Q5. How do I add the same logo to all videos in a folder?
A. Run the command in a loop. In bash:

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