Two decision docs for the live-HLS timeline work: - mse-timestamp-offset — native-PTS default for live; timestampOffset reserved for relocation (the manifest→buffer / encoded layer). - live-timeline-anchoring — align demuxed tracks and recover turnover via PDT, not sequence number (the manifest layer). Resolve open questions [4] (sync anchor) and turnover startTime recovery in live-presentation-modeling, pointing at the decisions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.6 KiB
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:
- 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. - Turnover recovery — on a full live-window slide with no overlap, the
absolute
startTimeis recovered from PDT rather than estimated fromtargetDuration × offset.
Scope of this decision: the anchor source is PDT. The parser surfaces
Segment.programDateTime (landed; see Verification). How that anchor drives a
shared presentation timeline — the cross-track adjuster / per-track
presentationTimeOffset derivation, and whether the model holds a single
rolling anchor vs. per-segment measured times — 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 roundEXTINF(both Mux streams advertised integer durations over non-integer media), compounding error; (c) once a segment rolls out of the window its actualEXTINFis 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 namepresentationTimeOffsetfor 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
- mse-timestamp-offset — the buffer-layer half; the manifest→buffer offset this decision's anchor feeds into.
- live-presentation-modeling — open questions [4] and turnover recovery, resolved here.
- non-zero-pts-support — consumes the offset-corrected timeline.