Skip to content

WebVTT

currentMigrated from docs/subtitles/webvtt.mdx at 37c3317fd058; modified for Encode Wiki · CC BY-SA 4.0

WebVTT (Web Video Text Tracks, .vtt) is the subtitle and caption format of the web. It is derived from SRT, adds positioning and CSS styling, and is what browsers expect in a <track> element, what HLS uses for subtitle segments, and the only text format WebM allows.

WEBVTT
00:01.000 --> 00:04.000
- Never drink liquid nitrogen.
intro
00:05.000 --> 00:09.000 line:10% align:start
- It will perforate your <i>stomach</i>.
- You could die.
  • The file starts with WEBVTT, then a blank line. UTF-8 only.
  • Timestamps are mm:ss.mmm or hh:mm:ss.mmm with a period; SRT uses a comma.
  • A cue may have an identifier line (intro above) and settings after the time range: line, position, size, align, vertical, region.
  • Cue text accepts <b>, <i>, <u>, <c.classname> (for CSS), <v Speaker> (voice) and <lang>, plus inline timestamps for karaoke-style reveals.
  • NOTE blocks are comments. STYLE blocks hold CSS targeting ::cue, and REGION blocks define scrolling caption areas.

Browsers support only a subset of styling; ::cue allows colour, font, background and similar properties, not arbitrary layout. For fine typography use ASS in a player that supports it, or burn the subtitles in.

<video controls src="video.mp4">
<track kind="subtitles" src="en.vtt" srclang="en" label="English" default />
<track kind="captions" src="en-sdh.vtt" srclang="en" label="English (SDH)" />
</video>

kind is subtitles (translation), captions (dialogue plus sound descriptions, for deaf and hard-of-hearing viewers), descriptions, chapters or metadata. Serve .vtt files as text/vtt. If they live on another origin, the server must send CORS headers and the <video> needs a matching crossorigin attribute, otherwise the track silently fails to load. Tracks may also fail to load from file:// pages, so test through a local web server.

Terminal window
ffmpeg -i subs.srt subs.vtt
ffmpeg -i subs.vtt subs.srt
ffmpeg -i video.mkv -map 0:s:0 subs.vtt

SRT to WebVTT is lossless for text, italics and bold. ASS to WebVTT keeps italics and bold but drops positioning and every other style. WebVTT to SRT drops cue settings and CSS.

Put WebVTT into WebM or MKV as a soft track:

Terminal window
ffmpeg -i video.webm -i subs.vtt -map 0 -map 1 -c copy -c:s webvtt output.webm

MP4 does not take WebVTT through FFmpeg; its text track is mov_text. Browsers do not reliably expose subtitle tracks embedded in a WebM or MP4, so the dependable pattern is a separate .vtt next to the video or listed in the HLS/DASH manifest.

HLS delivers subtitles as WebVTT segments referenced from the multivariant (master) playlist as a SUBTITLES rendition. DASH can use WebVTT or TTML/IMSC. Each HLS WebVTT segment should carry an X-TIMESTAMP-MAP=LOCAL:…,MPEGTS:… header mapping cue times to the video’s MPEG-TS timestamps; without it, players must assume cue time 0 is MPEG-TS time 0. FFmpeg’s hls muxer does not write the header and by default starts its MPEG-TS segments 1.4 s late, so its subtitles show up early in players that follow the spec. -muxdelay 0 removes that offset.