@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.
Files changed (238) hide show
  1. package/dist/default/core/signals/when.js +38 -0
  2. package/dist/default/core/signals/when.js.map +1 -0
  3. package/dist/default/core/tasks/delayed-reschedule.js +31 -0
  4. package/dist/default/core/tasks/delayed-reschedule.js.map +1 -0
  5. package/dist/default/core/tasks/task.js +133 -3
  6. package/dist/default/core/tasks/task.js.map +1 -1
  7. package/dist/default/hls-audio.js +3 -0
  8. package/dist/default/hls-background-video.js +3 -0
  9. package/dist/default/hls-video.js +4 -0
  10. package/dist/default/hls.js +6 -5
  11. package/dist/default/media/dom/capabilities.js +2 -0
  12. package/dist/default/media/dom/capabilities.js.map +1 -1
  13. package/dist/default/media/errors.js +62 -0
  14. package/dist/default/media/errors.js.map +1 -0
  15. package/dist/default/media/hls/parse-media-playlist.js +167 -16
  16. package/dist/default/media/hls/parse-media-playlist.js.map +1 -1
  17. package/dist/default/media/hls/parse-multivariant.js +14 -3
  18. package/dist/default/media/hls/parse-multivariant.js.map +1 -1
  19. package/dist/default/media/hls/reload-policy.js +71 -0
  20. package/dist/default/media/hls/reload-policy.js.map +1 -0
  21. package/dist/default/media/live-window.js +36 -0
  22. package/dist/default/media/live-window.js.map +1 -0
  23. package/dist/default/media/primitives/select-tracks.js +1 -24
  24. package/dist/default/media/primitives/select-tracks.js.map +1 -1
  25. package/dist/default/media/types/index.js +15 -1
  26. package/dist/default/media/types/index.js.map +1 -1
  27. package/dist/default/media/utils/tracks.js +14 -0
  28. package/dist/default/media/utils/tracks.js.map +1 -1
  29. package/dist/default/mux-audio.js +3 -0
  30. package/dist/default/mux-background-video.js +3 -0
  31. package/dist/default/mux-video.js +3 -0
  32. package/dist/default/playback/adapters/hls-audio/adapter.js +186 -0
  33. package/dist/default/playback/adapters/hls-audio/adapter.js.map +1 -0
  34. package/dist/default/playback/adapters/hls-audio/media.js +9 -0
  35. package/dist/default/playback/adapters/hls-audio/media.js.map +1 -0
  36. package/dist/default/playback/adapters/hls-background-video/adapter.js +123 -0
  37. package/dist/default/playback/adapters/hls-background-video/adapter.js.map +1 -0
  38. package/dist/default/playback/adapters/hls-background-video/host.js +60 -0
  39. package/dist/default/playback/adapters/hls-background-video/host.js.map +1 -0
  40. package/dist/default/playback/adapters/hls-background-video/media.js +21 -0
  41. package/dist/default/playback/adapters/hls-background-video/media.js.map +1 -0
  42. package/dist/default/playback/adapters/hls-video/adapter.js +316 -0
  43. package/dist/default/playback/adapters/hls-video/adapter.js.map +1 -0
  44. package/dist/default/playback/adapters/hls-video/error-surface.js +51 -0
  45. package/dist/default/playback/adapters/hls-video/error-surface.js.map +1 -0
  46. package/dist/default/playback/adapters/hls-video/media-tracks.js +126 -0
  47. package/dist/default/playback/adapters/hls-video/media-tracks.js.map +1 -0
  48. package/dist/default/playback/adapters/hls-video/media.js +11 -0
  49. package/dist/default/playback/adapters/hls-video/media.js.map +1 -0
  50. package/dist/default/playback/adapters/mux-audio/media.js +26 -0
  51. package/dist/default/playback/adapters/mux-audio/media.js.map +1 -0
  52. package/dist/default/playback/adapters/mux-video/adapter.js +92 -0
  53. package/dist/default/playback/adapters/mux-video/adapter.js.map +1 -0
  54. package/dist/default/playback/adapters/mux-video/media.js +23 -0
  55. package/dist/default/playback/adapters/mux-video/media.js.map +1 -0
  56. package/dist/default/playback/behaviors/collect-errors.js +77 -0
  57. package/dist/default/playback/behaviors/collect-errors.js.map +1 -0
  58. package/dist/default/playback/behaviors/dom/end-of-stream.js +1 -0
  59. package/dist/default/playback/behaviors/dom/end-of-stream.js.map +1 -1
  60. package/dist/default/playback/behaviors/dom/seek-to-live-edge.js +132 -0
  61. package/dist/default/playback/behaviors/dom/seek-to-live-edge.js.map +1 -0
  62. package/dist/default/playback/behaviors/dom/sync-live-seekable-range.js +26 -0
  63. package/dist/default/playback/behaviors/dom/sync-live-seekable-range.js.map +1 -0
  64. package/dist/default/playback/behaviors/dom/update-mediasource-duration.js +29 -7
  65. package/dist/default/playback/behaviors/dom/update-mediasource-duration.js.map +1 -1
  66. package/dist/default/playback/behaviors/establish-start-media-time.js +78 -4
  67. package/dist/default/playback/behaviors/establish-start-media-time.js.map +1 -1
  68. package/dist/default/playback/behaviors/resolve-track.js +29 -8
  69. package/dist/default/playback/behaviors/resolve-track.js.map +1 -1
  70. package/dist/default/playback/behaviors/track-switching.js +18 -9
  71. package/dist/default/playback/behaviors/track-switching.js.map +1 -1
  72. package/dist/default/playback/engines/hls/engine-audio-only.js +9 -5
  73. package/dist/default/playback/engines/hls/engine-audio-only.js.map +1 -1
  74. package/dist/{dev/playback/engines/background-video/engine.js → default/playback/engines/hls/engine-background-video.js} +3 -3
  75. package/dist/default/playback/engines/hls/engine-background-video.js.map +1 -0
  76. package/dist/default/playback/engines/hls/engine.js +19 -6
  77. package/dist/default/playback/engines/hls/engine.js.map +1 -1
  78. package/dist/default/playback/primitives/error-messages.js +39 -0
  79. package/dist/default/playback/primitives/error-messages.js.map +1 -0
  80. package/dist/default/playback/primitives/live-window.js +66 -0
  81. package/dist/default/playback/primitives/live-window.js.map +1 -0
  82. package/dist/default/playback/primitives/report-track-conditions.js +86 -0
  83. package/dist/default/playback/primitives/report-track-conditions.js.map +1 -0
  84. package/dist/dev/core/signals/when.js +38 -0
  85. package/dist/dev/core/signals/when.js.map +1 -0
  86. package/dist/dev/core/tasks/delayed-reschedule.js +31 -0
  87. package/dist/dev/core/tasks/delayed-reschedule.js.map +1 -0
  88. package/dist/dev/core/tasks/task.d.ts +52 -1
  89. package/dist/dev/core/tasks/task.d.ts.map +1 -1
  90. package/dist/dev/core/tasks/task.js +133 -3
  91. package/dist/dev/core/tasks/task.js.map +1 -1
  92. package/dist/dev/hls-audio.d.ts +3 -0
  93. package/dist/dev/hls-audio.js +3 -0
  94. package/dist/dev/hls-background-video.d.ts +3 -0
  95. package/dist/dev/hls-background-video.js +3 -0
  96. package/dist/dev/hls-video.d.ts +5 -0
  97. package/dist/dev/hls-video.js +4 -0
  98. package/dist/dev/hls.d.ts +6 -5
  99. package/dist/dev/hls.js +6 -5
  100. package/dist/dev/media/dom/capabilities.js +2 -0
  101. package/dist/dev/media/dom/capabilities.js.map +1 -1
  102. package/dist/dev/media/errors.d.ts +82 -0
  103. package/dist/dev/media/errors.d.ts.map +1 -0
  104. package/dist/dev/media/errors.js +62 -0
  105. package/dist/dev/media/errors.js.map +1 -0
  106. package/dist/dev/media/hls/parse-media-playlist.js +167 -16
  107. package/dist/dev/media/hls/parse-media-playlist.js.map +1 -1
  108. package/dist/dev/media/hls/parse-multivariant.js +14 -3
  109. package/dist/dev/media/hls/parse-multivariant.js.map +1 -1
  110. package/dist/dev/media/hls/reload-policy.js +71 -0
  111. package/dist/dev/media/hls/reload-policy.js.map +1 -0
  112. package/dist/dev/media/live-window.js +36 -0
  113. package/dist/dev/media/live-window.js.map +1 -0
  114. package/dist/dev/media/primitives/select-tracks.js +1 -24
  115. package/dist/dev/media/primitives/select-tracks.js.map +1 -1
  116. package/dist/dev/media/types/index.d.ts +125 -9
  117. package/dist/dev/media/types/index.d.ts.map +1 -1
  118. package/dist/dev/media/types/index.js +15 -1
  119. package/dist/dev/media/types/index.js.map +1 -1
  120. package/dist/dev/media/utils/tracks.js +14 -0
  121. package/dist/dev/media/utils/tracks.js.map +1 -1
  122. package/dist/dev/mux-audio.d.ts +4 -0
  123. package/dist/dev/mux-audio.js +3 -0
  124. package/dist/dev/mux-background-video.d.ts +3 -0
  125. package/dist/dev/mux-background-video.js +3 -0
  126. package/dist/dev/mux-video.d.ts +4 -0
  127. package/dist/dev/mux-video.js +3 -0
  128. package/dist/dev/playback/adapters/hls-audio/adapter.d.ts +54 -0
  129. package/dist/dev/playback/adapters/hls-audio/adapter.d.ts.map +1 -0
  130. package/dist/dev/playback/adapters/hls-audio/adapter.js +186 -0
  131. package/dist/dev/playback/adapters/hls-audio/adapter.js.map +1 -0
  132. package/dist/dev/playback/adapters/hls-audio/media.d.ts +10 -0
  133. package/dist/dev/playback/adapters/hls-audio/media.d.ts.map +1 -0
  134. package/dist/dev/playback/adapters/hls-audio/media.js +9 -0
  135. package/dist/dev/playback/adapters/hls-audio/media.js.map +1 -0
  136. package/dist/dev/playback/adapters/hls-background-video/adapter.d.ts +59 -0
  137. package/dist/dev/playback/adapters/hls-background-video/adapter.d.ts.map +1 -0
  138. package/dist/dev/playback/adapters/hls-background-video/adapter.js +123 -0
  139. package/dist/dev/playback/adapters/hls-background-video/adapter.js.map +1 -0
  140. package/dist/dev/playback/adapters/hls-background-video/host.d.ts +38 -0
  141. package/dist/dev/playback/adapters/hls-background-video/host.d.ts.map +1 -0
  142. package/dist/dev/playback/adapters/hls-background-video/host.js +60 -0
  143. package/dist/dev/playback/adapters/hls-background-video/host.js.map +1 -0
  144. package/dist/dev/playback/adapters/hls-background-video/media.d.ts +20 -0
  145. package/dist/dev/playback/adapters/hls-background-video/media.d.ts.map +1 -0
  146. package/dist/dev/playback/adapters/hls-background-video/media.js +21 -0
  147. package/dist/dev/playback/adapters/hls-background-video/media.js.map +1 -0
  148. package/dist/dev/playback/adapters/hls-video/adapter.d.ts +63 -0
  149. package/dist/dev/playback/adapters/hls-video/adapter.d.ts.map +1 -0
  150. package/dist/dev/playback/adapters/hls-video/adapter.js +316 -0
  151. package/dist/dev/playback/adapters/hls-video/adapter.js.map +1 -0
  152. package/dist/dev/playback/adapters/hls-video/error-surface.d.ts +18 -0
  153. package/dist/dev/playback/adapters/hls-video/error-surface.d.ts.map +1 -0
  154. package/dist/dev/playback/adapters/hls-video/error-surface.js +51 -0
  155. package/dist/dev/playback/adapters/hls-video/error-surface.js.map +1 -0
  156. package/dist/dev/playback/adapters/hls-video/media-tracks.d.ts +22 -0
  157. package/dist/dev/playback/adapters/hls-video/media-tracks.d.ts.map +1 -0
  158. package/dist/dev/playback/adapters/hls-video/media-tracks.js +126 -0
  159. package/dist/dev/playback/adapters/hls-video/media-tracks.js.map +1 -0
  160. package/dist/dev/playback/adapters/hls-video/media.d.ts +10 -0
  161. package/dist/dev/playback/adapters/hls-video/media.d.ts.map +1 -0
  162. package/dist/dev/playback/adapters/hls-video/media.js +11 -0
  163. package/dist/dev/playback/adapters/hls-video/media.js.map +1 -0
  164. package/dist/dev/playback/adapters/mux-audio/media.d.ts +28 -0
  165. package/dist/dev/playback/adapters/mux-audio/media.d.ts.map +1 -0
  166. package/dist/dev/playback/adapters/mux-audio/media.js +26 -0
  167. package/dist/dev/playback/adapters/mux-audio/media.js.map +1 -0
  168. package/dist/dev/playback/adapters/mux-video/adapter.d.ts +33 -0
  169. package/dist/dev/playback/adapters/mux-video/adapter.d.ts.map +1 -0
  170. package/dist/dev/playback/adapters/mux-video/adapter.js +92 -0
  171. package/dist/dev/playback/adapters/mux-video/adapter.js.map +1 -0
  172. package/dist/dev/playback/adapters/mux-video/media.d.ts +24 -0
  173. package/dist/dev/playback/adapters/mux-video/media.d.ts.map +1 -0
  174. package/dist/dev/playback/adapters/mux-video/media.js +23 -0
  175. package/dist/dev/playback/adapters/mux-video/media.js.map +1 -0
  176. package/dist/dev/playback/behaviors/collect-errors.js +77 -0
  177. package/dist/dev/playback/behaviors/collect-errors.js.map +1 -0
  178. package/dist/dev/playback/behaviors/dom/end-of-stream.js +1 -0
  179. package/dist/dev/playback/behaviors/dom/end-of-stream.js.map +1 -1
  180. package/dist/dev/playback/behaviors/dom/seek-to-live-edge.js +132 -0
  181. package/dist/dev/playback/behaviors/dom/seek-to-live-edge.js.map +1 -0
  182. package/dist/dev/playback/behaviors/dom/sync-live-seekable-range.js +26 -0
  183. package/dist/dev/playback/behaviors/dom/sync-live-seekable-range.js.map +1 -0
  184. package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js +29 -7
  185. package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js.map +1 -1
  186. package/dist/dev/playback/behaviors/establish-start-media-time.d.ts +5 -0
  187. package/dist/dev/playback/behaviors/establish-start-media-time.d.ts.map +1 -1
  188. package/dist/dev/playback/behaviors/establish-start-media-time.js +78 -4
  189. package/dist/dev/playback/behaviors/establish-start-media-time.js.map +1 -1
  190. package/dist/dev/playback/behaviors/resolve-track.js +29 -8
  191. package/dist/dev/playback/behaviors/resolve-track.js.map +1 -1
  192. package/dist/dev/playback/behaviors/track-switching.js +18 -9
  193. package/dist/dev/playback/behaviors/track-switching.js.map +1 -1
  194. package/dist/dev/playback/engines/hls/engine-audio-only.d.ts +34 -17
  195. package/dist/dev/playback/engines/hls/engine-audio-only.d.ts.map +1 -1
  196. package/dist/dev/playback/engines/hls/engine-audio-only.js +9 -5
  197. package/dist/dev/playback/engines/hls/engine-audio-only.js.map +1 -1
  198. package/dist/dev/playback/engines/{background-video/engine.d.ts → hls/engine-background-video.d.ts} +7 -7
  199. package/dist/dev/playback/engines/hls/engine-background-video.d.ts.map +1 -0
  200. package/dist/{default/playback/engines/background-video/engine.js → dev/playback/engines/hls/engine-background-video.js} +3 -3
  201. package/dist/dev/playback/engines/hls/engine-background-video.js.map +1 -0
  202. package/dist/dev/playback/engines/hls/engine.d.ts +43 -15
  203. package/dist/dev/playback/engines/hls/engine.d.ts.map +1 -1
  204. package/dist/dev/playback/engines/hls/engine.js +19 -6
  205. package/dist/dev/playback/engines/hls/engine.js.map +1 -1
  206. package/dist/dev/playback/primitives/error-messages.js +39 -0
  207. package/dist/dev/playback/primitives/error-messages.js.map +1 -0
  208. package/dist/dev/playback/primitives/live-window.js +66 -0
  209. package/dist/dev/playback/primitives/live-window.js.map +1 -0
  210. package/dist/dev/playback/primitives/report-track-conditions.d.ts +11 -0
  211. package/dist/dev/playback/primitives/report-track-conditions.d.ts.map +1 -0
  212. package/dist/dev/playback/primitives/report-track-conditions.js +86 -0
  213. package/dist/dev/playback/primitives/report-track-conditions.js.map +1 -0
  214. package/package.json +32 -6
  215. package/dist/default/background-video.js +0 -3
  216. package/dist/default/playback/engines/background-video/adapter.js +0 -158
  217. package/dist/default/playback/engines/background-video/adapter.js.map +0 -1
  218. package/dist/default/playback/engines/background-video/engine.js.map +0 -1
  219. package/dist/default/playback/engines/hls/adapter-audio-only.js +0 -124
  220. package/dist/default/playback/engines/hls/adapter-audio-only.js.map +0 -1
  221. package/dist/default/playback/engines/hls/adapter.js +0 -120
  222. package/dist/default/playback/engines/hls/adapter.js.map +0 -1
  223. package/dist/dev/background-video.d.ts +0 -3
  224. package/dist/dev/background-video.js +0 -3
  225. package/dist/dev/playback/engines/background-video/adapter.d.ts +0 -59
  226. package/dist/dev/playback/engines/background-video/adapter.d.ts.map +0 -1
  227. package/dist/dev/playback/engines/background-video/adapter.js +0 -158
  228. package/dist/dev/playback/engines/background-video/adapter.js.map +0 -1
  229. package/dist/dev/playback/engines/background-video/engine.d.ts.map +0 -1
  230. package/dist/dev/playback/engines/background-video/engine.js.map +0 -1
  231. package/dist/dev/playback/engines/hls/adapter-audio-only.d.ts +0 -46
  232. package/dist/dev/playback/engines/hls/adapter-audio-only.d.ts.map +0 -1
  233. package/dist/dev/playback/engines/hls/adapter-audio-only.js +0 -124
  234. package/dist/dev/playback/engines/hls/adapter-audio-only.js.map +0 -1
  235. package/dist/dev/playback/engines/hls/adapter.d.ts +0 -42
  236. package/dist/dev/playback/engines/hls/adapter.d.ts.map +0 -1
  237. package/dist/dev/playback/engines/hls/adapter.js +0 -120
  238. 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 `createSimpleHlsEngine`: omits
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: SimpleHlsAudioOnlyEngineSignals;
47
- * const engine = createHlsAudioOnlyEngine({
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 createHlsAudioOnlyEngine(config = {}) {
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 { createHlsAudioOnlyEngine };
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"}
@@ -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/engine.d.ts
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 `SimpleHlsEngineState`: audio/text track slots are absent
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
- * `SimpleHlsEngineConfig`, audio/text/ABR/bandwidth/quality knobs are
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. `BackgroundVideoMediaElement`) install their own
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
- * `BackgroundVideoMediaElement` rather than the engine.
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/engine.ts
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
- * `BackgroundVideoMediaElement` rather than the engine.
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 { ParsePresentation } from "../../behaviors/resolve-presentation.js";
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 SimpleHlsEngineState {
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 SimpleHlsEngineContext {
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 SimpleHlsEngineSignals = {
127
- state: StateSignals<SimpleHlsEngineState>;
128
- context: ContextSignals<SimpleHlsEngineContext>;
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 SimpleHlsEngineConfig extends ShareSignalsConfig<SimpleHlsEngineState, SimpleHlsEngineContext> {
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: SimpleHlsEngineSignals;
263
- * const engine = createSimpleHlsEngine({
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 createSimpleHlsEngine(config?: SimpleHlsEngineConfig): Composition<SimpleHlsEngineState, SimpleHlsEngineContext>;
307
+ declare function createHlsVideoEngine(config?: HlsVideoEngineConfig): Composition<HlsVideoEngineState, HlsVideoEngineContext>;
280
308
  //#endregion
281
- export { SimpleHlsEngineConfig, SimpleHlsEngineContext, SimpleHlsEngineSignals, SimpleHlsEngineState, createSimpleHlsEngine };
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;UA+EiB;;;;;EAKf,eAAe;EACf;EACA;EACA;EACA;EACA,iBAAiB;EAGjB,qBAAqB,eAAe;EACpC,0BAA0B,QAAQ;;;;;;;EAOlC,0BAA0B,QAAQ;;;;;;;;;EASlC,yBAAyB,QAAQ;;;;;;;;;;EAUjC;;;;;;;;EAQA;EACA;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,8BAA8B,mBAAmB,sBAAsB;;;;;EAKtF;;;;;;;;EAQA,eAAe;EACf;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;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiDc,sBACd,SAAQ,wBACP,YAAY,sBAAsB"}
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: SimpleHlsEngineSignals;
56
- * const engine = createSimpleHlsEngine({
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 createSimpleHlsEngine(config = {}) {
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 { createSimpleHlsEngine };
143
+ export { createHlsVideoEngine };
131
144
 
132
145
  //# sourceMappingURL=engine.js.map