A watermark is an image drawn into every frame of a video — usually a logo in a corner, a little transparent, the same size whatever the resolution. FFmpeg does it with one filter, overlay, plus a few helpers for size and opacity. Every command here was run on 2026-11-07 with FFmpeg 9.0.2 (linuxserver/ffmpeg image) on a 10-second 1280×720, 30 fps H.264 video, with a transparent PNG logo; we checked a frame of each result.
The basic overlay
ffmpeg -i in.mp4 -i logo.png \
-filter_complex "[0][1]overlay=W-w-24:H-h-24" \
-c:a copy out.mp4
[0]is the video,[1]the logo, in the order of the-iinputs.- In
overlay=x:y,WandHare the video's width and height,wandhthe logo's.W-w-24:H-h-24places the logo's bottom-right corner 24 pixels from the video's. -c:a copykeeps the audio untouched. The video has to be re-encoded — the logo becomes part of every frame.
Positions for the other corners and the centre:
| Position | overlay= |
|---|---|
| Top left | 24:24 |
| Top right | W-w-24:24 |
| Bottom left | 24:H-h-24 |
| Bottom right | W-w-24:H-h-24 |
| Centre | (W-w)/2:(H-h)/2 |
A logo that fits any resolution
A 400-pixel logo is modest on 4K and huge on 480p. Scale it relative to the video instead:
ffmpeg -i in.mp4 -i logo.png -filter_complex \
"[1][0]scale=w=-1:h=rh*0.08[wm]; \
[wm]format=rgba,colorchannelmixer=aa=0.6[wm2]; \
[0][wm2]overlay=W-w-24:H-h-24" \
-c:a copy out.mp4
[1][0]scale=w=-1:h=rh*0.08scales the logo using the video as a reference:rhis the reference (video) height, so the logo is 8% of it, andw=-1keeps its proportions. On our 720p clip that made the 400×120 logo 190×57 pixels.format=rgba,colorchannelmixer=aa=0.6multiplies the logo's alpha by 0.6: 60% opaque. Useaa=1for a solid logo,0.3for a faint one.overlayplaces the result as before.
The older way, scale2ref, still works, but FFmpeg 9.0.2 prints "scale2ref is deprecated, use scale=rw:rh instead". If your FFmpeg is old and rejects the reference form, give a fixed height for your video size, such as scale=-1:57.
The whole command took 1.39 seconds for our 10-second 720p clip; time grows with length and resolution, as with any re-encode.
Why -c copy does not work
ffmpeg -i in.mp4 -i logo.png -filter_complex "[0][1]overlay=W-w-24:H-h-24" -c copy out.mp4
FFmpeg 9.0.2 refused: "Streamcopy requested for output stream fed from a complex filtergraph. Filtering and streamcopy cannot be used together." A filter changes the frames, and changed frames have to be encoded. Copy only the audio (-c:a copy) and choose the video encoder settings yourself, for example -c:v libx264 -crf 20 -preset medium.
The PNG matters
- Transparent background. The logo must be a PNG (or WebP) with an alpha channel;
ffprobe -v error -show_entries stream=pix_fmt -of csv=p=0 logo.pngshould printrgbaor similar. A JPEG, or a PNG with a white background, covers a rectangle of the video. - Large enough. Scaling a small logo up blurs it. Export at least as large as it will appear on your biggest video.
- Light and dark. A white logo disappears on snow, a black one at night. A soft shadow baked into the PNG, or a semi-transparent dark plate behind a white logo, keeps it readable on any footage.
Text instead of a logo
For a plain text watermark — a handle or a URL — the drawtext filter draws text without an image file:
ffmpeg -i in.mp4 -vf "drawtext=text='@trailnotes':fontfile=/path/to/font.ttf:fontsize=h/24:fontcolor=white@0.7:x=w-tw-24:y=h-th-24" -c:a copy out.mp4
Inside drawtext, w/h are the video's size and tw/th the text's. fontfile must point to a font file on the machine. See overlay and drawtext in the FFmpeg filter documentation for every option.
Watermark only part of the video
overlay takes an enable expression: overlay=W-w-24:H-h-24:enable='between(t,0,5)' shows the logo only in the first five seconds — useful for a "new episode" badge at the start, or a call to action near the end.
We checked each command above on a frame of its output: the logo in the corner at 60% opacity, the text watermark, and the logo gone after five seconds with enable.
Quality and a folder of videos
Re-encoding is where quality is lost or kept. With libx264, -crf sets quality — 18 is close to the source, 23 is the default, higher is smaller and softer — and -preset trades encoding time for file size at that quality (slow makes smaller files than fast). Keep the source's frame rate and resolution unless you mean to change them; overlay leaves both as they are.
To watermark every video in a folder with the same logo:
mkdir -p watermarked
for f in *.mp4; do
ffmpeg -n -i "$f" -i logo.png -filter_complex \
"[1][0]scale=w=-1:h=rh*0.08[wm];[wm]format=rgba,colorchannelmixer=aa=0.6[wm2];[0][wm2]overlay=W-w-24:H-h-24" \
-c:v libx264 -crf 20 -preset medium -c:a copy "watermarked/$f"
done
-n makes FFmpeg skip files that already exist, so the loop can be run again after an interruption. Because the logo is scaled to each video's height, vertical clips and 4K files in the same folder all get a logo that is 8% of their height.
Where our images fit
We do not edit video, and we cannot make your watermark: our rendered images are opaque — no transparent background — so they are not suited as overlays. Where they do fit is the frames around your video: a title card or end card with the episode title, guest and date, rendered from a template at 1280×720 and joined to the video with FFmpeg's concat filter, and the thumbnail for every upload. The merge guide shows the card-plus-video command we tested, and YouTube thumbnails the thumbnail side; with Shareglint, each is one request with the episode's data.