mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
wip(spf): wire non-zero-PTS relocation into the audio-only engine
Compose establishStartMediaTime + bake audioMessagePipelines + the mediaContainerData slot + deriveStartMediaTime config into createHlsAudioOnlyEngine, comment-marked, mirroring the default engine. The reactor's optional/defensive selection composes with only audio in scope. Audio relocates to a 0-based timeline — sandbox-verified on the Mux asset_start_time=60 clip via the html-simple-hls-audio-only harness (audio buffered/seekable 0-based, duration 540). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
05a0a6452d
commit
0b99687db4
@@ -39,33 +39,28 @@ your detailed pass; **DEFERRED** = later/open.
|
||||
- spike relocation (boolean/inline approach, since reworked) — `6a20bade9`
|
||||
- VTT `X-TIMESTAMP-MAP` parse — `7b0d8bbdc`
|
||||
- messagePipelines step model (loader step pipelines) — `041cecca6`
|
||||
- relocation as `establishStartMediaTime` reactor (DOM-free) + `relocation-steps`
|
||||
(config messagePipelines) + DOM split; deleted `relocation.ts`/`origin-discoverer.ts` — `05a0a6452`
|
||||
- audio-only relocation wiring (reactor + `audioMessagePipelines` baked into
|
||||
`engine-audio-only`) — audio 0-based sandbox-verified
|
||||
|
||||
### Uncommitted — KEEP (reactor + config-pipelines; typecheck/tests/lint/build green, A/V sandbox-verified 0-based)
|
||||
- `behaviors/dom/establish-start-media-time.ts` — **new**. Two pieces:
|
||||
- **Steps** (`relocationMessagePipelines`): a plain config array. `discover`
|
||||
(`readInitTimescale`/`readSegmentOrigin`) writes `state.mediaContainerData`;
|
||||
`stampStartMediaTime` reads that track's origin back and sets `timestampOffset`.
|
||||
Steps read composition `state` from their call-time `deps` — no closures, no
|
||||
context. One map serves both track types (steps key by the segment's trackId).
|
||||
- **Reactor** (`establishStartMediaTime`): 3 states — `inactive` (clears the slot
|
||||
per source) / `monitoring` (derive effect = injected `deriveStartMediaTime` seam
|
||||
→ writes `Track.startMediaTime`, the consume) / `established` (derive disabled,
|
||||
sticky). Owns `mediaContainerData` on `state`; selection **optional/defensive**.
|
||||
- `primitives/head-peek.ts` — **new** generic eager head-peek (replaces the old
|
||||
self-discriminating `origin-discoverer`).
|
||||
- `media/types/index.ts` — `Track.startMediaTime` + `MediaContainerData`.
|
||||
- `actors/dom/segment-loader.ts` — `StepDeps` widened with the composition
|
||||
`{ state, context, config }` (opaque conduit; loader never reads them).
|
||||
- `behaviors/dom/setup-buffer-actors.ts` — reads relocation pipelines from **config**
|
||||
(`video/audioMessagePipelines`), threads composition deps into the loader. No context slots.
|
||||
- `engines/hls/engine.ts` — composes the reactor before `setup*BufferActors`;
|
||||
bakes `video/audioMessagePipelines = relocationMessagePipelines` + `mediaContainerData`
|
||||
slot + `deriveStartMediaTime` config. All comment-marked for easy removal.
|
||||
- `engines/hls/index.ts` — exports `DeriveStartMediaTime` + `derivePerTrackStartMediaTime`.
|
||||
- **Deleted:** `engines/hls/relocation.ts`, `primitives/origin-discoverer.ts`.
|
||||
### Architecture (as landed)
|
||||
- **Steps** (`behaviors/dom/relocation-steps.ts`, `relocationMessagePipelines`): a
|
||||
plain config array. `discover` (`readInitTimescale`/`readSegmentOrigin`) writes
|
||||
`state.mediaContainerData`; `stampStartMediaTime` reads that track's origin back
|
||||
and sets `timestampOffset`. Steps read composition `state` from call-time `deps`
|
||||
(no closures/context); one map serves both track types (key by segment trackId).
|
||||
- **Reactor** (`behaviors/establish-start-media-time.ts`, DOM-free): 3 states —
|
||||
`inactive` (clears the slot per source) / `monitoring` (derive effect = injected
|
||||
`deriveStartMediaTime` seam → writes `Track.startMediaTime`, the consume) /
|
||||
`established` (derive disabled, sticky). Owns `mediaContainerData` on `state`;
|
||||
selection **optional/defensive** (composes across video-only/audio-only/both).
|
||||
- `StepDeps` carries the composition `{state,context,config}` (opaque conduit).
|
||||
Engines bake `*MessagePipelines = relocationMessagePipelines` + the reactor +
|
||||
`mediaContainerData` slot + `deriveStartMediaTime` config, all comment-marked.
|
||||
|
||||
### REVIEW — your detailed pass
|
||||
- The reactor + steps end-to-end (KEEP surface above).
|
||||
- The reactor + steps end-to-end (architecture above).
|
||||
- **`StepDeps` typing:** steps get composition `{state,context,config}` typed loose
|
||||
(`AnySlotMap`); relocation asserts its slots via `containerSlot(deps)` (one cast,
|
||||
since it legitimately knows the composition provides them). OK, or want it tighter?
|
||||
@@ -86,8 +81,10 @@ your detailed pass; **DEFERRED** = later/open.
|
||||
with comment markers; revisit a tree-shakeable opt-in + measure Tier-0 bundle.
|
||||
|
||||
### DEFERRED / open (see the doc's Open questions)
|
||||
- **Per-type keying + non-0th-segment origin (#3/#4)** — next up. `mediaContainerData`
|
||||
keyed by track *type* (ABR rungs share); `startMediaTime = bmdt/ts − segment.startTime`
|
||||
so non-zero starts (initial currentTime ≠ 0, live/DVR) relocate correctly.
|
||||
- Tier 2 shared-`min` (a `deriveStartMediaTime` swap) + barrier-liveness bound.
|
||||
- Audio-only composition wiring (reactor baked into the standard engine only).
|
||||
- Honest-`startMediaTime`-everywhere convergence + live-anchor dedup.
|
||||
- Suspected pre-existing: seek-into-evicted-back-buffer.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import type { BackBufferConfig } from '../../../media/buffer/back-buffer';
|
||||
import type { ForwardBufferConfig } from '../../../media/buffer/forward-buffer';
|
||||
import { canPlayTrack } from '../../../media/dom/capabilities';
|
||||
import { parseMultivariantPlaylist } from '../../../media/hls/parse-multivariant';
|
||||
import type { AudioTrack, CanPlayTrack, MaybeResolvedPresentation } from '../../../media/types';
|
||||
import type { AudioTrack, CanPlayTrack, MaybeResolvedPresentation, MediaContainerData } from '../../../media/types';
|
||||
import type { GetCdnId } from '../../../media/utils/cdn';
|
||||
import { getResolvedSelectedTrackDuration } from '../../../media/utils/track-selection';
|
||||
import type { SegmentLoaderActor } from '../../actors/dom/segment-loader';
|
||||
@@ -21,11 +21,16 @@ import {
|
||||
import { deriveCdnPriority } from '../../behaviors/derive-cdn-priority';
|
||||
import { endOfStream } from '../../behaviors/dom/end-of-stream';
|
||||
import { loadAudioSegments } from '../../behaviors/dom/load-segments';
|
||||
import { relocationMessagePipelines } from '../../behaviors/dom/relocation-steps';
|
||||
import { setupAudioBufferActors } from '../../behaviors/dom/setup-buffer-actors';
|
||||
import { setupMediaSource } from '../../behaviors/dom/setup-mediasource';
|
||||
import { trackCurrentTime } from '../../behaviors/dom/track-current-time';
|
||||
import { trackLoadTriggers } from '../../behaviors/dom/track-load-triggers';
|
||||
import { updateMediaSourceDuration } from '../../behaviors/dom/update-mediasource-duration';
|
||||
// Non-zero-PTS relocation (spike): remove this import, the composed reactor, the
|
||||
// `audioMessagePipelines` finalConfig entry, the `mediaContainerData` state slot,
|
||||
// and the `deriveStartMediaTime` config field to drop relocation from audio-only.
|
||||
import { type DeriveStartMediaTime, establishStartMediaTime } from '../../behaviors/establish-start-media-time';
|
||||
import { type ParsePresentation, resolvePresentation } from '../../behaviors/resolve-presentation';
|
||||
import { resolveAudioTrack } from '../../behaviors/resolve-track';
|
||||
import { type FailoverMonitorConfig, setupFailoverMonitor } from '../../behaviors/setup-failover-monitor';
|
||||
@@ -47,6 +52,9 @@ export interface SimpleHlsAudioOnlyEngineState {
|
||||
presentation?: MaybeResolvedPresentation;
|
||||
preload?: 'auto' | 'metadata' | 'none';
|
||||
selectedAudioTrackId?: string;
|
||||
// Non-zero-PTS relocation (spike): transient per-track container data owned by
|
||||
// `establishStartMediaTime`. Remove with the composed reactor.
|
||||
mediaContainerData?: Record<string, MediaContainerData>;
|
||||
/**
|
||||
* Consumer-driven constraint narrowing the audio candidate set. Sibling
|
||||
* of `userVideoTrackSelection` in the default engine. Partial-track
|
||||
@@ -119,6 +127,8 @@ export interface SimpleHlsAudioOnlyEngineConfig
|
||||
* Defaults to the URL origin; override to key on e.g. Mux's `cdn=` param.
|
||||
*/
|
||||
getCdnId?: GetCdnId;
|
||||
/** Non-zero-PTS relocation (spike): the reduce seam (tier knob); defaults to per-track own. */
|
||||
deriveStartMediaTime?: DeriveStartMediaTime;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -171,6 +181,9 @@ export function createHlsAudioOnlyEngine(
|
||||
canPlayTrack: config.canPlayTrack ?? canPlayTrack,
|
||||
resolveDuration: config.resolveDuration ?? getResolvedSelectedTrackDuration,
|
||||
parsePresentation: config.parsePresentation ?? parseMultivariantPlaylist,
|
||||
// Non-zero-PTS relocation (spike): pair the audio loader with the relocation
|
||||
// steps `establishStartMediaTime` derives from. Remove with the composed reactor.
|
||||
audioMessagePipelines: relocationMessagePipelines,
|
||||
};
|
||||
|
||||
return createComposition(
|
||||
@@ -210,6 +223,13 @@ export function createHlsAudioOnlyEngine(
|
||||
// so the Firefox `mozHasAudio` registration ordering is moot here.
|
||||
setupMediaSource,
|
||||
updateMediaSourceDuration,
|
||||
|
||||
// Non-zero-PTS relocation (spike): establishes per-track startMediaTime;
|
||||
// MUST precede setupAudioBufferActors. Remove this line + the import + the
|
||||
// finalConfig/state entries to drop relocation. (Selection is optional in the
|
||||
// reactor, so it works with only audio in scope.)
|
||||
establishStartMediaTime,
|
||||
|
||||
setupAudioBufferActors,
|
||||
|
||||
// Playback tracking
|
||||
|
||||
Reference in New Issue
Block a user