Skip to main content

Module webvtt

Module webvtt 

Source
Expand description

CEA-608/708 -> WebVTT cue conversion (issue #568).

Cite: specs/rules/webvtt-rules.md (curated W3C WebVTT §4 cue syntax + RFC 8216 §3.5 X-TIMESTAMP-MAP), and CTA-608-E / CTA-708-E for the caption semantics (decode owned entirely by the cc-data crate, feature cc-data).

This module is split in two independent halves:

  • Cue + write_document / write_segment (always available): pure WebVTT serialization from an already-extracted cue list. No dependency on cc-data.
  • Cea608CueExtractor / Cea708CueExtractor (feature cc-data): turn a decoded CEA-608 CC1 channel / CEA-708 service into a Cue sequence by feeding one access unit’s cc_data() triplets at a time, tagged with that access unit’s 33-bit PTS.
  • TeletextCueExtractor (feature teletext): turns an EBU Teletext (ETSI EN 300 706) subtitle page into a Cue sequence by feeding one access unit’s dvb_vbi::TeletextDataFields at a time. Unlike the CEA extractors, the protocol decode (Hamming-8/4 FEC, character sets, page composition) is NOT owned by the carriage crate (dvb-vbi is deliberately carriage-only — see its module docs) — it lives in teletext instead. See that module’s docs for the full design.

§Cue-boundary detection (the key design decision)

cc-data’s decoders expose only state (channel_text() / service_text()), not a “just committed” event. This module derives cue boundaries by diffing that displayed text before and after each fed frame:

  • Pop-on: channel_text()/screen() reflect only the displayed memory; while composing a caption (RCL -> PAC -> characters) writes go to the non-displayed buffer and produce no diff. The buffers swap only on EOC, so a diff-detected boundary is exactly the EOC commit event, and the next diff (typically an EDM erase, or the next EOC) is exactly the “next erase/replace” the spec notes describe.
  • Roll-up / paint-on: characters are written directly to the displayed buffer, so a diff can fire on every visible change (finer grained than “one cue per committed row”). In practice a roll-up row is usually written in one batch before the next control code, so real streams still produce one boundary per row; pathologically slow per-character delivery would fragment further. Documented as a known simplification (see webvtt-rules.md’s 608/708 mapping notes).

§Documented losses (round-trip is NOT claimed; conversion is lossy)

  • Placement: no line/position/align cue settings are emitted — webvtt-rules.md allows omitting them (“otherwise omit (player defaults)”); row/column/window-anchor information from 608 PACs / 708 window geometry is dropped.
  • Styling: italics/underline/colour (608 mid-row/PAC attributes, 708 pen attributes) are not carried into the payload as <i>/<u>/<c> tags; only plain decoded text is emitted.
  • 708 scope: only a single service’s window text (service_text) is read; multi-window overlap ordering beyond priority, and non-service-1 services, are the caller’s choice of service_number but are not auto-merged across services.
  • Roll-up granularity: see cue-boundary detection above.

Modules§

teletextteletext
EBU Teletext (ETSI EN 300 706 V1.2.1) subtitle page decode.

Structs§

Cea608CueExtractorcc-data
Extracts Cues from a single CEA-608 data channel (CTA-608-E), wrapping a cc-data cc_data::decode::Cea608Decoder.
Cea708CueExtractorcc-data
Extracts Cues from a single CEA-708 (DTVCC) service (CTA-708-E), wrapping a cc-data cc_data::decode::Cea708Decoder.
Cue
A single extracted caption cue: display text plus its media-timeline span.
TeletextCueExtractorteletext
Extracts Cues from an EBU Teletext (ETSI EN 300 706) subtitle page, feature teletext, layered on dvb-vbi’s carriage-only dvb_vbi::TeletextDataField (ETSI EN 301 775 §4.5).

Functions§

cue_block
Render one cue block: the timings line (start --> end) followed by the escaped payload lines, terminated with a single trailing newline. No cue identifier and no cue settings are emitted (first-pass simplification).
escape_payload
Escape a cue payload line per W3C WebVTT §6.4: & -> &amp;, < -> &lt;, > -> &gt; (order is immaterial here: this is a single left-to-right character scan, not a sequence of whole-string find-and-replace passes, so an inserted &amp; is never re-scanned and cannot be corrupted by a later </> substitution).
format_timestamp
Format a MediaTime as a WebVTT timestamp hh:mm:ss.ttt (W3C WebVTT §4.3.1). Hours are always emitted: the grammar (hh:)?mm:ss.ttt makes hours optional, not forbidden, and always including them keeps this function total and monotonic without a >=1h special case.
write_document
Render a standalone WebVTT document: the WEBVTT signature, a blank line, then each cue block separated by a blank line (W3C WebVTT §4).
write_segment
Render one HLS segment of WebVTT (RFC 8216 §3.5): the WEBVTT signature, an X-TIMESTAMP-MAP=MPEGTS:<n>,LOCAL:00:00:00.000 header mapping this segment’s local WebVTT clock to the shared MPEG-2 TS (PES) timeline, then each cue rendered with times relative to segment_start (so cue timestamps stay small and segment-local, per the RFC 8216 convention of LOCAL:00:00:00.000).