{"id":16153,"library":"node-webvtt","title":"Node WebVTT Parser, Compiler, and Segmenter","description":"node-webvtt is a JavaScript library designed for comprehensive handling of WebVTT (Web Video Text Tracks) files. It provides functionalities for parsing WebVTT input into a structured JavaScript object, compiling such objects back into WebVTT format, and segmenting WebVTT content. A key differentiator is its integrated support for HLS (HTTP Live Streaming), enabling the generation of HLS playlists and segments directly from WebVTT data, which is crucial for delivering timed text tracks alongside adaptive video streams. The library is currently at version 1.9.4 (as of the last recorded release in early 2022) and maintains an active release cadence, primarily focusing on bug fixes, dependency updates, and minor feature enhancements. It offers both strict and non-strict parsing options, allowing developers to control error handling behavior when processing potentially malformed VTT files, and also supports parsing of WebVTT metadata.","status":"active","version":"1.9.4","language":"javascript","source_language":"en","source_url":"git://github.com/osk/node-webvtt","tags":["javascript","webvtt","vtt","segment","hls","subtitle","closed","caption"],"install":[{"cmd":"npm install node-webvtt","lang":"bash","label":"npm"},{"cmd":"yarn add node-webvtt","lang":"bash","label":"yarn"},{"cmd":"pnpm add node-webvtt","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Utility belt dependency, used for various internal operations.","package":"lodash","optional":false}],"imports":[{"note":"The package supports both ES Module (ESM) `import` and CommonJS `require()`. For modern Node.js and browser environments, `import` is recommended.","wrong":"const webvtt = require('node-webvtt');","symbol":"webvtt","correct":"import webvtt from 'node-webvtt';"},{"note":"The `parse` function is a method of the default `webvtt` object, not a named export. It can throw `ParserError` in strict mode.","wrong":"import { parse } from 'node-webvtt';","symbol":"webvtt.parse","correct":"import webvtt from 'node-webvtt';\nconst parsed = webvtt.parse(input, { strict: true });"},{"note":"HLS-related functions are nested under the `hls` property of the main `webvtt` export.","wrong":"import { hlsSegmentPlaylist } from 'node-webvtt';","symbol":"webvtt.hls.hlsSegmentPlaylist","correct":"import webvtt from 'node-webvtt';\nconst playlist = webvtt.hls.hlsSegmentPlaylist(input, segmentDuration);"}],"quickstart":{"code":"import webvtt from 'node-webvtt';\n\nconst webvttInput = `WEBVTT\nKind: captions\nLanguage: en\n\n00:00:00.000 --> 00:00:01.000\nHello world!\n\n00:00:02.500 --> 00:00:04.000 align:start line:0%\nThis is a subtitle example.\n\n00:00:05.000 --> 00:00:06.000\nFoo bar.\n`;\n\nconst segmentDuration = 2; // segments will be 2 seconds long\n\ntry {\n  // 1. Parse the WebVTT input with metadata option\n  const parsed = webvtt.parse(webvttInput, { strict: false, meta: true });\n  console.log('--- Parsed WebVTT (Non-strict with Meta) ---');\n  console.log(JSON.stringify(parsed, null, 2));\n\n  // 2. Compile the parsed object back to WebVTT string\n  // Note: For compilation, the input typically matches the parsed output structure.\n  const compiledInput = {\n    valid: true,\n    meta: parsed.meta,\n    cues: parsed.cues.filter(cue => cue.start < cue.end) // Filter out malformed cues if strict:false was used\n  };\n  const compiled = webvtt.compile(compiledInput);\n  console.log('\\n--- Compiled WebVTT ---');\n  console.log(compiled);\n\n  // 3. Segment the WebVTT for HLS and generate a playlist\n  const segments = webvtt.hls.hlsSegment(webvttInput, segmentDuration);\n  console.log('\\n--- HLS Segments ---');\n  segments.forEach((seg, i) => console.log(`Segment ${i}: ${seg.filename}\\n${seg.content}`));\n\n  const playlist = webvtt.hls.hlsSegmentPlaylist(webvttInput, segmentDuration);\n  console.log('\\n--- HLS Playlist (M3U8) ---');\n  console.log(playlist);\n\n} catch (error) {\n  console.error('An error occurred during WebVTT processing:', error.message);\n}","lang":"javascript","description":"This quickstart demonstrates parsing a WebVTT string (including metadata), compiling a parsed object back to WebVTT, and then segmenting the input to generate HLS-compatible WebVTT segments and an associated M3U8 playlist. It also highlights the use of `strict: false` and `meta: true` options for parsing."},"warnings":[{"fix":"Use a `try/catch` block around `webvtt.parse()` calls or pass `{ strict: false }` as an option to tolerate malformed cues and receive errors in an `errors` array instead of an exception.","message":"The `parse` function operates in strict mode by default. If the WebVTT input is malformed (e.g., incorrect header, invalid cue timestamps), it will throw a `ParserError` exception, requiring developers to wrap calls in `try/catch` blocks.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure WebVTT cues have distinct start and end times (`start < end`) for maximum compatibility and future-proofing, especially if `strict: true` is desired.","message":"The README indicates that the parser will not categorize cues starting and ending at the same time as an error when `strict` is `false`. However, changing this behavior to be `true` (i.e., treating `start === end` as an error) would constitute a breaking change in a 1.x version. Users relying on this lenient behavior should be aware of potential future changes.","severity":"breaking","affected_versions":">=1.6.1"},{"fix":"Upgrade `node-webvtt` to version 1.3.0 or higher to enable WebVTT metadata parsing via the `{ meta: true }` option in `webvtt.parse()`.","message":"Support for parsing metadata from WebVTT files (e.g., `Kind: captions`) was added in version 1.3. Older versions will not correctly parse or return metadata, even if the `{ meta: true }` option is provided.","severity":"gotcha","affected_versions":"<1.3.0"},{"fix":"Explicitly define the `startOffset` parameter when calling `webvtt.hls.hlsSegment()` to ensure correct timestamp mapping for your HLS workflow, especially if not using the default 0 for `LOCAL` timestamp.","message":"The `webvtt.hls.hlsSegment` function's `startOffset` parameter (for MPEG TS timestamp mapping) defaults to `900000`. This default might not align with specific HLS stream requirements or expected subtitle timings if not explicitly set.","severity":"gotcha","affected_versions":">=1.2.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Review and correct the timestamp format in the WebVTT file. Alternatively, call `webvtt.parse(input, { strict: false })` to allow parsing with errors and inspect the `result.errors` array.","cause":"A cue in the WebVTT input has a malformed or invalid timestamp format (e.g., missing milliseconds, incorrect separators, start time greater than or equal to end time) and the parser is in strict mode.","error":"ParserError: Invalid cue timestamp (cue #X)"},{"fix":"Ensure the WebVTT file strictly adheres to the WebVTT specification, starting with 'WEBVTT' on the first line. For files with potential header variations, consider using `{ strict: false }`.","cause":"The WebVTT input string does not begin with 'WEBVTT' followed by a newline, or has other header-related issues, and the parser is in strict mode.","error":"ParserError: Header is incorrect"},{"fix":"Ensure you are using `import webvtt from 'node-webvtt';` (ESM) or `const webvtt = require('node-webvtt');` (CJS) and accessing `hls` as a property of the default export: `webvtt.hls.hlsSegmentPlaylist(...)`. Verify your `node-webvtt` version supports HLS features (added in v1.2).","cause":"This typically occurs if `webvtt.hls` is `undefined`, often due to incorrect import (`import { hls } from 'node-webvtt';` instead of `import webvtt from 'node-webvtt';`) or using an outdated version of the library that did not yet include HLS segmentation features.","error":"TypeError: Cannot read properties of undefined (reading 'hlsSegmentPlaylist')"}],"ecosystem":"npm"}