@videojs/spf 10.0.0-beta.26 → 10.0.0-beta.28
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.
- package/dist/default/core/signals/when.js +38 -0
- package/dist/default/core/signals/when.js.map +1 -0
- package/dist/default/core/tasks/delayed-reschedule.js +31 -0
- package/dist/default/core/tasks/delayed-reschedule.js.map +1 -0
- package/dist/default/core/tasks/task.js +133 -3
- package/dist/default/core/tasks/task.js.map +1 -1
- package/dist/default/hls-audio.js +3 -0
- package/dist/default/hls-background-video.js +3 -0
- package/dist/default/hls-video.js +4 -0
- package/dist/default/hls.js +6 -5
- package/dist/default/media/dom/capabilities.js +2 -0
- package/dist/default/media/dom/capabilities.js.map +1 -1
- package/dist/default/media/errors.js +62 -0
- package/dist/default/media/errors.js.map +1 -0
- package/dist/default/media/hls/parse-media-playlist.js +167 -16
- package/dist/default/media/hls/parse-media-playlist.js.map +1 -1
- package/dist/default/media/hls/parse-multivariant.js +14 -3
- package/dist/default/media/hls/parse-multivariant.js.map +1 -1
- package/dist/default/media/hls/reload-policy.js +71 -0
- package/dist/default/media/hls/reload-policy.js.map +1 -0
- package/dist/default/media/live-window.js +36 -0
- package/dist/default/media/live-window.js.map +1 -0
- package/dist/default/media/primitives/select-tracks.js +1 -24
- package/dist/default/media/primitives/select-tracks.js.map +1 -1
- package/dist/default/media/types/index.js +15 -1
- package/dist/default/media/types/index.js.map +1 -1
- package/dist/default/media/utils/tracks.js +14 -0
- package/dist/default/media/utils/tracks.js.map +1 -1
- package/dist/default/mux-audio.js +3 -0
- package/dist/default/mux-background-video.js +3 -0
- package/dist/default/mux-video.js +3 -0
- package/dist/default/playback/adapters/hls-audio/adapter.js +186 -0
- package/dist/default/playback/adapters/hls-audio/adapter.js.map +1 -0
- package/dist/default/playback/adapters/hls-audio/media.js +9 -0
- package/dist/default/playback/adapters/hls-audio/media.js.map +1 -0
- package/dist/default/playback/adapters/hls-background-video/adapter.js +123 -0
- package/dist/default/playback/adapters/hls-background-video/adapter.js.map +1 -0
- package/dist/default/playback/adapters/hls-background-video/host.js +60 -0
- package/dist/default/playback/adapters/hls-background-video/host.js.map +1 -0
- package/dist/default/playback/adapters/hls-background-video/media.js +21 -0
- package/dist/default/playback/adapters/hls-background-video/media.js.map +1 -0
- package/dist/default/playback/adapters/hls-video/adapter.js +316 -0
- package/dist/default/playback/adapters/hls-video/adapter.js.map +1 -0
- package/dist/default/playback/adapters/hls-video/error-surface.js +51 -0
- package/dist/default/playback/adapters/hls-video/error-surface.js.map +1 -0
- package/dist/default/playback/adapters/hls-video/media-tracks.js +126 -0
- package/dist/default/playback/adapters/hls-video/media-tracks.js.map +1 -0
- package/dist/default/playback/adapters/hls-video/media.js +11 -0
- package/dist/default/playback/adapters/hls-video/media.js.map +1 -0
- package/dist/default/playback/adapters/mux-audio/media.js +26 -0
- package/dist/default/playback/adapters/mux-audio/media.js.map +1 -0
- package/dist/default/playback/adapters/mux-video/adapter.js +92 -0
- package/dist/default/playback/adapters/mux-video/adapter.js.map +1 -0
- package/dist/default/playback/adapters/mux-video/media.js +23 -0
- package/dist/default/playback/adapters/mux-video/media.js.map +1 -0
- package/dist/default/playback/behaviors/collect-errors.js +77 -0
- package/dist/default/playback/behaviors/collect-errors.js.map +1 -0
- package/dist/default/playback/behaviors/dom/end-of-stream.js +1 -0
- package/dist/default/playback/behaviors/dom/end-of-stream.js.map +1 -1
- package/dist/default/playback/behaviors/dom/seek-to-live-edge.js +132 -0
- package/dist/default/playback/behaviors/dom/seek-to-live-edge.js.map +1 -0
- package/dist/default/playback/behaviors/dom/sync-live-seekable-range.js +26 -0
- package/dist/default/playback/behaviors/dom/sync-live-seekable-range.js.map +1 -0
- package/dist/default/playback/behaviors/dom/update-mediasource-duration.js +29 -7
- package/dist/default/playback/behaviors/dom/update-mediasource-duration.js.map +1 -1
- package/dist/default/playback/behaviors/establish-start-media-time.js +78 -4
- package/dist/default/playback/behaviors/establish-start-media-time.js.map +1 -1
- package/dist/default/playback/behaviors/resolve-track.js +29 -8
- package/dist/default/playback/behaviors/resolve-track.js.map +1 -1
- package/dist/default/playback/behaviors/track-switching.js +18 -9
- package/dist/default/playback/behaviors/track-switching.js.map +1 -1
- package/dist/default/playback/engines/hls/engine-audio-only.js +9 -5
- package/dist/default/playback/engines/hls/engine-audio-only.js.map +1 -1
- package/dist/{dev/playback/engines/background-video/engine.js → default/playback/engines/hls/engine-background-video.js} +3 -3
- package/dist/default/playback/engines/hls/engine-background-video.js.map +1 -0
- package/dist/default/playback/engines/hls/engine.js +19 -6
- package/dist/default/playback/engines/hls/engine.js.map +1 -1
- package/dist/default/playback/primitives/error-messages.js +39 -0
- package/dist/default/playback/primitives/error-messages.js.map +1 -0
- package/dist/default/playback/primitives/live-window.js +66 -0
- package/dist/default/playback/primitives/live-window.js.map +1 -0
- package/dist/default/playback/primitives/report-track-conditions.js +86 -0
- package/dist/default/playback/primitives/report-track-conditions.js.map +1 -0
- package/dist/dev/core/signals/when.js +38 -0
- package/dist/dev/core/signals/when.js.map +1 -0
- package/dist/dev/core/tasks/delayed-reschedule.js +31 -0
- package/dist/dev/core/tasks/delayed-reschedule.js.map +1 -0
- package/dist/dev/core/tasks/task.d.ts +52 -1
- package/dist/dev/core/tasks/task.d.ts.map +1 -1
- package/dist/dev/core/tasks/task.js +133 -3
- package/dist/dev/core/tasks/task.js.map +1 -1
- package/dist/dev/hls-audio.d.ts +3 -0
- package/dist/dev/hls-audio.js +3 -0
- package/dist/dev/hls-background-video.d.ts +3 -0
- package/dist/dev/hls-background-video.js +3 -0
- package/dist/dev/hls-video.d.ts +5 -0
- package/dist/dev/hls-video.js +4 -0
- package/dist/dev/hls.d.ts +6 -5
- package/dist/dev/hls.js +6 -5
- package/dist/dev/media/dom/capabilities.js +2 -0
- package/dist/dev/media/dom/capabilities.js.map +1 -1
- package/dist/dev/media/errors.d.ts +82 -0
- package/dist/dev/media/errors.d.ts.map +1 -0
- package/dist/dev/media/errors.js +62 -0
- package/dist/dev/media/errors.js.map +1 -0
- package/dist/dev/media/hls/parse-media-playlist.js +167 -16
- package/dist/dev/media/hls/parse-media-playlist.js.map +1 -1
- package/dist/dev/media/hls/parse-multivariant.js +14 -3
- package/dist/dev/media/hls/parse-multivariant.js.map +1 -1
- package/dist/dev/media/hls/reload-policy.js +71 -0
- package/dist/dev/media/hls/reload-policy.js.map +1 -0
- package/dist/dev/media/live-window.js +36 -0
- package/dist/dev/media/live-window.js.map +1 -0
- package/dist/dev/media/primitives/select-tracks.js +1 -24
- package/dist/dev/media/primitives/select-tracks.js.map +1 -1
- package/dist/dev/media/types/index.d.ts +125 -9
- package/dist/dev/media/types/index.d.ts.map +1 -1
- package/dist/dev/media/types/index.js +15 -1
- package/dist/dev/media/types/index.js.map +1 -1
- package/dist/dev/media/utils/tracks.js +14 -0
- package/dist/dev/media/utils/tracks.js.map +1 -1
- package/dist/dev/mux-audio.d.ts +4 -0
- package/dist/dev/mux-audio.js +3 -0
- package/dist/dev/mux-background-video.d.ts +3 -0
- package/dist/dev/mux-background-video.js +3 -0
- package/dist/dev/mux-video.d.ts +4 -0
- package/dist/dev/mux-video.js +3 -0
- package/dist/dev/playback/adapters/hls-audio/adapter.d.ts +54 -0
- package/dist/dev/playback/adapters/hls-audio/adapter.d.ts.map +1 -0
- package/dist/dev/playback/adapters/hls-audio/adapter.js +186 -0
- package/dist/dev/playback/adapters/hls-audio/adapter.js.map +1 -0
- package/dist/dev/playback/adapters/hls-audio/media.d.ts +10 -0
- package/dist/dev/playback/adapters/hls-audio/media.d.ts.map +1 -0
- package/dist/dev/playback/adapters/hls-audio/media.js +9 -0
- package/dist/dev/playback/adapters/hls-audio/media.js.map +1 -0
- package/dist/dev/playback/adapters/hls-background-video/adapter.d.ts +59 -0
- package/dist/dev/playback/adapters/hls-background-video/adapter.d.ts.map +1 -0
- package/dist/dev/playback/adapters/hls-background-video/adapter.js +123 -0
- package/dist/dev/playback/adapters/hls-background-video/adapter.js.map +1 -0
- package/dist/dev/playback/adapters/hls-background-video/host.d.ts +38 -0
- package/dist/dev/playback/adapters/hls-background-video/host.d.ts.map +1 -0
- package/dist/dev/playback/adapters/hls-background-video/host.js +60 -0
- package/dist/dev/playback/adapters/hls-background-video/host.js.map +1 -0
- package/dist/dev/playback/adapters/hls-background-video/media.d.ts +20 -0
- package/dist/dev/playback/adapters/hls-background-video/media.d.ts.map +1 -0
- package/dist/dev/playback/adapters/hls-background-video/media.js +21 -0
- package/dist/dev/playback/adapters/hls-background-video/media.js.map +1 -0
- package/dist/dev/playback/adapters/hls-video/adapter.d.ts +63 -0
- package/dist/dev/playback/adapters/hls-video/adapter.d.ts.map +1 -0
- package/dist/dev/playback/adapters/hls-video/adapter.js +316 -0
- package/dist/dev/playback/adapters/hls-video/adapter.js.map +1 -0
- package/dist/dev/playback/adapters/hls-video/error-surface.d.ts +18 -0
- package/dist/dev/playback/adapters/hls-video/error-surface.d.ts.map +1 -0
- package/dist/dev/playback/adapters/hls-video/error-surface.js +51 -0
- package/dist/dev/playback/adapters/hls-video/error-surface.js.map +1 -0
- package/dist/dev/playback/adapters/hls-video/media-tracks.d.ts +22 -0
- package/dist/dev/playback/adapters/hls-video/media-tracks.d.ts.map +1 -0
- package/dist/dev/playback/adapters/hls-video/media-tracks.js +126 -0
- package/dist/dev/playback/adapters/hls-video/media-tracks.js.map +1 -0
- package/dist/dev/playback/adapters/hls-video/media.d.ts +10 -0
- package/dist/dev/playback/adapters/hls-video/media.d.ts.map +1 -0
- package/dist/dev/playback/adapters/hls-video/media.js +11 -0
- package/dist/dev/playback/adapters/hls-video/media.js.map +1 -0
- package/dist/dev/playback/adapters/mux-audio/media.d.ts +28 -0
- package/dist/dev/playback/adapters/mux-audio/media.d.ts.map +1 -0
- package/dist/dev/playback/adapters/mux-audio/media.js +26 -0
- package/dist/dev/playback/adapters/mux-audio/media.js.map +1 -0
- package/dist/dev/playback/adapters/mux-video/adapter.d.ts +33 -0
- package/dist/dev/playback/adapters/mux-video/adapter.d.ts.map +1 -0
- package/dist/dev/playback/adapters/mux-video/adapter.js +92 -0
- package/dist/dev/playback/adapters/mux-video/adapter.js.map +1 -0
- package/dist/dev/playback/adapters/mux-video/media.d.ts +24 -0
- package/dist/dev/playback/adapters/mux-video/media.d.ts.map +1 -0
- package/dist/dev/playback/adapters/mux-video/media.js +23 -0
- package/dist/dev/playback/adapters/mux-video/media.js.map +1 -0
- package/dist/dev/playback/behaviors/collect-errors.js +77 -0
- package/dist/dev/playback/behaviors/collect-errors.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/end-of-stream.js +1 -0
- package/dist/dev/playback/behaviors/dom/end-of-stream.js.map +1 -1
- package/dist/dev/playback/behaviors/dom/seek-to-live-edge.js +132 -0
- package/dist/dev/playback/behaviors/dom/seek-to-live-edge.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/sync-live-seekable-range.js +26 -0
- package/dist/dev/playback/behaviors/dom/sync-live-seekable-range.js.map +1 -0
- package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js +29 -7
- package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js.map +1 -1
- package/dist/dev/playback/behaviors/establish-start-media-time.d.ts +5 -0
- package/dist/dev/playback/behaviors/establish-start-media-time.d.ts.map +1 -1
- package/dist/dev/playback/behaviors/establish-start-media-time.js +78 -4
- package/dist/dev/playback/behaviors/establish-start-media-time.js.map +1 -1
- package/dist/dev/playback/behaviors/resolve-track.js +29 -8
- package/dist/dev/playback/behaviors/resolve-track.js.map +1 -1
- package/dist/dev/playback/behaviors/track-switching.js +18 -9
- package/dist/dev/playback/behaviors/track-switching.js.map +1 -1
- package/dist/dev/playback/engines/hls/engine-audio-only.d.ts +34 -17
- package/dist/dev/playback/engines/hls/engine-audio-only.d.ts.map +1 -1
- package/dist/dev/playback/engines/hls/engine-audio-only.js +9 -5
- package/dist/dev/playback/engines/hls/engine-audio-only.js.map +1 -1
- package/dist/dev/playback/engines/{background-video/engine.d.ts → hls/engine-background-video.d.ts} +7 -7
- package/dist/dev/playback/engines/hls/engine-background-video.d.ts.map +1 -0
- package/dist/{default/playback/engines/background-video/engine.js → dev/playback/engines/hls/engine-background-video.js} +3 -3
- package/dist/dev/playback/engines/hls/engine-background-video.js.map +1 -0
- package/dist/dev/playback/engines/hls/engine.d.ts +43 -15
- package/dist/dev/playback/engines/hls/engine.d.ts.map +1 -1
- package/dist/dev/playback/engines/hls/engine.js +19 -6
- package/dist/dev/playback/engines/hls/engine.js.map +1 -1
- package/dist/dev/playback/primitives/error-messages.js +39 -0
- package/dist/dev/playback/primitives/error-messages.js.map +1 -0
- package/dist/dev/playback/primitives/live-window.js +66 -0
- package/dist/dev/playback/primitives/live-window.js.map +1 -0
- package/dist/dev/playback/primitives/report-track-conditions.d.ts +11 -0
- package/dist/dev/playback/primitives/report-track-conditions.d.ts.map +1 -0
- package/dist/dev/playback/primitives/report-track-conditions.js +86 -0
- package/dist/dev/playback/primitives/report-track-conditions.js.map +1 -0
- package/package.json +32 -6
- package/dist/default/background-video.js +0 -3
- package/dist/default/playback/engines/background-video/adapter.js +0 -158
- package/dist/default/playback/engines/background-video/adapter.js.map +0 -1
- package/dist/default/playback/engines/background-video/engine.js.map +0 -1
- package/dist/default/playback/engines/hls/adapter-audio-only.js +0 -124
- package/dist/default/playback/engines/hls/adapter-audio-only.js.map +0 -1
- package/dist/default/playback/engines/hls/adapter.js +0 -120
- package/dist/default/playback/engines/hls/adapter.js.map +0 -1
- package/dist/dev/background-video.d.ts +0 -3
- package/dist/dev/background-video.js +0 -3
- package/dist/dev/playback/engines/background-video/adapter.d.ts +0 -59
- package/dist/dev/playback/engines/background-video/adapter.d.ts.map +0 -1
- package/dist/dev/playback/engines/background-video/adapter.js +0 -158
- package/dist/dev/playback/engines/background-video/adapter.js.map +0 -1
- package/dist/dev/playback/engines/background-video/engine.d.ts.map +0 -1
- package/dist/dev/playback/engines/background-video/engine.js.map +0 -1
- package/dist/dev/playback/engines/hls/adapter-audio-only.d.ts +0 -46
- package/dist/dev/playback/engines/hls/adapter-audio-only.d.ts.map +0 -1
- package/dist/dev/playback/engines/hls/adapter-audio-only.js +0 -124
- package/dist/dev/playback/engines/hls/adapter-audio-only.js.map +0 -1
- package/dist/dev/playback/engines/hls/adapter.d.ts +0 -42
- package/dist/dev/playback/engines/hls/adapter.d.ts.map +0 -1
- package/dist/dev/playback/engines/hls/adapter.js +0 -120
- package/dist/dev/playback/engines/hls/adapter.js.map +0 -1
|
@@ -9,6 +9,7 @@ import { canPlayTrack } from "../../../media/dom/capabilities.js";
|
|
|
9
9
|
import { parseMultivariantPlaylist } from "../../../media/hls/parse-multivariant.js";
|
|
10
10
|
import { getResolvedSelectedTrackDuration } from "../../../media/utils/track-selection.js";
|
|
11
11
|
import { calculatePresentationDuration } from "../../behaviors/calculate-presentation-duration.js";
|
|
12
|
+
import { collectErrors } from "../../behaviors/collect-errors.js";
|
|
12
13
|
import { deriveCdnPriority } from "../../behaviors/derive-cdn-priority.js";
|
|
13
14
|
import { setupAirPlay } from "../../behaviors/dom/airplay.js";
|
|
14
15
|
import { applyStartPosition } from "../../behaviors/dom/apply-start-position.js";
|
|
@@ -23,12 +24,13 @@ import { setupFailoverMonitor } from "../../behaviors/setup-failover-monitor.js"
|
|
|
23
24
|
import { syncPreload } from "../../behaviors/sync-preload.js";
|
|
24
25
|
import { switchAudioTrack } from "../../behaviors/track-switching.js";
|
|
25
26
|
import { relocationPipelinesFor } from "../../primitives/relocation-pipelines.js";
|
|
27
|
+
import { reportUnsupportedTrackConditions } from "../../primitives/report-track-conditions.js";
|
|
26
28
|
//#region src/playback/engines/hls/engine-audio-only.ts
|
|
27
29
|
const shareSignals = makeShareSignals(["userAudioTrackSelection", "disableRemotePlayback"]);
|
|
28
30
|
/**
|
|
29
31
|
* Create an audio-only HLS playback engine.
|
|
30
32
|
*
|
|
31
|
-
* Subtractive composition variant of `
|
|
33
|
+
* Subtractive composition variant of `createHlsVideoEngine`: omits
|
|
32
34
|
* video-side behaviors (`resolveVideoTrack`, `switchVideoTrack`,
|
|
33
35
|
* `setupVideoBufferActors`, `loadVideoSegments`) and text-track behaviors
|
|
34
36
|
* (`switchTextTrack`, `resolveTextTrack`, `syncTextTracks`,
|
|
@@ -43,8 +45,8 @@ const shareSignals = makeShareSignals(["userAudioTrackSelection", "disableRemote
|
|
|
43
45
|
*
|
|
44
46
|
* @example
|
|
45
47
|
* ```ts
|
|
46
|
-
* let signals:
|
|
47
|
-
* const engine =
|
|
48
|
+
* let signals: HlsAudioEngineSignals;
|
|
49
|
+
* const engine = createHlsAudioEngine({
|
|
48
50
|
* preferredAudioLanguage: 'en',
|
|
49
51
|
* onSignalsReady: (refs) => {
|
|
50
52
|
* signals = refs;
|
|
@@ -55,13 +57,14 @@ const shareSignals = makeShareSignals(["userAudioTrackSelection", "disableRemote
|
|
|
55
57
|
* signals.state.presentation.set({ url: 'https://example.com/stream.m3u8' });
|
|
56
58
|
* ```
|
|
57
59
|
*/
|
|
58
|
-
function
|
|
60
|
+
function createHlsAudioEngine(config = {}) {
|
|
59
61
|
const deriveStartMediaTime = config.deriveStartMediaTime ?? deriveSharedMinStartMediaTime;
|
|
60
62
|
const finalConfig = {
|
|
61
63
|
...config,
|
|
62
64
|
deriveStartMediaTime,
|
|
63
65
|
attachMediaSource: attachMediaSourceAsSourceElement,
|
|
64
66
|
canPlayTrack: config.canPlayTrack ?? canPlayTrack,
|
|
67
|
+
reportUnsupportedTrackConditions: config.reportUnsupportedTrackConditions ?? reportUnsupportedTrackConditions,
|
|
65
68
|
resolveDuration: config.resolveDuration ?? getResolvedSelectedTrackDuration,
|
|
66
69
|
parsePresentation: config.parsePresentation ?? parseMultivariantPlaylist,
|
|
67
70
|
audioMessagePipelines: relocationPipelinesFor("audio", deriveStartMediaTime)
|
|
@@ -72,6 +75,7 @@ function createHlsAudioOnlyEngine(config = {}) {
|
|
|
72
75
|
resolvePresentation,
|
|
73
76
|
deriveCdnPriority,
|
|
74
77
|
setupFailoverMonitor,
|
|
78
|
+
collectErrors,
|
|
75
79
|
switchAudioTrack,
|
|
76
80
|
resolveAudioTrack,
|
|
77
81
|
calculatePresentationDuration,
|
|
@@ -89,6 +93,6 @@ function createHlsAudioOnlyEngine(config = {}) {
|
|
|
89
93
|
], { config: finalConfig });
|
|
90
94
|
}
|
|
91
95
|
//#endregion
|
|
92
|
-
export {
|
|
96
|
+
export { createHlsAudioEngine };
|
|
93
97
|
|
|
94
98
|
//# sourceMappingURL=engine-audio-only.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine-audio-only.js","names":[],"sources":["../../../../../src/playback/engines/hls/engine-audio-only.ts"],"sourcesContent":["import {\n type Composition,\n type ContextSignals,\n createComposition,\n type StateSignals,\n} from '../../../core/composition/create-composition';\nimport { makeShareSignals, type ShareSignalsConfig } from '../../../core/composition/share-signals';\nimport type { BackBufferConfig } from '../../../media/buffer/back-buffer';\nimport type { ForwardBufferConfig } from '../../../media/buffer/forward-buffer';\nimport { canPlayTrack } from '../../../media/dom/capabilities';\nimport { attachMediaSourceAsSourceElement } from '../../../media/dom/mse/mediasource-setup';\nimport { parseMultivariantPlaylist } from '../../../media/hls/parse-multivariant';\nimport type { AudioTrack, CanPlayTrack, MaybeResolvedPresentation, MediaContainerData } from '../../../media/types';\nimport type { GetCdnId } from '../../../media/utils/cdn';\nimport { getResolvedSelectedTrackDuration } from '../../../media/utils/track-selection';\nimport type { SegmentLoaderActor } from '../../actors/dom/segment-loader';\nimport type { SourceBufferActor } from '../../actors/dom/source-buffer';\nimport {\n calculatePresentationDuration,\n type PresentationDurationResolver,\n} from '../../behaviors/calculate-presentation-duration';\nimport { deriveCdnPriority } from '../../behaviors/derive-cdn-priority';\nimport { setupAirPlay } from '../../behaviors/dom/airplay';\nimport { applyStartPosition } from '../../behaviors/dom/apply-start-position';\nimport { endOfStream } from '../../behaviors/dom/end-of-stream';\nimport { loadAudioSegments } from '../../behaviors/dom/load-segments';\nimport { recoverEndStall } from '../../behaviors/dom/recover-end-stall';\nimport { setupAudioBufferActors } from '../../behaviors/dom/setup-buffer-actors';\nimport { setupMediaSource } from '../../behaviors/dom/setup-mediasource';\nimport { trackCurrentTime } from '../../behaviors/dom/track-current-time';\nimport { trackLoadTriggers } from '../../behaviors/dom/track-load-triggers';\nimport { updateMediaSourceDuration } from '../../behaviors/dom/update-mediasource-duration';\n// Non-zero-PTS relocation (spike): remove this import, the composed reactor, the\n// `audioMessagePipelines` finalConfig entry, the `mediaContainerData` state slot,\n// and the `deriveStartMediaTime` config field to drop relocation from audio-only.\nimport {\n type DeriveStartMediaTime,\n deriveSharedMinStartMediaTime,\n establishStartMediaTime,\n} from '../../behaviors/establish-start-media-time';\nimport { type ParsePresentation, resolvePresentation } from '../../behaviors/resolve-presentation';\nimport { resolveAudioTrack } from '../../behaviors/resolve-track';\nimport { type FailoverMonitorConfig, setupFailoverMonitor } from '../../behaviors/setup-failover-monitor';\nimport { syncPreload } from '../../behaviors/sync-preload';\nimport { switchAudioTrack } from '../../behaviors/track-switching';\nimport { relocationPipelinesFor } from '../../primitives/relocation-pipelines';\n\n// ============================================================================\n// Audio-Only HLS Engine State & Context\n// ============================================================================\n\n/**\n * State shape for the audio-only HLS playback engine.\n *\n * Subset of `SimpleHlsEngineState` covering only the slots written and read\n * by audio-side behaviors. Video and text-track slots are absent —\n * subtractive composition removes the behaviors that declare them.\n */\nexport interface SimpleHlsAudioOnlyEngineState {\n presentation?: MaybeResolvedPresentation;\n preload?: 'auto' | 'metadata' | 'none';\n selectedAudioTrackId?: string;\n // Non-zero-PTS relocation (spike): transient per-track container data owned by\n // `establishStartMediaTime`. Remove with the composed reactor.\n mediaContainerData?: Record<string, MediaContainerData>;\n /**\n * Consumer-driven constraint narrowing the audio candidate set. Sibling\n * of `userVideoTrackSelection` in the default engine. Partial-track\n * shape — `{ language: 'es' }`, `{ id: 'audio-en' }`, etc.\n * `selectAudioTrack` reads this and re-picks when it changes.\n * Multi-language-audio Tier 2 programmatic-write path.\n */\n userAudioTrackSelection?: Partial<AudioTrack>;\n /**\n * The CDNs the source is served from, in manifest priority order (mirrors\n * HLS content steering's `PATHWAY-PRIORITY`). Owned by `deriveCdnPriority`,\n * read by `track-switching`'s `preferActiveCdn` scope. Only meaningful for\n * redundant-stream sources; a single-CDN source has one entry.\n */\n cdnPriority?: string[];\n /**\n * CDN ids currently in failover cooldown — read by `track-switching`'s\n * `excludeFailedCdns` constraint, which prunes their tracks so the active-CDN\n * scope falls to the next CDN. Empty / absent means all CDNs are eligible.\n */\n failedCdns?: string[];\n currentTime?: number;\n loadActivated?: boolean;\n /**\n * One-shot command: start the current source at this position\n * (presentation-timeline seconds). Written by consumers or by\n * `setupAirPlay`'s session-end snapshot; consumed (cleared) by\n * `applyStartPosition` once the element seeks. See\n * `behaviors/dom/apply-start-position.ts`.\n */\n startPosition?: number;\n /**\n * Intent-level loading policy: initiate no new loading work while `true`.\n * Written by `setupAirPlay` (the only behavior declaring the key) while a\n * remote-playback session owns presentation; observed by `loadAudioSegments`\n * (parks in `'dormant'`) and by `setupMediaSource` (a pending rebuild\n * waits). See `SegmentLoadingState['loadingSuspended']`.\n */\n loadingSuspended?: boolean;\n /**\n * Author intent for the AirPlay/remote-playback picker, written by the media\n * adapter's `disableRemotePlayback` IDL property. `true` is an explicit\n * opt-out: `setupAirPlay` reads it at attach and sets nothing up, leaving the\n * element's remote playback disabled. Distinct from the underlying media\n * element's own `disableRemotePlayback`, which stays programmatically managed\n * (ManagedMediaSource / AirPlay).\n */\n disableRemotePlayback?: boolean;\n}\n\n/**\n * Context shape for the audio-only HLS playback engine.\n *\n * Subset of `SimpleHlsEngineContext` covering only the platform objects and\n * actor refs managed by audio-side behaviors.\n */\nexport interface SimpleHlsAudioOnlyEngineContext {\n mediaElement?: HTMLMediaElement | undefined;\n mediaSource?: MediaSource;\n audioBufferActor?: SourceBufferActor;\n audioSegmentLoaderActor?: SegmentLoaderActor;\n}\n\nexport type SimpleHlsAudioOnlyEngineSignals = {\n state: StateSignals<SimpleHlsAudioOnlyEngineState>;\n context: ContextSignals<SimpleHlsAudioOnlyEngineContext>;\n};\n\n/**\n * Configuration for the audio-only HLS playback engine.\n *\n * Subset of `SimpleHlsEngineConfig` — video-quality, bandwidth-estimator,\n * and text-track config fields are omitted (no behavior consumes them).\n */\nexport interface SimpleHlsAudioOnlyEngineConfig\n extends ShareSignalsConfig<SimpleHlsAudioOnlyEngineState, SimpleHlsAudioOnlyEngineContext> {\n preferredAudioLanguage?: string;\n /**\n * Codec capability probe read by `track-switching`'s `excludeUnplayableTracks`\n * constraint. Defaults to the `MediaSource.isTypeSupported`-backed\n * `canPlayTrack`; override to force-exclude a codec. Mirrors the default\n * engine — without it, capability probing (and TS / raw-AAC detection) would\n * be inert for audio-only playback.\n */\n canPlayTrack?: CanPlayTrack;\n resolveDuration?: PresentationDurationResolver;\n parsePresentation?: ParsePresentation;\n forwardBuffer?: Partial<ForwardBufferConfig>;\n backBuffer?: Partial<BackBufferConfig>;\n /** Multi-CDN failover monitor tuning. Defaults: `DEFAULT_FAILOVER_MONITOR_CONFIG`. */\n failover?: Partial<FailoverMonitorConfig>;\n /**\n * Derive a CDN grouping key from a track URL (used by `cdnPriority`, the\n * failover trip, and the track-switching CDN rules — one function read by all).\n * Defaults to the URL origin; override to key on e.g. Mux's `cdn=` param.\n */\n getCdnId?: GetCdnId;\n /** Non-zero-PTS relocation (spike): the reduce seam (tier knob); defaults to per-track own. */\n deriveStartMediaTime?: DeriveStartMediaTime;\n}\n\n// ============================================================================\n// Audio-Only HLS Playback Engine\n// ============================================================================\n\n// Materializes input slots no composed behavior produces — `userAudioTrackSelection`\n// (switchAudioTrack only reads it) and `disableRemotePlayback` (setupAirPlay only\n// reads it) — in addition to forwarding refs. `failedCdns` is owned by\n// `setupFailoverMonitor`, so it's already materialized and reachable on the\n// `onSignalsReady` refs without being listed here.\nconst shareSignals = makeShareSignals<SimpleHlsAudioOnlyEngineState, SimpleHlsAudioOnlyEngineContext>([\n 'userAudioTrackSelection',\n 'disableRemotePlayback',\n]);\n\n/**\n * Create an audio-only HLS playback engine.\n *\n * Subtractive composition variant of `createSimpleHlsEngine`: omits\n * video-side behaviors (`resolveVideoTrack`, `switchVideoTrack`,\n * `setupVideoBufferActors`, `loadVideoSegments`) and text-track behaviors\n * (`switchTextTrack`, `resolveTextTrack`, `syncTextTracks`,\n * `setupTextTrackActors`, `loadTextTrackSegments`). The remaining audio\n * pipeline composes unchanged.\n *\n * Handles both truly audio-only HLS sources (no video stream-inf) and\n * mixed-AV HLS sources where the audio rendition is selected and video /\n * subtitle renditions are ignored at composition time. The variant decision\n * is encoded by adapter choice; this engine does not branch on source\n * shape.\n *\n * @example\n * ```ts\n * let signals: SimpleHlsAudioOnlyEngineSignals;\n * const engine = createHlsAudioOnlyEngine({\n * preferredAudioLanguage: 'en',\n * onSignalsReady: (refs) => {\n * signals = refs;\n * },\n * });\n *\n * signals.context.mediaElement.set(audioEl);\n * signals.state.presentation.set({ url: 'https://example.com/stream.m3u8' });\n * ```\n */\nexport function createHlsAudioOnlyEngine(\n config: SimpleHlsAudioOnlyEngineConfig = {}\n): Composition<SimpleHlsAudioOnlyEngineState, SimpleHlsAudioOnlyEngineContext> {\n const deriveStartMediaTime = config.deriveStartMediaTime ?? deriveSharedMinStartMediaTime;\n const finalConfig = {\n ...config,\n deriveStartMediaTime,\n // Baked (not user-overridable): this engine composes `setupAirPlay`,\n // whose native fallback `<source>` requires the MSE attachment to keep\n // sibling source alternatives part of resource selection. The helper's\n // `video/mp4` source type is inert here — resource selection probes it\n // with `canPlayType`, which answers `'maybe'` on an audio element too.\n attachMediaSource: attachMediaSourceAsSourceElement,\n canPlayTrack: config.canPlayTrack ?? canPlayTrack,\n resolveDuration: config.resolveDuration ?? getResolvedSelectedTrackDuration,\n parsePresentation: config.parsePresentation ?? parseMultivariantPlaylist,\n // Non-zero-PTS relocation (spike): pair the audio loader with the relocation steps\n // `establishStartMediaTime` derives from; same `deriveStartMediaTime` seam. Remove\n // with the reactor.\n audioMessagePipelines: relocationPipelinesFor('audio', deriveStartMediaTime),\n };\n\n return createComposition(\n [\n syncPreload,\n trackLoadTriggers,\n resolvePresentation,\n\n // Session-level CDN priority for redundant-stream sources. Owns\n // `cdnPriority`; switchAudioTrack's preferActiveCdn scope reads it. No-op\n // for single-CDN sources.\n //\n // With a single track type there's no cross-type coherence to enforce and\n // the first pick is the primary CDN regardless, so composition order is\n // not load-bearing here today. It earns its place for forward-consistency\n // with the default engine and for future failover / steering, where the\n // active CDN changes dynamically (and selection stays reactive either way).\n deriveCdnPriority,\n\n // CDN failover cooldown: watches `failedCdns` (tripped directly by audio\n // track resolution on a failed media-playlist fetch) and removes each CDN\n // once its cooldown lapses.\n setupFailoverMonitor,\n\n // Audio track selection — slot owner with filter reactivity.\n // Mid-stream flush on language switch is handled in segment-loader's\n // planTasks, not here.\n switchAudioTrack,\n\n // Resolve selected tracks — audio only.\n resolveAudioTrack,\n\n // Presentation duration\n calculatePresentationDuration,\n\n // MSE setup. Single audio buffer; no video buffer to coordinate with,\n // so the Firefox `mozHasAudio` registration ordering is moot here.\n setupMediaSource,\n updateMediaSourceDuration,\n\n // Non-zero-PTS relocation (spike): establishes per-track startMediaTime;\n // MUST precede setupAudioBufferActors. Remove this line + the import + the\n // finalConfig/state entries to drop relocation. (Selection is optional in the\n // reactor, so it works with only audio in scope.)\n establishStartMediaTime,\n\n setupAudioBufferActors,\n\n // AirPlay/MSE bridge (WebKit only; no-op elsewhere). Audio-only sources\n // AirPlay to audio receivers (HomePod, AirPlay speakers) through the same\n // native-HLS fallback `<source>`; `webkitCurrentPlaybackTargetIsWireless`\n // and the picker are HTMLMediaElement-level, so an `<audio>` host is\n // AirPlay-capable on the same terms as a `<video>` one.\n setupAirPlay,\n\n // Playback tracking\n trackCurrentTime,\n // After trackCurrentTime: the one-shot currentTime seed must land after\n // the mirror's attach-time sync (see apply-start-position.ts).\n applyStartPosition,\n\n // Segment loading — audio only.\n loadAudioSegments,\n\n // End of stream coordination. `endOfStream` iterates buffer actors via\n // `[videoBufferActor, audioBufferActor].filter(Boolean)` and reads\n // `mediaSource.sourceBuffers` aggregately — composes unchanged with\n // only audio in scope.\n endOfStream,\n // Force native `ended` if Chrome freezes the playhead short of the buffered end\n // after `endOfStream`. Inert for a clean-ending single-track source.\n recoverEndStall,\n\n // Adapter signal callback.\n shareSignals,\n ],\n {\n config: finalConfig,\n }\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA+KA,MAAM,eAAe,iBAAiF,CACpG,2BACA,uBACF,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCD,SAAgB,yBACd,SAAyC,CAAC,GACmC;CAC7E,MAAM,uBAAuB,OAAO,wBAAwB;CAC5D,MAAM,cAAc;EAClB,GAAG;EACH;EAMA,mBAAmB;EACnB,cAAc,OAAO,gBAAgB;EACrC,iBAAiB,OAAO,mBAAmB;EAC3C,mBAAmB,OAAO,qBAAqB;EAI/C,uBAAuB,uBAAuB,SAAS,oBAAoB;CAC7E;CAEA,OAAO,kBACL;EACE;EACA;EACA;EAWA;EAKA;EAKA;EAGA;EAGA;EAIA;EACA;EAMA;EAEA;EAOA;EAGA;EAGA;EAGA;EAMA;EAGA;EAGA;CACF,GACA,EACE,QAAQ,YACV,CACF;AACF"}
|
|
1
|
+
{"version":3,"file":"engine-audio-only.js","names":[],"sources":["../../../../../src/playback/engines/hls/engine-audio-only.ts"],"sourcesContent":["import {\n type Composition,\n type ContextSignals,\n createComposition,\n type StateSignals,\n} from '../../../core/composition/create-composition';\nimport { makeShareSignals, type ShareSignalsConfig } from '../../../core/composition/share-signals';\nimport type { BackBufferConfig } from '../../../media/buffer/back-buffer';\nimport type { ForwardBufferConfig } from '../../../media/buffer/forward-buffer';\nimport { canPlayTrack } from '../../../media/dom/capabilities';\nimport { attachMediaSourceAsSourceElement } from '../../../media/dom/mse/mediasource-setup';\nimport type { SvtaError } from '../../../media/errors';\nimport { parseMultivariantPlaylist } from '../../../media/hls/parse-multivariant';\nimport type { AudioTrack, CanPlayTrack, MaybeResolvedPresentation, MediaContainerData } from '../../../media/types';\nimport type { GetCdnId } from '../../../media/utils/cdn';\nimport { getResolvedSelectedTrackDuration } from '../../../media/utils/track-selection';\nimport type { SegmentLoaderActor } from '../../actors/dom/segment-loader';\nimport type { SourceBufferActor } from '../../actors/dom/source-buffer';\nimport {\n calculatePresentationDuration,\n type PresentationDurationResolver,\n} from '../../behaviors/calculate-presentation-duration';\nimport { collectErrors } from '../../behaviors/collect-errors';\nimport { deriveCdnPriority } from '../../behaviors/derive-cdn-priority';\nimport { setupAirPlay } from '../../behaviors/dom/airplay';\nimport { applyStartPosition } from '../../behaviors/dom/apply-start-position';\nimport { endOfStream } from '../../behaviors/dom/end-of-stream';\nimport { loadAudioSegments } from '../../behaviors/dom/load-segments';\nimport { recoverEndStall } from '../../behaviors/dom/recover-end-stall';\nimport { setupAudioBufferActors } from '../../behaviors/dom/setup-buffer-actors';\nimport { setupMediaSource } from '../../behaviors/dom/setup-mediasource';\nimport { trackCurrentTime } from '../../behaviors/dom/track-current-time';\nimport { trackLoadTriggers } from '../../behaviors/dom/track-load-triggers';\nimport { updateMediaSourceDuration } from '../../behaviors/dom/update-mediasource-duration';\n// Non-zero-PTS relocation (spike): remove this import, the composed reactor, the\n// `audioMessagePipelines` finalConfig entry, the `mediaContainerData` state slot,\n// and the `deriveStartMediaTime` config field to drop relocation from audio-only.\nimport {\n type DeriveStartMediaTime,\n deriveSharedMinStartMediaTime,\n establishStartMediaTime,\n} from '../../behaviors/establish-start-media-time';\nimport { type ParsePresentation, resolvePresentation } from '../../behaviors/resolve-presentation';\nimport { resolveAudioTrack } from '../../behaviors/resolve-track';\nimport { type FailoverMonitorConfig, setupFailoverMonitor } from '../../behaviors/setup-failover-monitor';\nimport { syncPreload } from '../../behaviors/sync-preload';\nimport { switchAudioTrack } from '../../behaviors/track-switching';\nimport { relocationPipelinesFor } from '../../primitives/relocation-pipelines';\nimport {\n type ReportUnsupportedTrackConditions,\n reportUnsupportedTrackConditions,\n} from '../../primitives/report-track-conditions';\n\n// ============================================================================\n// Audio-Only HLS Engine State & Context\n// ============================================================================\n\n/**\n * State shape for the audio-only HLS playback engine.\n *\n * Subset of `HlsVideoEngineState` covering only the slots written and read\n * by audio-side behaviors. Video and text-track slots are absent —\n * subtractive composition removes the behaviors that declare them.\n */\nexport interface HlsAudioEngineState {\n presentation?: MaybeResolvedPresentation;\n preload?: 'auto' | 'metadata' | 'none';\n selectedAudioTrackId?: string;\n // Non-zero-PTS relocation (spike): transient per-track container data owned by\n // `establishStartMediaTime`. Remove with the composed reactor.\n mediaContainerData?: Record<string, MediaContainerData>;\n /**\n * Consumer-driven constraint narrowing the audio candidate set. Sibling\n * of `userVideoTrackSelection` in the default engine. Partial-track\n * shape — `{ language: 'es' }`, `{ id: 'audio-en' }`, etc.\n * `selectAudioTrack` reads this and re-picks when it changes.\n * Multi-language-audio Tier 2 programmatic-write path.\n */\n userAudioTrackSelection?: Partial<AudioTrack>;\n /**\n * The CDNs the source is served from, in manifest priority order (mirrors\n * HLS content steering's `PATHWAY-PRIORITY`). Owned by `deriveCdnPriority`,\n * read by `track-switching`'s `preferActiveCdn` scope. Only meaningful for\n * redundant-stream sources; a single-CDN source has one entry.\n */\n cdnPriority?: string[];\n /**\n * CDN ids currently in failover cooldown — read by `track-switching`'s\n * `excludeFailedCdns` constraint, which prunes their tracks so the active-CDN\n * scope falls to the next CDN. Empty / absent means all CDNs are eligible.\n */\n failedCdns?: string[];\n /**\n * Conditions reported during playback, in order — appended by whichever\n * behavior detects one, owned and cleared per source by `collectErrors`.\n * Severity is decided above the engine. Audio-only makes an all-audio-pruned\n * source unrecoverable: there's no video fallback to fall back to.\n */\n errors?: SvtaError[];\n currentTime?: number;\n loadActivated?: boolean;\n /**\n * One-shot command: start the current source at this position\n * (presentation-timeline seconds). Written by consumers or by\n * `setupAirPlay`'s session-end snapshot; consumed (cleared) by\n * `applyStartPosition` once the element seeks. See\n * `behaviors/dom/apply-start-position.ts`.\n */\n startPosition?: number;\n /**\n * Intent-level loading policy: initiate no new loading work while `true`.\n * Written by `setupAirPlay` (the only behavior declaring the key) while a\n * remote-playback session owns presentation; observed by `loadAudioSegments`\n * (parks in `'dormant'`) and by `setupMediaSource` (a pending rebuild\n * waits). See `SegmentLoadingState['loadingSuspended']`.\n */\n loadingSuspended?: boolean;\n /**\n * Author intent for the AirPlay/remote-playback picker, written by the media\n * adapter's `disableRemotePlayback` IDL property. `true` is an explicit\n * opt-out: `setupAirPlay` reads it at attach and sets nothing up, leaving the\n * element's remote playback disabled. Distinct from the underlying media\n * element's own `disableRemotePlayback`, which stays programmatically managed\n * (ManagedMediaSource / AirPlay).\n */\n disableRemotePlayback?: boolean;\n}\n\n/**\n * Context shape for the audio-only HLS playback engine.\n *\n * Subset of `HlsVideoEngineContext` covering only the platform objects and\n * actor refs managed by audio-side behaviors.\n */\nexport interface HlsAudioEngineContext {\n mediaElement?: HTMLMediaElement | undefined;\n mediaSource?: MediaSource;\n audioBufferActor?: SourceBufferActor;\n audioSegmentLoaderActor?: SegmentLoaderActor;\n}\n\nexport type HlsAudioEngineSignals = {\n state: StateSignals<HlsAudioEngineState>;\n context: ContextSignals<HlsAudioEngineContext>;\n};\n\n/**\n * Configuration for the audio-only HLS playback engine.\n *\n * Subset of `HlsVideoEngineConfig` — video-quality, bandwidth-estimator,\n * and text-track config fields are omitted (no behavior consumes them).\n */\nexport interface HlsAudioEngineConfig extends ShareSignalsConfig<HlsAudioEngineState, HlsAudioEngineContext> {\n preferredAudioLanguage?: string;\n /**\n * Codec capability probe read by `track-switching`'s `excludeUnplayableTracks`\n * constraint. Defaults to the `MediaSource.isTypeSupported`-backed\n * `canPlayTrack`; override to force-exclude a codec. Mirrors the default\n * engine — without it, capability probing (and TS / raw-AAC detection) would\n * be inert for audio-only playback.\n */\n canPlayTrack?: CanPlayTrack;\n /**\n * Conditions reported about each rendition as it resolves — the *causes* behind\n * a later verdict, and the copy a verdict reuses when they agree. Defaults to\n * {@link reportUnsupportedTrackConditions}, which reports non-fMP4 containers\n * and encryption; supply your own to report a different set (a provider that\n * never ships MPEG-TS can drop that check) or `() => []` to report nothing.\n */\n reportUnsupportedTrackConditions?: ReportUnsupportedTrackConditions;\n resolveDuration?: PresentationDurationResolver;\n parsePresentation?: ParsePresentation;\n forwardBuffer?: Partial<ForwardBufferConfig>;\n backBuffer?: Partial<BackBufferConfig>;\n /** Multi-CDN failover monitor tuning. Defaults: `DEFAULT_FAILOVER_MONITOR_CONFIG`. */\n failover?: Partial<FailoverMonitorConfig>;\n /**\n * Derive a CDN grouping key from a track URL (used by `cdnPriority`, the\n * failover trip, and the track-switching CDN rules — one function read by all).\n * Defaults to the URL origin; override to key on e.g. Mux's `cdn=` param.\n */\n getCdnId?: GetCdnId;\n /** Non-zero-PTS relocation (spike): the reduce seam (tier knob); defaults to per-track own. */\n deriveStartMediaTime?: DeriveStartMediaTime;\n}\n\n// ============================================================================\n// Audio-Only HLS Playback Engine\n// ============================================================================\n\n// Materializes input slots no composed behavior produces — `userAudioTrackSelection`\n// (switchAudioTrack only reads it) and `disableRemotePlayback` (setupAirPlay only\n// reads it) — in addition to forwarding refs. `failedCdns` is owned by\n// `setupFailoverMonitor`, so it's already materialized and reachable on the\n// `onSignalsReady` refs without being listed here.\nconst shareSignals = makeShareSignals<HlsAudioEngineState, HlsAudioEngineContext>([\n 'userAudioTrackSelection',\n 'disableRemotePlayback',\n]);\n\n/**\n * Create an audio-only HLS playback engine.\n *\n * Subtractive composition variant of `createHlsVideoEngine`: omits\n * video-side behaviors (`resolveVideoTrack`, `switchVideoTrack`,\n * `setupVideoBufferActors`, `loadVideoSegments`) and text-track behaviors\n * (`switchTextTrack`, `resolveTextTrack`, `syncTextTracks`,\n * `setupTextTrackActors`, `loadTextTrackSegments`). The remaining audio\n * pipeline composes unchanged.\n *\n * Handles both truly audio-only HLS sources (no video stream-inf) and\n * mixed-AV HLS sources where the audio rendition is selected and video /\n * subtitle renditions are ignored at composition time. The variant decision\n * is encoded by adapter choice; this engine does not branch on source\n * shape.\n *\n * @example\n * ```ts\n * let signals: HlsAudioEngineSignals;\n * const engine = createHlsAudioEngine({\n * preferredAudioLanguage: 'en',\n * onSignalsReady: (refs) => {\n * signals = refs;\n * },\n * });\n *\n * signals.context.mediaElement.set(audioEl);\n * signals.state.presentation.set({ url: 'https://example.com/stream.m3u8' });\n * ```\n */\nexport function createHlsAudioEngine(\n config: HlsAudioEngineConfig = {}\n): Composition<HlsAudioEngineState, HlsAudioEngineContext> {\n const deriveStartMediaTime = config.deriveStartMediaTime ?? deriveSharedMinStartMediaTime;\n const finalConfig = {\n ...config,\n deriveStartMediaTime,\n // Baked (not user-overridable): this engine composes `setupAirPlay`,\n // whose native fallback `<source>` requires the MSE attachment to keep\n // sibling source alternatives part of resource selection. The helper's\n // `video/mp4` source type is inert here — resource selection probes it\n // with `canPlayType`, which answers `'maybe'` on an audio element too.\n attachMediaSource: attachMediaSourceAsSourceElement,\n canPlayTrack: config.canPlayTrack ?? canPlayTrack,\n reportUnsupportedTrackConditions: config.reportUnsupportedTrackConditions ?? reportUnsupportedTrackConditions,\n resolveDuration: config.resolveDuration ?? getResolvedSelectedTrackDuration,\n parsePresentation: config.parsePresentation ?? parseMultivariantPlaylist,\n // Non-zero-PTS relocation (spike): pair the audio loader with the relocation steps\n // `establishStartMediaTime` derives from; same `deriveStartMediaTime` seam. Remove\n // with the reactor.\n audioMessagePipelines: relocationPipelinesFor('audio', deriveStartMediaTime),\n };\n\n return createComposition(\n [\n syncPreload,\n trackLoadTriggers,\n resolvePresentation,\n\n // Session-level CDN priority for redundant-stream sources. Owns\n // `cdnPriority`; switchAudioTrack's preferActiveCdn scope reads it. No-op\n // for single-CDN sources.\n //\n // With a single track type there's no cross-type coherence to enforce and\n // the first pick is the primary CDN regardless, so composition order is\n // not load-bearing here today. It earns its place for forward-consistency\n // with the default engine and for future failover / steering, where the\n // active CDN changes dynamically (and selection stays reactive either way).\n deriveCdnPriority,\n\n // CDN failover cooldown: watches `failedCdns` (tripped directly by audio\n // track resolution on a failed media-playlist fetch) and removes each CDN\n // once its cooldown lapses.\n setupFailoverMonitor,\n\n // Owns `errors` and its per-source lifecycle; reporters append into it.\n collectErrors,\n\n // Audio track selection — slot owner with filter reactivity.\n // Mid-stream flush on language switch is handled in segment-loader's\n // planTasks, not here.\n switchAudioTrack,\n\n // Resolve selected tracks — audio only.\n resolveAudioTrack,\n\n // Presentation duration\n calculatePresentationDuration,\n\n // MSE setup. Single audio buffer; no video buffer to coordinate with,\n // so the Firefox `mozHasAudio` registration ordering is moot here.\n setupMediaSource,\n updateMediaSourceDuration,\n\n // Non-zero-PTS relocation (spike): establishes per-track startMediaTime;\n // MUST precede setupAudioBufferActors. Remove this line + the import + the\n // finalConfig/state entries to drop relocation. (Selection is optional in the\n // reactor, so it works with only audio in scope.)\n establishStartMediaTime,\n\n setupAudioBufferActors,\n\n // AirPlay/MSE bridge (WebKit only; no-op elsewhere). Audio-only sources\n // AirPlay to audio receivers (HomePod, AirPlay speakers) through the same\n // native-HLS fallback `<source>`; `webkitCurrentPlaybackTargetIsWireless`\n // and the picker are HTMLMediaElement-level, so an `<audio>` host is\n // AirPlay-capable on the same terms as a `<video>` one.\n setupAirPlay,\n\n // Playback tracking\n trackCurrentTime,\n // After trackCurrentTime: the one-shot currentTime seed must land after\n // the mirror's attach-time sync (see apply-start-position.ts).\n applyStartPosition,\n\n // Segment loading — audio only.\n loadAudioSegments,\n\n // End of stream coordination. `endOfStream` iterates buffer actors via\n // `[videoBufferActor, audioBufferActor].filter(Boolean)` and reads\n // `mediaSource.sourceBuffers` aggregately — composes unchanged with\n // only audio in scope.\n endOfStream,\n // Force native `ended` if Chrome freezes the playhead short of the buffered end\n // after `endOfStream`. Inert for a clean-ending single-track source.\n recoverEndStall,\n\n // Adapter signal callback.\n shareSignals,\n ],\n {\n config: finalConfig,\n }\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmMA,MAAM,eAAe,iBAA6D,CAChF,2BACA,uBACF,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCD,SAAgB,qBACd,SAA+B,CAAC,GACyB;CACzD,MAAM,uBAAuB,OAAO,wBAAwB;CAC5D,MAAM,cAAc;EAClB,GAAG;EACH;EAMA,mBAAmB;EACnB,cAAc,OAAO,gBAAgB;EACrC,kCAAkC,OAAO,oCAAoC;EAC7E,iBAAiB,OAAO,mBAAmB;EAC3C,mBAAmB,OAAO,qBAAqB;EAI/C,uBAAuB,uBAAuB,SAAS,oBAAoB;CAC7E;CAEA,OAAO,kBACL;EACE;EACA;EACA;EAWA;EAKA;EAGA;EAKA;EAGA;EAGA;EAIA;EACA;EAMA;EAEA;EAOA;EAGA;EAGA;EAGA;EAMA;EAGA;EAGA;CACF,GACA,EACE,QAAQ,YACV,CACF;AACF"}
|
package/dist/dev/playback/engines/{background-video/engine.d.ts → hls/engine-background-video.d.ts}
RENAMED
|
@@ -3,14 +3,14 @@ import { Composition, ContextSignals, StateSignals } from "../../../core/composi
|
|
|
3
3
|
import { ShareSignalsConfig } from "../../../core/composition/share-signals.js";
|
|
4
4
|
import { SourceBufferActor } from "../../actors/dom/source-buffer.js";
|
|
5
5
|
import { SegmentLoaderActor } from "../../actors/dom/segment-loader.js";
|
|
6
|
-
import { TrackPicker } from "../../../media/primitives/select-tracks.js";
|
|
7
6
|
import { ParsePresentation } from "../../behaviors/resolve-presentation.js";
|
|
7
|
+
import { TrackPicker } from "../../../media/primitives/select-tracks.js";
|
|
8
8
|
import { SelectVideoTrackConfig } from "../../behaviors/select-tracks.js";
|
|
9
|
-
//#region src/playback/engines/background-video
|
|
9
|
+
//#region src/playback/engines/hls/engine-background-video.d.ts
|
|
10
10
|
/**
|
|
11
11
|
* State shape for the background-video playback engine.
|
|
12
12
|
*
|
|
13
|
-
* Narrower than `
|
|
13
|
+
* Narrower than `HlsVideoEngineState`: audio/text track slots are absent
|
|
14
14
|
* because their selection/resolution behaviors are subtracted. `bandwidthState`
|
|
15
15
|
* is present because `setupVideoBufferActors` declares it and `loadVideoSegments`
|
|
16
16
|
* samples into it (wasted work in this variant — a Phase 3 alt-impl will skip
|
|
@@ -50,7 +50,7 @@ type BackgroundVideoEngineSignals = {
|
|
|
50
50
|
*
|
|
51
51
|
* Each option is consumed by the appropriate behavior — the engine itself
|
|
52
52
|
* has no config beyond what its behaviors read. Compared to
|
|
53
|
-
* `
|
|
53
|
+
* `HlsVideoEngineConfig`, audio/text/ABR/bandwidth/quality knobs are
|
|
54
54
|
* dropped: the variant subtracts the behaviors that read them.
|
|
55
55
|
*/
|
|
56
56
|
interface BackgroundVideoEngineConfig extends ShareSignalsConfig<BackgroundVideoEngineState, BackgroundVideoEngineContext> {
|
|
@@ -60,7 +60,7 @@ interface BackgroundVideoEngineConfig extends ShareSignalsConfig<BackgroundVideo
|
|
|
60
60
|
* presentation resolve and pins it for the session. Override for
|
|
61
61
|
* mobile-aware or content-aware caps.
|
|
62
62
|
*
|
|
63
|
-
* Adapters (e.g. `
|
|
63
|
+
* Adapters (e.g. `HlsBackgroundVideoMediaElement`) install their own
|
|
64
64
|
* picker; this default applies when the engine is constructed directly.
|
|
65
65
|
*/
|
|
66
66
|
picker?: TrackPicker<SelectVideoTrackConfig>;
|
|
@@ -83,7 +83,7 @@ interface BackgroundVideoEngineConfig extends ShareSignalsConfig<BackgroundVideo
|
|
|
83
83
|
* surfaces that should start loading the moment a src is set.
|
|
84
84
|
*
|
|
85
85
|
* Native `loop` / `muted` / `autoplay` are adapter concerns and live on
|
|
86
|
-
* `
|
|
86
|
+
* `HlsBackgroundVideoMediaElement` rather than the engine.
|
|
87
87
|
*
|
|
88
88
|
* @example
|
|
89
89
|
* ```ts
|
|
@@ -103,4 +103,4 @@ interface BackgroundVideoEngineConfig extends ShareSignalsConfig<BackgroundVideo
|
|
|
103
103
|
declare function createBackgroundVideoEngine(config?: BackgroundVideoEngineConfig): Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext>;
|
|
104
104
|
//#endregion
|
|
105
105
|
export { BackgroundVideoEngineConfig, BackgroundVideoEngineContext, BackgroundVideoEngineSignals, BackgroundVideoEngineState, createBackgroundVideoEngine };
|
|
106
|
-
//# sourceMappingURL=engine.d.ts.map
|
|
106
|
+
//# sourceMappingURL=engine-background-video.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-background-video.d.ts","names":[],"sources":["../../../../../src/playback/engines/hls/engine-background-video.ts"],"mappings":";;;;;;;;;;;;;;;;;;UAqCiB;;;;;EAKf,eAAe;EACf;EACA;EACA;;;;;UAMe;EACf,eAAe;EACf,cAAc;EACd,mBAAmB;EACnB,0BAA0B;;;;;;;;KAShB;EACV,OAAO,aAAa;EACpB,SAAS,eAAe;;;;;;;;;;UAWT,oCACP,mBAAmB,4BAA4B;;;;;;;;;;EAUvD,SAAS,YAAY;;;;;EAKrB,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuCN,4BACd,SAAQ,8BACP,YAAY,4BAA4B"}
|
|
@@ -13,7 +13,7 @@ import { resolvePresentation } from "../../behaviors/resolve-presentation.js";
|
|
|
13
13
|
import { resolveVideoTrack } from "../../behaviors/resolve-track.js";
|
|
14
14
|
import { pickHighestResolutionVideoTrack } from "../../../media/primitives/select-tracks.js";
|
|
15
15
|
import { selectVideoTrack } from "../../behaviors/select-tracks.js";
|
|
16
|
-
//#region src/playback/engines/background-video
|
|
16
|
+
//#region src/playback/engines/hls/engine-background-video.ts
|
|
17
17
|
const shareSignals = makeShareSignals();
|
|
18
18
|
/**
|
|
19
19
|
* Create a background-video playback engine.
|
|
@@ -28,7 +28,7 @@ const shareSignals = makeShareSignals();
|
|
|
28
28
|
* surfaces that should start loading the moment a src is set.
|
|
29
29
|
*
|
|
30
30
|
* Native `loop` / `muted` / `autoplay` are adapter concerns and live on
|
|
31
|
-
* `
|
|
31
|
+
* `HlsBackgroundVideoMediaElement` rather than the engine.
|
|
32
32
|
*
|
|
33
33
|
* @example
|
|
34
34
|
* ```ts
|
|
@@ -72,4 +72,4 @@ function createBackgroundVideoEngine(config = {}) {
|
|
|
72
72
|
//#endregion
|
|
73
73
|
export { createBackgroundVideoEngine };
|
|
74
74
|
|
|
75
|
-
//# sourceMappingURL=engine.js.map
|
|
75
|
+
//# sourceMappingURL=engine-background-video.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-background-video.js","names":[],"sources":["../../../../../src/playback/engines/hls/engine-background-video.ts"],"sourcesContent":["import {\n type Composition,\n type ContextSignals,\n createComposition,\n type StateSignals,\n} from '../../../core/composition/create-composition';\nimport { makeShareSignals, type ShareSignalsConfig } from '../../../core/composition/share-signals';\nimport { parseMultivariantPlaylist } from '../../../media/hls/parse-multivariant';\nimport { pickHighestResolutionVideoTrack, type TrackPicker } from '../../../media/primitives/select-tracks';\nimport type { MaybeResolvedPresentation } from '../../../media/types';\nimport { getResolvedSelectedTrackDuration } from '../../../media/utils/track-selection';\nimport type { SegmentLoaderActor } from '../../actors/dom/segment-loader';\nimport type { SourceBufferActor } from '../../actors/dom/source-buffer';\nimport { calculatePresentationDuration } from '../../behaviors/calculate-presentation-duration';\nimport { endOfStream } from '../../behaviors/dom/end-of-stream';\nimport { loadVideoSegments } from '../../behaviors/dom/load-segments';\nimport { setupVideoBufferActors } from '../../behaviors/dom/setup-buffer-actors';\nimport { setupMediaSource } from '../../behaviors/dom/setup-mediasource';\nimport { trackCurrentTime } from '../../behaviors/dom/track-current-time';\nimport { updateMediaSourceDuration } from '../../behaviors/dom/update-mediasource-duration';\nimport { type ParsePresentation, resolvePresentation } from '../../behaviors/resolve-presentation';\nimport { resolveVideoTrack } from '../../behaviors/resolve-track';\nimport { type SelectVideoTrackConfig, selectVideoTrack } from '../../behaviors/select-tracks';\n\n// ============================================================================\n// Background-video engine state & context\n// ============================================================================\n\n/**\n * State shape for the background-video playback engine.\n *\n * Narrower than `HlsVideoEngineState`: audio/text track slots are absent\n * because their selection/resolution behaviors are subtracted. `bandwidthState`\n * is present because `setupVideoBufferActors` declares it and `loadVideoSegments`\n * samples into it (wasted work in this variant — a Phase 3 alt-impl will skip\n * sampling).\n */\nexport interface BackgroundVideoEngineState {\n /**\n * The presentation being played. A caller writes `{ url }`;\n * `resolvePresentation` parses the manifest and populates the rest.\n */\n presentation?: MaybeResolvedPresentation;\n preload?: 'auto' | 'metadata' | 'none';\n selectedVideoTrackId?: string;\n loadActivated?: boolean;\n}\n\n/**\n * Context shape for the background-video engine.\n */\nexport interface BackgroundVideoEngineContext {\n mediaElement?: HTMLMediaElement | undefined;\n mediaSource?: MediaSource;\n videoBufferActor?: SourceBufferActor;\n videoSegmentLoaderActor?: SegmentLoaderActor;\n}\n\n/**\n * The composition signal refs handed to `onSignalsReady` callers — the\n * canonical way to drive the engine externally (writes) or observe its\n * state (reads) without touching `composition.state` / `composition.context`\n * directly.\n */\nexport type BackgroundVideoEngineSignals = {\n state: StateSignals<BackgroundVideoEngineState>;\n context: ContextSignals<BackgroundVideoEngineContext>;\n};\n\n/**\n * Configuration for the background-video engine.\n *\n * Each option is consumed by the appropriate behavior — the engine itself\n * has no config beyond what its behaviors read. Compared to\n * `HlsVideoEngineConfig`, audio/text/ABR/bandwidth/quality knobs are\n * dropped: the variant subtracts the behaviors that read them.\n */\nexport interface BackgroundVideoEngineConfig\n extends ShareSignalsConfig<BackgroundVideoEngineState, BackgroundVideoEngineContext> {\n /**\n * Track picker handed to `selectVideoTrack`. Default:\n * `pickHighestResolutionVideoTrack` — picks the highest-resolution variant on\n * presentation resolve and pins it for the session. Override for\n * mobile-aware or content-aware caps.\n *\n * Adapters (e.g. `HlsBackgroundVideoMediaElement`) install their own\n * picker; this default applies when the engine is constructed directly.\n */\n picker?: TrackPicker<SelectVideoTrackConfig>;\n /**\n * Manifest parser handed to `resolvePresentation`. Defaults to the HLS\n * multivariant-playlist parser.\n */\n parsePresentation?: ParsePresentation;\n}\n\n// ============================================================================\n// Background-video playback engine\n// ============================================================================\n\nconst shareSignals = makeShareSignals<BackgroundVideoEngineState, BackgroundVideoEngineContext>();\n\n/**\n * Create a background-video playback engine.\n *\n * Subtractive composition over the HLS engine baseline:\n * audio-side, text-side, ABR-driven, preload-monitoring, and play/seek\n * load-trigger behaviors are removed. `selectVideoTrack` (with a\n * max-resolution picker by default) replaces `switchVideoQuality`, pinning\n * a single rendition for the session. The initial state seeds\n * `loadActivated: true` so the composition behaves as if preload has\n * already been activated — appropriate for ambient / hero / GIF-replacement\n * surfaces that should start loading the moment a src is set.\n *\n * Native `loop` / `muted` / `autoplay` are adapter concerns and live on\n * `HlsBackgroundVideoMediaElement` rather than the engine.\n *\n * @example\n * ```ts\n * let signals: BackgroundVideoEngineSignals;\n * const engine = createBackgroundVideoEngine({\n * onSignalsReady: (refs) => {\n * signals = refs;\n * },\n * });\n *\n * signals.context.mediaElement.set(videoEl);\n * signals.state.presentation.set({ url: 'https://example.com/stream.m3u8' });\n *\n * await engine.destroy();\n * ```\n */\nexport function createBackgroundVideoEngine(\n config: BackgroundVideoEngineConfig = {}\n): Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext> {\n const finalConfig = {\n ...config,\n picker: config.picker ?? pickHighestResolutionVideoTrack,\n parsePresentation: config.parsePresentation ?? parseMultivariantPlaylist,\n resolveDuration: getResolvedSelectedTrackDuration,\n };\n\n return createComposition(\n [\n resolvePresentation,\n // Presentation duration\n calculatePresentationDuration,\n\n // Track selection - pinned single-rendition pick on presentation resolve.\n selectVideoTrack,\n // Resolve selected video track (fetch its media playlist)\n resolveVideoTrack,\n // Segment loading — video-only.\n loadVideoSegments,\n\n // MSE setup — video-only.\n setupMediaSource,\n updateMediaSourceDuration,\n setupVideoBufferActors,\n\n // Playback tracking\n trackCurrentTime,\n\n // End of stream coordination\n endOfStream,\n\n // Behavior whose sole purpose is to expose signal refs via a callback\n // (e.g. to an adapter). Listed last so initial signal setup has run\n // before the callback fires.\n shareSignals,\n ],\n {\n config: finalConfig,\n initialState: {\n // Note: Set to true until we add preload configuration\n loadActivated: true,\n },\n }\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAoGA,MAAM,eAAe,iBAA2E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgChG,SAAgB,4BACd,SAAsC,CAAC,GACgC;CACvE,MAAM,cAAc;EAClB,GAAG;EACH,QAAQ,OAAO,UAAU;EACzB,mBAAmB,OAAO,qBAAqB;EAC/C,iBAAiB;CACnB;CAEA,OAAO,kBACL;EACE;EAEA;EAGA;EAEA;EAEA;EAGA;EACA;EACA;EAGA;EAGA;EAKA;CACF,GACA;EACE,QAAQ;EACR,cAAc,EAEZ,eAAe,KACjB;CACF,CACF;AACF"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { AudioTrack, CanPlayTrack, MaybeResolvedPresentation, MediaContainerData, TextTrack, VideoTrack } from "../../../media/types/index.js";
|
|
1
|
+
import { AudioTrack, CanPlayTrack, MaybeResolvedPresentation, MediaContainerData, ResolvedTrack, TextTrack, VideoTrack } from "../../../media/types/index.js";
|
|
2
2
|
import { Composition, ContextSignals, StateSignals } from "../../../core/composition/create-composition.js";
|
|
3
3
|
import { ShareSignalsConfig } from "../../../core/composition/share-signals.js";
|
|
4
|
+
import { Reschedule } from "../../../core/tasks/task.js";
|
|
4
5
|
import { BackBufferConfig } from "../../../media/buffer/back-buffer.js";
|
|
5
6
|
import { ForwardBufferConfig } from "../../../media/buffer/forward-buffer.js";
|
|
6
7
|
import { SourceBufferActor } from "../../actors/dom/source-buffer.js";
|
|
@@ -8,16 +9,18 @@ import { SegmentLoaderActor } from "../../actors/dom/segment-loader.js";
|
|
|
8
9
|
import { TextTrackSegmentResolver } from "../../primitives/text-segment-load-pipeline.js";
|
|
9
10
|
import { TextTracksActor } from "../../actors/text-tracks.js";
|
|
10
11
|
import { TextTrackSegmentLoaderActor } from "../../actors/text-track-segment-loader.js";
|
|
11
|
-
import {
|
|
12
|
+
import { SvtaError } from "../../../media/errors.js";
|
|
13
|
+
import { GetCdnId } from "../../../media/utils/cdn.js";
|
|
14
|
+
import { PresentationDurationResolver } from "../../behaviors/calculate-presentation-duration.js";
|
|
12
15
|
import { DeriveStartMediaTime } from "../../primitives/derive-start-media-time.js";
|
|
13
16
|
import "../../behaviors/establish-start-media-time.js";
|
|
17
|
+
import { ParsePresentation } from "../../behaviors/resolve-presentation.js";
|
|
18
|
+
import { FailoverMonitorConfig } from "../../behaviors/setup-failover-monitor.js";
|
|
19
|
+
import { ReportUnsupportedTrackConditions } from "../../primitives/report-track-conditions.js";
|
|
14
20
|
import { QualityConfig } from "../../../media/abr/quality-selection.js";
|
|
15
21
|
import { addSubtitlesTracksToMedia, getShowingSubtitlesTrackFromMedia, removeAllSubtitlesTracksFromMedia } from "../../../media/dom/text/text-track-slots.js";
|
|
16
|
-
import { GetCdnId } from "../../../media/utils/cdn.js";
|
|
17
22
|
import { BandwidthConfig, BandwidthState } from "../../../network/bandwidth-estimator.js";
|
|
18
23
|
import "../../actors/dom/text-tracks.js";
|
|
19
|
-
import { PresentationDurationResolver } from "../../behaviors/calculate-presentation-duration.js";
|
|
20
|
-
import { FailoverMonitorConfig } from "../../behaviors/setup-failover-monitor.js";
|
|
21
24
|
//#region src/playback/engines/hls/engine.d.ts
|
|
22
25
|
/**
|
|
23
26
|
* State shape for the HLS playback engine.
|
|
@@ -26,7 +29,7 @@ import { FailoverMonitorConfig } from "../../behaviors/setup-failover-monitor.js
|
|
|
26
29
|
* the HLS engine. Each behavior declares its own state interface; this
|
|
27
30
|
* type satisfies all of them.
|
|
28
31
|
*/
|
|
29
|
-
interface
|
|
32
|
+
interface HlsVideoEngineState {
|
|
30
33
|
/**
|
|
31
34
|
* The presentation being played. A caller writes `{ url }`;
|
|
32
35
|
* `resolvePresentation` parses the manifest and populates the rest.
|
|
@@ -73,6 +76,14 @@ interface SimpleHlsEngineState {
|
|
|
73
76
|
* means all CDNs are eligible.
|
|
74
77
|
*/
|
|
75
78
|
failedCdns?: string[];
|
|
79
|
+
/**
|
|
80
|
+
* Conditions reported during playback, in the order encountered — appended by
|
|
81
|
+
* whichever behavior detects one (`emitError`), owned and cleared per source by
|
|
82
|
+
* `collectErrors`. Carries no severity: which of these is fatal is decided
|
|
83
|
+
* above the engine, at the adapter. See
|
|
84
|
+
* `internal/design/spf/features/errors.md`.
|
|
85
|
+
*/
|
|
86
|
+
errors?: SvtaError[];
|
|
76
87
|
currentTime?: number;
|
|
77
88
|
loadActivated?: boolean;
|
|
78
89
|
/**
|
|
@@ -107,7 +118,7 @@ interface SimpleHlsEngineState {
|
|
|
107
118
|
*
|
|
108
119
|
* Platform objects and actor references managed by HLS behaviors.
|
|
109
120
|
*/
|
|
110
|
-
interface
|
|
121
|
+
interface HlsVideoEngineContext {
|
|
111
122
|
mediaElement?: HTMLMediaElement | undefined;
|
|
112
123
|
mediaSource?: MediaSource;
|
|
113
124
|
videoBufferActor?: SourceBufferActor;
|
|
@@ -123,9 +134,9 @@ interface SimpleHlsEngineContext {
|
|
|
123
134
|
* state (reads) without touching `composition.state` / `composition.context`
|
|
124
135
|
* directly.
|
|
125
136
|
*/
|
|
126
|
-
type
|
|
127
|
-
state: StateSignals<
|
|
128
|
-
context: ContextSignals<
|
|
137
|
+
type HlsVideoEngineSignals = {
|
|
138
|
+
state: StateSignals<HlsVideoEngineState>;
|
|
139
|
+
context: ContextSignals<HlsVideoEngineContext>;
|
|
129
140
|
};
|
|
130
141
|
/**
|
|
131
142
|
* Configuration for the HLS playback engine.
|
|
@@ -133,7 +144,7 @@ type SimpleHlsEngineSignals = {
|
|
|
133
144
|
* Each option is consumed by the appropriate behavior — the engine itself
|
|
134
145
|
* has no config beyond what its behaviors read.
|
|
135
146
|
*/
|
|
136
|
-
interface
|
|
147
|
+
interface HlsVideoEngineConfig extends ShareSignalsConfig<HlsVideoEngineState, HlsVideoEngineContext> {
|
|
137
148
|
/**
|
|
138
149
|
* Bandwidth estimate in bps to use before enough samples have been
|
|
139
150
|
* collected. Default: `DEFAULT_INITIAL_BANDWIDTH` (5 Mbps).
|
|
@@ -147,6 +158,14 @@ interface SimpleHlsEngineConfig extends ShareSignalsConfig<SimpleHlsEngineState,
|
|
|
147
158
|
* codec).
|
|
148
159
|
*/
|
|
149
160
|
canPlayTrack?: CanPlayTrack;
|
|
161
|
+
/**
|
|
162
|
+
* Conditions reported about each rendition as it resolves — the *causes* behind
|
|
163
|
+
* a later verdict, and the copy a verdict reuses when they agree. Defaults to
|
|
164
|
+
* {@link reportUnsupportedTrackConditions}, which reports non-fMP4 containers
|
|
165
|
+
* and encryption; supply your own to report a different set (a provider that
|
|
166
|
+
* never ships MPEG-TS can drop that check) or `() => []` to report nothing.
|
|
167
|
+
*/
|
|
168
|
+
reportUnsupportedTrackConditions?: ReportUnsupportedTrackConditions;
|
|
150
169
|
preferredAudioLanguage?: string;
|
|
151
170
|
preferredSubtitleLanguage?: string;
|
|
152
171
|
includeForcedTracks?: boolean;
|
|
@@ -249,6 +268,15 @@ interface SimpleHlsEngineConfig extends ShareSignalsConfig<SimpleHlsEngineState,
|
|
|
249
268
|
* `behaviors/dom/recover-end-stall`.
|
|
250
269
|
*/
|
|
251
270
|
endStallNudgeWindow?: number;
|
|
271
|
+
/**
|
|
272
|
+
* Live media-playlist re-run policy for the resolve* loaders' `RecurringRunner`:
|
|
273
|
+
* returns a promise that resolves when the playlist should reload, or `null` to
|
|
274
|
+
* stop. Defaults to `mediaPlaylistReloadDelay` (target-duration cadence, half on
|
|
275
|
+
* an unchanged window, stop on `#EXT-X-ENDLIST`) composed with a cancellable
|
|
276
|
+
* `sleep`. Inert for VoD (a complete playlist stops it after the first resolve).
|
|
277
|
+
* Override to tune live reload timing.
|
|
278
|
+
*/
|
|
279
|
+
reschedule?: Reschedule<ResolvedTrack>;
|
|
252
280
|
}
|
|
253
281
|
/**
|
|
254
282
|
* Create an HLS playback engine.
|
|
@@ -259,8 +287,8 @@ interface SimpleHlsEngineConfig extends ShareSignalsConfig<SimpleHlsEngineState,
|
|
|
259
287
|
*
|
|
260
288
|
* @example
|
|
261
289
|
* ```ts
|
|
262
|
-
* let signals:
|
|
263
|
-
* const engine =
|
|
290
|
+
* let signals: HlsVideoEngineSignals;
|
|
291
|
+
* const engine = createHlsVideoEngine({
|
|
264
292
|
* initialBandwidth: 2_000_000,
|
|
265
293
|
* preferredAudioLanguage: 'en',
|
|
266
294
|
* onSignalsReady: (refs) => {
|
|
@@ -276,7 +304,7 @@ interface SimpleHlsEngineConfig extends ShareSignalsConfig<SimpleHlsEngineState,
|
|
|
276
304
|
* await engine.destroy();
|
|
277
305
|
* ```
|
|
278
306
|
*/
|
|
279
|
-
declare function
|
|
307
|
+
declare function createHlsVideoEngine(config?: HlsVideoEngineConfig): Composition<HlsVideoEngineState, HlsVideoEngineContext>;
|
|
280
308
|
//#endregion
|
|
281
|
-
export {
|
|
309
|
+
export { HlsVideoEngineConfig, HlsVideoEngineContext, HlsVideoEngineSignals, HlsVideoEngineState, createHlsVideoEngine };
|
|
282
310
|
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","names":[],"sources":["../../../../../src/playback/engines/hls/engine.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"engine.d.ts","names":[],"sources":["../../../../../src/playback/engines/hls/engine.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA4FiB;;;;;EAKf,eAAe;EACf;EACA;EACA;EACA;EACA,iBAAiB;EAGjB,qBAAqB,eAAe;EACpC,0BAA0B,QAAQ;;;;;;;EAOlC,0BAA0B,QAAQ;;;;;;;;;EASlC,yBAAyB,QAAQ;;;;;;;;;;EAUjC;;;;;;;;EAQA;;;;;;;;EAQA,SAAS;EACT;EACA;;;;;;;;EAQA;;;;;;;;;EASA;;;;;;;;;EASA;;;;;;;UAQe;EACf,eAAe;EACf,cAAc;EACd,mBAAmB;EACnB,mBAAmB;EACnB,0BAA0B;EAC1B,0BAA0B;EAC1B,kBAAkB;EAClB,8BAA8B;;;;;;;;KASpB;EACV,OAAO,aAAa;EACpB,SAAS,eAAe;;;;;;;;UAST,6BAA6B,mBAAmB,qBAAqB;;;;;EAKpF;;;;;;;;EAQA,eAAe;;;;;;;;EAQf,mCAAmC;EACnC;EACA;EACA;EACA;;;;;;EAMA,0BAA0B,yBAAyB;;;;;;;;;EASnD,kBAAkB;;;;;;EAMlB,oBAAoB;;;;;;EAMpB,mCAAmC;;;;;;EAMnC,2CAA2C;;;;;;EAM3C,2CAA2C;;;;;;;;EAQ3C,gBAAgB,QAAQ;;;;;;;EAOxB,aAAa,QAAQ;;;;;;;EAOrB,YAAY,QAAQ;;;;;;EAMpB,UAAU,QAAQ;;;;;;;EAOlB,WAAW,QAAQ;;;;;;;;EAQnB,WAAW;;;;;;;;;EASX,uBAAuB;;;;;;;EAOvB;;;;;;;;;EASA,aAAa,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiDV,qBACd,SAAQ,uBACP,YAAY,qBAAqB"}
|
|
@@ -5,20 +5,25 @@ import { loadAudioSegments, loadTextTrackSegments, loadVideoSegments } from "../
|
|
|
5
5
|
import { setupTextTrackActors } from "../../behaviors/dom/setup-text-track-actors.js";
|
|
6
6
|
import { trackCurrentTime } from "../../behaviors/dom/track-current-time.js";
|
|
7
7
|
import { trackLoadTriggers } from "../../behaviors/dom/track-load-triggers.js";
|
|
8
|
-
import { deriveSharedMinStartMediaTime, establishStartMediaTime } from "../../behaviors/establish-start-media-time.js";
|
|
8
|
+
import { deriveSharedMinStartMediaTime, establishStartMediaTime, gateFirstParseOnAnchor } from "../../behaviors/establish-start-media-time.js";
|
|
9
|
+
import { delayedReschedule } from "../../../core/tasks/delayed-reschedule.js";
|
|
9
10
|
import { attachMediaSourceAsSourceElement } from "../../../media/dom/mse/mediasource-setup.js";
|
|
10
11
|
import { canPlayTrack } from "../../../media/dom/capabilities.js";
|
|
11
12
|
import { addSubtitlesTracksToMedia, getShowingSubtitlesTrackFromMedia, removeAllSubtitlesTracksFromMedia } from "../../../media/dom/text/text-track-slots.js";
|
|
12
13
|
import { parseMultivariantPlaylist } from "../../../media/hls/parse-multivariant.js";
|
|
14
|
+
import { mediaPlaylistReloadDelay, resolveLiveLatency } from "../../../media/hls/reload-policy.js";
|
|
13
15
|
import { getResolvedSelectedTrackDuration } from "../../../media/utils/track-selection.js";
|
|
14
16
|
import { calculatePresentationDuration } from "../../behaviors/calculate-presentation-duration.js";
|
|
17
|
+
import { collectErrors } from "../../behaviors/collect-errors.js";
|
|
15
18
|
import { deriveCdnPriority } from "../../behaviors/derive-cdn-priority.js";
|
|
16
19
|
import { setupAirPlay } from "../../behaviors/dom/airplay.js";
|
|
17
20
|
import { applyStartPosition } from "../../behaviors/dom/apply-start-position.js";
|
|
18
21
|
import { endOfStream } from "../../behaviors/dom/end-of-stream.js";
|
|
19
22
|
import { recoverEndStall } from "../../behaviors/dom/recover-end-stall.js";
|
|
23
|
+
import { seekToLiveEdge } from "../../behaviors/dom/seek-to-live-edge.js";
|
|
20
24
|
import { setupAudioBufferActors, setupVideoBufferActors } from "../../behaviors/dom/setup-buffer-actors.js";
|
|
21
25
|
import { setupMediaSource } from "../../behaviors/dom/setup-mediasource.js";
|
|
26
|
+
import { syncLiveSeekableRange } from "../../behaviors/dom/sync-live-seekable-range.js";
|
|
22
27
|
import { syncTextTracks } from "../../behaviors/dom/sync-text-tracks.js";
|
|
23
28
|
import { updateMediaSourceDuration } from "../../behaviors/dom/update-mediasource-duration.js";
|
|
24
29
|
import { resolvePresentation } from "../../behaviors/resolve-presentation.js";
|
|
@@ -27,6 +32,7 @@ import { setupFailoverMonitor } from "../../behaviors/setup-failover-monitor.js"
|
|
|
27
32
|
import { syncPreload } from "../../behaviors/sync-preload.js";
|
|
28
33
|
import { switchAudioTrack, switchTextTrack, switchVideoTrack } from "../../behaviors/track-switching.js";
|
|
29
34
|
import { relocatingTextPipelines, relocationPipelinesFor } from "../../primitives/relocation-pipelines.js";
|
|
35
|
+
import { reportUnsupportedTrackConditions } from "../../primitives/report-track-conditions.js";
|
|
30
36
|
//#region src/playback/engines/hls/engine.ts
|
|
31
37
|
/**
|
|
32
38
|
* Generic `shareSignals` instantiated against the HLS engine's full state
|
|
@@ -52,8 +58,8 @@ const shareSignals = makeShareSignals([
|
|
|
52
58
|
*
|
|
53
59
|
* @example
|
|
54
60
|
* ```ts
|
|
55
|
-
* let signals:
|
|
56
|
-
* const engine =
|
|
61
|
+
* let signals: HlsVideoEngineSignals;
|
|
62
|
+
* const engine = createHlsVideoEngine({
|
|
57
63
|
* initialBandwidth: 2_000_000,
|
|
58
64
|
* preferredAudioLanguage: 'en',
|
|
59
65
|
* onSignalsReady: (refs) => {
|
|
@@ -69,13 +75,14 @@ const shareSignals = makeShareSignals([
|
|
|
69
75
|
* await engine.destroy();
|
|
70
76
|
* ```
|
|
71
77
|
*/
|
|
72
|
-
function
|
|
78
|
+
function createHlsVideoEngine(config = {}) {
|
|
73
79
|
const deriveStartMediaTime = config.deriveStartMediaTime ?? deriveSharedMinStartMediaTime;
|
|
74
80
|
const finalConfig = {
|
|
75
81
|
...config,
|
|
76
82
|
deriveStartMediaTime,
|
|
77
83
|
attachMediaSource: attachMediaSourceAsSourceElement,
|
|
78
84
|
canPlayTrack: config.canPlayTrack ?? canPlayTrack,
|
|
85
|
+
reportUnsupportedTrackConditions: config.reportUnsupportedTrackConditions ?? reportUnsupportedTrackConditions,
|
|
79
86
|
resolveTextTrackSegment: config.resolveTextTrackSegment ?? resolveVttSegment,
|
|
80
87
|
textMessagePipelines: relocatingTextPipelines,
|
|
81
88
|
resolveDuration: config.resolveDuration ?? getResolvedSelectedTrackDuration,
|
|
@@ -84,7 +91,10 @@ function createSimpleHlsEngine(config = {}) {
|
|
|
84
91
|
getShowingSubtitlesTrackFromMedia: config.getShowingSubtitlesTrackFromMedia ?? getShowingSubtitlesTrackFromMedia,
|
|
85
92
|
removeAllSubtitlesTracksFromMedia: config.removeAllSubtitlesTracksFromMedia ?? removeAllSubtitlesTracksFromMedia,
|
|
86
93
|
videoMessagePipelines: relocationPipelinesFor("video", deriveStartMediaTime),
|
|
87
|
-
audioMessagePipelines: relocationPipelinesFor("audio", deriveStartMediaTime)
|
|
94
|
+
audioMessagePipelines: relocationPipelinesFor("audio", deriveStartMediaTime),
|
|
95
|
+
gateFirstParse: gateFirstParseOnAnchor,
|
|
96
|
+
resolveLiveLatency,
|
|
97
|
+
reschedule: config.reschedule ?? delayedReschedule(mediaPlaylistReloadDelay)
|
|
88
98
|
};
|
|
89
99
|
return createComposition([
|
|
90
100
|
syncPreload,
|
|
@@ -92,6 +102,7 @@ function createSimpleHlsEngine(config = {}) {
|
|
|
92
102
|
resolvePresentation,
|
|
93
103
|
deriveCdnPriority,
|
|
94
104
|
setupFailoverMonitor,
|
|
105
|
+
collectErrors,
|
|
95
106
|
resolveVideoTrack,
|
|
96
107
|
resolveAudioTrack,
|
|
97
108
|
resolveTextTrack,
|
|
@@ -109,6 +120,8 @@ function createSimpleHlsEngine(config = {}) {
|
|
|
109
120
|
switchTextTrack,
|
|
110
121
|
loadVideoSegments,
|
|
111
122
|
loadAudioSegments,
|
|
123
|
+
syncLiveSeekableRange,
|
|
124
|
+
seekToLiveEdge,
|
|
112
125
|
endOfStream,
|
|
113
126
|
recoverEndStall,
|
|
114
127
|
syncTextTracks,
|
|
@@ -127,6 +140,6 @@ function createSimpleHlsEngine(config = {}) {
|
|
|
127
140
|
});
|
|
128
141
|
}
|
|
129
142
|
//#endregion
|
|
130
|
-
export {
|
|
143
|
+
export { createHlsVideoEngine };
|
|
131
144
|
|
|
132
145
|
//# sourceMappingURL=engine.js.map
|