Video watermarking API: protect UGC and branded content

You've got user uploads coming in and every one of them needs your mark on it before it goes anywhere. Doing that with a local FFmpeg install works fine for ten clips and falls apart at a thousand. What you actually need is the overlay step to happen somewhere else, on demand, without you running a media server.
Quick answer: A video watermarking API adds a logo or text overlay to video in the cloud with a single HTTP request, so you don't install FFmpeg or run a worker. With FFmpeg Micro you POST the input URL and an overlay option tohttps://api.ffmpeg-micro.com/v1/transcodes, pollGET /v1/transcodes/:iduntil status iscompleted, then fetch a signed download URL. The free tier includes 100 video processing minutes.
What a watermark actually protects
Conventional wisdom says a watermark protects your video. Mostly it doesn't. A corner logo is one command away from gone:
ffmpeg -i marked.mp4 -vf "crop=iw:ih*0.92:0:0" -c:a copy stripped.mp4
That crops off the bottom 8% of the frame, logo included, in about the time it takes to re-encode. Anyone who wants your clip badly enough will do it.
So the mechanism isn't obfuscation. It's attribution and traceability. A visible watermark does two jobs well: it survives the casual re-upload (which is 95% of what happens to UGC), and if you make the text unique per user, a leaked file tells you exactly which account leaked it. That second one is where a watermarking API earns its keep, because a per-user mark can't be a static asset you burn in once. It has to be generated at request time.
A UGC platform I'd describe as typical of this problem was stamping every creator submission with the same PNG in After Effects, by hand, in batches of 200 a night. Switching to a per-submission text mark carrying the creator handle and a submission ID meant every reposted clip could be traced back in one lookup.
The FFmpeg CLI way
Here are the commands that do the real work, so you know what the API is doing on your behalf.
Static logo in the corner
ffmpeg -i input.mp4 -i logo.png \
-filter_complex "[1]scale=iw*0.15:-1[wm];[0][wm]overlay=W-w-24:H-h-24" \
-c:a copy output.mp4
scale=iw*0.15:-1 sizes the logo to 15% of its own width with the aspect ratio preserved. W-w-24:H-h-24 anchors it 24 pixels in from the bottom-right corner, using the video's dimensions (W, H) and the overlay's (w, h).
Opacity
ffmpeg -i input.mp4 -i logo.png \
-filter_complex "[1]format=rgba,colorchannelmixer=aa=0.4[wm];[0][wm]overlay=W-w-24:H-h-24" \
-c:a copy output.mp4
The format=rgba is not optional. Without an alpha channel present, colorchannelmixer=aa=0.4 silently does nothing and you get a fully opaque logo.
Dynamic text, per user
ffmpeg -i input.mp4 \
-vf "drawtext=text='@creator_8842':fontcolor=white@0.35:fontsize=36:\
box=1:boxcolor=black@0.25:boxborderw=8:x=w-tw-30:y=h-th-30" \
-c:a copy output.mp4
This is the one that actually deters reposting, because the mark identifies a person rather than a brand.
Timed watermark
Add :enable='between(t,0,5)' to any overlay filter to show it only for the first five seconds. Useful for branded content where a permanent mark would annoy viewers.
The API way: one call instead of a worker
Same result, no binary, no queue, no disk. Three steps.
1. Upload the source. Request a presigned URL, PUT the bytes, confirm:
curl -X POST https://api.ffmpeg-micro.com/v1/upload/presigned-url \
-H "Authorization: Bearer $FFMPEG_MICRO_KEY" \
-H "Content-Type: application/json" \
-d '{"filename":"clip.mp4","contentType":"video/mp4","fileSize":18432001}'
fileSize has to be a JSON number in bytes. Send it as a string and the request fails validation. If your video already lives at a public URL, skip this and pass the URL straight into inputs.
2. Submit the watermark job.
curl -X POST https://api.ffmpeg-micro.com/v1/transcodes \
-H "Authorization: Bearer $FFMPEG_MICRO_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputs": [{ "url": "gs://your-bucket/1234567890-clip.mp4" }],
"outputFormat": "mp4",
"options": [
{ "option": "-c:v", "argument": "libx264" },
{ "option": "-crf", "argument": "23" },
{ "option": "@text-overlay", "argument": {
"text": "@creator_8842 | id 5f21",
"style": {
"position": "bottom-right",
"fontSize": 36,
"outlineThickness": 6,
"margin": 48
}
}
}
]
}'
@text-overlay is a virtual option: a high-level effect that expands to the right drawtext filter server-side. It takes position presets or raw x/y expressions like 0.15*w, plus fontColor, outlineThickness, margin, and textWidth for wrapping. Image overlays and the full current option list live at /docs/virtual-options. Standard flags go in the same array as {option, argument} pairs, so you control the encode alongside the mark.
3. Poll, then download.
curl -H "Authorization: Bearer $FFMPEG_MICRO_KEY" \
https://api.ffmpeg-micro.com/v1/transcodes/JOB_ID
{
"success": true,
"jobId": "job-uuid",
"status": "completed",
"outputUrl": "gs://output-bucket/processed-video.mp4",
"createdAt": "2025-01-01T00:00:00Z",
"completedAt": "2025-01-01T00:02:30Z"
}
Then GET /v1/transcodes/:id/download returns a signed HTTPS URL you can hand to a browser or a downstream step.
Batch watermarking in n8n, Make, or Zapier
The pattern for watermarking every upload automatically is the same in all three tools:
- Trigger on new file (Google Drive, S3, a webhook from your app).
- HTTP node: POST to
/v1/transcodeswith the creator's handle interpolated into the@text-overlaytext. - Wait, then poll
GET /v1/transcodes/:idon a loop untilstatusiscompletedorfailed. - GET the download URL and push the output wherever it goes next.
The polling loop is where most builds break, because n8n's default HTTP timeout will kill a long job before it finishes. The fix is to never hold the connection open. There's a full recipe in how to fix n8n timeout errors when processing video.
For reconciling a night's batch, GET /v1/transcodes?status=failed&since=2026-08-07T00:00:00Z gives you the ones to retry. Pagination defaults to 20 per page and caps at 100.
CLI vs API
| FFmpeg CLI on your box | Watermarking API | |
|---|---|---|
| Setup | Install FFmpeg, match versions across dev and prod | API key |
| 200 clips | Sequential, or you write a worker pool | 200 POSTs, concurrent |
| Long jobs | Your process holds the file and the RAM | Job ID, poll later |
| Per-user text | Shell-escape the string yourself | JSON field |
| Cost | Server + your time | Free tier: 100 minutes, 250 MB max input |
| `-filter_complex` | Full support | Not accepted; use options and virtual options |
That last row is a real constraint. If your watermark is a hand-tuned multi-input filtergraph, you'll express it as options rather than pasting the graph.
Common pitfalls
Fixed pixel sizes break across aspect ratios. A 300 px logo is 15% of a 1920-wide landscape frame and 28% of a 1080-wide vertical one. Size relative to the frame (iw*0.15) or set position presets and let the service do the math.
Bottom-right is the worst spot for social. On a 1080x1920 Reel or TikTok, roughly the bottom 250 px and the right 180 px sit under platform UI: the caption band, the action rail, the profile bubble. Your mark disappears under a like button. Move it up and left. The Instagram Reels settings post covers the rest of the frame geometry.
Order matters with compression. Watermark first, then compress, and a low-bitrate encoder will smear a thin logo into mush. Compress to your target bitrate, then apply the mark, or do both in one pass with a CRF around 23. See compress video for the web for the bitrate targets.
Watermarking always re-encodes video. You're changing pixels, so there's no stream-copy shortcut. Audio is a different story: -c:a copy keeps the original track untouched and saves real time on long files.
Free-tier inputs cap at 250 MB. A 20-minute 1080p source will blow past that. Starter is $19/month with a 1,024 MB cap and 2,000 processing minutes; Pro is $89/month for 12,000 minutes. Annual billing runs 40% cheaper.
When not to use a watermarking API
Be honest about which problem you have.
- You need forensic, invisible watermarking. Per-viewer imperceptible marks that survive re-encoding are a separate product category, sold by vendors like NexGuard, Irdeto, and Verimatrix. A visible overlay is deterrence and attribution, not tamper-proof tracing.
- You need DRM and signed playback. Mux and api.video handle encrypted delivery and token-gated streams. A batch processing API doesn't.
- Your watermark is really an animated template. If you want keyframed layers, transitions, and a design-tool workflow, Creatomate and Shotstack are template-first by design.
- You're already deep in Cloudinary. If your images run through Cloudinary transformations today, its video overlays may be less integration work than adding a service, even if the per-minute cost is higher.
- It's a live stream. Overlaying on a live feed is a streaming-stack job, not an async transcode job.
FAQ
How do I add a watermark to a video programmatically without installing FFmpeg?
Send the video URL and an overlay option to a hosted FFmpeg API. With FFmpeg Micro that's one POST to https://api.ffmpeg-micro.com/v1/transcodes with an @text-overlay or image overlay entry in the options array, then a poll on GET /v1/transcodes/:id. Nothing installs locally, and it works identically from Python, Node, Go, or an HTTP node in n8n.
Can I watermark every uploaded video automatically?
Yes. Trigger on the upload event, POST a transcode job with the watermark option, poll for completion, and store the output. In n8n, Make, or Zapier this is four nodes. In code it's a webhook handler and a background poller.
Does a watermark stop someone from stealing my video?
No. A visible watermark can be cropped, blurred, or covered by anyone with FFmpeg. What it does reliably is attribute the clip when it's reposted as-is, and if the text is unique per user, identify the source of a leak.
Can I use a different watermark for each user?
That's the strongest reason to use an API instead of a pre-rendered logo. The overlay text is a JSON field, so you interpolate the account handle, an order ID, or a session token per request and get a per-user mark with no extra assets.
How much does watermarking videos with an API cost?
FFmpeg Micro bills by processing minutes rather than per job. The free tier gives you 100 video processing minutes with a 250 MB input cap, which is enough to watermark a few hundred short-form clips before you pay anything. Paid plans start at $19/month for 2,000 minutes.
If you want to see the overlay on your own footage before wiring anything up, the playground runs a job against a real file in the browser. Sign up free and the 100 processing minutes are enough to watermark a full batch and check how the mark survives your platform's re-encode.
About Javid Jamae
Founder & CEO at FFmpeg Micro
Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.
You might also like

The Best GUI for FFmpeg (And When You Don't Need One)
An honest, tested rundown of the best GUI for FFmpeg: HandBrake, FastFlix, Videomass, ViComp, and when a browser playground and one API call beat a window.

Trim Silence From Video Automatically with FFmpeg (API)
How to remove silences from video automatically with FFmpeg silencedetect: detect, invert, and cut both streams in one pass without breaking lip sync.

How to Replace Audio in Video with FFmpeg (Track Swap API Guide)
Replace audio in video with FFmpeg by mapping the video and new audio streams, or run the same track swap as one API call with FFmpeg Micro's hosted API.
Skip the command line
The Logo Watermark blueprint stamps your logo on the video for you: upload both files, pick a corner, done.
Run it (free)