@videojs/spf 10.0.0-beta.31 → 10.0.0-beta.32

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 (520) hide show
  1. package/dist/default/core/actors/create-machine-actor.js +23 -25
  2. package/dist/default/core/actors/create-machine-actor.js.map +1 -1
  3. package/dist/default/core/actors/create-transition-actor.js +7 -9
  4. package/dist/default/core/actors/create-transition-actor.js.map +1 -1
  5. package/dist/default/core/composition/create-composition.js +26 -29
  6. package/dist/default/core/composition/create-composition.js.map +1 -1
  7. package/dist/default/core/composition/share-signals.js +12 -17
  8. package/dist/default/core/composition/share-signals.js.map +1 -1
  9. package/dist/default/core/machine.js +3 -4
  10. package/dist/default/core/machine.js.map +1 -1
  11. package/dist/default/core/reactors/create-machine-reactor.js +20 -19
  12. package/dist/default/core/reactors/create-machine-reactor.js.map +1 -1
  13. package/dist/default/core/signals/effect.js +24 -4
  14. package/dist/default/core/signals/effect.js.map +1 -1
  15. package/dist/default/core/signals/primitives.js +10 -14
  16. package/dist/default/core/signals/primitives.js.map +1 -1
  17. package/dist/default/core/signals/when.js +6 -8
  18. package/dist/default/core/signals/when.js.map +1 -1
  19. package/dist/default/core/tasks/delayed-reschedule.js +7 -11
  20. package/dist/default/core/tasks/delayed-reschedule.js.map +1 -1
  21. package/dist/default/core/tasks/task.js +59 -82
  22. package/dist/default/core/tasks/task.js.map +1 -1
  23. package/dist/default/hls.js +3 -1
  24. package/dist/default/index.js +2 -3
  25. package/dist/default/index.js.map +1 -1
  26. package/dist/default/media/abr/quality-selection.js +3 -7
  27. package/dist/default/media/abr/quality-selection.js.map +1 -1
  28. package/dist/default/media/buffer/back-buffer.js +15 -19
  29. package/dist/default/media/buffer/back-buffer.js.map +1 -1
  30. package/dist/default/media/buffer/forward-buffer.js +32 -41
  31. package/dist/default/media/buffer/forward-buffer.js.map +1 -1
  32. package/dist/default/media/dom/capabilities.js +26 -37
  33. package/dist/default/media/dom/capabilities.js.map +1 -1
  34. package/dist/default/media/dom/mse/append-segment.js +3 -5
  35. package/dist/default/media/dom/mse/append-segment.js.map +1 -1
  36. package/dist/default/media/dom/mse/buffer-flusher.js +5 -5
  37. package/dist/default/media/dom/mse/buffer-flusher.js.map +1 -1
  38. package/dist/default/media/dom/mse/duration.js +23 -31
  39. package/dist/default/media/dom/mse/duration.js.map +1 -1
  40. package/dist/default/media/dom/mse/end-of-stream.js +3 -6
  41. package/dist/default/media/dom/mse/end-of-stream.js.map +1 -1
  42. package/dist/default/media/dom/mse/mediasource-setup.js +65 -81
  43. package/dist/default/media/dom/mse/mediasource-setup.js.map +1 -1
  44. package/dist/default/media/dom/screen.js +37 -54
  45. package/dist/default/media/dom/screen.js.map +1 -1
  46. package/dist/default/media/dom/text/resolve-vtt-segment.js.map +1 -1
  47. package/dist/default/media/dom/text/text-track-slots.js +15 -23
  48. package/dist/default/media/dom/text/text-track-slots.js.map +1 -1
  49. package/dist/default/media/errors.js +25 -34
  50. package/dist/default/media/errors.js.map +1 -1
  51. package/dist/default/media/hls/parse-attributes.js +9 -26
  52. package/dist/default/media/hls/parse-attributes.js.map +1 -1
  53. package/dist/default/media/hls/parse-media-playlist.js +25 -33
  54. package/dist/default/media/hls/parse-media-playlist.js.map +1 -1
  55. package/dist/default/media/hls/parse-multivariant.js +3 -3
  56. package/dist/default/media/hls/parse-multivariant.js.map +1 -1
  57. package/dist/default/media/hls/reload-policy.js +19 -27
  58. package/dist/default/media/hls/reload-policy.js.map +1 -1
  59. package/dist/default/media/hls/resolve-url.js +1 -3
  60. package/dist/default/media/hls/resolve-url.js.map +1 -1
  61. package/dist/default/media/live-window.js +9 -13
  62. package/dist/default/media/live-window.js.map +1 -1
  63. package/dist/default/media/media-tracks/media-tracks.js +12 -17
  64. package/dist/default/media/media-tracks/media-tracks.js.map +1 -1
  65. package/dist/default/media/mp4/box.js +4 -5
  66. package/dist/default/media/mp4/box.js.map +1 -1
  67. package/dist/default/media/mp4/timestamp-origin.js +30 -42
  68. package/dist/default/media/mp4/timestamp-origin.js.map +1 -1
  69. package/dist/default/media/primitives/resolution.js +5 -8
  70. package/dist/default/media/primitives/resolution.js.map +1 -1
  71. package/dist/default/media/primitives/select-tracks.js +24 -34
  72. package/dist/default/media/primitives/select-tracks.js.map +1 -1
  73. package/dist/default/media/text/parse-vtt-timestamp-map.js +6 -8
  74. package/dist/default/media/text/parse-vtt-timestamp-map.js.map +1 -1
  75. package/dist/default/media/text/resolve-vtt-metadata.js +8 -9
  76. package/dist/default/media/text/resolve-vtt-metadata.js.map +1 -1
  77. package/dist/default/media/types/index.js +10 -18
  78. package/dist/default/media/types/index.js.map +1 -1
  79. package/dist/default/media/utils/cdn.js +10 -16
  80. package/dist/default/media/utils/cdn.js.map +1 -1
  81. package/dist/default/media/utils/preload.js +4 -6
  82. package/dist/default/media/utils/preload.js.map +1 -1
  83. package/dist/default/media/utils/track-selection.js +10 -14
  84. package/dist/default/media/utils/track-selection.js.map +1 -1
  85. package/dist/default/media/utils/tracks.js +56 -54
  86. package/dist/default/media/utils/tracks.js.map +1 -1
  87. package/dist/default/network/bandwidth-estimator.js +18 -19
  88. package/dist/default/network/bandwidth-estimator.js.map +1 -1
  89. package/dist/default/network/chunked-stream-iterable.js +4 -6
  90. package/dist/default/network/chunked-stream-iterable.js.map +1 -1
  91. package/dist/default/network/ewma.js +22 -25
  92. package/dist/default/network/ewma.js.map +1 -1
  93. package/dist/default/network/fetch.js +30 -37
  94. package/dist/default/network/fetch.js.map +1 -1
  95. package/dist/default/playback/actors/dom/segment-loader.js +28 -44
  96. package/dist/default/playback/actors/dom/segment-loader.js.map +1 -1
  97. package/dist/default/playback/actors/dom/source-buffer.js.map +1 -1
  98. package/dist/default/playback/actors/dom/text-tracks.js.map +1 -1
  99. package/dist/default/playback/actors/text-track-segment-loader.js +24 -35
  100. package/dist/default/playback/actors/text-track-segment-loader.js.map +1 -1
  101. package/dist/default/playback/adapters/hls-audio/adapter.js +23 -31
  102. package/dist/default/playback/adapters/hls-audio/adapter.js.map +1 -1
  103. package/dist/default/playback/adapters/hls-audio/media.js.map +1 -1
  104. package/dist/default/playback/adapters/hls-background-video/adapter.js +50 -70
  105. package/dist/default/playback/adapters/hls-background-video/adapter.js.map +1 -1
  106. package/dist/default/playback/adapters/hls-background-video/host.js +12 -16
  107. package/dist/default/playback/adapters/hls-background-video/host.js.map +1 -1
  108. package/dist/default/playback/adapters/hls-background-video/media.js +5 -8
  109. package/dist/default/playback/adapters/hls-background-video/media.js.map +1 -1
  110. package/dist/default/playback/adapters/hls-video/adapter.js +43 -60
  111. package/dist/default/playback/adapters/hls-video/adapter.js.map +1 -1
  112. package/dist/default/playback/adapters/hls-video/error-surface.js +13 -18
  113. package/dist/default/playback/adapters/hls-video/error-surface.js.map +1 -1
  114. package/dist/default/playback/adapters/hls-video/media-tracks.js +4 -5
  115. package/dist/default/playback/adapters/hls-video/media-tracks.js.map +1 -1
  116. package/dist/default/playback/adapters/hls-video/media.js.map +1 -1
  117. package/dist/default/playback/adapters/mux-audio/media.js +8 -12
  118. package/dist/default/playback/adapters/mux-audio/media.js.map +1 -1
  119. package/dist/default/playback/adapters/mux-video/adapter.js +25 -33
  120. package/dist/default/playback/adapters/mux-video/adapter.js.map +1 -1
  121. package/dist/default/playback/adapters/mux-video/media.js +7 -9
  122. package/dist/default/playback/adapters/mux-video/media.js.map +1 -1
  123. package/dist/default/playback/behaviors/calculate-presentation-duration.js +5 -8
  124. package/dist/default/playback/behaviors/calculate-presentation-duration.js.map +1 -1
  125. package/dist/default/playback/behaviors/collect-errors.js +39 -52
  126. package/dist/default/playback/behaviors/collect-errors.js.map +1 -1
  127. package/dist/default/playback/behaviors/derive-cdn-priority.js +16 -23
  128. package/dist/default/playback/behaviors/derive-cdn-priority.js.map +1 -1
  129. package/dist/default/playback/behaviors/dom/airplay.js +38 -61
  130. package/dist/default/playback/behaviors/dom/airplay.js.map +1 -1
  131. package/dist/default/playback/behaviors/dom/apply-start-position.js +23 -35
  132. package/dist/default/playback/behaviors/dom/apply-start-position.js.map +1 -1
  133. package/dist/default/playback/behaviors/dom/end-of-stream.js +11 -16
  134. package/dist/default/playback/behaviors/dom/end-of-stream.js.map +1 -1
  135. package/dist/default/playback/behaviors/dom/load-segments.js +27 -39
  136. package/dist/default/playback/behaviors/dom/load-segments.js.map +1 -1
  137. package/dist/default/playback/behaviors/dom/recover-end-stall.js +21 -26
  138. package/dist/default/playback/behaviors/dom/recover-end-stall.js.map +1 -1
  139. package/dist/default/playback/behaviors/dom/seek-to-live-edge.js +41 -60
  140. package/dist/default/playback/behaviors/dom/seek-to-live-edge.js.map +1 -1
  141. package/dist/default/playback/behaviors/dom/setup-buffer-actors.js +50 -74
  142. package/dist/default/playback/behaviors/dom/setup-buffer-actors.js.map +1 -1
  143. package/dist/default/playback/behaviors/dom/setup-mediasource.js +29 -43
  144. package/dist/default/playback/behaviors/dom/setup-mediasource.js.map +1 -1
  145. package/dist/default/playback/behaviors/dom/setup-text-track-actors.js.map +1 -1
  146. package/dist/default/playback/behaviors/dom/sync-live-seekable-range.js +3 -4
  147. package/dist/default/playback/behaviors/dom/sync-live-seekable-range.js.map +1 -1
  148. package/dist/default/playback/behaviors/dom/sync-text-tracks.js +30 -45
  149. package/dist/default/playback/behaviors/dom/sync-text-tracks.js.map +1 -1
  150. package/dist/default/playback/behaviors/dom/track-current-time.js +9 -11
  151. package/dist/default/playback/behaviors/dom/track-current-time.js.map +1 -1
  152. package/dist/default/playback/behaviors/dom/track-load-triggers.js +24 -32
  153. package/dist/default/playback/behaviors/dom/track-load-triggers.js.map +1 -1
  154. package/dist/default/playback/behaviors/dom/track-playback-rate.js +6 -8
  155. package/dist/default/playback/behaviors/dom/track-playback-rate.js.map +1 -1
  156. package/dist/default/playback/behaviors/dom/track-player-resolution.js +10 -14
  157. package/dist/default/playback/behaviors/dom/track-player-resolution.js.map +1 -1
  158. package/dist/default/playback/behaviors/dom/track-screen-resolution.js +8 -9
  159. package/dist/default/playback/behaviors/dom/track-screen-resolution.js.map +1 -1
  160. package/dist/default/playback/behaviors/dom/update-mediasource-duration.js +28 -43
  161. package/dist/default/playback/behaviors/dom/update-mediasource-duration.js.map +1 -1
  162. package/dist/default/playback/behaviors/establish-start-media-time.js +32 -42
  163. package/dist/default/playback/behaviors/establish-start-media-time.js.map +1 -1
  164. package/dist/default/playback/behaviors/resolve-presentation.js +13 -22
  165. package/dist/default/playback/behaviors/resolve-presentation.js.map +1 -1
  166. package/dist/default/playback/behaviors/resolve-track.js +5 -12
  167. package/dist/default/playback/behaviors/resolve-track.js.map +1 -1
  168. package/dist/default/playback/behaviors/select-tracks.js +77 -104
  169. package/dist/default/playback/behaviors/select-tracks.js.map +1 -1
  170. package/dist/default/playback/behaviors/setup-failover-monitor.js +11 -16
  171. package/dist/default/playback/behaviors/setup-failover-monitor.js.map +1 -1
  172. package/dist/default/playback/behaviors/sync-preload.js +9 -13
  173. package/dist/default/playback/behaviors/sync-preload.js.map +1 -1
  174. package/dist/default/playback/behaviors/track-switching.js +189 -173
  175. package/dist/default/playback/behaviors/track-switching.js.map +1 -1
  176. package/dist/default/playback/engines/hls/engine-audio-only.js +20 -24
  177. package/dist/default/playback/engines/hls/engine-audio-only.js.map +1 -1
  178. package/dist/default/playback/engines/hls/engine-background-video.js +22 -27
  179. package/dist/default/playback/engines/hls/engine-background-video.js.map +1 -1
  180. package/dist/default/playback/engines/hls/engine.js +22 -25
  181. package/dist/default/playback/engines/hls/engine.js.map +1 -1
  182. package/dist/default/playback/primitives/error-messages.js +16 -25
  183. package/dist/default/playback/primitives/error-messages.js.map +1 -1
  184. package/dist/default/playback/primitives/failover-fetch.js +9 -14
  185. package/dist/default/playback/primitives/failover-fetch.js.map +1 -1
  186. package/dist/default/playback/primitives/head-peek.js +7 -10
  187. package/dist/default/playback/primitives/head-peek.js.map +1 -1
  188. package/dist/default/playback/primitives/live-window.js +12 -15
  189. package/dist/default/playback/primitives/live-window.js.map +1 -1
  190. package/dist/default/playback/primitives/relocation-pipelines.js +34 -46
  191. package/dist/default/playback/primitives/relocation-pipelines.js.map +1 -1
  192. package/dist/default/playback/primitives/report-track-conditions.js +26 -38
  193. package/dist/default/playback/primitives/report-track-conditions.js.map +1 -1
  194. package/dist/default/playback/primitives/segment-load-pipeline.js +15 -15
  195. package/dist/default/playback/primitives/segment-load-pipeline.js.map +1 -1
  196. package/dist/default/playback/primitives/selection-rules.js +65 -36
  197. package/dist/default/playback/primitives/selection-rules.js.map +1 -1
  198. package/dist/default/playback/primitives/text-segment-load-pipeline.js +4 -5
  199. package/dist/default/playback/primitives/text-segment-load-pipeline.js.map +1 -1
  200. package/dist/default/playback/primitives/track-types.js +10 -18
  201. package/dist/default/playback/primitives/track-types.js.map +1 -1
  202. package/dist/dev/core/actors/actor.d.ts +4 -4
  203. package/dist/dev/core/actors/actor.d.ts.map +1 -1
  204. package/dist/dev/core/actors/create-machine-actor.d.ts +38 -47
  205. package/dist/dev/core/actors/create-machine-actor.d.ts.map +1 -1
  206. package/dist/dev/core/actors/create-machine-actor.js +23 -25
  207. package/dist/dev/core/actors/create-machine-actor.js.map +1 -1
  208. package/dist/dev/core/actors/create-transition-actor.d.ts +11 -15
  209. package/dist/dev/core/actors/create-transition-actor.d.ts.map +1 -1
  210. package/dist/dev/core/actors/create-transition-actor.js +7 -9
  211. package/dist/dev/core/actors/create-transition-actor.js.map +1 -1
  212. package/dist/dev/core/composition/create-composition.d.ts +70 -102
  213. package/dist/dev/core/composition/create-composition.d.ts.map +1 -1
  214. package/dist/dev/core/composition/create-composition.js +26 -29
  215. package/dist/dev/core/composition/create-composition.js.map +1 -1
  216. package/dist/dev/core/composition/share-signals.d.ts +17 -24
  217. package/dist/dev/core/composition/share-signals.d.ts.map +1 -1
  218. package/dist/dev/core/composition/share-signals.js +12 -17
  219. package/dist/dev/core/composition/share-signals.js.map +1 -1
  220. package/dist/dev/core/machine.d.ts +4 -4
  221. package/dist/dev/core/machine.js +3 -4
  222. package/dist/dev/core/machine.js.map +1 -1
  223. package/dist/dev/core/reactors/create-machine-reactor.d.ts +33 -39
  224. package/dist/dev/core/reactors/create-machine-reactor.d.ts.map +1 -1
  225. package/dist/dev/core/reactors/create-machine-reactor.js +20 -19
  226. package/dist/dev/core/reactors/create-machine-reactor.js.map +1 -1
  227. package/dist/dev/core/signals/effect.d.ts +3 -4
  228. package/dist/dev/core/signals/effect.d.ts.map +1 -1
  229. package/dist/dev/core/signals/effect.js +24 -4
  230. package/dist/dev/core/signals/effect.js.map +1 -1
  231. package/dist/dev/core/signals/primitives.d.ts +10 -12
  232. package/dist/dev/core/signals/primitives.d.ts.map +1 -1
  233. package/dist/dev/core/signals/primitives.js +10 -14
  234. package/dist/dev/core/signals/primitives.js.map +1 -1
  235. package/dist/dev/core/signals/when.js +6 -8
  236. package/dist/dev/core/signals/when.js.map +1 -1
  237. package/dist/dev/core/tasks/delayed-reschedule.js +7 -11
  238. package/dist/dev/core/tasks/delayed-reschedule.js.map +1 -1
  239. package/dist/dev/core/tasks/task.d.ts +51 -73
  240. package/dist/dev/core/tasks/task.d.ts.map +1 -1
  241. package/dist/dev/core/tasks/task.js +59 -82
  242. package/dist/dev/core/tasks/task.js.map +1 -1
  243. package/dist/dev/hls.d.ts +3 -1
  244. package/dist/dev/hls.js +3 -1
  245. package/dist/dev/index.d.ts +2 -3
  246. package/dist/dev/index.d.ts.map +1 -1
  247. package/dist/dev/index.js +2 -3
  248. package/dist/dev/index.js.map +1 -1
  249. package/dist/dev/media/abr/quality-selection.d.ts +7 -10
  250. package/dist/dev/media/abr/quality-selection.d.ts.map +1 -1
  251. package/dist/dev/media/abr/quality-selection.js +3 -7
  252. package/dist/dev/media/abr/quality-selection.js.map +1 -1
  253. package/dist/dev/media/buffer/back-buffer.d.ts +2 -7
  254. package/dist/dev/media/buffer/back-buffer.d.ts.map +1 -1
  255. package/dist/dev/media/buffer/back-buffer.js +15 -19
  256. package/dist/dev/media/buffer/back-buffer.js.map +1 -1
  257. package/dist/dev/media/buffer/forward-buffer.d.ts +2 -7
  258. package/dist/dev/media/buffer/forward-buffer.d.ts.map +1 -1
  259. package/dist/dev/media/buffer/forward-buffer.js +32 -41
  260. package/dist/dev/media/buffer/forward-buffer.js.map +1 -1
  261. package/dist/dev/media/dom/capabilities.js +26 -37
  262. package/dist/dev/media/dom/capabilities.js.map +1 -1
  263. package/dist/dev/media/dom/mse/append-segment.d.ts +3 -5
  264. package/dist/dev/media/dom/mse/append-segment.d.ts.map +1 -1
  265. package/dist/dev/media/dom/mse/append-segment.js +3 -5
  266. package/dist/dev/media/dom/mse/append-segment.js.map +1 -1
  267. package/dist/dev/media/dom/mse/buffer-flusher.d.ts +5 -5
  268. package/dist/dev/media/dom/mse/buffer-flusher.js +5 -5
  269. package/dist/dev/media/dom/mse/buffer-flusher.js.map +1 -1
  270. package/dist/dev/media/dom/mse/duration.js +23 -31
  271. package/dist/dev/media/dom/mse/duration.js.map +1 -1
  272. package/dist/dev/media/dom/mse/end-of-stream.js +3 -6
  273. package/dist/dev/media/dom/mse/end-of-stream.js.map +1 -1
  274. package/dist/dev/media/dom/mse/mediasource-setup.js +65 -81
  275. package/dist/dev/media/dom/mse/mediasource-setup.js.map +1 -1
  276. package/dist/dev/media/dom/screen.d.ts.map +1 -1
  277. package/dist/dev/media/dom/screen.js +37 -54
  278. package/dist/dev/media/dom/screen.js.map +1 -1
  279. package/dist/dev/media/dom/text/resolve-vtt-segment.d.ts.map +1 -1
  280. package/dist/dev/media/dom/text/resolve-vtt-segment.js.map +1 -1
  281. package/dist/dev/media/dom/text/text-track-slots.d.ts +10 -16
  282. package/dist/dev/media/dom/text/text-track-slots.d.ts.map +1 -1
  283. package/dist/dev/media/dom/text/text-track-slots.js +15 -23
  284. package/dist/dev/media/dom/text/text-track-slots.js.map +1 -1
  285. package/dist/dev/media/errors.d.ts +32 -46
  286. package/dist/dev/media/errors.d.ts.map +1 -1
  287. package/dist/dev/media/errors.js +25 -34
  288. package/dist/dev/media/errors.js.map +1 -1
  289. package/dist/dev/media/hls/parse-attributes.js +9 -26
  290. package/dist/dev/media/hls/parse-attributes.js.map +1 -1
  291. package/dist/dev/media/hls/parse-media-playlist.js +25 -33
  292. package/dist/dev/media/hls/parse-media-playlist.js.map +1 -1
  293. package/dist/dev/media/hls/parse-multivariant.js +3 -3
  294. package/dist/dev/media/hls/parse-multivariant.js.map +1 -1
  295. package/dist/dev/media/hls/reload-policy.js +19 -27
  296. package/dist/dev/media/hls/reload-policy.js.map +1 -1
  297. package/dist/dev/media/hls/resolve-url.js +1 -3
  298. package/dist/dev/media/hls/resolve-url.js.map +1 -1
  299. package/dist/dev/media/live-window.js +9 -13
  300. package/dist/dev/media/live-window.js.map +1 -1
  301. package/dist/dev/media/media-tracks/media-tracks.d.ts +8 -13
  302. package/dist/dev/media/media-tracks/media-tracks.d.ts.map +1 -1
  303. package/dist/dev/media/media-tracks/media-tracks.js +12 -17
  304. package/dist/dev/media/media-tracks/media-tracks.js.map +1 -1
  305. package/dist/dev/media/mp4/box.js +4 -5
  306. package/dist/dev/media/mp4/box.js.map +1 -1
  307. package/dist/dev/media/mp4/timestamp-origin.js +30 -42
  308. package/dist/dev/media/mp4/timestamp-origin.js.map +1 -1
  309. package/dist/dev/media/primitives/resolution.d.ts +6 -8
  310. package/dist/dev/media/primitives/resolution.d.ts.map +1 -1
  311. package/dist/dev/media/primitives/resolution.js +5 -8
  312. package/dist/dev/media/primitives/resolution.js.map +1 -1
  313. package/dist/dev/media/primitives/select-tracks.js +24 -34
  314. package/dist/dev/media/primitives/select-tracks.js.map +1 -1
  315. package/dist/dev/media/text/parse-vtt-timestamp-map.js +6 -8
  316. package/dist/dev/media/text/parse-vtt-timestamp-map.js.map +1 -1
  317. package/dist/dev/media/text/resolve-vtt-metadata.js +8 -9
  318. package/dist/dev/media/text/resolve-vtt-metadata.js.map +1 -1
  319. package/dist/dev/media/types/index.d.ts +106 -177
  320. package/dist/dev/media/types/index.d.ts.map +1 -1
  321. package/dist/dev/media/types/index.js +10 -18
  322. package/dist/dev/media/types/index.js.map +1 -1
  323. package/dist/dev/media/utils/cdn.d.ts +4 -6
  324. package/dist/dev/media/utils/cdn.d.ts.map +1 -1
  325. package/dist/dev/media/utils/cdn.js +10 -16
  326. package/dist/dev/media/utils/cdn.js.map +1 -1
  327. package/dist/dev/media/utils/preload.js +4 -6
  328. package/dist/dev/media/utils/preload.js.map +1 -1
  329. package/dist/dev/media/utils/track-selection.js +10 -14
  330. package/dist/dev/media/utils/track-selection.js.map +1 -1
  331. package/dist/dev/media/utils/tracks.js +56 -54
  332. package/dist/dev/media/utils/tracks.js.map +1 -1
  333. package/dist/dev/network/bandwidth-estimator.d.ts +7 -9
  334. package/dist/dev/network/bandwidth-estimator.d.ts.map +1 -1
  335. package/dist/dev/network/bandwidth-estimator.js +18 -19
  336. package/dist/dev/network/bandwidth-estimator.js.map +1 -1
  337. package/dist/dev/network/chunked-stream-iterable.js +4 -6
  338. package/dist/dev/network/chunked-stream-iterable.js.map +1 -1
  339. package/dist/dev/network/ewma.js +22 -25
  340. package/dist/dev/network/ewma.js.map +1 -1
  341. package/dist/dev/network/fetch.js +30 -37
  342. package/dist/dev/network/fetch.js.map +1 -1
  343. package/dist/dev/playback/actors/dom/segment-loader.d.ts +7 -11
  344. package/dist/dev/playback/actors/dom/segment-loader.d.ts.map +1 -1
  345. package/dist/dev/playback/actors/dom/segment-loader.js +28 -44
  346. package/dist/dev/playback/actors/dom/segment-loader.js.map +1 -1
  347. package/dist/dev/playback/actors/dom/source-buffer.d.ts +5 -7
  348. package/dist/dev/playback/actors/dom/source-buffer.d.ts.map +1 -1
  349. package/dist/dev/playback/actors/dom/source-buffer.js.map +1 -1
  350. package/dist/dev/playback/actors/dom/text-tracks.js.map +1 -1
  351. package/dist/dev/playback/actors/text-track-segment-loader.d.ts +10 -16
  352. package/dist/dev/playback/actors/text-track-segment-loader.d.ts.map +1 -1
  353. package/dist/dev/playback/actors/text-track-segment-loader.js +24 -35
  354. package/dist/dev/playback/actors/text-track-segment-loader.js.map +1 -1
  355. package/dist/dev/playback/actors/text-tracks.d.ts +5 -8
  356. package/dist/dev/playback/actors/text-tracks.d.ts.map +1 -1
  357. package/dist/dev/playback/adapters/hls-audio/adapter.d.ts +11 -14
  358. package/dist/dev/playback/adapters/hls-audio/adapter.d.ts.map +1 -1
  359. package/dist/dev/playback/adapters/hls-audio/adapter.js +23 -31
  360. package/dist/dev/playback/adapters/hls-audio/adapter.js.map +1 -1
  361. package/dist/dev/playback/adapters/hls-audio/media.d.ts.map +1 -1
  362. package/dist/dev/playback/adapters/hls-audio/media.js.map +1 -1
  363. package/dist/dev/playback/adapters/hls-background-video/adapter.d.ts +28 -39
  364. package/dist/dev/playback/adapters/hls-background-video/adapter.d.ts.map +1 -1
  365. package/dist/dev/playback/adapters/hls-background-video/adapter.js +50 -70
  366. package/dist/dev/playback/adapters/hls-background-video/adapter.js.map +1 -1
  367. package/dist/dev/playback/adapters/hls-background-video/host.d.ts +12 -16
  368. package/dist/dev/playback/adapters/hls-background-video/host.d.ts.map +1 -1
  369. package/dist/dev/playback/adapters/hls-background-video/host.js +12 -16
  370. package/dist/dev/playback/adapters/hls-background-video/host.js.map +1 -1
  371. package/dist/dev/playback/adapters/hls-background-video/media.d.ts +5 -8
  372. package/dist/dev/playback/adapters/hls-background-video/media.d.ts.map +1 -1
  373. package/dist/dev/playback/adapters/hls-background-video/media.js +5 -8
  374. package/dist/dev/playback/adapters/hls-background-video/media.js.map +1 -1
  375. package/dist/dev/playback/adapters/hls-video/adapter.d.ts +12 -14
  376. package/dist/dev/playback/adapters/hls-video/adapter.d.ts.map +1 -1
  377. package/dist/dev/playback/adapters/hls-video/adapter.js +43 -60
  378. package/dist/dev/playback/adapters/hls-video/adapter.js.map +1 -1
  379. package/dist/dev/playback/adapters/hls-video/error-surface.d.ts +4 -5
  380. package/dist/dev/playback/adapters/hls-video/error-surface.d.ts.map +1 -1
  381. package/dist/dev/playback/adapters/hls-video/error-surface.js +13 -18
  382. package/dist/dev/playback/adapters/hls-video/error-surface.js.map +1 -1
  383. package/dist/dev/playback/adapters/hls-video/media-tracks.d.ts +4 -5
  384. package/dist/dev/playback/adapters/hls-video/media-tracks.d.ts.map +1 -1
  385. package/dist/dev/playback/adapters/hls-video/media-tracks.js +4 -5
  386. package/dist/dev/playback/adapters/hls-video/media-tracks.js.map +1 -1
  387. package/dist/dev/playback/adapters/hls-video/media.d.ts.map +1 -1
  388. package/dist/dev/playback/adapters/hls-video/media.js.map +1 -1
  389. package/dist/dev/playback/adapters/mux-audio/media.d.ts +8 -12
  390. package/dist/dev/playback/adapters/mux-audio/media.d.ts.map +1 -1
  391. package/dist/dev/playback/adapters/mux-audio/media.js +8 -12
  392. package/dist/dev/playback/adapters/mux-audio/media.js.map +1 -1
  393. package/dist/dev/playback/adapters/mux-video/adapter.d.ts +9 -11
  394. package/dist/dev/playback/adapters/mux-video/adapter.d.ts.map +1 -1
  395. package/dist/dev/playback/adapters/mux-video/adapter.js +25 -33
  396. package/dist/dev/playback/adapters/mux-video/adapter.js.map +1 -1
  397. package/dist/dev/playback/adapters/mux-video/media.d.ts +7 -9
  398. package/dist/dev/playback/adapters/mux-video/media.d.ts.map +1 -1
  399. package/dist/dev/playback/adapters/mux-video/media.js +7 -9
  400. package/dist/dev/playback/adapters/mux-video/media.js.map +1 -1
  401. package/dist/dev/playback/behaviors/calculate-presentation-duration.d.ts +5 -8
  402. package/dist/dev/playback/behaviors/calculate-presentation-duration.d.ts.map +1 -1
  403. package/dist/dev/playback/behaviors/calculate-presentation-duration.js +5 -8
  404. package/dist/dev/playback/behaviors/calculate-presentation-duration.js.map +1 -1
  405. package/dist/dev/playback/behaviors/collect-errors.d.ts +2 -0
  406. package/dist/dev/playback/behaviors/collect-errors.js +39 -52
  407. package/dist/dev/playback/behaviors/collect-errors.js.map +1 -1
  408. package/dist/dev/playback/behaviors/derive-cdn-priority.js +16 -23
  409. package/dist/dev/playback/behaviors/derive-cdn-priority.js.map +1 -1
  410. package/dist/dev/playback/behaviors/dom/airplay.js +38 -61
  411. package/dist/dev/playback/behaviors/dom/airplay.js.map +1 -1
  412. package/dist/dev/playback/behaviors/dom/apply-start-position.js +23 -35
  413. package/dist/dev/playback/behaviors/dom/apply-start-position.js.map +1 -1
  414. package/dist/dev/playback/behaviors/dom/end-of-stream.js +11 -16
  415. package/dist/dev/playback/behaviors/dom/end-of-stream.js.map +1 -1
  416. package/dist/dev/playback/behaviors/dom/load-segments.d.ts +5 -8
  417. package/dist/dev/playback/behaviors/dom/load-segments.d.ts.map +1 -1
  418. package/dist/dev/playback/behaviors/dom/load-segments.js +27 -39
  419. package/dist/dev/playback/behaviors/dom/load-segments.js.map +1 -1
  420. package/dist/dev/playback/behaviors/dom/recover-end-stall.js +21 -26
  421. package/dist/dev/playback/behaviors/dom/recover-end-stall.js.map +1 -1
  422. package/dist/dev/playback/behaviors/dom/seek-to-live-edge.js +41 -60
  423. package/dist/dev/playback/behaviors/dom/seek-to-live-edge.js.map +1 -1
  424. package/dist/dev/playback/behaviors/dom/setup-buffer-actors.js +50 -74
  425. package/dist/dev/playback/behaviors/dom/setup-buffer-actors.js.map +1 -1
  426. package/dist/dev/playback/behaviors/dom/setup-mediasource.js +29 -43
  427. package/dist/dev/playback/behaviors/dom/setup-mediasource.js.map +1 -1
  428. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.d.ts +3 -3
  429. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.d.ts.map +1 -1
  430. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.js.map +1 -1
  431. package/dist/dev/playback/behaviors/dom/sync-live-seekable-range.js +3 -4
  432. package/dist/dev/playback/behaviors/dom/sync-live-seekable-range.js.map +1 -1
  433. package/dist/dev/playback/behaviors/dom/sync-text-tracks.js +30 -45
  434. package/dist/dev/playback/behaviors/dom/sync-text-tracks.js.map +1 -1
  435. package/dist/dev/playback/behaviors/dom/track-current-time.d.ts +2 -2
  436. package/dist/dev/playback/behaviors/dom/track-current-time.d.ts.map +1 -1
  437. package/dist/dev/playback/behaviors/dom/track-current-time.js +9 -11
  438. package/dist/dev/playback/behaviors/dom/track-current-time.js.map +1 -1
  439. package/dist/dev/playback/behaviors/dom/track-load-triggers.d.ts +6 -12
  440. package/dist/dev/playback/behaviors/dom/track-load-triggers.d.ts.map +1 -1
  441. package/dist/dev/playback/behaviors/dom/track-load-triggers.js +24 -32
  442. package/dist/dev/playback/behaviors/dom/track-load-triggers.js.map +1 -1
  443. package/dist/dev/playback/behaviors/dom/track-playback-rate.d.ts +2 -2
  444. package/dist/dev/playback/behaviors/dom/track-playback-rate.d.ts.map +1 -1
  445. package/dist/dev/playback/behaviors/dom/track-playback-rate.js +6 -8
  446. package/dist/dev/playback/behaviors/dom/track-playback-rate.js.map +1 -1
  447. package/dist/dev/playback/behaviors/dom/track-player-resolution.d.ts.map +1 -1
  448. package/dist/dev/playback/behaviors/dom/track-player-resolution.js +10 -14
  449. package/dist/dev/playback/behaviors/dom/track-player-resolution.js.map +1 -1
  450. package/dist/dev/playback/behaviors/dom/track-screen-resolution.js +8 -9
  451. package/dist/dev/playback/behaviors/dom/track-screen-resolution.js.map +1 -1
  452. package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js +28 -43
  453. package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js.map +1 -1
  454. package/dist/dev/playback/behaviors/establish-start-media-time.d.ts +15 -19
  455. package/dist/dev/playback/behaviors/establish-start-media-time.d.ts.map +1 -1
  456. package/dist/dev/playback/behaviors/establish-start-media-time.js +32 -42
  457. package/dist/dev/playback/behaviors/establish-start-media-time.js.map +1 -1
  458. package/dist/dev/playback/behaviors/resolve-presentation.d.ts.map +1 -1
  459. package/dist/dev/playback/behaviors/resolve-presentation.js +13 -22
  460. package/dist/dev/playback/behaviors/resolve-presentation.js.map +1 -1
  461. package/dist/dev/playback/behaviors/resolve-track.js +5 -12
  462. package/dist/dev/playback/behaviors/resolve-track.js.map +1 -1
  463. package/dist/dev/playback/behaviors/select-tracks.d.ts +28 -39
  464. package/dist/dev/playback/behaviors/select-tracks.d.ts.map +1 -1
  465. package/dist/dev/playback/behaviors/select-tracks.js +77 -104
  466. package/dist/dev/playback/behaviors/select-tracks.js.map +1 -1
  467. package/dist/dev/playback/behaviors/setup-failover-monitor.d.ts +1 -4
  468. package/dist/dev/playback/behaviors/setup-failover-monitor.d.ts.map +1 -1
  469. package/dist/dev/playback/behaviors/setup-failover-monitor.js +11 -16
  470. package/dist/dev/playback/behaviors/setup-failover-monitor.js.map +1 -1
  471. package/dist/dev/playback/behaviors/sync-preload.js +9 -13
  472. package/dist/dev/playback/behaviors/sync-preload.js.map +1 -1
  473. package/dist/dev/playback/behaviors/track-switching.d.ts +110 -0
  474. package/dist/dev/playback/behaviors/track-switching.d.ts.map +1 -0
  475. package/dist/dev/playback/behaviors/track-switching.js +189 -173
  476. package/dist/dev/playback/behaviors/track-switching.js.map +1 -1
  477. package/dist/dev/playback/engines/hls/engine-audio-only.d.ts +59 -72
  478. package/dist/dev/playback/engines/hls/engine-audio-only.d.ts.map +1 -1
  479. package/dist/dev/playback/engines/hls/engine-audio-only.js +20 -24
  480. package/dist/dev/playback/engines/hls/engine-audio-only.js.map +1 -1
  481. package/dist/dev/playback/engines/hls/engine-background-video.d.ts +51 -78
  482. package/dist/dev/playback/engines/hls/engine-background-video.d.ts.map +1 -1
  483. package/dist/dev/playback/engines/hls/engine-background-video.js +22 -27
  484. package/dist/dev/playback/engines/hls/engine-background-video.js.map +1 -1
  485. package/dist/dev/playback/engines/hls/engine.d.ts +115 -155
  486. package/dist/dev/playback/engines/hls/engine.d.ts.map +1 -1
  487. package/dist/dev/playback/engines/hls/engine.js +22 -25
  488. package/dist/dev/playback/engines/hls/engine.js.map +1 -1
  489. package/dist/dev/playback/primitives/derive-start-media-time.d.ts +3 -3
  490. package/dist/dev/playback/primitives/derive-start-media-time.d.ts.map +1 -1
  491. package/dist/dev/playback/primitives/error-messages.js +16 -25
  492. package/dist/dev/playback/primitives/error-messages.js.map +1 -1
  493. package/dist/dev/playback/primitives/failover-fetch.js +9 -14
  494. package/dist/dev/playback/primitives/failover-fetch.js.map +1 -1
  495. package/dist/dev/playback/primitives/head-peek.js +7 -10
  496. package/dist/dev/playback/primitives/head-peek.js.map +1 -1
  497. package/dist/dev/playback/primitives/live-window.js +12 -15
  498. package/dist/dev/playback/primitives/live-window.js.map +1 -1
  499. package/dist/dev/playback/primitives/relocation-pipelines.js +34 -46
  500. package/dist/dev/playback/primitives/relocation-pipelines.js.map +1 -1
  501. package/dist/dev/playback/primitives/report-track-conditions.d.ts +1 -4
  502. package/dist/dev/playback/primitives/report-track-conditions.d.ts.map +1 -1
  503. package/dist/dev/playback/primitives/report-track-conditions.js +26 -38
  504. package/dist/dev/playback/primitives/report-track-conditions.js.map +1 -1
  505. package/dist/dev/playback/primitives/segment-load-pipeline.js +15 -15
  506. package/dist/dev/playback/primitives/segment-load-pipeline.js.map +1 -1
  507. package/dist/dev/playback/primitives/selection-rules.d.ts +45 -17
  508. package/dist/dev/playback/primitives/selection-rules.d.ts.map +1 -1
  509. package/dist/dev/playback/primitives/selection-rules.js +65 -36
  510. package/dist/dev/playback/primitives/selection-rules.js.map +1 -1
  511. package/dist/dev/playback/primitives/source-buffer-messages.d.ts +6 -9
  512. package/dist/dev/playback/primitives/source-buffer-messages.d.ts.map +1 -1
  513. package/dist/dev/playback/primitives/text-segment-load-pipeline.d.ts +20 -29
  514. package/dist/dev/playback/primitives/text-segment-load-pipeline.d.ts.map +1 -1
  515. package/dist/dev/playback/primitives/text-segment-load-pipeline.js +4 -5
  516. package/dist/dev/playback/primitives/text-segment-load-pipeline.js.map +1 -1
  517. package/dist/dev/playback/primitives/text-track-messages.d.ts.map +1 -1
  518. package/dist/dev/playback/primitives/track-types.js +10 -18
  519. package/dist/dev/playback/primitives/track-types.js.map +1 -1
  520. package/package.json +25 -28
@@ -10,44 +10,39 @@ const hlsAudioMediaDefaultProps = {
10
10
  disableRemotePlayback: false
11
11
  };
12
12
  /**
13
- * Which reported conditions this composition treats as fatal. Only the audio
14
- * verdict: an audio-only engine composes no video selection, so
15
- * `SVTA_NO_SUPPORTED_VIDEO_TRACK` is never reported and surfacing it would
16
- * describe a track type this media doesn't have.
13
+ * Which reported conditions this composition treats as fatal. Only the audio verdict: an audio-only engine composes no
14
+ * video selection, so `SVTA_NO_SUPPORTED_VIDEO_TRACK` is never reported and surfacing it would describe a track type
15
+ * this media doesn't have.
17
16
  */
18
17
  const FATAL_SVTA_CODES = /* @__PURE__ */ new Set([SVTA_NO_SUPPORTED_AUDIO_TRACK]);
19
18
  /**
20
19
  * Mixin that adds SPF audio-only HLS playback to any base class.
21
20
  *
22
- * @fires error - Fired when a fatal condition is reported. Read `error` for it.
21
+ * @example
22
+ * class HlsAudioMedia extends HlsAudioMediaMixin(HTMLVideoElementHost) {}
23
23
  *
24
- * Parallel to `HlsVideoMediaMixin` with one substantive difference: the
25
- * underlying engine is the audio-only variant (`createHlsAudioEngine`),
26
- * which omits video and text-track behaviors. The src / preload /
27
- * disableRemotePlayback / play() contract per the WHATWG HTML spec is identical
28
- * to the default adapter.
24
+ * const media = new HlsAudioMedia();
25
+ * media.attach(document.querySelector('video'));
26
+ * media.src = 'https://stream.mux.com/abc123.m3u8';
29
27
  *
30
- * Selecting this adapter is the variant decision: instantiating
31
- * `HlsAudioMediaElement` opts the consumer into audio-only
32
- * delivery even when the source is a mixed-AV HLS manifest.
28
+ * @fires error - Fired when a fatal condition is reported. Read `error` for it.
33
29
  *
34
- * @example
35
- * class HlsAudioMedia extends HlsAudioMediaMixin(HTMLVideoElementHost) {}
30
+ * Parallel to `HlsVideoMediaMixin` with one substantive difference: the underlying engine is the audio-only variant
31
+ * (`createHlsAudioEngine`), which omits video and text-track behaviors. The src / preload / disableRemotePlayback /
32
+ * play() contract per the WHATWG HTML spec is identical to the default adapter.
36
33
  *
37
- * const media = new HlsAudioMedia();
38
- * media.attach(document.querySelector('video'));
39
- * media.src = 'https://stream.mux.com/abc123.m3u8';
34
+ * Selecting this adapter is the variant decision: instantiating `HlsAudioMediaElement` opts the consumer into
35
+ * audio-only delivery even when the source is a mixed-AV HLS manifest.
40
36
  */
41
37
  function HlsAudioMediaMixin(BaseClass) {
42
38
  class HlsAudioMediaImpl extends BaseClass {
43
39
  /**
44
- * A complete sentence naming the Media to reach for when this one can't play
45
- * a source. Appended to the copy this adapter logs.
40
+ * A complete sentence naming the Media to reach for when this one can't play a source. Appended to the copy this
41
+ * adapter logs.
46
42
  *
47
- * Empty here, and overridden the same way as on the video adapter — see its
48
- * note. `hls-audio` has no better-equipped sibling of its own; the
49
- * Mux audio Media built on this engine does, and points at the hls.js-backed
50
- * one.
43
+ * Empty here, and overridden the same way as on the video adapter — see its note. `hls-audio` has no
44
+ * better-equipped sibling of its own; the Mux audio Media built on this engine does, and points at the
45
+ * hls.js-backed one.
51
46
  */
52
47
  static get alternativeMediaSuggestion() {}
53
48
  #engine;
@@ -72,9 +67,8 @@ function HlsAudioMediaMixin(BaseClass) {
72
67
  });
73
68
  }
74
69
  /**
75
- * The current fatal error, or `null`. Only *fatal* conditions appear here —
76
- * the engine reports non-fatal ones too, which stay in `engine.state.errors`.
77
- * Resets per source. Fires `'error'` when set.
70
+ * The current fatal error, or `null`. Only _fatal_ conditions appear here — the engine reports non-fatal ones too,
71
+ * which stay in `engine.state.errors`. Resets per source. Fires `'error'` when set.
78
72
  */
79
73
  get error() {
80
74
  return this.#error;
@@ -97,10 +91,8 @@ function HlsAudioMediaMixin(BaseClass) {
97
91
  this.dispatchEvent?.(new Event("error"));
98
92
  }
99
93
  /**
100
- * Underlying playback engine — the low-level SPF reactive composition that
101
- * drives playback. An advanced escape hatch for direct engine access;
102
- * normal playback is driven through this element's own properties and
103
- * methods.
94
+ * Underlying playback engine — the low-level SPF reactive composition that drives playback. An advanced escape
95
+ * hatch for direct engine access; normal playback is driven through this element's own properties and methods.
104
96
  */
105
97
  get engine() {
106
98
  return this.#engine;
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.js","names":["#engine","#config","#createEngine","#stopErrorSync","#signals","#setError","#error","#reportedCode","#withSuggestion","#cancelPendingPlay","#preload","#disableRemotePlayback","#loadstartListener"],"sources":["../../../../../src/playback/adapters/hls-audio/adapter.ts"],"sourcesContent":["import type { Constructor, MixinReturn } from '@videojs/utils/types';\nimport type { Composition } from '../../../core/composition/create-composition';\nimport { effect } from '../../../core/signals/effect';\nimport {\n SVTA_NO_SUPPORTED_AUDIO_TRACK,\n SVTA_UNSUPPORTED_PLAYBACK_FEATURE,\n type SvtaError,\n} from '../../../media/errors';\nimport {\n createHlsAudioEngine,\n type HlsAudioEngineConfig,\n type HlsAudioEngineContext,\n type HlsAudioEngineSignals,\n type HlsAudioEngineState,\n} from '../../engines/hls/engine-audio-only';\nimport { UNSUPPORTED_PLAYBACK_FEATURE_MESSAGE } from '../../primitives/error-messages';\nimport {\n firstFatal,\n type HlsVideoMediaError,\n hasUnsupportedFeatureCause,\n withAlternativeMediaSuggestion,\n} from '../hls-video/error-surface';\n\nexport interface HlsAudioMediaProps {\n src: string;\n preload: '' | 'none' | 'metadata' | 'auto';\n disableRemotePlayback: boolean;\n}\n\nexport const hlsAudioMediaDefaultProps: HlsAudioMediaProps = {\n src: '',\n preload: '',\n disableRemotePlayback: false,\n};\n\nexport interface HlsAudioMediaAPI extends HlsAudioMediaProps {\n readonly engine: Composition<HlsAudioEngineState, HlsAudioEngineContext>;\n readonly error: HlsVideoMediaError | null;\n attach(mediaElement: HTMLMediaElement): void;\n detach(): void;\n destroy(): void;\n play(): Promise<void>;\n}\n\n/**\n * Which reported conditions this composition treats as fatal. Only the audio\n * verdict: an audio-only engine composes no video selection, so\n * `SVTA_NO_SUPPORTED_VIDEO_TRACK` is never reported and surfacing it would\n * describe a track type this media doesn't have.\n */\nconst FATAL_SVTA_CODES: ReadonlySet<number> = new Set<number>([SVTA_NO_SUPPORTED_AUDIO_TRACK]);\n\n/**\n * Mixin that adds SPF audio-only HLS playback to any base class.\n *\n * @fires error - Fired when a fatal condition is reported. Read `error` for it.\n *\n * Parallel to `HlsVideoMediaMixin` with one substantive difference: the\n * underlying engine is the audio-only variant (`createHlsAudioEngine`),\n * which omits video and text-track behaviors. The src / preload /\n * disableRemotePlayback / play() contract per the WHATWG HTML spec is identical\n * to the default adapter.\n *\n * Selecting this adapter is the variant decision: instantiating\n * `HlsAudioMediaElement` opts the consumer into audio-only\n * delivery even when the source is a mixed-AV HLS manifest.\n *\n * @example\n * class HlsAudioMedia extends HlsAudioMediaMixin(HTMLVideoElementHost) {}\n *\n * const media = new HlsAudioMedia();\n * media.attach(document.querySelector('video'));\n * media.src = 'https://stream.mux.com/abc123.m3u8';\n */\nexport function HlsAudioMediaMixin<Base extends Constructor<any>>(BaseClass: Base) {\n class HlsAudioMediaImpl extends BaseClass {\n /**\n * A complete sentence naming the Media to reach for when this one can't play\n * a source. Appended to the copy this adapter logs.\n *\n * Empty here, and overridden the same way as on the video adapter — see its\n * note. `hls-audio` has no better-equipped sibling of its own; the\n * Mux audio Media built on this engine does, and points at the hls.js-backed\n * one.\n */\n static get alternativeMediaSuggestion(): string | undefined {\n return undefined;\n }\n\n readonly #engine: Composition<HlsAudioEngineState, HlsAudioEngineContext>;\n #config: HlsAudioEngineConfig;\n #signals!: HlsAudioEngineSignals;\n #preload: '' | 'none' | 'metadata' | 'auto' = hlsAudioMediaDefaultProps.preload;\n #disableRemotePlayback: boolean = hlsAudioMediaDefaultProps.disableRemotePlayback;\n #error: HlsVideoMediaError | null = null;\n /** Reported condition currently surfaced — see the video adapter's note. */\n #reportedCode: number | null = null;\n #stopErrorSync: () => void;\n\n /** Pending loadstart listener from a deferred play() retry, if any. */\n #loadstartListener: (() => void) | null = null;\n\n constructor(...args: any[]) {\n super(...args);\n\n const { config } = args?.[0] ?? {};\n this.#config = config;\n this.#engine = this.#createEngine();\n\n // Promote the first fatal condition out of the engine's reported sequence\n // onto the media surface. Clearing rides the same signal: `collectErrors`\n // resets the slot per source, so a new source starts with no error without\n // this needing its own source-change hook.\n this.#stopErrorSync = effect(() => {\n const errors = this.#signals.state.errors.get();\n this.#setError(firstFatal(errors, FATAL_SVTA_CODES), errors);\n });\n }\n\n /**\n * The current fatal error, or `null`. Only *fatal* conditions appear here —\n * the engine reports non-fatal ones too, which stay in `engine.state.errors`.\n * Resets per source. Fires `'error'` when set.\n */\n get error(): HlsVideoMediaError | null {\n return this.#error;\n }\n\n #setError(reported: SvtaError | undefined, errors: readonly SvtaError[] | undefined): void {\n if (!reported) {\n // Cleared (new source). No event: `'error'` announces a failure, and\n // consumers reset their own copy on source change.\n this.#error = null;\n this.#reportedCode = null;\n return;\n }\n // Keyed on the code, not the object: a later append re-runs this effect\n // with an equal-but-new array, and re-firing `'error'` for a condition\n // already surfaced would look like a second failure.\n if (this.#reportedCode === reported.code) return;\n this.#reportedCode = reported.code;\n\n // See the video adapter: a cause this engine can't implement is what the\n // consumer needs, so it replaces the verdict's code on the surface.\n const unsupported = hasUnsupportedFeatureCause(errors);\n if (unsupported) {\n console.error(this.#withSuggestion(UNSUPPORTED_PLAYBACK_FEATURE_MESSAGE), { conditions: errors });\n }\n\n this.#error = {\n code: unsupported ? SVTA_UNSUPPORTED_PLAYBACK_FEATURE : reported.code,\n message: reported.message ?? '',\n ...(reported.data === undefined ? {} : { data: reported.data }),\n };\n this.dispatchEvent?.(new Event('error'));\n }\n\n /**\n * Underlying playback engine — the low-level SPF reactive composition that\n * drives playback. An advanced escape hatch for direct engine access;\n * normal playback is driven through this element's own properties and\n * methods.\n */\n get engine(): Composition<HlsAudioEngineState, HlsAudioEngineContext> {\n return this.#engine;\n }\n\n // -------------------------------------------------------------------------\n // Media element lifecycle\n // -------------------------------------------------------------------------\n\n attach(mediaElement: HTMLMediaElement): void {\n super.attach?.(mediaElement);\n this.#signals.context.mediaElement.set(mediaElement);\n }\n\n detach(): void {\n this.#cancelPendingPlay();\n this.#signals.context.mediaElement.set(undefined);\n super.detach?.();\n }\n\n destroy(): void {\n this.#cancelPendingPlay();\n this.#stopErrorSync();\n this.#engine.destroy();\n }\n\n // -------------------------------------------------------------------------\n // preload — synchronous IDL attribute (WHATWG §4.8.11.2)\n // -------------------------------------------------------------------------\n\n /** Preload type (`'none'` / `'metadata'` / `'auto'`). */\n get preload(): '' | 'none' | 'metadata' | 'auto' {\n return this.#preload;\n }\n\n set preload(value: '' | 'none' | 'metadata' | 'auto') {\n this.#preload = value;\n if (value) {\n this.#signals.state.preload.set(value);\n }\n }\n\n // -------------------------------------------------------------------------\n // disableRemotePlayback — synchronous IDL attribute (WHATWG Remote Playback)\n // Author intent for whether the AirPlay/remote picker is offered. Mirrors\n // the DOM attribute name; the value flows to `state.disableRemotePlayback`,\n // which `setupAirPlay` reads to honor an explicit opt-out. The underlying\n // media element's own `disableRemotePlayback` stays programmatically managed\n // (ManagedMediaSource needs it `true` to open; AirPlay flips it `false` once\n // the source is open), so author intent and the effective flag stay distinct.\n // -------------------------------------------------------------------------\n\n get disableRemotePlayback(): boolean {\n return this.#disableRemotePlayback;\n }\n\n set disableRemotePlayback(value: boolean) {\n this.#disableRemotePlayback = value;\n this.#signals.state.disableRemotePlayback.set(value);\n }\n\n // -------------------------------------------------------------------------\n // src — synchronous IDL attribute (WHATWG §4.8.11.2)\n // Each assignment overwrites the engine's presentation state in place. The\n // resolver FSM routes back through teardown → rebuild on the same engine,\n // mirroring how the browser's load algorithm resets media state on src change\n // — without recreating the engine or re-capturing its signals. Setting an\n // empty src un-resolves the presentation, tearing the current source down to\n // the engine's fresh-but-attached \"no source\" state.\n // -------------------------------------------------------------------------\n\n get src(): string {\n return this.#signals.state.presentation.get()?.url ?? '';\n }\n\n set src(value: string) {\n // Unchanged URL, no reload — see the video adapter's note.\n if (value === this.src) return;\n\n this.#cancelPendingPlay();\n this.#signals.state.presentation.set(value ? { url: value } : undefined);\n }\n\n // -------------------------------------------------------------------------\n // play() — WHATWG §4.8.11.8\n // -------------------------------------------------------------------------\n\n play(): Promise<void> {\n const mediaElement = this.#signals.context.mediaElement.get();\n if (!mediaElement) {\n return Promise.reject(new Error('HlsAudioMediaElement: no media element attached'));\n }\n\n this.#signals.state.loadActivated.set(true);\n\n return mediaElement.play().catch((err: unknown) => {\n if (this.src) {\n return new Promise<void>((resolve, reject) => {\n const listener = () => {\n this.#loadstartListener = null;\n mediaElement.play().then(resolve, reject);\n };\n this.#loadstartListener = listener;\n mediaElement.addEventListener('loadstart', listener, { once: true });\n });\n }\n throw err;\n });\n }\n\n // -------------------------------------------------------------------------\n // Private\n // -------------------------------------------------------------------------\n\n /** `message`, plus the alternative-Media sentence when this class names one. */\n #withSuggestion(message: string): string {\n return withAlternativeMediaSuggestion(message, this);\n }\n\n #createEngine(): Composition<HlsAudioEngineState, HlsAudioEngineContext> {\n return createHlsAudioEngine({\n ...this.#config,\n onSignalsReady: (signals) => {\n this.#signals = signals;\n },\n });\n }\n\n #cancelPendingPlay(): void {\n if (!this.#loadstartListener) return;\n const mediaElement = this.#signals.context.mediaElement.get();\n mediaElement?.removeEventListener('loadstart', this.#loadstartListener);\n this.#loadstartListener = null;\n }\n }\n\n // `MixinReturn` sources statics from `Base`, so the adapter's own static needs\n // adding back to the type or callers can't read it.\n return HlsAudioMediaImpl as unknown as MixinReturn<Base, HlsAudioMediaAPI> & {\n readonly alternativeMediaSuggestion: string | undefined;\n };\n}\n\n/** Standalone SPF audio-only media adapter with no base class. */\nexport class HlsAudioMediaElement extends HlsAudioMediaMixin(class {}) {}\n"],"mappings":"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"}
1
+ {"version":3,"file":"adapter.js","names":["#engine","#config","#createEngine","#stopErrorSync","#signals","#setError","#error","#reportedCode","#withSuggestion","#cancelPendingPlay","#preload","#disableRemotePlayback","#loadstartListener"],"sources":["../../../../../src/playback/adapters/hls-audio/adapter.ts"],"sourcesContent":["import type { Constructor, MixinReturn } from '@videojs/utils/types';\n\nimport type { Composition } from '../../../core/composition/create-composition';\nimport { effect } from '../../../core/signals/effect';\nimport {\n SVTA_NO_SUPPORTED_AUDIO_TRACK,\n SVTA_UNSUPPORTED_PLAYBACK_FEATURE,\n type SvtaError,\n} from '../../../media/errors';\nimport {\n createHlsAudioEngine,\n type HlsAudioEngineConfig,\n type HlsAudioEngineContext,\n type HlsAudioEngineSignals,\n type HlsAudioEngineState,\n} from '../../engines/hls/engine-audio-only';\nimport { UNSUPPORTED_PLAYBACK_FEATURE_MESSAGE } from '../../primitives/error-messages';\nimport {\n firstFatal,\n type HlsVideoMediaError,\n hasUnsupportedFeatureCause,\n withAlternativeMediaSuggestion,\n} from '../hls-video/error-surface';\n\nexport interface HlsAudioMediaProps {\n src: string;\n preload: '' | 'none' | 'metadata' | 'auto';\n disableRemotePlayback: boolean;\n}\n\nexport const hlsAudioMediaDefaultProps: HlsAudioMediaProps = {\n src: '',\n preload: '',\n disableRemotePlayback: false,\n};\n\nexport interface HlsAudioMediaAPI extends HlsAudioMediaProps {\n readonly engine: Composition<HlsAudioEngineState, HlsAudioEngineContext>;\n readonly error: HlsVideoMediaError | null;\n attach(mediaElement: HTMLMediaElement): void;\n detach(): void;\n destroy(): void;\n play(): Promise<void>;\n}\n\n/**\n * Which reported conditions this composition treats as fatal. Only the audio verdict: an audio-only engine composes no\n * video selection, so `SVTA_NO_SUPPORTED_VIDEO_TRACK` is never reported and surfacing it would describe a track type\n * this media doesn't have.\n */\nconst FATAL_SVTA_CODES: ReadonlySet<number> = new Set<number>([SVTA_NO_SUPPORTED_AUDIO_TRACK]);\n\n/**\n * Mixin that adds SPF audio-only HLS playback to any base class.\n *\n * @example\n * class HlsAudioMedia extends HlsAudioMediaMixin(HTMLVideoElementHost) {}\n *\n * const media = new HlsAudioMedia();\n * media.attach(document.querySelector('video'));\n * media.src = 'https://stream.mux.com/abc123.m3u8';\n *\n * @fires error - Fired when a fatal condition is reported. Read `error` for it.\n *\n * Parallel to `HlsVideoMediaMixin` with one substantive difference: the underlying engine is the audio-only variant\n * (`createHlsAudioEngine`), which omits video and text-track behaviors. The src / preload / disableRemotePlayback /\n * play() contract per the WHATWG HTML spec is identical to the default adapter.\n *\n * Selecting this adapter is the variant decision: instantiating `HlsAudioMediaElement` opts the consumer into\n * audio-only delivery even when the source is a mixed-AV HLS manifest.\n */\nexport function HlsAudioMediaMixin<Base extends Constructor<any>>(BaseClass: Base) {\n class HlsAudioMediaImpl extends BaseClass {\n /**\n * A complete sentence naming the Media to reach for when this one can't play a source. Appended to the copy this\n * adapter logs.\n *\n * Empty here, and overridden the same way as on the video adapter — see its note. `hls-audio` has no\n * better-equipped sibling of its own; the Mux audio Media built on this engine does, and points at the\n * hls.js-backed one.\n */\n static get alternativeMediaSuggestion(): string | undefined {\n return undefined;\n }\n\n readonly #engine: Composition<HlsAudioEngineState, HlsAudioEngineContext>;\n #config: HlsAudioEngineConfig;\n #signals!: HlsAudioEngineSignals;\n #preload: '' | 'none' | 'metadata' | 'auto' = hlsAudioMediaDefaultProps.preload;\n #disableRemotePlayback: boolean = hlsAudioMediaDefaultProps.disableRemotePlayback;\n #error: HlsVideoMediaError | null = null;\n /** Reported condition currently surfaced — see the video adapter's note. */\n #reportedCode: number | null = null;\n #stopErrorSync: () => void;\n\n /** Pending loadstart listener from a deferred play() retry, if any. */\n #loadstartListener: (() => void) | null = null;\n\n constructor(...args: any[]) {\n super(...args);\n\n const { config } = args?.[0] ?? {};\n\n this.#config = config;\n this.#engine = this.#createEngine();\n\n // Promote the first fatal condition out of the engine's reported sequence\n // onto the media surface. Clearing rides the same signal: `collectErrors`\n // resets the slot per source, so a new source starts with no error without\n // this needing its own source-change hook.\n this.#stopErrorSync = effect(() => {\n const errors = this.#signals.state.errors.get();\n\n this.#setError(firstFatal(errors, FATAL_SVTA_CODES), errors);\n });\n }\n\n /**\n * The current fatal error, or `null`. Only _fatal_ conditions appear here — the engine reports non-fatal ones too,\n * which stay in `engine.state.errors`. Resets per source. Fires `'error'` when set.\n */\n get error(): HlsVideoMediaError | null {\n return this.#error;\n }\n\n #setError(reported: SvtaError | undefined, errors: readonly SvtaError[] | undefined): void {\n if (!reported) {\n // Cleared (new source). No event: `'error'` announces a failure, and\n // consumers reset their own copy on source change.\n this.#error = null;\n this.#reportedCode = null;\n return;\n }\n\n // Keyed on the code, not the object: a later append re-runs this effect\n // with an equal-but-new array, and re-firing `'error'` for a condition\n // already surfaced would look like a second failure.\n if (this.#reportedCode === reported.code) return;\n\n this.#reportedCode = reported.code;\n\n // See the video adapter: a cause this engine can't implement is what the\n // consumer needs, so it replaces the verdict's code on the surface.\n const unsupported = hasUnsupportedFeatureCause(errors);\n\n if (unsupported) {\n console.error(this.#withSuggestion(UNSUPPORTED_PLAYBACK_FEATURE_MESSAGE), { conditions: errors });\n }\n\n this.#error = {\n code: unsupported ? SVTA_UNSUPPORTED_PLAYBACK_FEATURE : reported.code,\n message: reported.message ?? '',\n ...(reported.data === undefined ? {} : { data: reported.data }),\n };\n this.dispatchEvent?.(new Event('error'));\n }\n\n /**\n * Underlying playback engine — the low-level SPF reactive composition that drives playback. An advanced escape\n * hatch for direct engine access; normal playback is driven through this element's own properties and methods.\n */\n get engine(): Composition<HlsAudioEngineState, HlsAudioEngineContext> {\n return this.#engine;\n }\n\n // -------------------------------------------------------------------------\n // Media element lifecycle\n // -------------------------------------------------------------------------\n\n attach(mediaElement: HTMLMediaElement): void {\n super.attach?.(mediaElement);\n this.#signals.context.mediaElement.set(mediaElement);\n }\n\n detach(): void {\n this.#cancelPendingPlay();\n this.#signals.context.mediaElement.set(undefined);\n super.detach?.();\n }\n\n destroy(): void {\n this.#cancelPendingPlay();\n this.#stopErrorSync();\n this.#engine.destroy();\n }\n\n // -------------------------------------------------------------------------\n // preload — synchronous IDL attribute (WHATWG §4.8.11.2)\n // -------------------------------------------------------------------------\n\n /** Preload type (`'none'` / `'metadata'` / `'auto'`). */\n get preload(): '' | 'none' | 'metadata' | 'auto' {\n return this.#preload;\n }\n\n set preload(value: '' | 'none' | 'metadata' | 'auto') {\n this.#preload = value;\n\n if (value) {\n this.#signals.state.preload.set(value);\n }\n }\n\n // -------------------------------------------------------------------------\n // disableRemotePlayback — synchronous IDL attribute (WHATWG Remote Playback)\n // Author intent for whether the AirPlay/remote picker is offered. Mirrors\n // the DOM attribute name; the value flows to `state.disableRemotePlayback`,\n // which `setupAirPlay` reads to honor an explicit opt-out. The underlying\n // media element's own `disableRemotePlayback` stays programmatically managed\n // (ManagedMediaSource needs it `true` to open; AirPlay flips it `false` once\n // the source is open), so author intent and the effective flag stay distinct.\n // -------------------------------------------------------------------------\n\n get disableRemotePlayback(): boolean {\n return this.#disableRemotePlayback;\n }\n\n set disableRemotePlayback(value: boolean) {\n this.#disableRemotePlayback = value;\n this.#signals.state.disableRemotePlayback.set(value);\n }\n\n // -------------------------------------------------------------------------\n // src — synchronous IDL attribute (WHATWG §4.8.11.2)\n // Each assignment overwrites the engine's presentation state in place. The\n // resolver FSM routes back through teardown → rebuild on the same engine,\n // mirroring how the browser's load algorithm resets media state on src change\n // — without recreating the engine or re-capturing its signals. Setting an\n // empty src un-resolves the presentation, tearing the current source down to\n // the engine's fresh-but-attached \"no source\" state.\n // -------------------------------------------------------------------------\n\n get src(): string {\n return this.#signals.state.presentation.get()?.url ?? '';\n }\n\n set src(value: string) {\n // Unchanged URL, no reload — see the video adapter's note.\n if (value === this.src) return;\n\n this.#cancelPendingPlay();\n this.#signals.state.presentation.set(value ? { url: value } : undefined);\n }\n\n // -------------------------------------------------------------------------\n // play() — WHATWG §4.8.11.8\n // -------------------------------------------------------------------------\n\n play(): Promise<void> {\n const mediaElement = this.#signals.context.mediaElement.get();\n if (!mediaElement) return Promise.reject(new Error('HlsAudioMediaElement: no media element attached'));\n\n this.#signals.state.loadActivated.set(true);\n\n return mediaElement.play().catch((err: unknown) => {\n if (this.src) {\n return new Promise<void>((resolve, reject) => {\n const listener = () => {\n this.#loadstartListener = null;\n mediaElement.play().then(resolve, reject);\n };\n\n this.#loadstartListener = listener;\n mediaElement.addEventListener('loadstart', listener, { once: true });\n });\n }\n\n throw err;\n });\n }\n\n // -------------------------------------------------------------------------\n // Private\n // -------------------------------------------------------------------------\n\n /** `message`, plus the alternative-Media sentence when this class names one. */\n #withSuggestion(message: string): string {\n return withAlternativeMediaSuggestion(message, this);\n }\n\n #createEngine(): Composition<HlsAudioEngineState, HlsAudioEngineContext> {\n return createHlsAudioEngine({\n ...this.#config,\n onSignalsReady: (signals) => {\n this.#signals = signals;\n },\n });\n }\n\n #cancelPendingPlay(): void {\n if (!this.#loadstartListener) return;\n\n const mediaElement = this.#signals.context.mediaElement.get();\n\n mediaElement?.removeEventListener('loadstart', this.#loadstartListener);\n this.#loadstartListener = null;\n }\n }\n\n // `MixinReturn` sources statics from `Base`, so the adapter's own static needs\n // adding back to the type or callers can't read it.\n return HlsAudioMediaImpl as unknown as MixinReturn<Base, HlsAudioMediaAPI> & {\n readonly alternativeMediaSuggestion: string | undefined;\n };\n}\n\n/** Standalone SPF audio-only media adapter with no base class. */\nexport class HlsAudioMediaElement extends HlsAudioMediaMixin(class {}) {}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"media.d.ts","names":[],"sources":["../../../../../src/playback/adapters/hls-audio/media.ts"],"mappings":";;;cAGM,kDAAiB,YAAA,uBAAA,2BAAA,YAAA;;;cAEV,sBAAsB"}
1
+ {"version":3,"file":"media.d.ts","names":[],"sources":["../../../../../src/playback/adapters/hls-audio/media.ts"],"mappings":";;;cAIM,kDAAiB,YAAA,uBAAA,2BAAA,YAAA;;;cAEV,sBAAsB"}
@@ -1 +1 @@
1
- {"version":3,"file":"media.js","names":[],"sources":["../../../../../src/playback/adapters/hls-audio/media.ts"],"sourcesContent":["import { HTMLAudioElementHost } from '@videojs/media/dom/audio-host';\nimport { HlsAudioMediaMixin } from './adapter';\n\nconst HlsAudioMediaBase = HlsAudioMediaMixin(HTMLAudioElementHost);\n\nexport class HlsAudioMedia extends HlsAudioMediaBase {}\n"],"mappings":";;;AAGA,MAAM,oBAAoB,mBAAmB,oBAAoB;AAEjE,IAAa,gBAAb,cAAmC,kBAAkB,CAAC"}
1
+ {"version":3,"file":"media.js","names":[],"sources":["../../../../../src/playback/adapters/hls-audio/media.ts"],"sourcesContent":["import { HTMLAudioElementHost } from '@videojs/media/dom/audio-host';\n\nimport { HlsAudioMediaMixin } from './adapter';\n\nconst HlsAudioMediaBase = HlsAudioMediaMixin(HTMLAudioElementHost);\n\nexport class HlsAudioMedia extends HlsAudioMediaBase {}\n"],"mappings":";;;AAIA,MAAM,oBAAoB,mBAAmB,oBAAoB;AAEjE,IAAa,gBAAb,cAAmC,kBAAkB,CAAC"}
@@ -16,55 +16,44 @@ interface HlsBackgroundVideoMediaAPI extends HlsBackgroundVideoMediaProps {
16
16
  play(): Promise<void>;
17
17
  }
18
18
  /**
19
- * Mixin that adds the background-video SPF playback engine to any base class,
20
- * for an HLS URL.
19
+ * Mixin that adds the background-video SPF playback engine to any base class, for an HLS URL.
21
20
  *
22
- * `src` is the whole input surface, and `error` is the one output: nothing about
23
- * an unplayable source reaches the media element on its own here — an unsupported
24
- * container, encryption with no EME, and an undecodable codec all leave
25
- * `HTMLMediaElement.error` null with the element stalled at `readyState 0`
26
- * (measured on Chromium and WebKit) so a consumer that watched only the
27
- * `<video>` would see a source that never appears and never says why. The engine
28
- * reports each condition onto `engine.state.errors` and logs it; this adapter
29
- * promotes the first fatal one, mapping it the same way the video and audio Medias
30
- * map theirs. See `internal/design/spf/features/errors.md`.
21
+ * `src` is the whole input surface, and `error` is the one output: nothing about an unplayable source reaches the media
22
+ * element on its own here — an unsupported container, encryption with no EME, and an undecodable codec all leave
23
+ * `HTMLMediaElement.error` null with the element stalled at `readyState 0` (measured on Chromium and WebKit) so a
24
+ * consumer that watched only the `<video>` would see a source that never appears and never says why. The engine reports
25
+ * each condition onto `engine.state.errors` and logs it; this adapter promotes the first fatal one, mapping it the same
26
+ * way the video and audio Medias map theirs. See `internal/design/spf/features/errors.md`.
31
27
  *
32
- * Selection pins the largest rendition that *fits the screen*, and holds it for
33
- * the session. The manifest is still the better place to narrow further: a
34
- * delivery param `?max_resolution=720p` on a Mux stream URL, for one — keeps
35
- * the renditions it excludes out of the manifest entirely, rather than
36
- * fetched-then-unpicked.
28
+ * Selection pins the largest rendition that _fits the screen_, and holds it for the session. The manifest is still the
29
+ * better place to narrow further: a delivery param `?max_resolution=720p` on a Mux stream URL, for one — keeps the
30
+ * renditions it excludes out of the manifest entirely, rather than fetched-then-unpicked.
37
31
  *
38
- * The pin is given up, never moved, if the pick turns out to be unplayable: the
39
- * container is only known once a media playlist resolves, which is after the pick
40
- * is made, so the selection clears rather than quietly appending bytes nothing can
41
- * decode.
32
+ * The pin is given up, never moved, if the pick turns out to be unplayable: the container is only known once a media
33
+ * playlist resolves, which is after the pick is made, so the selection clears rather than quietly appending bytes
34
+ * nothing can decode.
42
35
  *
43
- * `@videojs/spf/mux-background-video` is this same Media under a Mux-flavored
44
- * name — an alias, not a variant. Nothing about the surface changes with the
45
- * import path.
36
+ * `@videojs/spf/mux-background-video` is this same Media under a Mux-flavored name — an alias, not a variant. Nothing
37
+ * about the surface changes with the import path.
46
38
  *
47
- * Everything else the use case fixes rather than exposes: video-only, looping,
48
- * muted, autoplaying, loading as soon as there is a source. `attach` writes that
49
- * onto the element and nothing here declares `loop` / `muted` / `autoplay` /
50
- * `preload` of its own a host-bound Media inherits all four from the host
51
- * already, and shadowing them with fixed values would only make reads describe
52
- * an intention rather than what the element is doing.
39
+ * Everything else the use case fixes rather than exposes: video-only, looping, muted, autoplaying, loading as soon as
40
+ * there is a source. `attach` writes that onto the element and nothing here declares `loop` / `muted` / `autoplay` /
41
+ * `preload` of its own a host-bound Media inherits all four from the host already, and shadowing them with fixed
42
+ * values would only make reads describe an intention rather than what the element is doing.
53
43
  *
54
- * A new src re-resolves the presentation, tearing down the state, SourceBuffers,
55
- * and in-flight requests the previous one built before the next begins. The
56
- * engine instance and the attached media element are both kept, so neither has to
44
+ * A new src re-resolves the presentation, tearing down the state, SourceBuffers, and in-flight requests the previous
45
+ * one built before the next begins. The engine instance and the attached media element are both kept, so neither has to
57
46
  * be rewired.
58
47
  *
59
- * @fires error - Fired when a fatal condition is reported. Read `error` for it.
60
- *
61
48
  * @example
62
- * class HlsBackgroundVideoMedia extends HlsBackgroundVideoMediaMixin(BackgroundVideoHost) {}
49
+ * class HlsBackgroundVideoMedia extends HlsBackgroundVideoMediaMixin(BackgroundVideoHost) {}
63
50
  *
64
- * const media = new HlsBackgroundVideoMedia();
65
- * media.attach(document.querySelector('video'));
66
- * media.src = 'https://stream.mux.com/PLAYBACK_ID.m3u8?max_resolution=720p';
67
- * media.play();
51
+ * const media = new HlsBackgroundVideoMedia();
52
+ * media.attach(document.querySelector('video'));
53
+ * media.src = 'https://stream.mux.com/PLAYBACK_ID.m3u8?max_resolution=720p';
54
+ * media.play();
55
+ *
56
+ * @fires error - Fired when a fatal condition is reported. Read `error` for it.
68
57
  */
69
58
  declare function HlsBackgroundVideoMediaMixin<Base extends Constructor<any>>(BaseClass: Base): MixinReturn<Base, HlsBackgroundVideoMediaAPI>;
70
59
  declare const HlsBackgroundVideoMediaElement_base: MixinReturn<{
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","names":[],"sources":["../../../../../src/playback/adapters/hls-background-video/adapter.ts"],"mappings":";;;;;UAyBiB;EACf;;cAGW,qCAAqC;UAIjC,mCAAmC;WACzC,QAAQ,YAAY,4BAA4B;WAChD,OAAO;EAChB,OAAO,cAAc;EACrB;EACA;EACA,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmFM,6BAA6B,aAAa,kBAAkB,WAAW,OAgMpC,YAAY,MAAM;;;;;cAIxD,uCAAuC"}
1
+ {"version":3,"file":"adapter.d.ts","names":[],"sources":["../../../../../src/playback/adapters/hls-background-video/adapter.ts"],"mappings":";;;;;UA0BiB;EACf;;cAGW,qCAAqC;UAIjC,mCAAmC;WACzC,QAAQ,YAAY,4BAA4B;WAChD,OAAO;EAChB,OAAO,cAAc;EACrB;EACA;EACA,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmEM,6BAA6B,aAAa,kBAAkB,WAAW,OAkMpC,YAAY,MAAM;;;;;cAIxD,uCAAuC"}
@@ -6,27 +6,22 @@ import { firstFatal, hasUnsupportedFeatureCause } from "../hls-video/error-surfa
6
6
  //#region src/playback/adapters/hls-background-video/adapter.ts
7
7
  const hlsBackgroundVideoMediaDefaultProps = { src: "" };
8
8
  /**
9
- * Which reported conditions this composition treats as **fatal** — the ones that
10
- * reach `error` and fire `'error'`. Severity isn't part of an SVTA code
11
- * (§Approach: "impact varies with player implementation"), so it's decided at
12
- * this boundary rather than by the reporter.
9
+ * Which reported conditions this composition treats as **fatal** — the ones that reach `error` and fire `'error'`.
10
+ * Severity isn't part of an SVTA code (§Approach: "impact varies with player implementation"), so it's decided at this
11
+ * boundary rather than by the reporter.
13
12
  *
14
- * **Causes are fatal here, unlike on the other two adapters.** There, a cause is
15
- * context — one unplayable rendition doesn't fail a source whose others still
16
- * play, and a verdict follows if the type empties. In the pinned variant a cause
17
- * *is* the verdict: only the pinned rendition's playlist is ever resolved, so a
18
- * cause can only be about the pick itself, and dropping that pick is final
19
- * nothing here re-picks (that is what `switchVideoTrack` exists for, and this
20
- * engine doesn't compose it). Measured on Chromium: an MPEG-TS source reports
21
- * 1004 and an encrypted one 4008, each with no verdict behind it, and the element
22
- * then sits at `readyState 0` with `error` null forever.
13
+ * **Causes are fatal here, unlike on the other two adapters.** There, a cause is context — one unplayable rendition
14
+ * doesn't fail a source whose others still play, and a verdict follows if the type empties. In the pinned variant a
15
+ * cause _is_ the verdict: only the pinned rendition's playlist is ever resolved, so a cause can only be about the pick
16
+ * itself, and dropping that pick is final nothing here re-picks (that is what `switchVideoTrack` exists for, and this
17
+ * engine doesn't compose it). Measured on Chromium: an MPEG-TS source reports 1004 and an encrypted one 4008, each with
18
+ * no verdict behind it, and the element then sits at `readyState 0` with `error` null forever.
23
19
  *
24
- * The verdict is still listed, for the shapes that report nothing else: no video
25
- * renditions at all, or a ladder pruned before anything resolves both of which
26
- * `reportAbsentTrackType` covers from the tail of the constraint chain.
20
+ * The verdict is still listed, for the shapes that report nothing else: no video renditions at all, or a ladder pruned
21
+ * before anything resolves both of which `reportAbsentTrackType` covers from the tail of the constraint chain.
27
22
  *
28
- * First-fatal-wins then surfaces the cause rather than the verdict when both are
29
- * present, which is the more specific of the two.
23
+ * First-fatal-wins then surfaces the cause rather than the verdict when both are present, which is the more specific of
24
+ * the two.
30
25
  */
31
26
  const FATAL_SVTA_CODES = /* @__PURE__ */ new Set([
32
27
  SVTA_NO_SUPPORTED_VIDEO_TRACK,
@@ -34,55 +29,44 @@ const FATAL_SVTA_CODES = /* @__PURE__ */ new Set([
34
29
  SVTA_UNSUPPORTED_DRM_SYSTEM
35
30
  ]);
36
31
  /**
37
- * Mixin that adds the background-video SPF playback engine to any base class,
38
- * for an HLS URL.
32
+ * Mixin that adds the background-video SPF playback engine to any base class, for an HLS URL.
39
33
  *
40
- * `src` is the whole input surface, and `error` is the one output: nothing about
41
- * an unplayable source reaches the media element on its own here — an unsupported
42
- * container, encryption with no EME, and an undecodable codec all leave
43
- * `HTMLMediaElement.error` null with the element stalled at `readyState 0`
44
- * (measured on Chromium and WebKit) so a consumer that watched only the
45
- * `<video>` would see a source that never appears and never says why. The engine
46
- * reports each condition onto `engine.state.errors` and logs it; this adapter
47
- * promotes the first fatal one, mapping it the same way the video and audio Medias
48
- * map theirs. See `internal/design/spf/features/errors.md`.
34
+ * `src` is the whole input surface, and `error` is the one output: nothing about an unplayable source reaches the media
35
+ * element on its own here — an unsupported container, encryption with no EME, and an undecodable codec all leave
36
+ * `HTMLMediaElement.error` null with the element stalled at `readyState 0` (measured on Chromium and WebKit) so a
37
+ * consumer that watched only the `<video>` would see a source that never appears and never says why. The engine reports
38
+ * each condition onto `engine.state.errors` and logs it; this adapter promotes the first fatal one, mapping it the same
39
+ * way the video and audio Medias map theirs. See `internal/design/spf/features/errors.md`.
49
40
  *
50
- * Selection pins the largest rendition that *fits the screen*, and holds it for
51
- * the session. The manifest is still the better place to narrow further: a
52
- * delivery param `?max_resolution=720p` on a Mux stream URL, for one — keeps
53
- * the renditions it excludes out of the manifest entirely, rather than
54
- * fetched-then-unpicked.
41
+ * Selection pins the largest rendition that _fits the screen_, and holds it for the session. The manifest is still the
42
+ * better place to narrow further: a delivery param `?max_resolution=720p` on a Mux stream URL, for one — keeps the
43
+ * renditions it excludes out of the manifest entirely, rather than fetched-then-unpicked.
55
44
  *
56
- * The pin is given up, never moved, if the pick turns out to be unplayable: the
57
- * container is only known once a media playlist resolves, which is after the pick
58
- * is made, so the selection clears rather than quietly appending bytes nothing can
59
- * decode.
45
+ * The pin is given up, never moved, if the pick turns out to be unplayable: the container is only known once a media
46
+ * playlist resolves, which is after the pick is made, so the selection clears rather than quietly appending bytes
47
+ * nothing can decode.
60
48
  *
61
- * `@videojs/spf/mux-background-video` is this same Media under a Mux-flavored
62
- * name — an alias, not a variant. Nothing about the surface changes with the
63
- * import path.
49
+ * `@videojs/spf/mux-background-video` is this same Media under a Mux-flavored name — an alias, not a variant. Nothing
50
+ * about the surface changes with the import path.
64
51
  *
65
- * Everything else the use case fixes rather than exposes: video-only, looping,
66
- * muted, autoplaying, loading as soon as there is a source. `attach` writes that
67
- * onto the element and nothing here declares `loop` / `muted` / `autoplay` /
68
- * `preload` of its own a host-bound Media inherits all four from the host
69
- * already, and shadowing them with fixed values would only make reads describe
70
- * an intention rather than what the element is doing.
52
+ * Everything else the use case fixes rather than exposes: video-only, looping, muted, autoplaying, loading as soon as
53
+ * there is a source. `attach` writes that onto the element and nothing here declares `loop` / `muted` / `autoplay` /
54
+ * `preload` of its own a host-bound Media inherits all four from the host already, and shadowing them with fixed
55
+ * values would only make reads describe an intention rather than what the element is doing.
71
56
  *
72
- * A new src re-resolves the presentation, tearing down the state, SourceBuffers,
73
- * and in-flight requests the previous one built before the next begins. The
74
- * engine instance and the attached media element are both kept, so neither has to
57
+ * A new src re-resolves the presentation, tearing down the state, SourceBuffers, and in-flight requests the previous
58
+ * one built before the next begins. The engine instance and the attached media element are both kept, so neither has to
75
59
  * be rewired.
76
60
  *
77
- * @fires error - Fired when a fatal condition is reported. Read `error` for it.
78
- *
79
61
  * @example
80
- * class HlsBackgroundVideoMedia extends HlsBackgroundVideoMediaMixin(BackgroundVideoHost) {}
62
+ * class HlsBackgroundVideoMedia extends HlsBackgroundVideoMediaMixin(BackgroundVideoHost) {}
81
63
  *
82
- * const media = new HlsBackgroundVideoMedia();
83
- * media.attach(document.querySelector('video'));
84
- * media.src = 'https://stream.mux.com/PLAYBACK_ID.m3u8?max_resolution=720p';
85
- * media.play();
64
+ * const media = new HlsBackgroundVideoMedia();
65
+ * media.attach(document.querySelector('video'));
66
+ * media.src = 'https://stream.mux.com/PLAYBACK_ID.m3u8?max_resolution=720p';
67
+ * media.play();
68
+ *
69
+ * @fires error - Fired when a fatal condition is reported. Read `error` for it.
86
70
  */
87
71
  function HlsBackgroundVideoMediaMixin(BaseClass) {
88
72
  class HlsBackgroundVideoMediaImpl extends BaseClass {
@@ -91,9 +75,8 @@ function HlsBackgroundVideoMediaMixin(BaseClass) {
91
75
  #signals;
92
76
  #error = null;
93
77
  /**
94
- * The *reported* condition currently surfaced, which is what the re-fire latch
95
- * keys on. Not `#error.code`: that's the code this adapter chose to surface,
96
- * and the substitution below can make the two differ.
78
+ * The _reported_ condition currently surfaced, which is what the re-fire latch keys on. Not `#error.code`: that's
79
+ * the code this adapter chose to surface, and the substitution below can make the two differ.
97
80
  */
98
81
  #reportedCode = null;
99
82
  #stopErrorSync;
@@ -113,17 +96,14 @@ function HlsBackgroundVideoMediaMixin(BaseClass) {
113
96
  return this.#engine;
114
97
  }
115
98
  /**
116
- * The current fatal condition, or `null`. Only *fatal* ones appear here — the
117
- * engine reports non-fatal ones too (they stay in `engine.state.errors`), and
118
- * promoting them would say playback had failed when it hadn't. Which ones are
119
- * fatal is wider here than on the video and audio Medias; see
120
- * {@link FATAL_SVTA_CODES}. Resets per source. Fires `'error'` when set.
99
+ * The current fatal condition, or `null`. Only _fatal_ ones appear here — the engine reports non-fatal ones too
100
+ * (they stay in `engine.state.errors`), and promoting them would say playback had failed when it hadn't. Which ones
101
+ * are fatal is wider here than on the video and audio Medias; see {@link FATAL_SVTA_CODES}. Resets per source.
102
+ * Fires `'error'` when set.
121
103
  *
122
- * Mapped the same way theirs are: a sequence holding an
123
- * unimplemented-capability cause surfaces as
124
- * {@link SVTA_UNSUPPORTED_PLAYBACK_FEATURE} (99001) with the specifics logged,
125
- * because "this player can't play this source" is what a consumer can act on,
126
- * where a raw container or DRM code only says what to go and look up.
104
+ * Mapped the same way theirs are: a sequence holding an unimplemented-capability cause surfaces as
105
+ * {@link SVTA_UNSUPPORTED_PLAYBACK_FEATURE} (99001) with the specifics logged, because "this player can't play this
106
+ * source" is what a consumer can act on, where a raw container or DRM code only says what to go and look up.
127
107
  */
128
108
  get error() {
129
109
  return this.#error;
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.js","names":["#config","#engine","#createEngine","#stopErrorSync","#signals","#setError","#error","#reportedCode","#cancelPendingPlay","#loadstartListener"],"sources":["../../../../../src/playback/adapters/hls-background-video/adapter.ts"],"sourcesContent":["import type { Constructor, MixinReturn } from '@videojs/utils/types';\nimport type { Composition } from '../../../core/composition/create-composition';\nimport { effect } from '../../../core/signals/effect';\nimport {\n SVTA_NO_SUPPORTED_VIDEO_TRACK,\n SVTA_UNSUPPORTED_DRM_SYSTEM,\n SVTA_UNSUPPORTED_PLAYBACK_FEATURE,\n SVTA_UNSUPPORTED_VIDEO_FORMAT,\n type SvtaError,\n} from '../../../media/errors';\nimport {\n type BackgroundVideoEngineConfig,\n type BackgroundVideoEngineContext,\n type BackgroundVideoEngineSignals,\n type BackgroundVideoEngineState,\n createBackgroundVideoEngine,\n} from '../../engines/hls/engine-background-video';\nimport { UNPLAYABLE_SOURCE_MESSAGE } from '../../primitives/error-messages';\nimport { firstFatal, type HlsVideoMediaError, hasUnsupportedFeatureCause } from '../hls-video/error-surface';\n\n// The same error shape the video and audio Medias expose, under the name they\n// publish it as — one type for all three surfaces rather than a background-flavored\n// copy of it.\nexport type { HlsVideoMediaError } from '../hls-video/error-surface';\n\nexport interface HlsBackgroundVideoMediaProps {\n src: string;\n}\n\nexport const hlsBackgroundVideoMediaDefaultProps: HlsBackgroundVideoMediaProps = {\n src: '',\n};\n\nexport interface HlsBackgroundVideoMediaAPI extends HlsBackgroundVideoMediaProps {\n readonly engine: Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext>;\n readonly error: HlsVideoMediaError | null;\n attach(mediaElement: HTMLMediaElement): void;\n detach(): void;\n destroy(): void;\n play(): Promise<void>;\n}\n\n/**\n * Which reported conditions this composition treats as **fatal** — the ones that\n * reach `error` and fire `'error'`. Severity isn't part of an SVTA code\n * (§Approach: \"impact varies with player implementation\"), so it's decided at\n * this boundary rather than by the reporter.\n *\n * **Causes are fatal here, unlike on the other two adapters.** There, a cause is\n * context — one unplayable rendition doesn't fail a source whose others still\n * play, and a verdict follows if the type empties. In the pinned variant a cause\n * *is* the verdict: only the pinned rendition's playlist is ever resolved, so a\n * cause can only be about the pick itself, and dropping that pick is final —\n * nothing here re-picks (that is what `switchVideoTrack` exists for, and this\n * engine doesn't compose it). Measured on Chromium: an MPEG-TS source reports\n * 1004 and an encrypted one 4008, each with no verdict behind it, and the element\n * then sits at `readyState 0` with `error` null forever.\n *\n * The verdict is still listed, for the shapes that report nothing else: no video\n * renditions at all, or a ladder pruned before anything resolves — both of which\n * `reportAbsentTrackType` covers from the tail of the constraint chain.\n *\n * First-fatal-wins then surfaces the cause rather than the verdict when both are\n * present, which is the more specific of the two.\n */\nconst FATAL_SVTA_CODES: ReadonlySet<number> = new Set<number>([\n SVTA_NO_SUPPORTED_VIDEO_TRACK,\n SVTA_UNSUPPORTED_VIDEO_FORMAT,\n SVTA_UNSUPPORTED_DRM_SYSTEM,\n]);\n\n/**\n * Mixin that adds the background-video SPF playback engine to any base class,\n * for an HLS URL.\n *\n * `src` is the whole input surface, and `error` is the one output: nothing about\n * an unplayable source reaches the media element on its own here — an unsupported\n * container, encryption with no EME, and an undecodable codec all leave\n * `HTMLMediaElement.error` null with the element stalled at `readyState 0`\n * (measured on Chromium and WebKit) — so a consumer that watched only the\n * `<video>` would see a source that never appears and never says why. The engine\n * reports each condition onto `engine.state.errors` and logs it; this adapter\n * promotes the first fatal one, mapping it the same way the video and audio Medias\n * map theirs. See `internal/design/spf/features/errors.md`.\n *\n * Selection pins the largest rendition that *fits the screen*, and holds it for\n * the session. The manifest is still the better place to narrow further: a\n * delivery param — `?max_resolution=720p` on a Mux stream URL, for one — keeps\n * the renditions it excludes out of the manifest entirely, rather than\n * fetched-then-unpicked.\n *\n * The pin is given up, never moved, if the pick turns out to be unplayable: the\n * container is only known once a media playlist resolves, which is after the pick\n * is made, so the selection clears rather than quietly appending bytes nothing can\n * decode.\n *\n * `@videojs/spf/mux-background-video` is this same Media under a Mux-flavored\n * name — an alias, not a variant. Nothing about the surface changes with the\n * import path.\n *\n * Everything else the use case fixes rather than exposes: video-only, looping,\n * muted, autoplaying, loading as soon as there is a source. `attach` writes that\n * onto the element and nothing here declares `loop` / `muted` / `autoplay` /\n * `preload` of its own — a host-bound Media inherits all four from the host\n * already, and shadowing them with fixed values would only make reads describe\n * an intention rather than what the element is doing.\n *\n * A new src re-resolves the presentation, tearing down the state, SourceBuffers,\n * and in-flight requests the previous one built before the next begins. The\n * engine instance and the attached media element are both kept, so neither has to\n * be rewired.\n *\n * @fires error - Fired when a fatal condition is reported. Read `error` for it.\n *\n * @example\n * class HlsBackgroundVideoMedia extends HlsBackgroundVideoMediaMixin(BackgroundVideoHost) {}\n *\n * const media = new HlsBackgroundVideoMedia();\n * media.attach(document.querySelector('video'));\n * media.src = 'https://stream.mux.com/PLAYBACK_ID.m3u8?max_resolution=720p';\n * media.play();\n */\nexport function HlsBackgroundVideoMediaMixin<Base extends Constructor<any>>(BaseClass: Base) {\n class HlsBackgroundVideoMediaImpl extends BaseClass {\n #engine: Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext>;\n #config: BackgroundVideoEngineConfig;\n #signals!: BackgroundVideoEngineSignals;\n #error: HlsVideoMediaError | null = null;\n /**\n * The *reported* condition currently surfaced, which is what the re-fire latch\n * keys on. Not `#error.code`: that's the code this adapter chose to surface,\n * and the substitution below can make the two differ.\n */\n #reportedCode: number | null = null;\n #stopErrorSync: () => void;\n\n /** Pending loadstart listener from a deferred play() retry, if any. */\n #loadstartListener: (() => void) | null = null;\n\n constructor(...args: any[]) {\n super(...args);\n\n const { config } = args?.[0] ?? {};\n this.#config = config;\n this.#engine = this.#createEngine();\n\n // Promote the first fatal condition out of the engine's reported sequence\n // onto this surface. Clearing rides the same signal: `collectErrors` resets\n // the slot per source, so a new source starts with no error without this\n // needing its own source-change hook.\n this.#stopErrorSync = effect(() => {\n const errors = this.#signals.state.errors.get();\n this.#setError(firstFatal(errors, FATAL_SVTA_CODES), errors);\n });\n }\n\n get engine(): Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext> {\n return this.#engine;\n }\n\n /**\n * The current fatal condition, or `null`. Only *fatal* ones appear here — the\n * engine reports non-fatal ones too (they stay in `engine.state.errors`), and\n * promoting them would say playback had failed when it hadn't. Which ones are\n * fatal is wider here than on the video and audio Medias; see\n * {@link FATAL_SVTA_CODES}. Resets per source. Fires `'error'` when set.\n *\n * Mapped the same way theirs are: a sequence holding an\n * unimplemented-capability cause surfaces as\n * {@link SVTA_UNSUPPORTED_PLAYBACK_FEATURE} (99001) with the specifics logged,\n * because \"this player can't play this source\" is what a consumer can act on,\n * where a raw container or DRM code only says what to go and look up.\n */\n get error(): HlsVideoMediaError | null {\n return this.#error;\n }\n\n #setError(reported: SvtaError | undefined, errors: readonly SvtaError[] | undefined): void {\n if (!reported) {\n // Cleared (new source). No event: `'error'` announces a failure, and\n // consumers reset their own copy on source change.\n this.#error = null;\n this.#reportedCode = null;\n return;\n }\n // Keyed on the code, not the object: a later append re-runs this effect\n // with an equal-but-new array, and re-firing `'error'` for a condition\n // already surfaced would look like a second failure.\n if (this.#reportedCode === reported.code) return;\n this.#reportedCode = reported.code;\n\n // Logged for every fatal condition, not just the substituted ones: a source\n // with no video renditions is as dead as an unplayable container, and it\n // would otherwise reach a developer as a bare code. One generic sentence\n // rather than one per case — the conditions beside it carry the specifics.\n //\n // Prose stays here rather than on `error.message`, matching the other two:\n // viewer-facing copy is the consumer's to localize, and a background video\n // has no chrome to put it in anyway.\n console.error(UNPLAYABLE_SOURCE_MESSAGE, { conditions: errors });\n\n this.#error = {\n code: hasUnsupportedFeatureCause(errors) ? SVTA_UNSUPPORTED_PLAYBACK_FEATURE : reported.code,\n message: reported.message ?? '',\n ...(reported.data === undefined ? {} : { data: reported.data }),\n };\n // Optional-chained: with an EventTarget-less base (`HlsBackgroundVideoMediaElement`\n // standalone) there's nowhere to dispatch.\n this.dispatchEvent?.(new Event('error'));\n }\n\n // -------------------------------------------------------------------------\n // Media element lifecycle\n // -------------------------------------------------------------------------\n\n attach(mediaElement: HTMLMediaElement): void {\n super.attach?.(mediaElement);\n // The one place the fixed behavior is stated. Muted and autoplay are what\n // let it start without a gesture, loop is the defining behavior, and\n // `preload` says out loud what the engine does regardless — it subtracts\n // preload monitoring and loads from the moment it has a source.\n mediaElement.loop = true;\n mediaElement.muted = true;\n mediaElement.autoplay = true;\n mediaElement.preload = 'auto';\n\n this.#signals.context.mediaElement.set(mediaElement);\n }\n\n detach(): void {\n this.#cancelPendingPlay();\n this.#signals.context.mediaElement.set(undefined);\n super.detach?.();\n }\n\n destroy(): void {\n this.#cancelPendingPlay();\n this.#stopErrorSync();\n this.#engine.destroy();\n }\n\n // -------------------------------------------------------------------------\n // src — synchronous IDL attribute (WHATWG §4.8.11.2)\n // -------------------------------------------------------------------------\n\n get src(): string {\n return this.#signals.state.presentation.get()?.url ?? '';\n }\n\n set src(value: string) {\n // Same line the HLS Medias draw: the presentation is set from a fresh\n // object every time, so re-resolving a URL already playing would restart\n // it for no reason.\n if (value === this.src) return;\n\n this.#cancelPendingPlay();\n this.#signals.state.presentation.set(value ? { url: value } : undefined);\n }\n\n // -------------------------------------------------------------------------\n // play() — WHATWG §4.8.11.8\n // Delegates to the attached media element's native play().\n // -------------------------------------------------------------------------\n\n async play(): Promise<void> {\n const mediaElement = this.#signals.context.mediaElement.get();\n if (!mediaElement) {\n return Promise.reject(new Error('HlsBackgroundVideoMediaElement: no media element attached'));\n }\n\n try {\n return await mediaElement.play();\n } catch (err) {\n // If we have a pending HLS source, the rejection may be because MSE\n // hasn't attached a blob URL yet. Wait for loadstart (src assigned by\n // MSE setup) and retry once.\n if (this.src) {\n return new Promise<void>((resolve, reject) => {\n const listener = () => {\n this.#loadstartListener = null;\n mediaElement.play().then(resolve, reject);\n };\n this.#loadstartListener = listener;\n mediaElement.addEventListener('loadstart', listener, { once: true });\n });\n }\n throw err;\n }\n }\n\n // -------------------------------------------------------------------------\n // Private\n // -------------------------------------------------------------------------\n\n #createEngine(): Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext> {\n // No selection config of its own: the engine's default rule chain already\n // narrows to the largest rendition that fits the screen, which is exactly\n // what this adapter used to hand over as a bespoke picker.\n return createBackgroundVideoEngine({\n ...this.#config,\n onSignalsReady: (signals) => {\n this.#signals = signals;\n },\n });\n }\n\n #cancelPendingPlay(): void {\n if (!this.#loadstartListener) return;\n const mediaElement = this.#signals.context.mediaElement.get();\n mediaElement?.removeEventListener('loadstart', this.#loadstartListener);\n this.#loadstartListener = null;\n }\n }\n\n return HlsBackgroundVideoMediaImpl as unknown as MixinReturn<Base, HlsBackgroundVideoMediaAPI>;\n}\n\n/** Standalone SPF background-video adapter with no base class. */\nexport class HlsBackgroundVideoMediaElement extends HlsBackgroundVideoMediaMixin(class {}) {}\n"],"mappings":"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"}
1
+ {"version":3,"file":"adapter.js","names":["#config","#engine","#createEngine","#stopErrorSync","#signals","#setError","#error","#reportedCode","#cancelPendingPlay","#loadstartListener"],"sources":["../../../../../src/playback/adapters/hls-background-video/adapter.ts"],"sourcesContent":["import type { Constructor, MixinReturn } from '@videojs/utils/types';\n\nimport type { Composition } from '../../../core/composition/create-composition';\nimport { effect } from '../../../core/signals/effect';\nimport {\n SVTA_NO_SUPPORTED_VIDEO_TRACK,\n SVTA_UNSUPPORTED_DRM_SYSTEM,\n SVTA_UNSUPPORTED_PLAYBACK_FEATURE,\n SVTA_UNSUPPORTED_VIDEO_FORMAT,\n type SvtaError,\n} from '../../../media/errors';\nimport {\n type BackgroundVideoEngineConfig,\n type BackgroundVideoEngineContext,\n type BackgroundVideoEngineSignals,\n type BackgroundVideoEngineState,\n createBackgroundVideoEngine,\n} from '../../engines/hls/engine-background-video';\nimport { UNPLAYABLE_SOURCE_MESSAGE } from '../../primitives/error-messages';\nimport { firstFatal, type HlsVideoMediaError, hasUnsupportedFeatureCause } from '../hls-video/error-surface';\n\n// The same error shape the video and audio Medias expose, under the name they\n// publish it as — one type for all three surfaces rather than a background-flavored\n// copy of it.\nexport type { HlsVideoMediaError } from '../hls-video/error-surface';\n\nexport interface HlsBackgroundVideoMediaProps {\n src: string;\n}\n\nexport const hlsBackgroundVideoMediaDefaultProps: HlsBackgroundVideoMediaProps = {\n src: '',\n};\n\nexport interface HlsBackgroundVideoMediaAPI extends HlsBackgroundVideoMediaProps {\n readonly engine: Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext>;\n readonly error: HlsVideoMediaError | null;\n attach(mediaElement: HTMLMediaElement): void;\n detach(): void;\n destroy(): void;\n play(): Promise<void>;\n}\n\n/**\n * Which reported conditions this composition treats as **fatal** — the ones that reach `error` and fire `'error'`.\n * Severity isn't part of an SVTA code (§Approach: \"impact varies with player implementation\"), so it's decided at this\n * boundary rather than by the reporter.\n *\n * **Causes are fatal here, unlike on the other two adapters.** There, a cause is context — one unplayable rendition\n * doesn't fail a source whose others still play, and a verdict follows if the type empties. In the pinned variant a\n * cause _is_ the verdict: only the pinned rendition's playlist is ever resolved, so a cause can only be about the pick\n * itself, and dropping that pick is final — nothing here re-picks (that is what `switchVideoTrack` exists for, and this\n * engine doesn't compose it). Measured on Chromium: an MPEG-TS source reports 1004 and an encrypted one 4008, each with\n * no verdict behind it, and the element then sits at `readyState 0` with `error` null forever.\n *\n * The verdict is still listed, for the shapes that report nothing else: no video renditions at all, or a ladder pruned\n * before anything resolves — both of which `reportAbsentTrackType` covers from the tail of the constraint chain.\n *\n * First-fatal-wins then surfaces the cause rather than the verdict when both are present, which is the more specific of\n * the two.\n */\nconst FATAL_SVTA_CODES: ReadonlySet<number> = new Set<number>([\n SVTA_NO_SUPPORTED_VIDEO_TRACK,\n SVTA_UNSUPPORTED_VIDEO_FORMAT,\n SVTA_UNSUPPORTED_DRM_SYSTEM,\n]);\n\n/**\n * Mixin that adds the background-video SPF playback engine to any base class, for an HLS URL.\n *\n * `src` is the whole input surface, and `error` is the one output: nothing about an unplayable source reaches the media\n * element on its own here — an unsupported container, encryption with no EME, and an undecodable codec all leave\n * `HTMLMediaElement.error` null with the element stalled at `readyState 0` (measured on Chromium and WebKit) — so a\n * consumer that watched only the `<video>` would see a source that never appears and never says why. The engine reports\n * each condition onto `engine.state.errors` and logs it; this adapter promotes the first fatal one, mapping it the same\n * way the video and audio Medias map theirs. See `internal/design/spf/features/errors.md`.\n *\n * Selection pins the largest rendition that _fits the screen_, and holds it for the session. The manifest is still the\n * better place to narrow further: a delivery param — `?max_resolution=720p` on a Mux stream URL, for one — keeps the\n * renditions it excludes out of the manifest entirely, rather than fetched-then-unpicked.\n *\n * The pin is given up, never moved, if the pick turns out to be unplayable: the container is only known once a media\n * playlist resolves, which is after the pick is made, so the selection clears rather than quietly appending bytes\n * nothing can decode.\n *\n * `@videojs/spf/mux-background-video` is this same Media under a Mux-flavored name — an alias, not a variant. Nothing\n * about the surface changes with the import path.\n *\n * Everything else the use case fixes rather than exposes: video-only, looping, muted, autoplaying, loading as soon as\n * there is a source. `attach` writes that onto the element and nothing here declares `loop` / `muted` / `autoplay` /\n * `preload` of its own — a host-bound Media inherits all four from the host already, and shadowing them with fixed\n * values would only make reads describe an intention rather than what the element is doing.\n *\n * A new src re-resolves the presentation, tearing down the state, SourceBuffers, and in-flight requests the previous\n * one built before the next begins. The engine instance and the attached media element are both kept, so neither has to\n * be rewired.\n *\n * @example\n * class HlsBackgroundVideoMedia extends HlsBackgroundVideoMediaMixin(BackgroundVideoHost) {}\n *\n * const media = new HlsBackgroundVideoMedia();\n * media.attach(document.querySelector('video'));\n * media.src = 'https://stream.mux.com/PLAYBACK_ID.m3u8?max_resolution=720p';\n * media.play();\n *\n * @fires error - Fired when a fatal condition is reported. Read `error` for it.\n */\nexport function HlsBackgroundVideoMediaMixin<Base extends Constructor<any>>(BaseClass: Base) {\n class HlsBackgroundVideoMediaImpl extends BaseClass {\n #engine: Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext>;\n #config: BackgroundVideoEngineConfig;\n #signals!: BackgroundVideoEngineSignals;\n #error: HlsVideoMediaError | null = null;\n /**\n * The _reported_ condition currently surfaced, which is what the re-fire latch keys on. Not `#error.code`: that's\n * the code this adapter chose to surface, and the substitution below can make the two differ.\n */\n #reportedCode: number | null = null;\n #stopErrorSync: () => void;\n\n /** Pending loadstart listener from a deferred play() retry, if any. */\n #loadstartListener: (() => void) | null = null;\n\n constructor(...args: any[]) {\n super(...args);\n\n const { config } = args?.[0] ?? {};\n\n this.#config = config;\n this.#engine = this.#createEngine();\n\n // Promote the first fatal condition out of the engine's reported sequence\n // onto this surface. Clearing rides the same signal: `collectErrors` resets\n // the slot per source, so a new source starts with no error without this\n // needing its own source-change hook.\n this.#stopErrorSync = effect(() => {\n const errors = this.#signals.state.errors.get();\n\n this.#setError(firstFatal(errors, FATAL_SVTA_CODES), errors);\n });\n }\n\n get engine(): Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext> {\n return this.#engine;\n }\n\n /**\n * The current fatal condition, or `null`. Only _fatal_ ones appear here — the engine reports non-fatal ones too\n * (they stay in `engine.state.errors`), and promoting them would say playback had failed when it hadn't. Which ones\n * are fatal is wider here than on the video and audio Medias; see {@link FATAL_SVTA_CODES}. Resets per source.\n * Fires `'error'` when set.\n *\n * Mapped the same way theirs are: a sequence holding an unimplemented-capability cause surfaces as\n * {@link SVTA_UNSUPPORTED_PLAYBACK_FEATURE} (99001) with the specifics logged, because \"this player can't play this\n * source\" is what a consumer can act on, where a raw container or DRM code only says what to go and look up.\n */\n get error(): HlsVideoMediaError | null {\n return this.#error;\n }\n\n #setError(reported: SvtaError | undefined, errors: readonly SvtaError[] | undefined): void {\n if (!reported) {\n // Cleared (new source). No event: `'error'` announces a failure, and\n // consumers reset their own copy on source change.\n this.#error = null;\n this.#reportedCode = null;\n return;\n }\n\n // Keyed on the code, not the object: a later append re-runs this effect\n // with an equal-but-new array, and re-firing `'error'` for a condition\n // already surfaced would look like a second failure.\n if (this.#reportedCode === reported.code) return;\n\n this.#reportedCode = reported.code;\n\n // Logged for every fatal condition, not just the substituted ones: a source\n // with no video renditions is as dead as an unplayable container, and it\n // would otherwise reach a developer as a bare code. One generic sentence\n // rather than one per case — the conditions beside it carry the specifics.\n //\n // Prose stays here rather than on `error.message`, matching the other two:\n // viewer-facing copy is the consumer's to localize, and a background video\n // has no chrome to put it in anyway.\n console.error(UNPLAYABLE_SOURCE_MESSAGE, { conditions: errors });\n\n this.#error = {\n code: hasUnsupportedFeatureCause(errors) ? SVTA_UNSUPPORTED_PLAYBACK_FEATURE : reported.code,\n message: reported.message ?? '',\n ...(reported.data === undefined ? {} : { data: reported.data }),\n };\n // Optional-chained: with an EventTarget-less base (`HlsBackgroundVideoMediaElement`\n // standalone) there's nowhere to dispatch.\n this.dispatchEvent?.(new Event('error'));\n }\n\n // -------------------------------------------------------------------------\n // Media element lifecycle\n // -------------------------------------------------------------------------\n\n attach(mediaElement: HTMLMediaElement): void {\n super.attach?.(mediaElement);\n // The one place the fixed behavior is stated. Muted and autoplay are what\n // let it start without a gesture, loop is the defining behavior, and\n // `preload` says out loud what the engine does regardless — it subtracts\n // preload monitoring and loads from the moment it has a source.\n mediaElement.loop = true;\n mediaElement.muted = true;\n mediaElement.autoplay = true;\n mediaElement.preload = 'auto';\n\n this.#signals.context.mediaElement.set(mediaElement);\n }\n\n detach(): void {\n this.#cancelPendingPlay();\n this.#signals.context.mediaElement.set(undefined);\n super.detach?.();\n }\n\n destroy(): void {\n this.#cancelPendingPlay();\n this.#stopErrorSync();\n this.#engine.destroy();\n }\n\n // -------------------------------------------------------------------------\n // src — synchronous IDL attribute (WHATWG §4.8.11.2)\n // -------------------------------------------------------------------------\n\n get src(): string {\n return this.#signals.state.presentation.get()?.url ?? '';\n }\n\n set src(value: string) {\n // Same line the HLS Medias draw: the presentation is set from a fresh\n // object every time, so re-resolving a URL already playing would restart\n // it for no reason.\n if (value === this.src) return;\n\n this.#cancelPendingPlay();\n this.#signals.state.presentation.set(value ? { url: value } : undefined);\n }\n\n // -------------------------------------------------------------------------\n // play() — WHATWG §4.8.11.8\n // Delegates to the attached media element's native play().\n // -------------------------------------------------------------------------\n\n async play(): Promise<void> {\n const mediaElement = this.#signals.context.mediaElement.get();\n if (!mediaElement) return Promise.reject(new Error('HlsBackgroundVideoMediaElement: no media element attached'));\n\n try {\n return await mediaElement.play();\n } catch (err) {\n // If we have a pending HLS source, the rejection may be because MSE\n // hasn't attached a blob URL yet. Wait for loadstart (src assigned by\n // MSE setup) and retry once.\n if (this.src) {\n return new Promise<void>((resolve, reject) => {\n const listener = () => {\n this.#loadstartListener = null;\n mediaElement.play().then(resolve, reject);\n };\n\n this.#loadstartListener = listener;\n mediaElement.addEventListener('loadstart', listener, { once: true });\n });\n }\n\n throw err;\n }\n }\n\n // -------------------------------------------------------------------------\n // Private\n // -------------------------------------------------------------------------\n\n #createEngine(): Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext> {\n // No selection config of its own: the engine's default rule chain already\n // narrows to the largest rendition that fits the screen, which is exactly\n // what this adapter used to hand over as a bespoke picker.\n return createBackgroundVideoEngine({\n ...this.#config,\n onSignalsReady: (signals) => {\n this.#signals = signals;\n },\n });\n }\n\n #cancelPendingPlay(): void {\n if (!this.#loadstartListener) return;\n\n const mediaElement = this.#signals.context.mediaElement.get();\n\n mediaElement?.removeEventListener('loadstart', this.#loadstartListener);\n this.#loadstartListener = null;\n }\n }\n\n return HlsBackgroundVideoMediaImpl as unknown as MixinReturn<Base, HlsBackgroundVideoMediaAPI>;\n}\n\n/** Standalone SPF background-video adapter with no base class. */\nexport class HlsBackgroundVideoMediaElement extends HlsBackgroundVideoMediaMixin(class {}) {}\n"],"mappings":"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"}
@@ -1,24 +1,20 @@
1
1
  //#region src/playback/adapters/hls-background-video/host.d.ts
2
2
  /**
3
- * The `<video>` binding a background video uses: somewhere to keep the attached
4
- * element, and the four properties the Media fixes on it.
3
+ * The `<video>` binding a background video uses: somewhere to keep the attached element, and the four properties the
4
+ * Media fixes on it.
5
5
  *
6
- * That is the whole surface anything here reaches. The engine drives playback,
7
- * the element exposes `src` and nothing else, and the background player
8
- * subscribes to no store features, so nothing asks a background video for
9
- * `currentTime`, `play()`, picture-in-picture, fullscreen, forwarded events, or
10
- * media components. Holding the host to what is reachable is what keeps this
11
- * entry free of `@videojs/media`, and small enough to suit a component whose
12
- * whole pitch is its size.
6
+ * That is the whole surface anything here reaches. The engine drives playback, the element exposes `src` and nothing
7
+ * else, and the background player subscribes to no store features, so nothing asks a background video for
8
+ * `currentTime`, `play()`, picture-in-picture, fullscreen, forwarded events, or media components. Holding the host to
9
+ * what is reachable is what keeps this entry free of `@videojs/media`, and small enough to suit a component whose whole
10
+ * pitch is its size.
13
11
  *
14
- * An `EventTarget`, because a Media is one: the store and the element layers
15
- * take anything they attach as an event source, and inheriting the three methods
16
- * satisfies that for free rather than by stubbing them.
12
+ * An `EventTarget`, because a Media is one: the store and the element layers take anything they attach as an event
13
+ * source, and inheriting the three methods satisfies that for free rather than by stubbing them.
17
14
  *
18
- * ⚠️ It still implements too little to carry the rest of the media surface, which
19
- * bounds what may consume it: a store feature reading a property outside this set
20
- * gets `undefined` rather than an error. A Media needing more of that surface
21
- * belongs on a host that provides it.
15
+ * ⚠️ It still implements too little to carry the rest of the media surface, which bounds what may consume it: a store
16
+ * feature reading a property outside this set gets `undefined` rather than an error. A Media needing more of that
17
+ * surface belongs on a host that provides it.
22
18
  */
23
19
  declare class BackgroundVideoHost extends EventTarget {
24
20
  #private;
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","names":[],"sources":["../../../../../src/playback/adapters/hls-background-video/host.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;cAqBa,4BAA4B;;EAGvC,OAAO,QAAQ;EAKf;MAOI;MAIA,KAAK;MAIL;MAIA,MAAM;MAIN;MAIA,SAAS;MAIT,WAAW;MAIX,QAAQ,OAAO"}
1
+ {"version":3,"file":"host.d.ts","names":[],"sources":["../../../../../src/playback/adapters/hls-background-video/host.ts"],"mappings":";;;;;;;;;;;;;;;;;;cAiBa,4BAA4B;;EAGvC,OAAO,QAAQ;EAMf;MAOI;MAIA,KAAK;MAIL;MAIA,MAAM;MAIN;MAIA,SAAS;MAIT,WAAW;MAIX,QAAQ,OAAO"}