@videojs/spf 10.0.0-beta.3 → 10.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -345,6 +345,28 @@ interface Actor<Status extends string, Context> {
345
345
  destroy(): void;
346
346
  }
347
347
  //#endregion
348
+ //#region src/dom/media/append-segment.d.ts
349
+ /**
350
+ * Segment appender helper.
351
+ *
352
+ * Appends media data (ArrayBuffer or AsyncIterable<Uint8Array> stream) to a
353
+ * SourceBuffer, waiting for `updateend` between calls so the browser can
354
+ * process each append before the next one arrives.
355
+ */
356
+ /** Data accepted by appendSegment — a full buffer or an async chunk stream. */
357
+ type AppendData = ArrayBuffer | AsyncIterable<Uint8Array>;
358
+ /**
359
+ * Append media data to a SourceBuffer.
360
+ *
361
+ * Accepts either a full ArrayBuffer (single append) or an AsyncIterable of
362
+ * Uint8Array chunks (one append per chunk, in order). Waits for `updateend`
363
+ * between each call so appends are serialized correctly.
364
+ *
365
+ * Errors from the SourceBuffer (`error` event) or from the iterable are
366
+ * propagated as rejections.
367
+ */
368
+ declare function appendSegment(sourceBuffer: SourceBuffer, data: AppendData, signal?: AbortSignal): Promise<void>;
369
+ //#endregion
348
370
  //#region src/dom/media/source-buffer-actor.d.ts
349
371
  interface BufferedRange {
350
372
  start: number;
@@ -357,14 +379,14 @@ type AppendSegmentMeta = Pick<Segment, 'id' | 'startTime' | 'duration'> & {
357
379
  };
358
380
  type AppendInitMessage = {
359
381
  type: 'append-init';
360
- data: ArrayBuffer;
382
+ data: AppendData;
361
383
  meta: {
362
384
  trackId: Track['id'];
363
385
  };
364
386
  };
365
387
  type AppendSegmentMessage = {
366
388
  type: 'append-segment';
367
- data: ArrayBuffer;
389
+ data: AppendData;
368
390
  meta: AppendSegmentMeta;
369
391
  };
370
392
  type RemoveMessage = {
@@ -381,6 +403,12 @@ interface SourceBufferActorContext {
381
403
  segments: Array<Pick<Segment, 'id' | 'startTime' | 'duration'> & {
382
404
  trackId: Track['id'];
383
405
  trackBandwidth?: number;
406
+ /**
407
+ * True while a streaming append is in progress for this segment.
408
+ * The segment's data is partially present in the SourceBuffer.
409
+ * Downstream code must not treat a partial segment as fully buffered.
410
+ */
411
+ partial?: boolean;
384
412
  }>;
385
413
  bufferedRanges: BufferedRange[];
386
414
  }
@@ -685,5 +713,5 @@ declare class SpfMedia {
685
713
  play(): Promise<void>;
686
714
  }
687
715
  //#endregion
688
- export { PresentationAction as a, SourceBufferActor as c, WritableState as d, BandwidthState as f, createPlaybackEngine as i, TrackSelectionState as l, PlaybackEngine as n, EventStream as o, PlaybackEngineConfig as r, loadTextTrackCues as s, SpfMedia as t, Presentation as u };
689
- //# sourceMappingURL=adapter-l8iJN_GI.d.ts.map
716
+ export { PresentationAction as a, SourceBufferActor as c, Presentation as d, WritableState as f, createPlaybackEngine as i, appendSegment as l, PlaybackEngine as n, EventStream as o, BandwidthState as p, PlaybackEngineConfig as r, loadTextTrackCues as s, SpfMedia as t, TrackSelectionState as u };
717
+ //# sourceMappingURL=adapter-CE86m9Eh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-CE86m9Eh.d.ts","names":[],"sources":["../src/core/abr/bandwidth-estimator.ts","../src/core/state/create-state.ts","../src/core/types/index.ts","../src/core/utils/track-selection.ts","../src/core/actor.ts","../src/dom/media/append-segment.ts","../src/dom/media/source-buffer-actor.ts","../src/dom/features/load-text-track-cues.ts","../src/core/events/create-event-stream.ts","../src/core/features/resolve-presentation.ts","../src/core/features/resolve-track.ts","../src/core/features/select-tracks.ts","../src/dom/playback-engine/engine.ts","../src/dom/playback-engine/adapter.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { listen } from "@videojs/utils/dom";
2
- import { isNil, isUndefined } from "@videojs/utils/predicate";
2
+ import { isNil } from "@videojs/utils/predicate";
3
3
 
4
4
  //#region src/core/state/create-state.ts
5
5
  /**
@@ -1067,6 +1067,53 @@ function isCodecSupported(mimeCodec) {
1067
1067
  return MediaSource.isTypeSupported(mimeCodec);
1068
1068
  }
1069
1069
 
1070
+ //#endregion
1071
+ //#region src/dom/network/chunked-stream-iterable.ts
1072
+ const DEFAULT_MIN_CHUNK_SIZE = 2 ** 17;
1073
+ /**
1074
+ * Adapts a `ReadableStream<Uint8Array>` (e.g. `response.body`) into an
1075
+ * `AsyncIterable<Uint8Array>` that yields chunks no smaller than
1076
+ * `minChunkSize` bytes. Smaller network chunks are accumulated and yielded
1077
+ * together once the threshold is met. Any remainder is flushed on stream end.
1078
+ *
1079
+ * Errors from the underlying stream propagate naturally — the reader lock is
1080
+ * always released via `finally`.
1081
+ */
1082
+ var ChunkedStreamIterable = class {
1083
+ minChunkSize;
1084
+ #readableStream;
1085
+ constructor(readableStream, { minChunkSize = DEFAULT_MIN_CHUNK_SIZE } = {}) {
1086
+ this.#readableStream = readableStream;
1087
+ this.minChunkSize = minChunkSize;
1088
+ }
1089
+ async *[Symbol.asyncIterator]() {
1090
+ let pending;
1091
+ const reader = this.#readableStream.getReader();
1092
+ try {
1093
+ while (true) {
1094
+ const { done, value } = await reader.read();
1095
+ if (done) {
1096
+ if (pending) yield pending;
1097
+ break;
1098
+ }
1099
+ pending = pending ? concat(pending, value) : value;
1100
+ if (pending.length >= this.minChunkSize) {
1101
+ yield pending;
1102
+ pending = void 0;
1103
+ }
1104
+ }
1105
+ } finally {
1106
+ reader.releaseLock();
1107
+ }
1108
+ }
1109
+ };
1110
+ function concat(a, b) {
1111
+ const result = new Uint8Array(a.length + b.length);
1112
+ result.set(a);
1113
+ result.set(b, a.length);
1114
+ return result;
1115
+ }
1116
+
1070
1117
  //#endregion
1071
1118
  //#region src/dom/network/fetch.ts
1072
1119
  /**
@@ -1103,16 +1150,6 @@ async function fetchResolvable(addressable, options) {
1103
1150
  return fetch(request);
1104
1151
  }
1105
1152
  /**
1106
- * Fetch resolvable as bytes.
1107
- *
1108
- * Convenience wrapper around fetchResolvable that resolves the body as an
1109
- * ArrayBuffer. Use this when you need the raw bytes (e.g. segment appends).
1110
- * For text or streaming consumption, use fetchResolvable directly.
1111
- */
1112
- async function fetchResolvableBytes(addressable, options) {
1113
- return (await fetchResolvable(addressable, options)).arrayBuffer();
1114
- }
1115
- /**
1116
1153
  * Extract text from Response.
1117
1154
  *
1118
1155
  * Accepts minimal Response-like object (just needs text() method).
@@ -1411,14 +1448,6 @@ const SelectedTrackIdKeyByType = {
1411
1448
  text: "selectedTextTrackId"
1412
1449
  };
1413
1450
  /**
1414
- * Map track type to buffer owner property key.
1415
- * Used for SourceBuffer references in owners.
1416
- */
1417
- const BufferKeyByType = {
1418
- video: "videoBuffer",
1419
- audio: "audioBuffer"
1420
- };
1421
- /**
1422
1451
  * Get selected track from state by type.
1423
1452
  * Returns properly typed track (partially or fully resolved) or undefined.
1424
1453
  * Type parameter T is inferred from the type argument.
@@ -1452,7 +1481,9 @@ function getSelectedTrack(state, type) {
1452
1481
  * operation (if still needed) or preempts it.
1453
1482
  *
1454
1483
  * @param sourceBufferActor - Shared SourceBufferActor reference (not owned)
1455
- * @param fetchBytes - Tracked fetch closure (owns throughput sampling)
1484
+ * @param fetchBytes - Tracked fetch closure (owns throughput sampling for segments).
1485
+ * Accepts an optional `minChunkSize` in options; init segments pass `Infinity`
1486
+ * so the entire body accumulates as one chunk before appending.
1456
1487
  */
1457
1488
  function createSegmentLoaderActor(sourceBufferActor, fetchBytes) {
1458
1489
  let pendingTasks = null;
@@ -1462,7 +1493,7 @@ function createSegmentLoaderActor(sourceBufferActor, fetchBytes) {
1462
1493
  let running = false;
1463
1494
  let destroyed = false;
1464
1495
  const getBufferedSegments = (allSegments) => {
1465
- const bufferedIds = new Set(sourceBufferActor.snapshot.context.segments.map((s) => s.id));
1496
+ const bufferedIds = new Set(sourceBufferActor.snapshot.context.segments.filter((s) => !s.partial).map((s) => s.id));
1466
1497
  return allSegments.filter((s) => bufferedIds.has(s.id));
1467
1498
  };
1468
1499
  /**
@@ -1503,12 +1534,14 @@ function createSegmentLoaderActor(sourceBufferActor, fetchBytes) {
1503
1534
  if (actorCtx.initTrackId !== track.id) tasks.push({
1504
1535
  type: "append-init",
1505
1536
  meta: { trackId: track.id },
1506
- url: track.initialization.url
1537
+ url: track.initialization.url,
1538
+ ...track.initialization.byteRange !== void 0 && { byteRange: track.initialization.byteRange }
1507
1539
  });
1508
1540
  if (range) {
1509
1541
  const EPSILON = 1e-4;
1510
1542
  const segmentsToLoad = getSegmentsToLoad(track.segments, bufferedSegments, currentTime).filter((seg) => {
1511
1543
  const existing = actorCtx.segments.find((s) => Math.abs(s.startTime - seg.startTime) < EPSILON);
1544
+ if (existing?.partial) return true;
1512
1545
  if (!existing?.trackBandwidth || !track.bandwidth) return true;
1513
1546
  return track.bandwidth > existing.trackBandwidth;
1514
1547
  });
@@ -1521,7 +1554,8 @@ function createSegmentLoaderActor(sourceBufferActor, fetchBytes) {
1521
1554
  trackId: track.id,
1522
1555
  trackBandwidth: track.bandwidth
1523
1556
  },
1524
- url: segment.url
1557
+ url: segment.url,
1558
+ ...segment.byteRange !== void 0 && { byteRange: segment.byteRange }
1525
1559
  });
1526
1560
  }
1527
1561
  return tasks;
@@ -1543,7 +1577,10 @@ function createSegmentLoaderActor(sourceBufferActor, fetchBytes) {
1543
1577
  if (task.type === "append-init") {
1544
1578
  inFlightInitTrackId = task.meta.trackId;
1545
1579
  if (!signal.aborted) {
1546
- const data = await fetchBytes(task, { signal });
1580
+ const data = await fetchBytes(task, {
1581
+ signal,
1582
+ minChunkSize: Infinity
1583
+ });
1547
1584
  const isTrackSwitch = pendingTasks?.some((t) => t.type === "append-init" && t.meta.trackId !== task.meta.trackId);
1548
1585
  if (!signal.aborted || !isTrackSwitch) {
1549
1586
  const appendSignal = signal.aborted ? new AbortController().signal : signal;
@@ -1558,10 +1595,10 @@ function createSegmentLoaderActor(sourceBufferActor, fetchBytes) {
1558
1595
  }
1559
1596
  inFlightSegmentId = task.meta.id;
1560
1597
  if (!signal.aborted) {
1561
- const data = await fetchBytes(task, { signal });
1598
+ const stream = await fetchBytes(task, { signal });
1562
1599
  if (!signal.aborted) await sourceBufferActor.send({
1563
1600
  type: "append-segment",
1564
- data,
1601
+ data: stream,
1565
1602
  meta: task.meta
1566
1603
  }, signal);
1567
1604
  }
@@ -1623,32 +1660,42 @@ function createSegmentLoaderActor(sourceBufferActor, fetchBytes) {
1623
1660
 
1624
1661
  //#endregion
1625
1662
  //#region src/dom/features/load-segments.ts
1626
- const ActorKeyByType$1 = {
1663
+ const ActorKeyByType = {
1627
1664
  video: "videoBufferActor",
1628
1665
  audio: "audioBufferActor"
1629
1666
  };
1630
- /**
1631
- * Creates a fetch function that transparently samples bandwidth after each
1632
- * completed request. Callers receive bytes; throughput tracking is invisible.
1633
- *
1634
- * `onSample` is an optional callback invoked after each sample is recorded,
1635
- * used for bridging throughput state outward (e.g. migration bridge to global
1636
- * state). A callback is used rather than a subscription so that no immediate
1637
- * fire occurs at setup time — subscriptions fire on registration and would
1638
- * trigger spurious state changes before any work has started.
1639
- */
1640
1667
  function createTrackedFetch(throughput, onSample) {
1641
1668
  return async (addressable, options) => {
1642
- const start = performance.now();
1643
- const data = await fetchResolvableBytes(addressable, options);
1644
- const elapsed = performance.now() - start;
1645
- const next = sampleBandwidth(throughput.current, elapsed, data.byteLength);
1646
- throughput.patch(next);
1647
- throughput.flush();
1648
- onSample?.(next);
1649
- return data;
1669
+ const { minChunkSize,...fetchOptions } = options ?? {};
1670
+ const response = await fetchResolvable(addressable, fetchOptions);
1671
+ if (!response.body) throw new Error("Response has no body");
1672
+ const body = response.body;
1673
+ return { [Symbol.asyncIterator]: async function* () {
1674
+ let chunkStart = performance.now();
1675
+ for await (const chunk of new ChunkedStreamIterable(body, ...minChunkSize !== void 0 ? [{ minChunkSize }] : [])) {
1676
+ const elapsed = performance.now() - chunkStart;
1677
+ const next = sampleBandwidth(throughput.current, elapsed, chunk.byteLength);
1678
+ throughput.patch(next);
1679
+ throughput.flush();
1680
+ onSample?.(next);
1681
+ yield chunk;
1682
+ chunkStart = performance.now();
1683
+ }
1684
+ } };
1650
1685
  };
1651
1686
  }
1687
+ /**
1688
+ * Non-tracking fetch: eagerly starts the request and returns the response body
1689
+ * as a lazy chunk iterable. Used for audio tracks which don't sample bandwidth.
1690
+ * Pass `minChunkSize: Infinity` to accumulate the full body as a single chunk
1691
+ * (equivalent to arrayBuffer() but through the same streaming path).
1692
+ */
1693
+ async function fetchStream(addressable, options) {
1694
+ const { minChunkSize,...fetchOptions } = options ?? {};
1695
+ const response = await fetchResolvable(addressable, fetchOptions);
1696
+ if (!response.body) throw new Error("Response has no body");
1697
+ return new ChunkedStreamIterable(response.body, ...minChunkSize !== void 0 ? [{ minChunkSize }] : []);
1698
+ }
1652
1699
  function selectLoadingInputs([segmentsCanLoad, state], type) {
1653
1700
  const { playbackInitiated, preload, currentTime } = state;
1654
1701
  return {
@@ -1731,7 +1778,7 @@ function loadingInputsEq(prevState, curState) {
1731
1778
  */
1732
1779
  function loadSegments({ state, owners }, config) {
1733
1780
  const { type } = config;
1734
- const actorKey = ActorKeyByType$1[type];
1781
+ const actorKey = ActorKeyByType[type];
1735
1782
  const initialBandwidth = state.current.bandwidthState;
1736
1783
  const throughput = createState(initialBandwidth ?? {
1737
1784
  fastEstimate: 0,
@@ -1743,7 +1790,7 @@ function loadSegments({ state, owners }, config) {
1743
1790
  const fetchBytes = type === "video" ? createTrackedFetch(throughput, initialBandwidth !== void 0 ? (next) => {
1744
1791
  state.patch({ bandwidthState: next });
1745
1792
  state.flush();
1746
- } : void 0) : fetchResolvableBytes;
1793
+ } : void 0) : fetchStream;
1747
1794
  const segmentLoader = createState(void 0);
1748
1795
  const unsubActorLifecycle = owners.subscribe((o) => o[actorKey], (actor) => {
1749
1796
  if (actor) segmentLoader.patch(createSegmentLoaderActor(actor, fetchBytes));
@@ -2080,25 +2127,23 @@ function trackPlaybackInitiated({ state, owners, events }) {
2080
2127
  //#endregion
2081
2128
  //#region src/dom/media/append-segment.ts
2082
2129
  /**
2083
- * Segment appender helper (P11)
2084
- *
2085
- * Appends media segments (ArrayBuffer) to SourceBuffer.
2086
- */
2087
- /**
2088
- * Append a media segment to a SourceBuffer.
2089
- *
2090
- * Waits for the SourceBuffer to be ready (not updating), then appends
2091
- * the segment data. Returns a promise that resolves when append completes.
2130
+ * Append media data to a SourceBuffer.
2092
2131
  *
2093
- * @param sourceBuffer - The SourceBuffer to append to
2094
- * @param segmentData - The segment data as ArrayBuffer
2095
- * @returns Promise that resolves when append completes
2132
+ * Accepts either a full ArrayBuffer (single append) or an AsyncIterable of
2133
+ * Uint8Array chunks (one append per chunk, in order). Waits for `updateend`
2134
+ * between each call so appends are serialized correctly.
2096
2135
  *
2097
- * @example
2098
- * const data = await fetch(segmentUrl).then(r => r.arrayBuffer());
2099
- * await appendSegment(videoSourceBuffer, data);
2136
+ * Errors from the SourceBuffer (`error` event) or from the iterable are
2137
+ * propagated as rejections.
2100
2138
  */
2101
- async function appendSegment(sourceBuffer, segmentData) {
2139
+ async function appendSegment(sourceBuffer, data, signal) {
2140
+ if (data instanceof ArrayBuffer) await appendChunk(sourceBuffer, data);
2141
+ else for await (const chunk of data) {
2142
+ if (signal?.aborted) throw signal.reason ?? new DOMException("Aborted", "AbortError");
2143
+ await appendChunk(sourceBuffer, chunk);
2144
+ }
2145
+ }
2146
+ async function appendChunk(sourceBuffer, data) {
2102
2147
  if (sourceBuffer.updating) await new Promise((resolve) => {
2103
2148
  const onUpdateEnd = () => {
2104
2149
  sourceBuffer.removeEventListener("updateend", onUpdateEnd);
@@ -2122,7 +2167,7 @@ async function appendSegment(sourceBuffer, segmentData) {
2122
2167
  sourceBuffer.addEventListener("updateend", onUpdateEnd);
2123
2168
  sourceBuffer.addEventListener("error", onError);
2124
2169
  try {
2125
- sourceBuffer.appendBuffer(segmentData);
2170
+ sourceBuffer.appendBuffer(data);
2126
2171
  } catch (error) {
2127
2172
  cleanup();
2128
2173
  reject(error);
@@ -2570,7 +2615,7 @@ function isLastSegmentAppended(segments, actor) {
2570
2615
  if (segments.length === 0) return true;
2571
2616
  const lastSeg = segments[segments.length - 1];
2572
2617
  if (!lastSeg) return false;
2573
- return actor?.snapshot.context.segments.some((s) => s.id === lastSeg.id) ?? false;
2618
+ return actor?.snapshot.context.segments.some((s) => s.id === lastSeg.id && !s.partial) ?? false;
2574
2619
  }
2575
2620
  /**
2576
2621
  * Check if the last segment has been appended for each selected track.
@@ -2800,14 +2845,26 @@ function appendInitTask(message, { signal, getCtx, sourceBuffer }) {
2800
2845
  };
2801
2846
  }, { signal });
2802
2847
  }
2803
- function appendSegmentTask(message, { signal, getCtx, sourceBuffer }) {
2848
+ function appendSegmentTask(message, { signal, getCtx, sourceBuffer, onPartialContext }) {
2804
2849
  return new Task(async (taskSignal) => {
2805
2850
  const ctx = getCtx();
2806
2851
  if (taskSignal.aborted) return ctx;
2807
- await appendSegment(sourceBuffer, message.data);
2808
2852
  const { meta } = message;
2809
2853
  const EPSILON = 1e-4;
2810
2854
  const filtered = ctx.segments.filter((s) => Math.abs(s.startTime - meta.startTime) >= EPSILON);
2855
+ if (!(message.data instanceof ArrayBuffer)) onPartialContext({
2856
+ ...ctx,
2857
+ segments: [...filtered, {
2858
+ id: meta.id,
2859
+ startTime: meta.startTime,
2860
+ duration: meta.duration,
2861
+ trackId: meta.trackId,
2862
+ ...meta.trackBandwidth !== void 0 && { trackBandwidth: meta.trackBandwidth },
2863
+ partial: true
2864
+ }],
2865
+ bufferedRanges: ctx.bufferedRanges
2866
+ });
2867
+ await appendSegment(sourceBuffer, message.data, taskSignal);
2811
2868
  return {
2812
2869
  ...ctx,
2813
2870
  segments: [...filtered, {
@@ -2882,10 +2939,18 @@ function createSourceBufferActor(sourceBuffer, initialContext) {
2882
2939
  send(message, signal) {
2883
2940
  if (state.current.status !== "idle") return Promise.reject(new SourceBufferActorError(`send() called while actor is ${state.current.status}`));
2884
2941
  state.patch({ status: "updating" });
2942
+ const onPartialContext = (ctx) => {
2943
+ state.patch({
2944
+ status: "updating",
2945
+ context: ctx
2946
+ });
2947
+ state.flush();
2948
+ };
2885
2949
  const task = messageToTask(message, {
2886
2950
  signal,
2887
2951
  getCtx: () => state.current.context,
2888
- sourceBuffer
2952
+ sourceBuffer,
2953
+ onPartialContext
2889
2954
  });
2890
2955
  return runner.schedule(task).then(applyResult).catch(handleError);
2891
2956
  },
@@ -2894,11 +2959,19 @@ function createSourceBufferActor(sourceBuffer, initialContext) {
2894
2959
  if (messages.length === 0) return Promise.resolve();
2895
2960
  state.patch({ status: "updating" });
2896
2961
  let workingCtx = state.current.context;
2962
+ const onPartialContext = (ctx) => {
2963
+ state.patch({
2964
+ status: "updating",
2965
+ context: ctx
2966
+ });
2967
+ state.flush();
2968
+ };
2897
2969
  for (const message of messages.slice(0, -1)) {
2898
2970
  const task = messageToTask(message, {
2899
2971
  signal,
2900
2972
  getCtx: () => workingCtx,
2901
- sourceBuffer
2973
+ sourceBuffer,
2974
+ onPartialContext
2902
2975
  });
2903
2976
  runner.schedule(task).then((newCtx) => {
2904
2977
  workingCtx = newCtx;
@@ -2907,7 +2980,8 @@ function createSourceBufferActor(sourceBuffer, initialContext) {
2907
2980
  const lastTask = messageToTask(messages[messages.length - 1], {
2908
2981
  signal,
2909
2982
  getCtx: () => workingCtx,
2910
- sourceBuffer
2983
+ sourceBuffer,
2984
+ onPartialContext
2911
2985
  });
2912
2986
  return runner.schedule(lastTask).then(applyResult).catch(handleError);
2913
2987
  },
@@ -2921,30 +2995,6 @@ function createSourceBufferActor(sourceBuffer, initialContext) {
2921
2995
 
2922
2996
  //#endregion
2923
2997
  //#region src/dom/features/setup-sourcebuffer.ts
2924
- /** Map track type to SourceBufferActor owner property key. */
2925
- const ActorKeyByType = {
2926
- video: "videoBufferActor",
2927
- audio: "audioBufferActor"
2928
- };
2929
- /**
2930
- * Setup SourceBuffer task (module-level, pure).
2931
- * Creates SourceBuffer for resolved track and waits a frame before completing.
2932
- */
2933
- const setupSourceBufferTask = async ({ currentState, currentOwners }, context) => {
2934
- const track = getSelectedTrack(currentState, context.config.type);
2935
- if (!track || !isResolvedTrack(track)) return;
2936
- if (!track.codecs || track.codecs.length === 0) return;
2937
- const mimeCodec = buildMimeCodec(track);
2938
- const buffer = createSourceBuffer(currentOwners.mediaSource, mimeCodec);
2939
- const actor = createSourceBufferActor(buffer);
2940
- const bufferKey = BufferKeyByType[context.config.type];
2941
- const actorKey = ActorKeyByType[context.config.type];
2942
- context.owners.patch({
2943
- [bufferKey]: buffer,
2944
- [actorKey]: actor
2945
- });
2946
- await new Promise((resolve) => requestAnimationFrame(resolve));
2947
- };
2948
2998
  /**
2949
2999
  * Build MIME codec string from track metadata.
2950
3000
  *
@@ -2960,66 +3010,47 @@ function buildMimeCodec(track) {
2960
3010
  return `${track.mimeType}; codecs="${codecString}"`;
2961
3011
  }
2962
3012
  /**
2963
- * Check if we can setup SourceBuffer for track type.
3013
+ * Setup all needed SourceBuffers as a single coordinated operation.
2964
3014
  *
2965
- * Requires:
2966
- * - MediaSource exists in owners
2967
- * - Track is selected
3015
+ * Waits until ALL selected tracks (video and/or audio) are resolved with
3016
+ * codecs, then creates every SourceBuffer in one synchronous block before
3017
+ * patching owners. This guarantees that downstream consumers (e.g.
3018
+ * loadSegments) never see a partial set of SourceBuffers — preventing the
3019
+ * Firefox bug where appending to a video SourceBuffer before the audio
3020
+ * SourceBuffer exists causes mozHasAudio to be permanently false.
2968
3021
  *
2969
- * Note: We don't check mediaSource.readyState because owners holds references
2970
- * to mutable objects. Changes to properties on those objects won't trigger
2971
- * observations. Instead, setupMediaSource only patches owners.mediaSource after
2972
- * it's already open, so if it exists in owners, it's ready to use.
3022
+ * Handles video-only, audio-only, and combined presentations correctly:
3023
+ * only the tracks that are actually selected are waited on and created.
2973
3024
  *
2974
- * Note: Track does not need to be resolved yet. The orchestration will wait
2975
- * for the track to be resolved (via resolveTrack) before creating the SourceBuffer.
2976
- */
2977
- function canSetupBuffer(state, owners, type) {
2978
- if (!owners.mediaSource) return false;
2979
- if (!getSelectedTrack(state, type)) return false;
2980
- return true;
2981
- }
2982
- /**
2983
- * Check if we should create SourceBuffer (not already created).
2984
- */
2985
- function shouldSetupBuffer(owners, type) {
2986
- const bufferKey = BufferKeyByType[type];
2987
- return isUndefined(owners[bufferKey]);
2988
- }
2989
- /**
2990
- * Setup SourceBuffer orchestration.
2991
- *
2992
- * Triggers when:
2993
- * - MediaSource exists and is in 'open' state
2994
- * - Track is selected (same condition as resolveTrack)
2995
- *
2996
- * Creates SourceBuffer when track becomes resolved with codecs.
2997
- * This allows setupSourceBuffer to run in parallel with resolveTrack.
2998
- *
2999
- * Note: Text tracks don't use SourceBuffers and should be handled separately.
3000
- *
3001
- * Generic over track type - create one orchestration per track type:
3002
3025
  * @example
3003
- * const videoCleanup = setupSourceBuffer({ state, owners }, { type: 'video' });
3004
- * const audioCleanup = setupSourceBuffer({ state, owners }, { type: 'audio' });
3026
+ * const cleanup = setupSourceBuffers({ state, owners });
3005
3027
  */
3006
- function setupSourceBuffer({ state, owners }, config) {
3007
- let currentTask = null;
3028
+ function setupSourceBuffers({ state, owners }) {
3029
+ let setupDone = false;
3008
3030
  return combineLatest([state, owners]).subscribe(async ([currentState, currentOwners]) => {
3009
- if (currentTask) return;
3010
- if (!canSetupBuffer(currentState, currentOwners, config.type) || !shouldSetupBuffer(currentOwners, config.type)) return;
3011
- currentTask = setupSourceBufferTask({
3012
- currentState,
3013
- currentOwners
3014
- }, {
3015
- owners,
3016
- config
3017
- });
3018
- try {
3019
- await currentTask;
3020
- } finally {
3021
- currentTask = null;
3031
+ if (setupDone) return;
3032
+ if (!currentOwners.mediaSource) return;
3033
+ const videoSelected = !!currentState.selectedVideoTrackId;
3034
+ const audioSelected = !!currentState.selectedAudioTrackId;
3035
+ if (!videoSelected && !audioSelected) return;
3036
+ const videoTrack = videoSelected ? getSelectedTrack(currentState, "video") : null;
3037
+ const audioTrack = audioSelected ? getSelectedTrack(currentState, "audio") : null;
3038
+ if (videoSelected && (!videoTrack || !isResolvedTrack(videoTrack) || !videoTrack.codecs?.length)) return;
3039
+ if (audioSelected && (!audioTrack || !isResolvedTrack(audioTrack) || !audioTrack.codecs?.length)) return;
3040
+ setupDone = true;
3041
+ const patch = {};
3042
+ if (videoSelected && videoTrack && isResolvedTrack(videoTrack)) {
3043
+ const buffer = createSourceBuffer(currentOwners.mediaSource, buildMimeCodec(videoTrack));
3044
+ patch.videoBuffer = buffer;
3045
+ patch.videoBufferActor = createSourceBufferActor(buffer);
3046
+ }
3047
+ if (audioSelected && audioTrack && isResolvedTrack(audioTrack)) {
3048
+ const buffer = createSourceBuffer(currentOwners.mediaSource, buildMimeCodec(audioTrack));
3049
+ patch.audioBuffer = buffer;
3050
+ patch.audioBufferActor = createSourceBufferActor(buffer);
3022
3051
  }
3052
+ owners.patch(patch);
3053
+ await new Promise((resolve) => requestAnimationFrame(resolve));
3023
3054
  });
3024
3055
  }
3025
3056
 
@@ -3371,14 +3402,10 @@ function createPlaybackEngine(config = {}) {
3371
3402
  state,
3372
3403
  owners
3373
3404
  }),
3374
- setupSourceBuffer({
3405
+ setupSourceBuffers({
3375
3406
  state,
3376
3407
  owners
3377
- }, { type: "video" }),
3378
- setupSourceBuffer({
3379
- state,
3380
- owners
3381
- }, { type: "audio" }),
3408
+ }),
3382
3409
  trackCurrentTime({
3383
3410
  state,
3384
3411
  owners
@@ -3509,4 +3536,4 @@ var SpfMedia = class {
3509
3536
 
3510
3537
  //#endregion
3511
3538
  export { trackPlaybackInitiated as a, destroyVttParser as c, appendSegment as i, parseVttSegment as l, createPlaybackEngine as n, trackCurrentTime as o, flushBuffer as r, loadTextTrackCues as s, SpfMedia as t, loadSegments as u };
3512
- //# sourceMappingURL=adapter-CMw-rvbk.js.map
3539
+ //# sourceMappingURL=adapter-ClnRGbQf.js.map