Four Ways to Add Watermarks to Web Video, Compared

“Add a watermark to the video” is sentence from product and four completely different engineering routes. Picking wrong means rework: the CSS approach ships, two weeks later you need user IDs — impossible; the FFmpeg burn-in ships, three months later the copy changes — tens of thousands of videos to re-transcode. This article puts all four side by side so you choose right the first time.

Requirements First, Solutions Second

Ask yourself five questions:

  1. Static or dynamic: a fixed logo, or a moving anti-recording watermark?
  2. User variables: does the watermark need to show the current viewer’s ID?
  3. Cost of change: does changing the watermark mean reprocessing video files?
  4. Clarity: is “good enough” fine, or must it be crisp?
  5. Budget: ten minutes of frontend, or a backend transcoding pipeline?

Way 1: CSS/DOM Overlay

The intuitive route: an absolutely-positioned div on top of the <video>.

<div class="stage" style="position:relative">
  <video src="lesson.mp4" controls></video>
  <div class="wm" style="position:absolute;top:8%;right:3%">© MyCourse</div>
</div>

CSS overlay watermark Figure 1: the CSS/DOM overlay — a native video with a positioned div

Pros: ships in ten minutes, pure frontend, instant copy/style changes. Fatal cons: when the player goes fullscreen or picture-in-picture, DOM overlays frequently vanish or misplace; the watermark attaches to the container, not the picture area (it can end up on letterbox bars). Use for: internal tool pages and demos.

Way 2: Canvas Rendering

Draw drawImage(video) frame by frame a Canvas and composite the watermark text — or use Canvas just to generate a watermark sprite. Fully dynamic per frame, at the cost of:

  • per-frame CPU/GPU burn — noticeable heat and dropped frames at 4K;
  • fullscreen, PiP, and hardware-decode paths each have traps;
  • still a “web layer” watermark with CSS-level anti-record value.

Use for: rare effects where the watermark must react to picture content.

Way 3: FFmpeg Burn-In

ffmpeg -i in.mp4 -vf "drawtext=text='© MyCourse':x=10:y=H-th-10" out.mp4

The watermark becomes pixels: every player, every download, every share carries it.

Pros: the “hardest” watermark — even the raw downloaded file has it; zero frontend cost. Cons: one static watermark for every user — no user variables, no tracing; changing it means re-transcoding the entire library, cost growing linearly with catalog size; couples tightly with your HLS/DASH pipeline. Use for: brand-statement watermarks over a stable catalog. Not for traceable paid content.

Way 4: Player-Native Watermarks (ZWPlayer watermarks)

Mature players ship watermarking as a playback capability — ZWPlayer’s watermarks:

new ZWPlayer({
  playerElm: 'player',
  url: 'lesson.mp4',
  watermarks: [
    { type: 'text', behavior: 'static', text: '© MyCourse', dock: 'left', x: '3%', y: '90%' },
    { type: 'text', behavior: 'dynamic', text: '{user_id} · {sys_time}',
      movement: { direction: 'random', speed: 3 } },
    { type: 'text', behavior: 'tile', text: 'Internal · {user_id}',
      tile: { angle: -30, rowSpacing: 110, colSpacing: 280 } },
  ],
  variables: { user_id: '138****1234' },
});
  • Rendered inside the player’s own layer — consistent across fullscreen/PiP/web-fullscreen, tracking the picture area rather than container bars;
  • Three behaviors (static/roaming/tile) plus {user_id}/{sys_time} macros out of the box — the two needs “CSS can’t do, FFmpeg can’t afford” (user variables and dynamic motion) covered at once;
  • Watermarks live apart from the files — changing them never re-transcodes: edit JSON, site-wide;
  • Configure visually in Watermark Studio instead of hand-writing JSON.

The result is the three-layer combo in Figure 4 of Video Anti-Recording: Watermarks, Marquee & Tracing.

Comparison

CSS overlay Canvas FFmpeg burn-in Player-native
Effort Minimal High Medium (pipeline) Low (config)
Dynamic watermark Hard Possible No Built-in
User variables Possible (fragile) Possible No Built-in macros
Fullscreen/PiP consistency Often broken Often broken Consistent Consistent
Cost to change Instant Instant Full re-transcode Config edit
Watermark survives raw download No No Yes No

Conclusions:

  • Brand-only mark, stable catalog → FFmpeg burn-in is simplest;
  • Internal tool page → CSS overlay suffices;
  • Paid content, user tracing, evolving watermark strategy → player-native is the route covering dynamics + variables + low change cost simultaneously;
  • Ultimate case (raw downloads must also carry per-user marks) = FFmpeg universal layer + player-native per-user layer, stacked.