mirror of
https://github.com/zoriya/v10.git
synced 2026-08-11 16:40:27 +00:00
refactor(spf): extract text-loader vocabulary to primitives behind a CueSink seam
Mirror of the v/a extraction for the text side. The text step vocabulary (TextFrame/TextLoadStep/TextStepDeps/TextMessagePipelines/TextLoadTask/ TextTrackSegmentResolver + resolveCues/dispatchCues) and the cue-sink message DTOs (AddCuesMessage/CueSegmentMeta) move out of the text loader / text-tracks actor into primitives/. All DOM-free (generic over Cue), so they land in primitives/ root. The dispatch step reaches its sink through a structural CueSink seam instead of the concrete TextTracksActor, so the pipeline names no actor; the loader keeps only scheduling. actors/ (root) and engines/hls gain primitives references. Net effect: relocation-pipelines now imports only core/media/primitives — zero actors/behaviors. It's ready to move to primitives; only the DOM VTTCue in its text step keeps it in behaviors/dom for now (slice 3). 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
a09473a372
commit
0b8efb34bc
@@ -1,13 +1,7 @@
|
||||
import { createTransitionActor } from '../../../core/actors/create-transition-actor';
|
||||
import type { Cue } from '../../../media/types';
|
||||
import type {
|
||||
AddCuesMessage,
|
||||
ClearMessage,
|
||||
CueSegmentMeta,
|
||||
TextTracksActor,
|
||||
TextTracksActorContext,
|
||||
TextTracksActorMessage,
|
||||
} from '../text-tracks';
|
||||
import type { AddCuesMessage, CueSegmentMeta } from '../../primitives/text-track-messages';
|
||||
import type { ClearMessage, TextTracksActor, TextTracksActorContext, TextTracksActorMessage } from '../text-tracks';
|
||||
|
||||
// Re-export the host-agnostic types so existing dom-side consumers can keep
|
||||
// importing from this module.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { createMachineActor, type HandlerContext, type MessageActor } from '../../core/actors/create-machine-actor';
|
||||
import type { AnySlotMap } from '../../core/composition/create-composition';
|
||||
import { peek } from '../../core/signals/primitives';
|
||||
import { SerialRunner, Task } from '../../core/tasks/task';
|
||||
import {
|
||||
@@ -7,7 +6,15 @@ import {
|
||||
type ForwardBufferConfig,
|
||||
getSegmentsToLoad,
|
||||
} from '../../media/buffer/forward-buffer';
|
||||
import type { Cue, Segment, TextTrack } from '../../media/types';
|
||||
import type { Cue, TextTrack } from '../../media/types';
|
||||
import {
|
||||
DEFAULT_TEXT_MESSAGE_PIPELINES,
|
||||
type TextFrame,
|
||||
type TextLoadTask,
|
||||
type TextMessagePipelines,
|
||||
type TextStepDeps,
|
||||
type TextTrackSegmentResolver,
|
||||
} from '../primitives/text-segment-load-pipeline';
|
||||
import type { TextTracksActor } from './text-tracks';
|
||||
|
||||
// =============================================================================
|
||||
@@ -52,81 +59,6 @@ export type TextTrackSegmentLoaderActor = MessageActor<
|
||||
TextTrackSegmentLoaderMessage
|
||||
>;
|
||||
|
||||
/**
|
||||
* Resolves a text-track segment URL into the array of cues it contains.
|
||||
*
|
||||
* "Resolve" because the fn covers both network fetch and parse into the
|
||||
* domain model. Host-agnostic — the concrete resolver (e.g. the
|
||||
* browser's native VTT resolver) is supplied at engine-assembly time,
|
||||
* so this actor stays DOM-free. A pure `url → cues` primitive (the text
|
||||
* analog of the v/a loader's `fetchBytes`); composition-awareness lives in
|
||||
* the injected {@link TextLoadStep}s, not here.
|
||||
*/
|
||||
export type TextTrackSegmentResolver<C extends Cue = Cue> = (url: string) => Promise<C[]>;
|
||||
|
||||
/**
|
||||
* A text load in mid-pipeline — the text analog of the v/a loader's `Frame`.
|
||||
* `resolveCuesStep` fills `cues`; `dispatchCuesStep` sends them. `metadata` is
|
||||
* opaque header metadata a resolve step may attach for a later step to read
|
||||
* (e.g. relocation stashes the `X-TIMESTAMP-MAP` correlation here for its rebase
|
||||
* step). Typed `unknown` so the generic loader stays host-agnostic — the step
|
||||
* that reads it knows its concrete shape (mirrors `StepDeps.state`).
|
||||
*/
|
||||
export interface TextFrame<C extends Cue = Cue> {
|
||||
readonly op: TextLoadTask;
|
||||
cues?: C[];
|
||||
metadata?: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* One stage of a text message pipeline — the text analog of the v/a loader's
|
||||
* `LoadStep`. Mutates the {@link TextFrame} in place and may be async; the runner
|
||||
* checks `signal.aborted` before each step and passes the actor's
|
||||
* {@link TextStepDeps} on every call, so a stateless step (`resolveCuesStep`) is a
|
||||
* plain value and a step that needs composition signals (relocation's cue rebase)
|
||||
* reads them from `deps` at call time.
|
||||
*/
|
||||
export type TextLoadStep<C extends Cue = Cue> = (
|
||||
frame: TextFrame<C>,
|
||||
signal: AbortSignal,
|
||||
deps: TextStepDeps
|
||||
) => void | Promise<void>;
|
||||
|
||||
/**
|
||||
* The uniform passthrough handed to each {@link TextLoadStep} — the composition triple,
|
||||
* the text analog of `StepDeps`. `state`/`context` are the composition signal maps;
|
||||
* `config` is the threaded config with the loader's wiring folded in (see
|
||||
* {@link textStepWiring} + `createTextTrackSegmentLoaderActor`). Typed loose: composition
|
||||
* steps read `state`; base steps read the folded wiring off `config`.
|
||||
*/
|
||||
export interface TextStepDeps {
|
||||
state: AnySlotMap;
|
||||
context: AnySlotMap;
|
||||
config: object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base-step view of the loader's wiring, folded into `config` by
|
||||
* `createTextTrackSegmentLoaderActor` so base steps read it from the uniform passthrough
|
||||
* — present in both composition and standalone use. `config` is loose (`object`), so
|
||||
* assert the shape here (mirrors the v/a loader's `stepWiring`).
|
||||
*/
|
||||
export function textStepWiring<C extends Cue>(
|
||||
deps: TextStepDeps
|
||||
): { textTracksActor: TextTracksActor<C>; resolveSegment: TextTrackSegmentResolver<C> } {
|
||||
return deps.config as { textTracksActor: TextTracksActor<C>; resolveSegment: TextTrackSegmentResolver<C> };
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the ordered step list, called **once per actor** (mirrors the v/a loader's
|
||||
* `MessagePipelines`, but text has a single op type so it's a flat array, not a
|
||||
* `Record`). The default ({@link DEFAULT_TEXT_MESSAGE_PIPELINES}) is
|
||||
* `resolveCues → dispatchCues`; a non-zero-PTS composition returns a list that
|
||||
* inserts a cue-rebase step (see `relocatingTextPipelines`), so the loader stays
|
||||
* oblivious to relocation.
|
||||
*/
|
||||
export type TextMessagePipelines<C extends Cue = Cue> = () => TextLoadStep<C>[];
|
||||
|
||||
/**
|
||||
* Configuration for `createTextTrackSegmentLoaderActor`. Spread over
|
||||
* `DEFAULT_FORWARD_BUFFER_CONFIG` to override individual forward-window
|
||||
@@ -144,54 +76,6 @@ export interface TextTrackSegmentLoaderActorConfig<C extends Cue = Cue> {
|
||||
// Implementation
|
||||
// =============================================================================
|
||||
|
||||
/** Internal load-task descriptor — one segment fetch + dispatch unit. */
|
||||
interface TextLoadTask {
|
||||
segment: Segment;
|
||||
trackId: string;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Steps
|
||||
// =============================================================================
|
||||
|
||||
// Base steps are generic over the cue type `C` (generic arrow consts, not
|
||||
// `TextLoadStep<Cue>` values): each touches `C` — `frame.cues: C[]` and the
|
||||
// `C`-typed `textStepWiring<C>` — so a `Cue`-typed const wouldn't slot into a
|
||||
// `VTTCue` pipeline. A generic function assigns to any `TextLoadStep<C>`.
|
||||
|
||||
/** Resolve the op's cues (via the injected host primitive) into the frame. The text analog of `fetchStep`. */
|
||||
export const resolveCuesStep = async <C extends Cue>(
|
||||
frame: TextFrame<C>,
|
||||
signal: AbortSignal,
|
||||
deps: TextStepDeps
|
||||
): Promise<void> => {
|
||||
const cues = await textStepWiring<C>(deps).resolveSegment(frame.op.segment.url);
|
||||
if (signal.aborted) return;
|
||||
frame.cues = cues;
|
||||
};
|
||||
|
||||
/** Dispatch the frame's cues to the TextTracksActor as `add-cues`. The text analog of `dispatchStep`. */
|
||||
export const dispatchCuesStep = <C extends Cue>(
|
||||
frame: TextFrame<C>,
|
||||
_signal: AbortSignal,
|
||||
deps: TextStepDeps
|
||||
): void => {
|
||||
const { op } = frame;
|
||||
textStepWiring<C>(deps).textTracksActor.send({
|
||||
type: 'add-cues',
|
||||
meta: {
|
||||
trackId: op.trackId,
|
||||
id: op.segment.id,
|
||||
startTime: op.segment.startTime,
|
||||
duration: op.segment.duration,
|
||||
},
|
||||
cues: frame.cues ?? [],
|
||||
});
|
||||
};
|
||||
|
||||
/** Tier 0 default: resolve then dispatch. No relocation vocabulary. */
|
||||
const DEFAULT_TEXT_MESSAGE_PIPELINES = <C extends Cue>(): TextLoadStep<C>[] => [resolveCuesStep, dispatchCuesStep];
|
||||
|
||||
/**
|
||||
* Loads text-track segments for a track and delegates cue management
|
||||
* to a TextTracksActor. Mirrors the v/a `SegmentLoaderActor` shape (FSM
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import type { TransitionActor } from '../../core/actors/create-transition-actor';
|
||||
import type { Cue, Segment } from '../../media/types';
|
||||
import type { AddCuesMessage } from '../primitives/text-track-messages';
|
||||
|
||||
// =============================================================================
|
||||
// Message / context shapes
|
||||
// =============================================================================
|
||||
|
||||
/** Segment identity and timing — mirrors AppendSegmentMeta without trackId (keyed separately). */
|
||||
export type CueSegmentMeta = Pick<Segment, 'id' | 'startTime' | 'duration'> & { trackId: string };
|
||||
|
||||
/** Non-finite (extended) data managed by the actor — the XState "context". */
|
||||
export interface TextTracksActorContext {
|
||||
/** Cues added per track ID. Used for duplicate detection and snapshot observability. */
|
||||
@@ -16,12 +14,6 @@ export interface TextTracksActorContext {
|
||||
segments: Record<string, Array<Pick<Segment, 'id' | 'startTime' | 'duration'>>>;
|
||||
}
|
||||
|
||||
export interface AddCuesMessage<C extends Cue = Cue> {
|
||||
type: 'add-cues';
|
||||
meta: CueSegmentMeta;
|
||||
cues: C[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Wipe the actor's `loaded` + `segments` context. Sent on source reset
|
||||
* (typically by `syncTextTracks` on state exit) so a subsequent
|
||||
|
||||
@@ -6,7 +6,12 @@
|
||||
"exactOptionalPropertyTypes": false,
|
||||
"declarationDir": "../../../types/playback/actors"
|
||||
},
|
||||
"references": [{ "path": "../../../../utils" }, { "path": "../../core" }, { "path": "../../media" }],
|
||||
"references": [
|
||||
{ "path": "../../../../utils" },
|
||||
{ "path": "../../core" },
|
||||
{ "path": "../../media" },
|
||||
{ "path": "../primitives" }
|
||||
],
|
||||
"include": ["./*.ts", "./tests/**/*.ts"],
|
||||
"exclude": ["./dom/**"]
|
||||
}
|
||||
|
||||
@@ -34,12 +34,6 @@ import { resolveVttSegmentMetadata, type TextSegmentMetadata } from '../../../me
|
||||
import { findMediaTrack, type MediaHandlerType, readBaseMediaDecodeTime } from '../../../media/mp4/timestamp-origin';
|
||||
import type { MaybeResolvedPresentation, MediaContainerData } from '../../../media/types';
|
||||
import { findTrackById } from '../../../media/utils/tracks';
|
||||
import {
|
||||
dispatchCuesStep,
|
||||
type TextLoadStep,
|
||||
type TextMessagePipelines,
|
||||
textStepWiring,
|
||||
} from '../../actors/text-track-segment-loader';
|
||||
import { peekHead } from '../../primitives/head-peek';
|
||||
import {
|
||||
dispatchStep,
|
||||
@@ -48,6 +42,12 @@ import {
|
||||
type MessagePipelines,
|
||||
type StepDeps,
|
||||
} from '../../primitives/segment-load-pipeline';
|
||||
import {
|
||||
dispatchCuesStep,
|
||||
type TextLoadStep,
|
||||
type TextMessagePipelines,
|
||||
textStepWiring,
|
||||
} from '../../primitives/text-segment-load-pipeline';
|
||||
|
||||
// Declared locally so this module carries no `behaviors` import (first step toward
|
||||
// relocating it to `primitives/dom`). Structurally identical to the
|
||||
|
||||
@@ -24,12 +24,11 @@ import type { ReadonlySignal, Signal } from '../../../core/signals/primitives';
|
||||
import { createTextTracksActor } from '../../actors/dom/text-tracks';
|
||||
import {
|
||||
createTextTrackSegmentLoaderActor,
|
||||
type TextMessagePipelines,
|
||||
type TextTrackSegmentLoaderActor,
|
||||
type TextTrackSegmentLoaderActorConfig,
|
||||
type TextTrackSegmentResolver,
|
||||
} from '../../actors/text-track-segment-loader';
|
||||
import type { TextTracksActor } from '../../actors/text-tracks';
|
||||
import type { TextMessagePipelines, TextTrackSegmentResolver } from '../../primitives/text-segment-load-pipeline';
|
||||
|
||||
export interface TextTrackActorsContext {
|
||||
mediaElement?: HTMLMediaElement | undefined;
|
||||
|
||||
@@ -30,7 +30,7 @@ import type { BandwidthConfig, BandwidthState } from '../../../network/bandwidth
|
||||
import type { SegmentLoaderActor } from '../../actors/dom/segment-loader';
|
||||
import type { SourceBufferActor } from '../../actors/dom/source-buffer';
|
||||
import type { TextTracksActor } from '../../actors/dom/text-tracks';
|
||||
import type { TextTrackSegmentLoaderActor, TextTrackSegmentResolver } from '../../actors/text-track-segment-loader';
|
||||
import type { TextTrackSegmentLoaderActor } from '../../actors/text-track-segment-loader';
|
||||
import {
|
||||
calculatePresentationDuration,
|
||||
type PresentationDurationResolver,
|
||||
@@ -61,6 +61,7 @@ import { resolveAudioTrack, resolveTextTrack, resolveVideoTrack } from '../../be
|
||||
import { type FailoverMonitorConfig, setupFailoverMonitor } from '../../behaviors/setup-failover-monitor';
|
||||
import { syncPreload } from '../../behaviors/sync-preload';
|
||||
import { switchAudioTrack, switchTextTrack, switchVideoTrack } from '../../behaviors/track-switching';
|
||||
import type { TextTrackSegmentResolver } from '../../primitives/text-segment-load-pipeline';
|
||||
|
||||
// ============================================================================
|
||||
// HLS Engine State & Context
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
{ "path": "../../../network" },
|
||||
{ "path": "../../../media" },
|
||||
{ "path": "../../../media/dom" },
|
||||
{ "path": "../../primitives" },
|
||||
{ "path": "../../behaviors" },
|
||||
{ "path": "../../behaviors/dom" },
|
||||
{ "path": "../../actors" },
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* The text-track **load pipeline** — the step vocabulary and base steps a text-segment
|
||||
* loader runs, the text mirror of `segment-load-pipeline`. Extracted from the loader
|
||||
* actor so the "what" (the composable steps) is separable from the "how" (scheduling).
|
||||
* A pipeline is a flat, ordered list of {@link TextLoadStep}s (text has a single op
|
||||
* type, so no per-type `Record`); the default is `resolveCues → dispatchCues`, and a
|
||||
* composition can insert its own steps (e.g. non-zero-PTS cue rebase) without the
|
||||
* loader knowing.
|
||||
*
|
||||
* The dispatch step reaches its cue sink through the structural {@link CueSink} seam
|
||||
* rather than the concrete `TextTracksActor` type — the loader folds the real actor
|
||||
* into `config`, and it satisfies the seam by structure — so this module names no
|
||||
* actor and stays DOM-free (generic over the cue type `C`).
|
||||
*/
|
||||
import type { AnySlotMap } from '../../core/composition/create-composition';
|
||||
import type { Cue, Segment } from '../../media/types';
|
||||
import type { AddCuesMessage } from './text-track-messages';
|
||||
|
||||
// ============================================================================
|
||||
// SINK SEAM
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* The structural view of a cue sink the base steps use — just the `send`
|
||||
* {@link dispatchCuesStep} needs. The concrete `TextTracksActor` satisfies it by
|
||||
* structure, so the pipeline names no actor.
|
||||
*/
|
||||
export interface CueSink<C extends Cue = Cue> {
|
||||
send(message: AddCuesMessage<C>): void;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// STEP MODEL
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Resolves a text-track segment URL into the array of cues it contains.
|
||||
*
|
||||
* "Resolve" because the fn covers both network fetch and parse into the
|
||||
* domain model. Host-agnostic — the concrete resolver (e.g. the
|
||||
* browser's native VTT resolver) is supplied at engine-assembly time,
|
||||
* so this stays DOM-free. A pure `url → cues` primitive (the text
|
||||
* analog of the v/a loader's `fetchBytes`); composition-awareness lives in
|
||||
* the injected {@link TextLoadStep}s, not here.
|
||||
*/
|
||||
export type TextTrackSegmentResolver<C extends Cue = Cue> = (url: string) => Promise<C[]>;
|
||||
|
||||
/** Internal load-task descriptor — one segment fetch + dispatch unit. */
|
||||
export interface TextLoadTask {
|
||||
segment: Segment;
|
||||
trackId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A text load in mid-pipeline — the text analog of the v/a loader's `Frame`.
|
||||
* `resolveCuesStep` fills `cues`; `dispatchCuesStep` sends them. `metadata` is
|
||||
* opaque header metadata a resolve step may attach for a later step to read
|
||||
* (e.g. relocation stashes the `X-TIMESTAMP-MAP` correlation here for its rebase
|
||||
* step). Typed `unknown` so the generic loader stays host-agnostic — the step
|
||||
* that reads it knows its concrete shape (mirrors `StepDeps.state`).
|
||||
*/
|
||||
export interface TextFrame<C extends Cue = Cue> {
|
||||
readonly op: TextLoadTask;
|
||||
cues?: C[];
|
||||
metadata?: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* One stage of a text message pipeline — the text analog of the v/a loader's
|
||||
* `LoadStep`. Mutates the {@link TextFrame} in place and may be async; the runner
|
||||
* checks `signal.aborted` before each step and passes the actor's
|
||||
* {@link TextStepDeps} on every call, so a stateless step (`resolveCuesStep`) is a
|
||||
* plain value and a step that needs composition signals (relocation's cue rebase)
|
||||
* reads them from `deps` at call time.
|
||||
*/
|
||||
export type TextLoadStep<C extends Cue = Cue> = (
|
||||
frame: TextFrame<C>,
|
||||
signal: AbortSignal,
|
||||
deps: TextStepDeps
|
||||
) => void | Promise<void>;
|
||||
|
||||
/**
|
||||
* The uniform passthrough handed to each {@link TextLoadStep} — the composition triple,
|
||||
* the text analog of `StepDeps`. `state`/`context` are the composition signal maps;
|
||||
* `config` is the threaded config with the loader's wiring folded in (see
|
||||
* {@link textStepWiring} + `createTextTrackSegmentLoaderActor`). Typed loose: composition
|
||||
* steps read `state`; base steps read the folded wiring off `config`.
|
||||
*/
|
||||
export interface TextStepDeps {
|
||||
state: AnySlotMap;
|
||||
context: AnySlotMap;
|
||||
config: object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base-step view of the loader's wiring, folded into `config` by
|
||||
* `createTextTrackSegmentLoaderActor` so base steps read it from the uniform passthrough
|
||||
* — present in both composition and standalone use. `config` is loose (`object`), so
|
||||
* assert the shape here (mirrors the v/a loader's `stepWiring`). The sink is the
|
||||
* structural {@link CueSink}, not the concrete actor.
|
||||
*/
|
||||
export function textStepWiring<C extends Cue>(
|
||||
deps: TextStepDeps
|
||||
): { textTracksActor: CueSink<C>; resolveSegment: TextTrackSegmentResolver<C> } {
|
||||
return deps.config as { textTracksActor: CueSink<C>; resolveSegment: TextTrackSegmentResolver<C> };
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the ordered step list, called **once per actor** (mirrors the v/a loader's
|
||||
* `MessagePipelines`, but text has a single op type so it's a flat array, not a
|
||||
* `Record`). The default ({@link DEFAULT_TEXT_MESSAGE_PIPELINES}) is
|
||||
* `resolveCues → dispatchCues`; a non-zero-PTS composition returns a list that
|
||||
* inserts a cue-rebase step (see `relocatingTextPipelines`), so the loader stays
|
||||
* oblivious to relocation.
|
||||
*/
|
||||
export type TextMessagePipelines<C extends Cue = Cue> = () => TextLoadStep<C>[];
|
||||
|
||||
// ============================================================================
|
||||
// BASE STEPS
|
||||
// ============================================================================
|
||||
|
||||
// Base steps are generic over the cue type `C` (generic arrow consts, not
|
||||
// `TextLoadStep<Cue>` values): each touches `C` — `frame.cues: C[]` and the
|
||||
// `C`-typed `textStepWiring<C>` — so a `Cue`-typed const wouldn't slot into a
|
||||
// `VTTCue` pipeline. A generic function assigns to any `TextLoadStep<C>`.
|
||||
|
||||
/** Resolve the op's cues (via the injected host primitive) into the frame. The text analog of `fetchStep`. */
|
||||
export const resolveCuesStep = async <C extends Cue>(
|
||||
frame: TextFrame<C>,
|
||||
signal: AbortSignal,
|
||||
deps: TextStepDeps
|
||||
): Promise<void> => {
|
||||
const cues = await textStepWiring<C>(deps).resolveSegment(frame.op.segment.url);
|
||||
if (signal.aborted) return;
|
||||
frame.cues = cues;
|
||||
};
|
||||
|
||||
/** Dispatch the frame's cues to the TextTracksActor as `add-cues`. The text analog of `dispatchStep`. */
|
||||
export const dispatchCuesStep = <C extends Cue>(
|
||||
frame: TextFrame<C>,
|
||||
_signal: AbortSignal,
|
||||
deps: TextStepDeps
|
||||
): void => {
|
||||
const { op } = frame;
|
||||
textStepWiring<C>(deps).textTracksActor.send({
|
||||
type: 'add-cues',
|
||||
meta: {
|
||||
trackId: op.trackId,
|
||||
id: op.segment.id,
|
||||
startTime: op.segment.startTime,
|
||||
duration: op.segment.duration,
|
||||
},
|
||||
cues: frame.cues ?? [],
|
||||
});
|
||||
};
|
||||
|
||||
/** Tier 0 default: resolve then dispatch. No relocation vocabulary. */
|
||||
export const DEFAULT_TEXT_MESSAGE_PIPELINES = <C extends Cue>(): TextLoadStep<C>[] => [
|
||||
resolveCuesStep,
|
||||
dispatchCuesStep,
|
||||
];
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Cue-sink message protocol — the `add-cues` operation a text-track sink accepts.
|
||||
* Plain, transport-neutral data: the text load pipeline (`text-segment-load-pipeline`)
|
||||
* produces it and the TextTracksActor consumes it, so it lives at the primitives layer
|
||||
* both depend on. The text mirror of `source-buffer-messages`.
|
||||
*/
|
||||
import type { Cue, Segment } from '../../media/types';
|
||||
|
||||
/** Segment identity and timing — mirrors AppendSegmentMeta without trackId (keyed separately). */
|
||||
export type CueSegmentMeta = Pick<Segment, 'id' | 'startTime' | 'duration'> & { trackId: string };
|
||||
|
||||
export interface AddCuesMessage<C extends Cue = Cue> {
|
||||
type: 'add-cues';
|
||||
meta: CueSegmentMeta;
|
||||
cues: C[];
|
||||
}
|
||||
Reference in New Issue
Block a user