Add a watermark to a video with FFmpeg
The overlay filter composites a second input onto the video. The examples below scale a PNG logo, place it with margin expressions, fade it to 50 % opacity, limit it to a time range and, for text, use drawtext. Each output was probed and the corner luminance checked.
Verified with FFmpeg 9.0.1 on 26 August 2026. Search intent: ffmpeg watermark.
ffmpeg -i input.mp4 -i logo.png -filter_complex "[1:v]scale=240:-1[wm];[0:v][wm]overlay=W-w-24:H-h-24" -c:v libx264 -crf 23 -preset medium -c:a copy watermarked.mp4Scales the logo to 240 px wide, keeps its alpha, and draws it 24 px from the right and bottom edges on every frame. W and H are the video size, w and h the logo size. The bottom-right corner of the 1 s frame dropped from an average luma of 147 to 107: the logo is there. Audio is copied.
Flags, explained
- -i logo.png
- The watermark is a second input. PNG keeps transparency; a JPEG is opaque unless you cut alpha with format and colorchannelmixer.
- [1:v]scale=240:-1[wm]
- Scale the second input to 240 px wide with proportional height and label the result wm. -1 is fine here because the overlay is not encoded on its own.
- overlay=W-w-24:H-h-24
- Place the top-left corner of the overlay at x and y. W,H are the main video dimensions, w,h the overlay dimensions, so this is the bottom-right corner with a 24 px margin.
- colorchannelmixer=aa=0.5
- Multiply the alpha channel by 0.5, i.e. 50 % opacity for the whole overlay.
- enable='between(t,2,8)'
- Apply the filter only while the expression is true; t is the timestamp in seconds.
- drawtext=text=...:x=w-tw-24:y=h-th-24
- Render text with libfreetype; tw and th are the text width and height, w and h the frame size.
Variants
Top-left corner at its native size
ffmpeg -i input.mp4 -i logo.png -filter_complex "[0:v][1:v]overlay=24:24" -c:v libx264 -crf 23 -preset medium -c:a copy watermarked.mp4x and y are the top-left corner of the logo. Other corners: overlay=W-w-24:24 (top right), overlay=24:H-h-24 (bottom left).
Centered at 50 % opacity
ffmpeg -i input.mp4 -i logo.png -filter_complex "[1:v]scale=240:-1,format=rgba,colorchannelmixer=aa=0.5[wm];[0:v][wm]overlay=(W-w)/2:(H-h)/2" -c:v libx264 -crf 23 -preset medium -c:a copy watermarked.mp4format=rgba guarantees an alpha channel, colorchannelmixer=aa=0.5 halves it. Works for opaque JPEG logos too, because format adds the channel.
Show the watermark only between two timestamps
ffmpeg -i input.mp4 -i logo.png -filter_complex "[1:v]scale=240:-1[wm];[0:v][wm]overlay=W-w-24:H-h-24:enable='between(t,2,8)'" -c:v libx264 -crf 23 -preset medium -c:a copy watermarked.mp4enable takes an expression of t (seconds). The logo is drawn from 2 s to 8 s and absent elsewhere.
Text watermark with drawtext
ffmpeg -i input.mp4 -vf "drawtext=text='kinopipe.com':fontsize=36:fontcolor=white@0.8:x=w-tw-24:y=h-th-24" -c:v libx264 -crf 23 -preset medium -c:a copy watermarked.mp4No image needed. tw and th are the rendered text size. Requires a build with libfreetype (the Homebrew macOS build answered "Filter not found"; the command ran on a build with fontconfig and freetype).
Pitfalls we hit
- A watermark is a re-encode: -c:v copy is impossible because the pixels change. Budget the encode time and keep -crf at 18 to 23 to avoid degrading the source.
- Logos scaled with -1 can get an odd height; that is fine for the overlay but breaks if you ever encode the scaled logo alone. Use -2 when in doubt.
- The overlay is positioned in source pixels. A 240 px logo looks right on 1080p and huge on a 480p clip; derive the size from the frame with scale=iw*0.2:-1 on the main input width, or compute it from ffprobe first.
- drawtext depends on libfreetype and a font. Builds without it say "Filter not found", and a missing font falls back to whatever fontconfig picks, which may not be what you expect.
How we verified it
Run with FFmpeg 9.0.1 on 26 August 2026 against a 12 s, 1280x720 H.264/AAC file and a 200x80 RGBA PNG at 60 % red. Primary command: 1280x720, 360 frames, 4,596,062 bytes; signalstats on the 240x80 bottom-right area at 1 s: YAVG 147.5 in the source, 107.2 with the logo. Top-left variant: 4,671,984 bytes. Centered 50 %: 4,686,455 bytes. Timed 2 to 8 s: 4,635,355 bytes. drawtext ran on the KinoPipe worker build (Debian, libfreetype and fontconfig): 4,714,942 bytes; the Homebrew build reported "Filter not found".
The same edit as a typed operation
add_watermark_to_video takes a named position, a width in pixels and an opacity, then builds the scale, alpha and overlay graph itself and renders it with the rest of the recipe in one pass. Margins and alpha handling are validated before the encode starts.
{
"inputs": [
{ "id": "main", "url": "https://example.com/video.mp4" },
{ "id": "watermark", "url": "https://example.com/logo.png" }
],
"options": { "position": "bottom-right", "width": 240, "opacity": 0.85 }
}FAQ
How do I put a logo in the bottom-right corner with FFmpeg?
Give the logo as a second input and use overlay=W-w-24:H-h-24, where W and H are the video size, w and h the logo size and 24 the margin in pixels. Scale the logo first with a scale filter on [1:v] if it is too large.
How do I make the watermark semi-transparent?
Run the logo through format=rgba,colorchannelmixer=aa=0.5 before the overlay. The aa value is the opacity multiplier: 0.5 is half transparent, 0.2 is a faint ghost.
Can I watermark a video without re-encoding?
No. Compositing changes every frame, so the video must be decoded and encoded again. Only the audio can be copied.
Can I show the watermark only during part of the video?
Yes, add enable='between(t,2,8)' to the overlay filter for seconds 2 to 8, or any expression of t. The overlay is skipped when the expression is false.
Related commands
- ffmpeg burn subtitlesAdd subtitles to a video with FFmpegRead
- ffmpeg resize videoResize a video with FFmpegRead
- ffmpeg compress videoCompress a video with FFmpegRead