{
  "schemaVersion": 1,
  "contentVersion": "ca42e61ede0a24f789d7287a0001244ad22f4abf",
  "id": "docs/codecs/subtitles/webvtt",
  "collection": "docs",
  "title": "WebVTT",
  "description": "WebVTT is the subtitle format for web video: SRT-like cues with positioning and CSS styling, used with the HTML track element, HLS and WebM.",
  "canonicalUrl": "https://encode.wiki/codecs/subtitles/webvtt/",
  "apiUrl": "https://encode.wiki/api/v1/documents/docs/codecs/subtitles/webvtt.json",
  "markdownUrl": "https://encode.wiki/api/v1/markdown/docs/codecs/subtitles/webvtt.md",
  "status": "current",
  "tags": [
    "migrated"
  ],
  "license": "CC BY-SA 4.0",
  "dates": {
    "lastVerified": "2026-10-08T00:00:00.000Z"
  },
  "authors": [],
  "sources": [
    {
      "title": "WebVTT: The Web Video Text Tracks Format (W3C)",
      "url": "https://www.w3.org/TR/webvtt1/",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "MDN — HTML track element",
      "url": "https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/track",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "MDN — Web Video Text Tracks Format",
      "url": "https://developer.mozilla.org/en-US/docs/Web/API/WebVTT_API/Web_Video_Text_Tracks_format",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "FFmpeg — subtitle codecs",
      "url": "https://ffmpeg.org/ffmpeg-codecs.html#Subtitles-Encoders",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "RFC 8216 — HTTP Live Streaming, section 3.5 (WebVTT)",
      "url": "https://www.rfc-editor.org/rfc/rfc8216#section-3.5",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    }
  ],
  "provenance": {
    "originUrl": "https://github.com/av1-community-contributors/codec-wiki/blob/37c3317fd058b23c71a87679bed5619a98f77752/docs/subtitles/webvtt.mdx",
    "originCommit": "37c3317fd058b23c71a87679bed5619a98f77752",
    "migratedAt": "2026-08-21T00:00:00.000Z",
    "modified": true,
    "originPath": "docs/subtitles/webvtt.mdx"
  },
  "headings": [
    {
      "depth": 2,
      "text": "Format",
      "anchor": "format"
    },
    {
      "depth": 2,
      "text": "Use it in a web page",
      "anchor": "use-it-in-a-web-page"
    },
    {
      "depth": 2,
      "text": "Convert and mux",
      "anchor": "convert-and-mux"
    },
    {
      "depth": 2,
      "text": "Streaming",
      "anchor": "streaming"
    }
  ],
  "sections": [
    {
      "id": "_preamble",
      "title": "Page introduction",
      "depth": 0,
      "canonicalUrl": "https://encode.wiki/codecs/subtitles/webvtt/",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/codecs/subtitles/webvtt/_preamble.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/codecs/subtitles/webvtt/_preamble.md",
      "checksum": "61969cf63999416c9d46bba61e8d38ca1f53848c0ddae34ece804802b9ec7444",
      "bytes": 318
    },
    {
      "id": "format",
      "title": "Format",
      "depth": 2,
      "anchor": "format",
      "canonicalUrl": "https://encode.wiki/codecs/subtitles/webvtt/#format",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/codecs/subtitles/webvtt/format.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/codecs/subtitles/webvtt/format.md",
      "checksum": "5fc9a0667cc2ae29aef824fd3ecb84ea69603bff7b93a18f7b4dd3c882a73f5c",
      "bytes": 1009
    },
    {
      "id": "use-it-in-a-web-page",
      "title": "Use it in a web page",
      "depth": 2,
      "anchor": "use-it-in-a-web-page",
      "canonicalUrl": "https://encode.wiki/codecs/subtitles/webvtt/#use-it-in-a-web-page",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/codecs/subtitles/webvtt/use-it-in-a-web-page.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/codecs/subtitles/webvtt/use-it-in-a-web-page.md",
      "checksum": "3590f974b03a629158666ce087038936f79d54491eb9f779f5a159468cbc76bd",
      "bytes": 694
    },
    {
      "id": "convert-and-mux",
      "title": "Convert and mux",
      "depth": 2,
      "anchor": "convert-and-mux",
      "canonicalUrl": "https://encode.wiki/codecs/subtitles/webvtt/#convert-and-mux",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/codecs/subtitles/webvtt/convert-and-mux.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/codecs/subtitles/webvtt/convert-and-mux.md",
      "checksum": "0a1e1217917ac20ca1dad6d3255758d1ffc0465018c98db2b42da4fefa5f758d",
      "bytes": 709
    },
    {
      "id": "streaming",
      "title": "Streaming",
      "depth": 2,
      "anchor": "streaming",
      "canonicalUrl": "https://encode.wiki/codecs/subtitles/webvtt/#streaming",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/codecs/subtitles/webvtt/streaming.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/codecs/subtitles/webvtt/streaming.md",
      "checksum": "8da0c9cb852999922d3e4e69d2d306390aa6b739727829a9a8606fc2f9a9f3c2",
      "bytes": 571
    }
  ],
  "outboundReferences": [
    "/codecs/subtitles/srt/",
    "/codecs/subtitles/ssa/",
    "/containers/mp4/",
    "/containers/webm/"
  ],
  "checksum": "f228c6a124941e56f88b08f1535886d0bfb2ce799b5263406075143809a98226",
  "contentFormat": "markdown",
  "markdown": "WebVTT (Web Video Text Tracks, `.vtt`) is the subtitle and caption format of the web. It is derived from [SRT](/codecs/subtitles/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](/containers/webm/) allows.\n\n## Format\n\n```text\nWEBVTT\n\n00:01.000 --> 00:04.000\n- Never drink liquid nitrogen.\n\nintro\n00:05.000 --> 00:09.000 line:10% align:start\n- It will perforate your <i>stomach</i>.\n- You could die.\n```\n\n- The file starts with `WEBVTT`, then a blank line. UTF-8 only.\n- Timestamps are `mm:ss.mmm` or `hh:mm:ss.mmm` with a **period**; SRT uses a comma.\n- A cue may have an identifier line (`intro` above) and settings after the time range: `line`, `position`, `size`, `align`, `vertical`, `region`.\n- Cue text accepts `<b>`, `<i>`, `<u>`, `<c.classname>` (for CSS), `<v Speaker>` (voice) and `<lang>`, plus inline timestamps for karaoke-style reveals.\n- `NOTE` blocks are comments. `STYLE` blocks hold CSS targeting `::cue`, and `REGION` blocks define scrolling caption areas.\n\nBrowsers support only a subset of styling; `::cue` allows colour, font, background and similar properties, not arbitrary layout. For fine typography use [ASS](/codecs/subtitles/ssa/) in a player that supports it, or burn the subtitles in.\n\n## Use it in a web page\n\n```html\n<video controls src=\"video.mp4\">\n  <track kind=\"subtitles\" src=\"en.vtt\" srclang=\"en\" label=\"English\" default />\n  <track kind=\"captions\" src=\"en-sdh.vtt\" srclang=\"en\" label=\"English (SDH)\" />\n</video>\n```\n\n`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.\n\n## Convert and mux\n\n```sh\nffmpeg -i subs.srt subs.vtt\nffmpeg -i subs.vtt subs.srt\nffmpeg -i video.mkv -map 0:s:0 subs.vtt\n```\n\nSRT 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.\n\nPut WebVTT into WebM or MKV as a soft track:\n\n```sh\nffmpeg -i video.webm -i subs.vtt -map 0 -map 1 -c copy -c:s webvtt output.webm\n```\n\n[MP4](/containers/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.\n\n## Streaming\n\nHLS 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.\n"
}
