Files
v10/internal/decisions/live-timeline-anchoring.md
T
Christian PillsburyandClaude Opus 4.8 f531e1055c docs(spf): decide the single presentation-level live timeline anchor
Capture the decision to hold one rolling (media-time ↔ PDT) anchor — learned
from the first A/V track to obtain SourceBuffer ground truth and applied to all
selected tracks (incl. text) by per-segment PDT — replacing today's per-track
buffer pins, which are redundant under the no-skew assumption and can't anchor
text (no SourceBuffer). New decision doc live-presentation-anchor.md; resolves
the deferred single-rolling-anchor question in live-timeline-anchoring and
promotes [4] in live-presentation-modeling to presentation-level.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 10:00:45 -07:00

4.9 KiB
Raw Blame History

status, date
status date
decided 2026-06-15

Live timeline anchoring via PROGRAM-DATE-TIME

Decision

Anchor the live timeline on EXT-X-PROGRAM-DATE-TIME (PDT), not on media sequence number. PDT gives each segment an absolute wall-clock time (epoch seconds) used for two things:

  1. Cross-track alignment — demuxed audio and video are aligned by equal PDT (same real instant), not by equal sequence number or per-track relative startTime.
  2. Turnover recovery — on a full live-window slide with no overlap, the absolute startTime is recovered from PDT rather than estimated from targetDuration × offset.

Scope of this decision: the anchor source is PDT. The parser surfaces Segment.programDateTime (landed; see Verification). Whether the model holds a single rolling anchor vs. per-segment measured times is fixed in live-presentation-anchor — a single presentation-level (media-time ↔ PDT) anchor, learned from the first A/V track to buffer and applied to all tracks (incl. text) by PDT. The remaining per-track presentationTimeOffset derivation for the skew case is downstream and not fixed here.

This resolves open questions [4] sync anchor and turnover startTime recovery in live-presentation-modeling.

Context

For demuxed live HLS, each track is parsed independently and its segment startTimes accumulate from 0, so the same real instant lands at different per-track startTimes (measured: a demuxed Mux CMAF stream put segment-82 at startTime 2 in video but 0 in audio — a 2 s A/V skew). Sequence number identifies and orders segments but does not place them in time. The model needs a shared, absolute anchor that survives variable durations and window turnover.

Alternatives Considered

  • Sequence × duration. Reconstruct a segment's time as (seq seq₀) × duration. Rejected — it assumes uniform duration, which fails three ways: (a) audio and video segment durations differ (AAC frames are 1024 samples → a "2 s" audio segment is 2.005 s / 2.048 s, never the video's exact duration), so the tracks drift apart; (b) manifests round EXTINF (both Mux streams advertised integer durations over non-integer media), compounding error; (c) once a segment rolls out of the window its actual EXTINF is gone, so absolute time can't be reconstructed by summing. PDT gives each in-window segment its own absolute time, immune to all three.

  • CMAF-HAM presentationTimeOffset. Borrow the model shape from common-media-library. Rejected as a source — HAM declares the field but never populates it for HLS, its HLS mapper accumulates each track from 0 (same skew as ours), and it drops PDT entirely. We adopt the name presentationTimeOffset for the per-track offset, not HAM's DASH-centric (and unimplemented) derivation.

Rationale

PDT is the mechanism RFC 8216 itself describes for correlating positions across renditions (§4.3.2.6 associates a segment's first sample with absolute time). It is optional in RFC 8216 but required by Apple's HLS Authoring Specification, so it is reliably present on conformant content — Mux emits it on every segment of both the TS and CMAF/LL-HLS profiles we captured. It is the only anchor that is duration-variance-robust, survives window turnover, and is already shared across tracks.

Boundary. PDT aligns the manifest timelines across tracks. It does not by itself align the buffer (native-PTS) coordinate — that rides on CMAF's common encoded presentation timeline plus the per-track offset learned from buffered/tfdt (see mse-timestamp-offset). Two distinct steps: PDT → shared manifest timeline (alignment); manifest → buffer (the learned offset). PDT does the first only.

Verification

Segment.programDateTime (epoch seconds) and PDT capture landed in the parser (parse-media-playlist.ts), covered by parse-media-playlist.test.ts: synthetic cases (capture, EXTINF forward-interpolation, re-anchor on an explicit tag, variable-duration interpolation, absent-PDT → undefined) and real Mux fixtures — the demuxed CMAF case asserts video/audio segment-82 share PDT while per-track startTime disagrees (2 vs 0). PDT-anchored placement and the cross-track adjuster are not yet implemented.

See also