Client-side, visually-lossless video watermarker that runs entirely in your browser. Drop in an MP4, get back the same file with two short, timed promo overlays burned in — at native resolution, native frame rate, with zero dropped frames and no quality downgrade. Nothing is uploaded; the whole pipeline (demux → decode → composite → encode → mux) runs in a Web Worker on your own machine.
Most "add a watermark" tools either ship your video to a server, re-encode it at a lower resolution/bitrate, or tile a logo across every frame. Watermark Lab does none of that. It was built to prove a stricter set of constraints:
- No upload. The file never leaves the browser — works offline once loaded.
- Visually lossless. Never downscales, never caps fps, and encodes at ≥ source bitrate (measured from the input) or in constant-quality / quantizer mode where the hardware supports it.
- Hardware encode/decode via WebCodecs — fast, cool, low CPU.
- Streams to disk. Output is written straight to a file via the File System Access API, so the full MP4 never lives in RAM. Peak heap stays tiny even for long videos.
- Audio is copied through untouched — no re-encode, zero audio loss.
- Honest failure. The engine throws on any uncertainty rather than silently emitting degraded output. A thrown error means "this device/browser can't do it losslessly," not "fall back to something worse."
Instead of a full-video tiled watermark, two short branded cards are composited at native size in just two windows:
| Window | When | Content |
|---|---|---|
| Middle | a 10-second window placed pseudo-randomly in the middle third (only for videos ≥ 14 s) | promo card — "10 bin+ bölüm ücretsiz izlenir" |
| Ending | the last ≤ 30 seconds | full-width call-to-action band |
The middle window's position is jittered with a stable per-video hash so it isn't always in the same spot, but is deterministic for the same input.
It's a static site — no build step, no install.
# any static file server works, e.g.
python3 -m http.server 8000
# or
npx serve .Then open http://localhost:8000, pick a local .mp4 (or paste a CORS-enabled URL), set the brand text, choose a quality mode, and click Watermark uygula + indir. When prompted, choose where to save — that enables direct streaming to disk.
- VBR ≥ source bitrate (most compatible) — measures the true average source bitrate and encodes at or above it.
- Constant quality / quantizer — uses the hardware encoder's quantizer mode when available for size-efficient, quality-pinned output.
- A Chromium-based browser (Chrome/Edge) with WebCodecs
VideoEncodersupport and hardware H.264 encode. The page detects support and tells you if it's missing (e.g. some iOS/Safari versions). - Input must be MP4 with an H.264 (
avc1) video track; AAC audio is passed through if present. - The File System Access API enables streaming-to-disk; without it, the app falls back to building the file in memory and triggering a download.
┌──────────── Web Worker ────────────┐
MP4 ──▶ demux (mp4box) ──▶ HW decode (VideoDecoder)
│ │
│ composite overlays (2D canvas, native size)
│ │
│ HW encode (VideoEncoder) ──▶ mux (mp4-muxer)
└────────────────────────────────────┘ │
stream to disk ▶ watermarked.mp4
Backpressure (decode/encode queue depth) is the only pacing mechanism — no artificial sleeps — so the hardware codecs run at their natural rate and the worker keeps the page responsive. The UI surfaces hard metrics that prove the constraints: native resolution & fps, source vs. target bitrate, encoder used, decode/encode frame counts (must match → 0 dropped frames), throughput, elapsed time, and peak JS heap.
| File | Role |
|---|---|
index.html |
UI shell and styles |
src/app.js |
drives the worker, renders metrics, side-by-side preview |
src/worker.js |
download + transcode off the main thread |
src/engine.js |
the transcoder: demux, decode, overlay compositing, encode, mux, stream-to-disk |
Dependencies (mp4box and mp4-muxer) are loaded directly from a CDN as ES modules — there is no bundler and nothing to install.

