@videojs/spf 10.0.0-beta.24 → 10.0.0-beta.26

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 (375) hide show
  1. package/README.md +5 -0
  2. package/dist/default/background-video.js +3 -0
  3. package/dist/default/core/actors/create-machine-actor.js.map +1 -1
  4. package/dist/default/core/actors/create-transition-actor.js.map +1 -1
  5. package/dist/default/core/composition/create-composition.js +2 -2
  6. package/dist/default/core/composition/create-composition.js.map +1 -1
  7. package/dist/default/core/composition/share-signals.js +13 -11
  8. package/dist/default/core/composition/share-signals.js.map +1 -1
  9. package/dist/default/core/machine.js.map +1 -1
  10. package/dist/default/core/reactors/create-machine-reactor.js.map +1 -1
  11. package/dist/default/core/signals/effect.js.map +1 -1
  12. package/dist/default/core/signals/primitives.js.map +1 -1
  13. package/dist/default/core/tasks/task.js.map +1 -1
  14. package/dist/default/hls.js +4 -1
  15. package/dist/default/media/abr/quality-selection.js +6 -68
  16. package/dist/default/media/abr/quality-selection.js.map +1 -1
  17. package/dist/default/media/buffer/back-buffer.js.map +1 -1
  18. package/dist/default/media/buffer/forward-buffer.js +37 -3
  19. package/dist/default/media/buffer/forward-buffer.js.map +1 -1
  20. package/dist/default/media/dom/capabilities.js +70 -0
  21. package/dist/default/media/dom/capabilities.js.map +1 -0
  22. package/dist/default/media/dom/mse/append-segment.js.map +1 -1
  23. package/dist/default/media/dom/mse/buffer-flusher.js.map +1 -1
  24. package/dist/default/media/dom/mse/duration.js +27 -10
  25. package/dist/default/media/dom/mse/duration.js.map +1 -1
  26. package/dist/default/media/dom/mse/end-of-stream.js.map +1 -1
  27. package/dist/default/media/dom/mse/mediasource-setup.js +68 -17
  28. package/dist/default/media/dom/mse/mediasource-setup.js.map +1 -1
  29. package/dist/default/media/dom/text/resolve-vtt-segment.js +1 -7
  30. package/dist/default/media/dom/text/resolve-vtt-segment.js.map +1 -1
  31. package/dist/default/media/dom/text/text-track-slots.js +3 -3
  32. package/dist/default/media/dom/text/text-track-slots.js.map +1 -1
  33. package/dist/default/media/hls/parse-attributes.js +17 -3
  34. package/dist/default/media/hls/parse-attributes.js.map +1 -1
  35. package/dist/default/media/hls/parse-media-playlist.js +29 -1
  36. package/dist/default/media/hls/parse-media-playlist.js.map +1 -1
  37. package/dist/default/media/hls/parse-multivariant.js +15 -6
  38. package/dist/default/media/hls/parse-multivariant.js.map +1 -1
  39. package/dist/default/media/hls/resolve-url.js.map +1 -1
  40. package/dist/default/media/media-tracks/media-tracks.js +101 -0
  41. package/dist/default/media/media-tracks/media-tracks.js.map +1 -0
  42. package/dist/default/media/mp4/box.js +58 -0
  43. package/dist/default/media/mp4/box.js.map +1 -0
  44. package/dist/default/media/mp4/timestamp-origin.js +107 -0
  45. package/dist/default/media/mp4/timestamp-origin.js.map +1 -0
  46. package/dist/default/media/primitives/select-tracks.js +98 -13
  47. package/dist/default/media/primitives/select-tracks.js.map +1 -1
  48. package/dist/default/media/text/parse-vtt-timestamp-map.js +42 -0
  49. package/dist/default/media/text/parse-vtt-timestamp-map.js.map +1 -0
  50. package/dist/default/media/text/resolve-vtt-metadata.js +23 -0
  51. package/dist/default/media/text/resolve-vtt-metadata.js.map +1 -0
  52. package/dist/default/media/types/index.js.map +1 -1
  53. package/dist/default/media/utils/cdn.js +56 -0
  54. package/dist/default/media/utils/cdn.js.map +1 -0
  55. package/dist/default/media/utils/preload.js.map +1 -1
  56. package/dist/default/media/utils/track-selection.js +1 -1
  57. package/dist/default/media/utils/track-selection.js.map +1 -1
  58. package/dist/default/media/utils/tracks.js +31 -4
  59. package/dist/default/media/utils/tracks.js.map +1 -1
  60. package/dist/default/media-tracks.js +2 -0
  61. package/dist/default/network/bandwidth-estimator.js.map +1 -1
  62. package/dist/default/network/chunked-stream-iterable.js.map +1 -1
  63. package/dist/default/network/ewma.js +1 -1
  64. package/dist/default/network/ewma.js.map +1 -1
  65. package/dist/default/network/fetch.js +7 -1
  66. package/dist/default/network/fetch.js.map +1 -1
  67. package/dist/default/playback/actors/dom/segment-loader.js +103 -106
  68. package/dist/default/playback/actors/dom/segment-loader.js.map +1 -1
  69. package/dist/default/playback/actors/dom/source-buffer.js +3 -1
  70. package/dist/default/playback/actors/dom/source-buffer.js.map +1 -1
  71. package/dist/default/playback/actors/dom/text-tracks.js.map +1 -1
  72. package/dist/default/playback/actors/text-track-segment-loader.js +30 -16
  73. package/dist/default/playback/actors/text-track-segment-loader.js.map +1 -1
  74. package/dist/default/playback/behaviors/calculate-presentation-duration.js +21 -43
  75. package/dist/default/playback/behaviors/calculate-presentation-duration.js.map +1 -1
  76. package/dist/default/playback/behaviors/derive-cdn-priority.js +68 -0
  77. package/dist/default/playback/behaviors/derive-cdn-priority.js.map +1 -0
  78. package/dist/default/playback/behaviors/dom/airplay.js +211 -0
  79. package/dist/default/playback/behaviors/dom/airplay.js.map +1 -0
  80. package/dist/default/playback/behaviors/dom/apply-start-position.js +93 -0
  81. package/dist/default/playback/behaviors/dom/apply-start-position.js.map +1 -0
  82. package/dist/default/playback/behaviors/dom/end-of-stream.js +25 -102
  83. package/dist/default/playback/behaviors/dom/end-of-stream.js.map +1 -1
  84. package/dist/default/playback/behaviors/dom/load-segments.js +6 -2
  85. package/dist/default/playback/behaviors/dom/load-segments.js.map +1 -1
  86. package/dist/default/playback/behaviors/dom/recover-end-stall.js +77 -0
  87. package/dist/default/playback/behaviors/dom/recover-end-stall.js.map +1 -0
  88. package/dist/default/playback/behaviors/dom/setup-buffer-actors.js +50 -18
  89. package/dist/default/playback/behaviors/dom/setup-buffer-actors.js.map +1 -1
  90. package/dist/default/playback/behaviors/dom/setup-mediasource.js +36 -11
  91. package/dist/default/playback/behaviors/dom/setup-mediasource.js.map +1 -1
  92. package/dist/default/playback/behaviors/dom/setup-text-track-actors.js +11 -25
  93. package/dist/default/playback/behaviors/dom/setup-text-track-actors.js.map +1 -1
  94. package/dist/default/playback/behaviors/dom/sync-text-tracks.js +43 -18
  95. package/dist/default/playback/behaviors/dom/sync-text-tracks.js.map +1 -1
  96. package/dist/default/playback/behaviors/dom/track-current-time.js +6 -0
  97. package/dist/default/playback/behaviors/dom/track-current-time.js.map +1 -1
  98. package/dist/default/playback/behaviors/dom/track-load-triggers.js +4 -4
  99. package/dist/default/playback/behaviors/dom/track-load-triggers.js.map +1 -1
  100. package/dist/default/playback/behaviors/dom/track-playback-rate.js.map +1 -1
  101. package/dist/default/playback/behaviors/dom/update-mediasource-duration.js +3 -2
  102. package/dist/default/playback/behaviors/dom/update-mediasource-duration.js.map +1 -1
  103. package/dist/default/playback/behaviors/establish-start-media-time.js +123 -0
  104. package/dist/default/playback/behaviors/establish-start-media-time.js.map +1 -0
  105. package/dist/default/playback/behaviors/resolve-presentation.js.map +1 -1
  106. package/dist/default/playback/behaviors/resolve-track.js +45 -22
  107. package/dist/default/playback/behaviors/resolve-track.js.map +1 -1
  108. package/dist/default/playback/behaviors/select-tracks.js +46 -77
  109. package/dist/default/playback/behaviors/select-tracks.js.map +1 -1
  110. package/dist/default/playback/behaviors/setup-failover-monitor.js +66 -0
  111. package/dist/default/playback/behaviors/setup-failover-monitor.js.map +1 -0
  112. package/dist/default/playback/behaviors/sync-preload.js.map +1 -1
  113. package/dist/default/playback/behaviors/track-switching.js +403 -0
  114. package/dist/default/playback/behaviors/track-switching.js.map +1 -0
  115. package/dist/default/playback/engines/background-video/adapter.js +158 -0
  116. package/dist/default/playback/engines/background-video/adapter.js.map +1 -0
  117. package/dist/default/playback/engines/background-video/engine.js +75 -0
  118. package/dist/default/playback/engines/background-video/engine.js.map +1 -0
  119. package/dist/default/playback/engines/hls/adapter-audio-only.js +124 -0
  120. package/dist/default/playback/engines/hls/adapter-audio-only.js.map +1 -0
  121. package/dist/default/playback/engines/hls/adapter.js +20 -11
  122. package/dist/default/playback/engines/hls/adapter.js.map +1 -1
  123. package/dist/default/playback/engines/hls/engine-audio-only.js +94 -0
  124. package/dist/default/playback/engines/hls/engine-audio-only.js.map +1 -0
  125. package/dist/default/playback/engines/hls/engine.js +38 -8
  126. package/dist/default/playback/engines/hls/engine.js.map +1 -1
  127. package/dist/default/playback/primitives/failover-fetch.js +42 -0
  128. package/dist/default/playback/primitives/failover-fetch.js.map +1 -0
  129. package/dist/default/playback/primitives/head-peek.js +44 -0
  130. package/dist/default/playback/primitives/head-peek.js.map +1 -0
  131. package/dist/default/playback/primitives/relocation-pipelines.js +203 -0
  132. package/dist/default/playback/primitives/relocation-pipelines.js.map +1 -0
  133. package/dist/default/playback/primitives/segment-load-pipeline.js +96 -0
  134. package/dist/default/playback/primitives/segment-load-pipeline.js.map +1 -0
  135. package/dist/default/playback/primitives/text-segment-load-pipeline.js +37 -0
  136. package/dist/default/playback/primitives/text-segment-load-pipeline.js.map +1 -0
  137. package/dist/{dev/playback/behaviors → default/playback/primitives}/track-types.js +1 -1
  138. package/dist/default/playback/primitives/track-types.js.map +1 -0
  139. package/dist/dev/background-video.d.ts +3 -0
  140. package/dist/dev/background-video.js +3 -0
  141. package/dist/dev/core/actors/actor.d.ts +0 -1
  142. package/dist/dev/core/actors/actor.d.ts.map +1 -1
  143. package/dist/dev/core/actors/create-machine-actor.d.ts +9 -6
  144. package/dist/dev/core/actors/create-machine-actor.d.ts.map +1 -1
  145. package/dist/dev/core/actors/create-machine-actor.js.map +1 -1
  146. package/dist/dev/core/actors/create-transition-actor.d.ts +0 -1
  147. package/dist/dev/core/actors/create-transition-actor.d.ts.map +1 -1
  148. package/dist/dev/core/actors/create-transition-actor.js.map +1 -1
  149. package/dist/dev/core/composition/create-composition.d.ts +10 -11
  150. package/dist/dev/core/composition/create-composition.d.ts.map +1 -1
  151. package/dist/dev/core/composition/create-composition.js +2 -2
  152. package/dist/dev/core/composition/create-composition.js.map +1 -1
  153. package/dist/dev/core/composition/share-signals.d.ts +11 -10
  154. package/dist/dev/core/composition/share-signals.d.ts.map +1 -1
  155. package/dist/dev/core/composition/share-signals.js +13 -11
  156. package/dist/dev/core/composition/share-signals.js.map +1 -1
  157. package/dist/dev/core/machine.d.ts +1 -0
  158. package/dist/dev/core/machine.d.ts.map +1 -1
  159. package/dist/dev/core/machine.js.map +1 -1
  160. package/dist/dev/core/reactors/create-machine-reactor.d.ts +2 -2
  161. package/dist/dev/core/reactors/create-machine-reactor.d.ts.map +1 -1
  162. package/dist/dev/core/reactors/create-machine-reactor.js.map +1 -1
  163. package/dist/dev/core/signals/effect.d.ts.map +1 -1
  164. package/dist/dev/core/signals/effect.js.map +1 -1
  165. package/dist/dev/core/signals/primitives.d.ts +1 -2
  166. package/dist/dev/core/signals/primitives.d.ts.map +1 -1
  167. package/dist/dev/core/signals/primitives.js.map +1 -1
  168. package/dist/dev/core/tasks/task.d.ts +2 -2
  169. package/dist/dev/core/tasks/task.d.ts.map +1 -1
  170. package/dist/dev/core/tasks/task.js.map +1 -1
  171. package/dist/dev/hls.d.ts +5 -1
  172. package/dist/dev/hls.js +4 -1
  173. package/dist/dev/index.d.ts +0 -1
  174. package/dist/dev/index.d.ts.map +1 -1
  175. package/dist/dev/media/abr/quality-selection.d.ts.map +1 -1
  176. package/dist/dev/media/abr/quality-selection.js +6 -68
  177. package/dist/dev/media/abr/quality-selection.js.map +1 -1
  178. package/dist/dev/media/buffer/back-buffer.d.ts.map +1 -1
  179. package/dist/dev/media/buffer/back-buffer.js.map +1 -1
  180. package/dist/dev/media/buffer/forward-buffer.d.ts.map +1 -1
  181. package/dist/dev/media/buffer/forward-buffer.js +37 -3
  182. package/dist/dev/media/buffer/forward-buffer.js.map +1 -1
  183. package/dist/dev/media/dom/capabilities.js +70 -0
  184. package/dist/dev/media/dom/capabilities.js.map +1 -0
  185. package/dist/dev/media/dom/mse/append-segment.d.ts +3 -9
  186. package/dist/dev/media/dom/mse/append-segment.d.ts.map +1 -1
  187. package/dist/dev/media/dom/mse/append-segment.js.map +1 -1
  188. package/dist/dev/media/dom/mse/buffer-flusher.d.ts.map +1 -1
  189. package/dist/dev/media/dom/mse/buffer-flusher.js.map +1 -1
  190. package/dist/dev/media/dom/mse/duration.js +27 -10
  191. package/dist/dev/media/dom/mse/duration.js.map +1 -1
  192. package/dist/dev/media/dom/mse/end-of-stream.js.map +1 -1
  193. package/dist/dev/media/dom/mse/mediasource-setup.js +68 -17
  194. package/dist/dev/media/dom/mse/mediasource-setup.js.map +1 -1
  195. package/dist/dev/media/dom/text/resolve-vtt-segment.d.ts +0 -6
  196. package/dist/dev/media/dom/text/resolve-vtt-segment.d.ts.map +1 -1
  197. package/dist/dev/media/dom/text/resolve-vtt-segment.js +1 -7
  198. package/dist/dev/media/dom/text/resolve-vtt-segment.js.map +1 -1
  199. package/dist/dev/media/dom/text/text-track-slots.d.ts +0 -1
  200. package/dist/dev/media/dom/text/text-track-slots.d.ts.map +1 -1
  201. package/dist/dev/media/dom/text/text-track-slots.js +3 -3
  202. package/dist/dev/media/dom/text/text-track-slots.js.map +1 -1
  203. package/dist/dev/media/hls/parse-attributes.js +17 -3
  204. package/dist/dev/media/hls/parse-attributes.js.map +1 -1
  205. package/dist/dev/media/hls/parse-media-playlist.js +29 -1
  206. package/dist/dev/media/hls/parse-media-playlist.js.map +1 -1
  207. package/dist/dev/media/hls/parse-multivariant.js +15 -6
  208. package/dist/dev/media/hls/parse-multivariant.js.map +1 -1
  209. package/dist/dev/media/hls/resolve-url.js.map +1 -1
  210. package/dist/dev/media/media-tracks/media-tracks.d.ts +51 -0
  211. package/dist/dev/media/media-tracks/media-tracks.d.ts.map +1 -0
  212. package/dist/dev/media/media-tracks/media-tracks.js +101 -0
  213. package/dist/dev/media/media-tracks/media-tracks.js.map +1 -0
  214. package/dist/dev/media/mp4/box.js +58 -0
  215. package/dist/dev/media/mp4/box.js.map +1 -0
  216. package/dist/dev/media/mp4/timestamp-origin.js +107 -0
  217. package/dist/dev/media/mp4/timestamp-origin.js.map +1 -0
  218. package/dist/dev/media/primitives/select-tracks.d.ts +35 -0
  219. package/dist/dev/media/primitives/select-tracks.d.ts.map +1 -0
  220. package/dist/dev/media/primitives/select-tracks.js +98 -13
  221. package/dist/dev/media/primitives/select-tracks.js.map +1 -1
  222. package/dist/dev/media/text/parse-vtt-timestamp-map.js +42 -0
  223. package/dist/dev/media/text/parse-vtt-timestamp-map.js.map +1 -0
  224. package/dist/dev/media/text/resolve-vtt-metadata.js +23 -0
  225. package/dist/dev/media/text/resolve-vtt-metadata.js.map +1 -0
  226. package/dist/dev/media/types/index.d.ts +69 -2
  227. package/dist/dev/media/types/index.d.ts.map +1 -1
  228. package/dist/dev/media/types/index.js.map +1 -1
  229. package/dist/dev/media/utils/cdn.d.ts +13 -0
  230. package/dist/dev/media/utils/cdn.d.ts.map +1 -0
  231. package/dist/dev/media/utils/cdn.js +56 -0
  232. package/dist/dev/media/utils/cdn.js.map +1 -0
  233. package/dist/dev/media/utils/preload.js.map +1 -1
  234. package/dist/dev/media/utils/track-selection.js +1 -1
  235. package/dist/dev/media/utils/track-selection.js.map +1 -1
  236. package/dist/dev/media/utils/tracks.js +31 -4
  237. package/dist/dev/media/utils/tracks.js.map +1 -1
  238. package/dist/dev/media-tracks.d.ts +3 -0
  239. package/dist/dev/media-tracks.js +2 -0
  240. package/dist/dev/network/bandwidth-estimator.d.ts.map +1 -1
  241. package/dist/dev/network/bandwidth-estimator.js.map +1 -1
  242. package/dist/dev/network/chunked-stream-iterable.js.map +1 -1
  243. package/dist/dev/network/ewma.js +1 -1
  244. package/dist/dev/network/ewma.js.map +1 -1
  245. package/dist/dev/network/fetch.js +7 -1
  246. package/dist/dev/network/fetch.js.map +1 -1
  247. package/dist/dev/playback/actors/dom/segment-loader.d.ts +16 -4
  248. package/dist/dev/playback/actors/dom/segment-loader.d.ts.map +1 -1
  249. package/dist/dev/playback/actors/dom/segment-loader.js +103 -106
  250. package/dist/dev/playback/actors/dom/segment-loader.js.map +1 -1
  251. package/dist/dev/playback/actors/dom/source-buffer.d.ts +10 -25
  252. package/dist/dev/playback/actors/dom/source-buffer.d.ts.map +1 -1
  253. package/dist/dev/playback/actors/dom/source-buffer.js +3 -1
  254. package/dist/dev/playback/actors/dom/source-buffer.js.map +1 -1
  255. package/dist/dev/playback/actors/dom/text-tracks.d.ts +3 -1
  256. package/dist/dev/playback/actors/dom/text-tracks.js.map +1 -1
  257. package/dist/dev/playback/actors/text-track-segment-loader.d.ts +7 -12
  258. package/dist/dev/playback/actors/text-track-segment-loader.d.ts.map +1 -1
  259. package/dist/dev/playback/actors/text-track-segment-loader.js +30 -16
  260. package/dist/dev/playback/actors/text-track-segment-loader.js.map +1 -1
  261. package/dist/dev/playback/actors/text-tracks.d.ts +3 -12
  262. package/dist/dev/playback/actors/text-tracks.d.ts.map +1 -1
  263. package/dist/dev/playback/behaviors/calculate-presentation-duration.d.ts +11 -2
  264. package/dist/dev/playback/behaviors/calculate-presentation-duration.d.ts.map +1 -1
  265. package/dist/dev/playback/behaviors/calculate-presentation-duration.js +21 -43
  266. package/dist/dev/playback/behaviors/calculate-presentation-duration.js.map +1 -1
  267. package/dist/dev/playback/behaviors/derive-cdn-priority.js +68 -0
  268. package/dist/dev/playback/behaviors/derive-cdn-priority.js.map +1 -0
  269. package/dist/dev/playback/behaviors/dom/airplay.js +211 -0
  270. package/dist/dev/playback/behaviors/dom/airplay.js.map +1 -0
  271. package/dist/dev/playback/behaviors/dom/apply-start-position.js +93 -0
  272. package/dist/dev/playback/behaviors/dom/apply-start-position.js.map +1 -0
  273. package/dist/dev/playback/behaviors/dom/end-of-stream.js +25 -102
  274. package/dist/dev/playback/behaviors/dom/end-of-stream.js.map +1 -1
  275. package/dist/dev/playback/behaviors/dom/load-segments.d.ts +14 -4
  276. package/dist/dev/playback/behaviors/dom/load-segments.d.ts.map +1 -1
  277. package/dist/dev/playback/behaviors/dom/load-segments.js +6 -2
  278. package/dist/dev/playback/behaviors/dom/load-segments.js.map +1 -1
  279. package/dist/dev/playback/behaviors/dom/recover-end-stall.js +77 -0
  280. package/dist/dev/playback/behaviors/dom/recover-end-stall.js.map +1 -0
  281. package/dist/dev/playback/behaviors/dom/setup-buffer-actors.js +50 -18
  282. package/dist/dev/playback/behaviors/dom/setup-buffer-actors.js.map +1 -1
  283. package/dist/dev/playback/behaviors/dom/setup-mediasource.js +36 -11
  284. package/dist/dev/playback/behaviors/dom/setup-mediasource.js.map +1 -1
  285. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.d.ts +16 -19
  286. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.d.ts.map +1 -1
  287. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.js +11 -25
  288. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.js.map +1 -1
  289. package/dist/dev/playback/behaviors/dom/sync-text-tracks.js +43 -18
  290. package/dist/dev/playback/behaviors/dom/sync-text-tracks.js.map +1 -1
  291. package/dist/dev/playback/behaviors/dom/track-current-time.d.ts +1 -2
  292. package/dist/dev/playback/behaviors/dom/track-current-time.d.ts.map +1 -1
  293. package/dist/dev/playback/behaviors/dom/track-current-time.js +6 -0
  294. package/dist/dev/playback/behaviors/dom/track-current-time.js.map +1 -1
  295. package/dist/dev/playback/behaviors/dom/track-load-triggers.d.ts +1 -2
  296. package/dist/dev/playback/behaviors/dom/track-load-triggers.d.ts.map +1 -1
  297. package/dist/dev/playback/behaviors/dom/track-load-triggers.js +4 -4
  298. package/dist/dev/playback/behaviors/dom/track-load-triggers.js.map +1 -1
  299. package/dist/dev/playback/behaviors/dom/track-playback-rate.d.ts +1 -2
  300. package/dist/dev/playback/behaviors/dom/track-playback-rate.d.ts.map +1 -1
  301. package/dist/dev/playback/behaviors/dom/track-playback-rate.js.map +1 -1
  302. package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js +3 -2
  303. package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js.map +1 -1
  304. package/dist/dev/playback/behaviors/establish-start-media-time.d.ts +31 -0
  305. package/dist/dev/playback/behaviors/establish-start-media-time.d.ts.map +1 -0
  306. package/dist/dev/playback/behaviors/establish-start-media-time.js +123 -0
  307. package/dist/dev/playback/behaviors/establish-start-media-time.js.map +1 -0
  308. package/dist/dev/playback/behaviors/resolve-presentation.d.ts +2 -1
  309. package/dist/dev/playback/behaviors/resolve-presentation.d.ts.map +1 -1
  310. package/dist/dev/playback/behaviors/resolve-presentation.js.map +1 -1
  311. package/dist/dev/playback/behaviors/resolve-track.js +45 -22
  312. package/dist/dev/playback/behaviors/resolve-track.js.map +1 -1
  313. package/dist/dev/playback/behaviors/select-tracks.d.ts +14 -0
  314. package/dist/dev/playback/behaviors/select-tracks.d.ts.map +1 -0
  315. package/dist/dev/playback/behaviors/select-tracks.js +46 -77
  316. package/dist/dev/playback/behaviors/select-tracks.js.map +1 -1
  317. package/dist/dev/playback/behaviors/setup-failover-monitor.d.ts +14 -0
  318. package/dist/dev/playback/behaviors/setup-failover-monitor.d.ts.map +1 -0
  319. package/dist/dev/playback/behaviors/setup-failover-monitor.js +66 -0
  320. package/dist/dev/playback/behaviors/setup-failover-monitor.js.map +1 -0
  321. package/dist/dev/playback/behaviors/sync-preload.js.map +1 -1
  322. package/dist/dev/playback/behaviors/track-switching.js +403 -0
  323. package/dist/dev/playback/behaviors/track-switching.js.map +1 -0
  324. package/dist/dev/playback/engines/background-video/adapter.d.ts +59 -0
  325. package/dist/dev/playback/engines/background-video/adapter.d.ts.map +1 -0
  326. package/dist/dev/playback/engines/background-video/adapter.js +158 -0
  327. package/dist/dev/playback/engines/background-video/adapter.js.map +1 -0
  328. package/dist/dev/playback/engines/background-video/engine.d.ts +106 -0
  329. package/dist/dev/playback/engines/background-video/engine.d.ts.map +1 -0
  330. package/dist/dev/playback/engines/background-video/engine.js +75 -0
  331. package/dist/dev/playback/engines/background-video/engine.js.map +1 -0
  332. package/dist/dev/playback/engines/hls/adapter-audio-only.d.ts +46 -0
  333. package/dist/dev/playback/engines/hls/adapter-audio-only.d.ts.map +1 -0
  334. package/dist/dev/playback/engines/hls/adapter-audio-only.js +124 -0
  335. package/dist/dev/playback/engines/hls/adapter-audio-only.js.map +1 -0
  336. package/dist/dev/playback/engines/hls/adapter.d.ts +3 -5
  337. package/dist/dev/playback/engines/hls/adapter.d.ts.map +1 -1
  338. package/dist/dev/playback/engines/hls/adapter.js +20 -11
  339. package/dist/dev/playback/engines/hls/adapter.js.map +1 -1
  340. package/dist/dev/playback/engines/hls/engine-audio-only.d.ts +156 -0
  341. package/dist/dev/playback/engines/hls/engine-audio-only.d.ts.map +1 -0
  342. package/dist/dev/playback/engines/hls/engine-audio-only.js +94 -0
  343. package/dist/dev/playback/engines/hls/engine-audio-only.js.map +1 -0
  344. package/dist/dev/playback/engines/hls/engine.d.ts +109 -4
  345. package/dist/dev/playback/engines/hls/engine.d.ts.map +1 -1
  346. package/dist/dev/playback/engines/hls/engine.js +38 -8
  347. package/dist/dev/playback/engines/hls/engine.js.map +1 -1
  348. package/dist/dev/playback/primitives/derive-start-media-time.d.ts +16 -0
  349. package/dist/dev/playback/primitives/derive-start-media-time.d.ts.map +1 -0
  350. package/dist/dev/playback/primitives/failover-fetch.js +42 -0
  351. package/dist/dev/playback/primitives/failover-fetch.js.map +1 -0
  352. package/dist/dev/playback/primitives/head-peek.js +44 -0
  353. package/dist/dev/playback/primitives/head-peek.js.map +1 -0
  354. package/dist/dev/playback/primitives/relocation-pipelines.js +203 -0
  355. package/dist/dev/playback/primitives/relocation-pipelines.js.map +1 -0
  356. package/dist/dev/playback/primitives/segment-load-pipeline.d.ts +2 -0
  357. package/dist/dev/playback/primitives/segment-load-pipeline.js +96 -0
  358. package/dist/dev/playback/primitives/segment-load-pipeline.js.map +1 -0
  359. package/dist/dev/playback/primitives/source-buffer-messages.d.ts +43 -0
  360. package/dist/dev/playback/primitives/source-buffer-messages.d.ts.map +1 -0
  361. package/dist/dev/playback/primitives/text-segment-load-pipeline.d.ts +65 -0
  362. package/dist/dev/playback/primitives/text-segment-load-pipeline.d.ts.map +1 -0
  363. package/dist/dev/playback/primitives/text-segment-load-pipeline.js +37 -0
  364. package/dist/dev/playback/primitives/text-segment-load-pipeline.js.map +1 -0
  365. package/dist/dev/playback/primitives/text-track-messages.d.ts +14 -0
  366. package/dist/dev/playback/primitives/text-track-messages.d.ts.map +1 -0
  367. package/dist/{default/playback/behaviors → dev/playback/primitives}/track-types.js +1 -1
  368. package/dist/dev/playback/primitives/track-types.js.map +1 -0
  369. package/package.json +17 -7
  370. package/dist/default/playback/behaviors/quality-switching.js +0 -96
  371. package/dist/default/playback/behaviors/quality-switching.js.map +0 -1
  372. package/dist/default/playback/behaviors/track-types.js.map +0 -1
  373. package/dist/dev/playback/behaviors/quality-switching.js +0 -96
  374. package/dist/dev/playback/behaviors/quality-switching.js.map +0 -1
  375. package/dist/dev/playback/behaviors/track-types.js.map +0 -1
@@ -0,0 +1,158 @@
1
+ import { maxResolutionToPixelArea, pickTrackUnderPixelArea } from "../../../media/primitives/select-tracks.js";
2
+ import { createBackgroundVideoEngine } from "./engine.js";
3
+ //#region src/playback/engines/background-video/adapter.ts
4
+ const backgroundVideoMediaDefaultProps = {
5
+ src: "",
6
+ preload: "auto",
7
+ loop: true,
8
+ muted: true,
9
+ autoplay: true,
10
+ maxResolution: void 0
11
+ };
12
+ /**
13
+ * Mixin that adds the background-video SPF playback engine to any
14
+ * base class.
15
+ *
16
+ * Implements the WHATWG HTML media element contract (`src`, `preload`,
17
+ * `loop`, `muted`, `autoplay`, `play()`) so it can be dropped in anywhere a
18
+ * media element API is expected. Compared to `SimpleHlsMediaMixin`, this
19
+ * variant:
20
+ *
21
+ * - exposes `loop`, `muted`, and `autoplay` as adapter-owned native
22
+ * passthroughs, all defaulting to `true` — the use case is silent
23
+ * autoplay-looping video, so muted + autoplay satisfy browser autoplay
24
+ * policies and loop is the defining behavior;
25
+ * - drives the underlying engine with the background-video
26
+ * composition (single-rendition, video-only, autoplay-from-construction).
27
+ *
28
+ * A new engine is created on every src assignment — this fully tears down
29
+ * all state, SourceBuffers, and in-flight requests from the previous
30
+ * source before the next one begins. The media element reference is
31
+ * preserved across src changes and re-applied to the new engine
32
+ * automatically.
33
+ *
34
+ * @example
35
+ * class BackgroundVideoMedia extends BackgroundVideoMediaMixin(HTMLVideoElementHost) {}
36
+ *
37
+ * const media = new BackgroundVideoMedia();
38
+ * media.attach(document.querySelector('video'));
39
+ * media.src = 'https://stream.mux.com/abc123.m3u8';
40
+ * media.play();
41
+ */
42
+ function BackgroundVideoMediaMixin(BaseClass) {
43
+ class BackgroundVideoMediaImpl extends BaseClass {
44
+ #engine;
45
+ #config;
46
+ #signals;
47
+ #preload = backgroundVideoMediaDefaultProps.preload;
48
+ #loop = backgroundVideoMediaDefaultProps.loop;
49
+ #muted = backgroundVideoMediaDefaultProps.muted;
50
+ #autoplay = backgroundVideoMediaDefaultProps.autoplay;
51
+ #maxResolution;
52
+ /** Pending loadstart listener from a deferred play() retry, if any. */
53
+ #loadstartListener = null;
54
+ constructor(...args) {
55
+ super(...args);
56
+ const { config } = args?.[0] ?? {};
57
+ this.#config = config;
58
+ this.#maxResolution = config?.maxResolution;
59
+ this.#engine = this.#createEngine();
60
+ }
61
+ get engine() {
62
+ return this.#engine;
63
+ }
64
+ attach(mediaElement) {
65
+ super.attach?.(mediaElement);
66
+ mediaElement.loop = this.#loop;
67
+ mediaElement.muted = this.#muted;
68
+ mediaElement.autoplay = this.#autoplay;
69
+ this.#signals.context.mediaElement.set(mediaElement);
70
+ }
71
+ detach() {
72
+ this.#cancelPendingPlay();
73
+ this.#signals.context.mediaElement.set(void 0);
74
+ super.detach?.();
75
+ }
76
+ destroy() {
77
+ this.#cancelPendingPlay();
78
+ this.#engine.destroy();
79
+ }
80
+ get preload() {
81
+ return this.#preload;
82
+ }
83
+ set preload(_value) {}
84
+ get loop() {
85
+ return this.#loop;
86
+ }
87
+ set loop(_value) {}
88
+ get muted() {
89
+ return this.#muted;
90
+ }
91
+ set muted(_value) {}
92
+ get autoplay() {
93
+ return this.#autoplay;
94
+ }
95
+ set autoplay(_value) {}
96
+ get maxResolution() {
97
+ return this.#maxResolution;
98
+ }
99
+ /**
100
+ * Set the cap. Accepts `"720p"` / `"1080p"` etc., a bare number
101
+ * (interpreted as pixel area), or `undefined` to clear. Unrecognized
102
+ * values are treated as no cap.
103
+ */
104
+ set maxResolution(value) {
105
+ if (value === this.#maxResolution) return;
106
+ this.#maxResolution = value;
107
+ }
108
+ get src() {
109
+ return this.#signals.state.presentation.get()?.url ?? "";
110
+ }
111
+ set src(value) {
112
+ this.#cancelPendingPlay();
113
+ if (value) this.#signals.state.presentation.set({ url: value });
114
+ else this.#signals.state.presentation.set(void 0);
115
+ }
116
+ async play() {
117
+ const mediaElement = this.#signals.context.mediaElement.get();
118
+ if (!mediaElement) return Promise.reject(/* @__PURE__ */ new Error("BackgroundVideoMediaElement: no media element attached"));
119
+ try {
120
+ return await mediaElement.play();
121
+ } catch (err) {
122
+ if (this.src) return new Promise((resolve, reject) => {
123
+ const listener = () => {
124
+ this.#loadstartListener = null;
125
+ mediaElement.play().then(resolve, reject);
126
+ };
127
+ this.#loadstartListener = listener;
128
+ mediaElement.addEventListener("loadstart", listener, { once: true });
129
+ });
130
+ throw err;
131
+ }
132
+ }
133
+ #createEngine() {
134
+ const adapterPicker = (presentation) => {
135
+ return pickTrackUnderPixelArea((presentation.selectionSets?.find((s) => s.type === "video"))?.switchingSets[0]?.tracks ?? [], maxResolutionToPixelArea(this.#maxResolution))?.id;
136
+ };
137
+ return createBackgroundVideoEngine({
138
+ picker: adapterPicker,
139
+ ...this.#config,
140
+ onSignalsReady: (signals) => {
141
+ this.#signals = signals;
142
+ }
143
+ });
144
+ }
145
+ #cancelPendingPlay() {
146
+ if (!this.#loadstartListener) return;
147
+ this.#signals.context.mediaElement.get()?.removeEventListener("loadstart", this.#loadstartListener);
148
+ this.#loadstartListener = null;
149
+ }
150
+ }
151
+ return BackgroundVideoMediaImpl;
152
+ }
153
+ /** Standalone SPF background-video adapter with no base class. */
154
+ var BackgroundVideoMediaElement = class extends BackgroundVideoMediaMixin(class {}) {};
155
+ //#endregion
156
+ export { BackgroundVideoMediaElement, BackgroundVideoMediaMixin, backgroundVideoMediaDefaultProps };
157
+
158
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","names":["#config","#maxResolution","#engine","#createEngine","#loop","#muted","#autoplay","#signals","#cancelPendingPlay","#preload","#loadstartListener"],"sources":["../../../../../src/playback/engines/background-video/adapter.ts"],"sourcesContent":["import type { Constructor, MixinReturn } from '@videojs/utils/types';\nimport type { Composition } from '../../../core/composition/create-composition';\nimport {\n maxResolutionToPixelArea,\n pickTrackUnderPixelArea,\n type TrackPicker,\n} from '../../../media/primitives/select-tracks';\nimport type { VideoSelectionSet } from '../../../media/types';\nimport {\n type BackgroundVideoEngineConfig,\n type BackgroundVideoEngineContext,\n type BackgroundVideoEngineSignals,\n type BackgroundVideoEngineState,\n createBackgroundVideoEngine,\n} from './engine';\n\nexport interface BackgroundVideoMediaProps {\n src: string;\n preload: '' | 'none' | 'metadata' | 'auto';\n loop: boolean;\n muted: boolean;\n autoplay: boolean;\n maxResolution: string | number | undefined;\n}\n\nexport const backgroundVideoMediaDefaultProps: BackgroundVideoMediaProps = {\n src: '',\n preload: 'auto',\n loop: true,\n muted: true,\n autoplay: true,\n maxResolution: undefined,\n};\n\nexport interface BackgroundVideoMediaAPI extends BackgroundVideoMediaProps {\n readonly engine: Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext>;\n attach(mediaElement: HTMLMediaElement): void;\n detach(): void;\n destroy(): void;\n play(): Promise<void>;\n}\n\n/**\n * Mixin that adds the background-video SPF playback engine to any\n * base class.\n *\n * Implements the WHATWG HTML media element contract (`src`, `preload`,\n * `loop`, `muted`, `autoplay`, `play()`) so it can be dropped in anywhere a\n * media element API is expected. Compared to `SimpleHlsMediaMixin`, this\n * variant:\n *\n * - exposes `loop`, `muted`, and `autoplay` as adapter-owned native\n * passthroughs, all defaulting to `true` — the use case is silent\n * autoplay-looping video, so muted + autoplay satisfy browser autoplay\n * policies and loop is the defining behavior;\n * - drives the underlying engine with the background-video\n * composition (single-rendition, video-only, autoplay-from-construction).\n *\n * A new engine is created on every src assignment — this fully tears down\n * all state, SourceBuffers, and in-flight requests from the previous\n * source before the next one begins. The media element reference is\n * preserved across src changes and re-applied to the new engine\n * automatically.\n *\n * @example\n * class BackgroundVideoMedia extends BackgroundVideoMediaMixin(HTMLVideoElementHost) {}\n *\n * const media = new BackgroundVideoMedia();\n * media.attach(document.querySelector('video'));\n * media.src = 'https://stream.mux.com/abc123.m3u8';\n * media.play();\n */\nexport function BackgroundVideoMediaMixin<Base extends Constructor<any>>(BaseClass: Base) {\n class BackgroundVideoMediaImpl extends BaseClass {\n #engine: Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext>;\n #config: BackgroundVideoEngineConfig;\n #signals!: BackgroundVideoEngineSignals;\n #preload: '' | 'none' | 'metadata' | 'auto' = backgroundVideoMediaDefaultProps.preload;\n #loop: boolean = backgroundVideoMediaDefaultProps.loop;\n #muted: boolean = backgroundVideoMediaDefaultProps.muted;\n #autoplay: boolean = backgroundVideoMediaDefaultProps.autoplay;\n #maxResolution: string | number | undefined;\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\n this.#maxResolution = config?.maxResolution;\n this.#engine = this.#createEngine();\n }\n\n get engine(): Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext> {\n return this.#engine;\n }\n\n // -------------------------------------------------------------------------\n // Media element lifecycle\n // -------------------------------------------------------------------------\n\n attach(mediaElement: HTMLMediaElement): void {\n super.attach?.(mediaElement);\n // Apply adapter-owned native props before the engine takes over —\n // the underlying element needs `loop` / `muted` / `autoplay` set for\n // the use case's autoplay-looping semantics.\n mediaElement.loop = this.#loop;\n mediaElement.muted = this.#muted;\n mediaElement.autoplay = this.#autoplay;\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.#engine.destroy();\n }\n\n // -------------------------------------------------------------------------\n // preload — synchronous IDL attribute (WHATWG §4.8.11.2)\n // -------------------------------------------------------------------------\n\n get preload(): '' | 'none' | 'metadata' | 'auto' {\n return this.#preload;\n }\n\n set preload(_value: '' | 'none' | 'metadata' | 'auto') {\n // Noop for this phase\n }\n\n // -------------------------------------------------------------------------\n // loop / muted / autoplay — adapter-owned IDL attributes mirrored onto\n // the attached media element. The engine itself has no opinion on any\n // of them.\n // -------------------------------------------------------------------------\n\n get loop(): boolean {\n return this.#loop;\n }\n\n set loop(_value: boolean) {\n // Noop for this phase\n }\n\n get muted(): boolean {\n return this.#muted;\n }\n\n set muted(_value: boolean) {\n // Noop for this phase\n }\n\n get autoplay(): boolean {\n return this.#autoplay;\n }\n\n set autoplay(_value: boolean) {\n // Noop for this phase\n }\n\n // -------------------------------------------------------------------------\n // maxResolution — adapter-owned cap on the picked rendition. The engine's\n // closure picker (see `#createEngine`) reads this field at pick time, so\n // setter writes take effect on the next `presentation-resolved` transition\n // without an engine rebuild.\n // -------------------------------------------------------------------------\n\n get maxResolution(): string | number | undefined {\n return this.#maxResolution;\n }\n\n /**\n * Set the cap. Accepts `\"720p\"` / `\"1080p\"` etc., a bare number\n * (interpreted as pixel area), or `undefined` to clear. Unrecognized\n * values are treated as no cap.\n */\n set maxResolution(value: string | number | undefined) {\n if (value === this.#maxResolution) return;\n this.#maxResolution = value;\n }\n\n // -------------------------------------------------------------------------\n // src — synchronous IDL attribute (WHATWG §4.8.11.2)\n // Each assignment destroys the current engine and starts a fresh one,\n // matching the browser's load algorithm reset on src change.\n // -------------------------------------------------------------------------\n\n get src(): string {\n return this.#signals.state.presentation.get()?.url ?? '';\n }\n\n set src(value: string) {\n this.#cancelPendingPlay();\n\n if (value) {\n this.#signals.state.presentation.set({ url: value });\n } else {\n this.#signals.state.presentation.set(undefined);\n }\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('BackgroundVideoMediaElement: 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\n // by 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 const adapterPicker: TrackPicker = (presentation) => {\n const videoSet = presentation.selectionSets?.find((s) => s.type === 'video') as VideoSelectionSet | undefined;\n const tracks = videoSet?.switchingSets[0]?.tracks ?? [];\n return pickTrackUnderPixelArea(tracks, maxResolutionToPixelArea(this.#maxResolution))?.id;\n };\n\n return createBackgroundVideoEngine({\n picker: adapterPicker,\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 BackgroundVideoMediaImpl as unknown as MixinReturn<Base, BackgroundVideoMediaAPI>;\n}\n\n/** Standalone SPF background-video adapter with no base class. */\nexport class BackgroundVideoMediaElement extends BackgroundVideoMediaMixin(class {}) {}\n"],"mappings":";;;AAyBA,MAAa,mCAA8D;CACzE,KAAK;CACL,SAAS;CACT,MAAM;CACN,OAAO;CACP,UAAU;CACV,eAAe,KAAA;AACjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,0BAAyD,WAAiB;CACxF,MAAM,iCAAiC,UAAU;EAC/C;EACA;EACA;EACA,WAA8C,iCAAiC;EAC/E,QAAiB,iCAAiC;EAClD,SAAkB,iCAAiC;EACnD,YAAqB,iCAAiC;EACtD;;EAGA,qBAA0C;EAE1C,YAAY,GAAG,MAAa;GAC1B,MAAM,GAAG,IAAI;GAEb,MAAM,EAAE,WAAW,OAAO,MAAM,CAAC;GACjC,KAAKA,UAAU;GAEf,KAAKC,iBAAiB,QAAQ;GAC9B,KAAKC,UAAU,KAAKC,cAAc;EACpC;EAEA,IAAI,SAAgF;GAClF,OAAO,KAAKD;EACd;EAMA,OAAO,cAAsC;GAC3C,MAAM,SAAS,YAAY;GAI3B,aAAa,OAAO,KAAKE;GACzB,aAAa,QAAQ,KAAKC;GAC1B,aAAa,WAAW,KAAKC;GAE7B,KAAKC,SAAS,QAAQ,aAAa,IAAI,YAAY;EACrD;EAEA,SAAe;GACb,KAAKC,mBAAmB;GACxB,KAAKD,SAAS,QAAQ,aAAa,IAAI,KAAA,CAAS;GAChD,MAAM,SAAS;EACjB;EAEA,UAAgB;GACd,KAAKC,mBAAmB;GACxB,KAAKN,QAAQ,QAAQ;EACvB;EAMA,IAAI,UAA6C;GAC/C,OAAO,KAAKO;EACd;EAEA,IAAI,QAAQ,QAA2C,CAEvD;EAQA,IAAI,OAAgB;GAClB,OAAO,KAAKL;EACd;EAEA,IAAI,KAAK,QAAiB,CAE1B;EAEA,IAAI,QAAiB;GACnB,OAAO,KAAKC;EACd;EAEA,IAAI,MAAM,QAAiB,CAE3B;EAEA,IAAI,WAAoB;GACtB,OAAO,KAAKC;EACd;EAEA,IAAI,SAAS,QAAiB,CAE9B;EASA,IAAI,gBAA6C;GAC/C,OAAO,KAAKL;EACd;;;;;;EAOA,IAAI,cAAc,OAAoC;GACpD,IAAI,UAAU,KAAKA,gBAAgB;GACnC,KAAKA,iBAAiB;EACxB;EAQA,IAAI,MAAc;GAChB,OAAO,KAAKM,SAAS,MAAM,aAAa,IAAI,CAAC,EAAE,OAAO;EACxD;EAEA,IAAI,IAAI,OAAe;GACrB,KAAKC,mBAAmB;GAExB,IAAI,OACF,KAAKD,SAAS,MAAM,aAAa,IAAI,EAAE,KAAK,MAAM,CAAC;QAEnD,KAAKA,SAAS,MAAM,aAAa,IAAI,KAAA,CAAS;EAElD;EAOA,MAAM,OAAsB;GAC1B,MAAM,eAAe,KAAKA,SAAS,QAAQ,aAAa,IAAI;GAC5D,IAAI,CAAC,cACH,OAAO,QAAQ,uBAAO,IAAI,MAAM,wDAAwD,CAAC;GAG3F,IAAI;IACF,OAAO,MAAM,aAAa,KAAK;GACjC,SAAS,KAAK;IAIZ,IAAI,KAAK,KACP,OAAO,IAAI,SAAe,SAAS,WAAW;KAC5C,MAAM,iBAAiB;MACrB,KAAKG,qBAAqB;MAC1B,aAAa,KAAK,CAAC,CAAC,KAAK,SAAS,MAAM;KAC1C;KACA,KAAKA,qBAAqB;KAC1B,aAAa,iBAAiB,aAAa,UAAU,EAAE,MAAM,KAAK,CAAC;IACrE,CAAC;IAEH,MAAM;GACR;EACF;EAMA,gBAAuF;GACrF,MAAM,iBAA8B,iBAAiB;IAGnD,OAAO,yBAFU,aAAa,eAAe,MAAM,MAAM,EAAE,SAAS,OAAO,EAAA,EAClD,cAAc,EAAE,EAAE,UAAU,CAAC,GACf,yBAAyB,KAAKT,cAAc,CAAC,CAAC,EAAE;GACzF;GAEA,OAAO,4BAA4B;IACjC,QAAQ;IACR,GAAG,KAAKD;IACR,iBAAiB,YAAY;KAC3B,KAAKO,WAAW;IAClB;GACF,CAAC;EACH;EAEA,qBAA2B;GACzB,IAAI,CAAC,KAAKG,oBAAoB;GAE9B,KAD0BH,SAAS,QAAQ,aAAa,IAC7C,CAAC,EAAE,oBAAoB,aAAa,KAAKG,kBAAkB;GACtE,KAAKA,qBAAqB;EAC5B;CACF;CAEA,OAAO;AACT;;AAGA,IAAa,8BAAb,cAAiD,0BAA0B,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,106 @@
1
+ import { MaybeResolvedPresentation } from "../../../media/types/index.js";
2
+ import { Composition, ContextSignals, StateSignals } from "../../../core/composition/create-composition.js";
3
+ import { ShareSignalsConfig } from "../../../core/composition/share-signals.js";
4
+ import { SourceBufferActor } from "../../actors/dom/source-buffer.js";
5
+ import { SegmentLoaderActor } from "../../actors/dom/segment-loader.js";
6
+ import { TrackPicker } from "../../../media/primitives/select-tracks.js";
7
+ import { ParsePresentation } from "../../behaviors/resolve-presentation.js";
8
+ import { SelectVideoTrackConfig } from "../../behaviors/select-tracks.js";
9
+ //#region src/playback/engines/background-video/engine.d.ts
10
+ /**
11
+ * State shape for the background-video playback engine.
12
+ *
13
+ * Narrower than `SimpleHlsEngineState`: audio/text track slots are absent
14
+ * because their selection/resolution behaviors are subtracted. `bandwidthState`
15
+ * is present because `setupVideoBufferActors` declares it and `loadVideoSegments`
16
+ * samples into it (wasted work in this variant — a Phase 3 alt-impl will skip
17
+ * sampling).
18
+ */
19
+ interface BackgroundVideoEngineState {
20
+ /**
21
+ * The presentation being played. A caller writes `{ url }`;
22
+ * `resolvePresentation` parses the manifest and populates the rest.
23
+ */
24
+ presentation?: MaybeResolvedPresentation;
25
+ preload?: 'auto' | 'metadata' | 'none';
26
+ selectedVideoTrackId?: string;
27
+ loadActivated?: boolean;
28
+ }
29
+ /**
30
+ * Context shape for the background-video engine.
31
+ */
32
+ interface BackgroundVideoEngineContext {
33
+ mediaElement?: HTMLMediaElement | undefined;
34
+ mediaSource?: MediaSource;
35
+ videoBufferActor?: SourceBufferActor;
36
+ videoSegmentLoaderActor?: SegmentLoaderActor;
37
+ }
38
+ /**
39
+ * The composition signal refs handed to `onSignalsReady` callers — the
40
+ * canonical way to drive the engine externally (writes) or observe its
41
+ * state (reads) without touching `composition.state` / `composition.context`
42
+ * directly.
43
+ */
44
+ type BackgroundVideoEngineSignals = {
45
+ state: StateSignals<BackgroundVideoEngineState>;
46
+ context: ContextSignals<BackgroundVideoEngineContext>;
47
+ };
48
+ /**
49
+ * Configuration for the background-video engine.
50
+ *
51
+ * Each option is consumed by the appropriate behavior — the engine itself
52
+ * has no config beyond what its behaviors read. Compared to
53
+ * `SimpleHlsEngineConfig`, audio/text/ABR/bandwidth/quality knobs are
54
+ * dropped: the variant subtracts the behaviors that read them.
55
+ */
56
+ interface BackgroundVideoEngineConfig extends ShareSignalsConfig<BackgroundVideoEngineState, BackgroundVideoEngineContext> {
57
+ /**
58
+ * Track picker handed to `selectVideoTrack`. Default:
59
+ * `pickHighestResolutionVideoTrack` — picks the highest-resolution variant on
60
+ * presentation resolve and pins it for the session. Override for
61
+ * mobile-aware or content-aware caps.
62
+ *
63
+ * Adapters (e.g. `BackgroundVideoMediaElement`) install their own
64
+ * picker; this default applies when the engine is constructed directly.
65
+ */
66
+ picker?: TrackPicker<SelectVideoTrackConfig>;
67
+ /**
68
+ * Manifest parser handed to `resolvePresentation`. Defaults to the HLS
69
+ * multivariant-playlist parser.
70
+ */
71
+ parsePresentation?: ParsePresentation;
72
+ }
73
+ /**
74
+ * Create a background-video playback engine.
75
+ *
76
+ * Subtractive composition over the HLS engine baseline:
77
+ * audio-side, text-side, ABR-driven, preload-monitoring, and play/seek
78
+ * load-trigger behaviors are removed. `selectVideoTrack` (with a
79
+ * max-resolution picker by default) replaces `switchVideoQuality`, pinning
80
+ * a single rendition for the session. The initial state seeds
81
+ * `loadActivated: true` so the composition behaves as if preload has
82
+ * already been activated — appropriate for ambient / hero / GIF-replacement
83
+ * surfaces that should start loading the moment a src is set.
84
+ *
85
+ * Native `loop` / `muted` / `autoplay` are adapter concerns and live on
86
+ * `BackgroundVideoMediaElement` rather than the engine.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * let signals: BackgroundVideoEngineSignals;
91
+ * const engine = createBackgroundVideoEngine({
92
+ * onSignalsReady: (refs) => {
93
+ * signals = refs;
94
+ * },
95
+ * });
96
+ *
97
+ * signals.context.mediaElement.set(videoEl);
98
+ * signals.state.presentation.set({ url: 'https://example.com/stream.m3u8' });
99
+ *
100
+ * await engine.destroy();
101
+ * ```
102
+ */
103
+ declare function createBackgroundVideoEngine(config?: BackgroundVideoEngineConfig): Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext>;
104
+ //#endregion
105
+ export { BackgroundVideoEngineConfig, BackgroundVideoEngineContext, BackgroundVideoEngineSignals, BackgroundVideoEngineState, createBackgroundVideoEngine };
106
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","names":[],"sources":["../../../../../src/playback/engines/background-video/engine.ts"],"mappings":";;;;;;;;;;;;;;;;;;UAqCiB;;;;;EAKf,eAAe;EACf;EACA;EACA;;;;;UAMe;EACf,eAAe;EACf,cAAc;EACd,mBAAmB;EACnB,0BAA0B;;;;;;;;KAShB;EACV,OAAO,aAAa;EACpB,SAAS,eAAe;;;;;;;;;;UAWT,oCACP,mBAAmB,4BAA4B;;;;;;;;;;EAUvD,SAAS,YAAY;;;;;EAKrB,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuCN,4BACd,SAAQ,8BACP,YAAY,4BAA4B"}
@@ -0,0 +1,75 @@
1
+ import { createComposition } from "../../../core/composition/create-composition.js";
2
+ import { makeShareSignals } from "../../../core/composition/share-signals.js";
3
+ import { loadVideoSegments } from "../../behaviors/dom/load-segments.js";
4
+ import { trackCurrentTime } from "../../behaviors/dom/track-current-time.js";
5
+ import { parseMultivariantPlaylist } from "../../../media/hls/parse-multivariant.js";
6
+ import { getResolvedSelectedTrackDuration } from "../../../media/utils/track-selection.js";
7
+ import { calculatePresentationDuration } from "../../behaviors/calculate-presentation-duration.js";
8
+ import { endOfStream } from "../../behaviors/dom/end-of-stream.js";
9
+ import { setupVideoBufferActors } from "../../behaviors/dom/setup-buffer-actors.js";
10
+ import { setupMediaSource } from "../../behaviors/dom/setup-mediasource.js";
11
+ import { updateMediaSourceDuration } from "../../behaviors/dom/update-mediasource-duration.js";
12
+ import { resolvePresentation } from "../../behaviors/resolve-presentation.js";
13
+ import { resolveVideoTrack } from "../../behaviors/resolve-track.js";
14
+ import { pickHighestResolutionVideoTrack } from "../../../media/primitives/select-tracks.js";
15
+ import { selectVideoTrack } from "../../behaviors/select-tracks.js";
16
+ //#region src/playback/engines/background-video/engine.ts
17
+ const shareSignals = makeShareSignals();
18
+ /**
19
+ * Create a background-video playback engine.
20
+ *
21
+ * Subtractive composition over the HLS engine baseline:
22
+ * audio-side, text-side, ABR-driven, preload-monitoring, and play/seek
23
+ * load-trigger behaviors are removed. `selectVideoTrack` (with a
24
+ * max-resolution picker by default) replaces `switchVideoQuality`, pinning
25
+ * a single rendition for the session. The initial state seeds
26
+ * `loadActivated: true` so the composition behaves as if preload has
27
+ * already been activated — appropriate for ambient / hero / GIF-replacement
28
+ * surfaces that should start loading the moment a src is set.
29
+ *
30
+ * Native `loop` / `muted` / `autoplay` are adapter concerns and live on
31
+ * `BackgroundVideoMediaElement` rather than the engine.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * let signals: BackgroundVideoEngineSignals;
36
+ * const engine = createBackgroundVideoEngine({
37
+ * onSignalsReady: (refs) => {
38
+ * signals = refs;
39
+ * },
40
+ * });
41
+ *
42
+ * signals.context.mediaElement.set(videoEl);
43
+ * signals.state.presentation.set({ url: 'https://example.com/stream.m3u8' });
44
+ *
45
+ * await engine.destroy();
46
+ * ```
47
+ */
48
+ function createBackgroundVideoEngine(config = {}) {
49
+ const finalConfig = {
50
+ ...config,
51
+ picker: config.picker ?? pickHighestResolutionVideoTrack,
52
+ parsePresentation: config.parsePresentation ?? parseMultivariantPlaylist,
53
+ resolveDuration: getResolvedSelectedTrackDuration
54
+ };
55
+ return createComposition([
56
+ resolvePresentation,
57
+ calculatePresentationDuration,
58
+ selectVideoTrack,
59
+ resolveVideoTrack,
60
+ loadVideoSegments,
61
+ setupMediaSource,
62
+ updateMediaSourceDuration,
63
+ setupVideoBufferActors,
64
+ trackCurrentTime,
65
+ endOfStream,
66
+ shareSignals
67
+ ], {
68
+ config: finalConfig,
69
+ initialState: { loadActivated: true }
70
+ });
71
+ }
72
+ //#endregion
73
+ export { createBackgroundVideoEngine };
74
+
75
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","names":[],"sources":["../../../../../src/playback/engines/background-video/engine.ts"],"sourcesContent":["import {\n type Composition,\n type ContextSignals,\n createComposition,\n type StateSignals,\n} from '../../../core/composition/create-composition';\nimport { makeShareSignals, type ShareSignalsConfig } from '../../../core/composition/share-signals';\nimport { parseMultivariantPlaylist } from '../../../media/hls/parse-multivariant';\nimport { pickHighestResolutionVideoTrack, type TrackPicker } from '../../../media/primitives/select-tracks';\nimport type { MaybeResolvedPresentation } from '../../../media/types';\nimport { getResolvedSelectedTrackDuration } from '../../../media/utils/track-selection';\nimport type { SegmentLoaderActor } from '../../actors/dom/segment-loader';\nimport type { SourceBufferActor } from '../../actors/dom/source-buffer';\nimport { calculatePresentationDuration } from '../../behaviors/calculate-presentation-duration';\nimport { endOfStream } from '../../behaviors/dom/end-of-stream';\nimport { loadVideoSegments } from '../../behaviors/dom/load-segments';\nimport { setupVideoBufferActors } from '../../behaviors/dom/setup-buffer-actors';\nimport { setupMediaSource } from '../../behaviors/dom/setup-mediasource';\nimport { trackCurrentTime } from '../../behaviors/dom/track-current-time';\nimport { updateMediaSourceDuration } from '../../behaviors/dom/update-mediasource-duration';\nimport { type ParsePresentation, resolvePresentation } from '../../behaviors/resolve-presentation';\nimport { resolveVideoTrack } from '../../behaviors/resolve-track';\nimport { type SelectVideoTrackConfig, selectVideoTrack } from '../../behaviors/select-tracks';\n\n// ============================================================================\n// Background-video engine state & context\n// ============================================================================\n\n/**\n * State shape for the background-video playback engine.\n *\n * Narrower than `SimpleHlsEngineState`: audio/text track slots are absent\n * because their selection/resolution behaviors are subtracted. `bandwidthState`\n * is present because `setupVideoBufferActors` declares it and `loadVideoSegments`\n * samples into it (wasted work in this variant — a Phase 3 alt-impl will skip\n * sampling).\n */\nexport interface BackgroundVideoEngineState {\n /**\n * The presentation being played. A caller writes `{ url }`;\n * `resolvePresentation` parses the manifest and populates the rest.\n */\n presentation?: MaybeResolvedPresentation;\n preload?: 'auto' | 'metadata' | 'none';\n selectedVideoTrackId?: string;\n loadActivated?: boolean;\n}\n\n/**\n * Context shape for the background-video engine.\n */\nexport interface BackgroundVideoEngineContext {\n mediaElement?: HTMLMediaElement | undefined;\n mediaSource?: MediaSource;\n videoBufferActor?: SourceBufferActor;\n videoSegmentLoaderActor?: SegmentLoaderActor;\n}\n\n/**\n * The composition signal refs handed to `onSignalsReady` callers — the\n * canonical way to drive the engine externally (writes) or observe its\n * state (reads) without touching `composition.state` / `composition.context`\n * directly.\n */\nexport type BackgroundVideoEngineSignals = {\n state: StateSignals<BackgroundVideoEngineState>;\n context: ContextSignals<BackgroundVideoEngineContext>;\n};\n\n/**\n * Configuration for the background-video engine.\n *\n * Each option is consumed by the appropriate behavior — the engine itself\n * has no config beyond what its behaviors read. Compared to\n * `SimpleHlsEngineConfig`, audio/text/ABR/bandwidth/quality knobs are\n * dropped: the variant subtracts the behaviors that read them.\n */\nexport interface BackgroundVideoEngineConfig\n extends ShareSignalsConfig<BackgroundVideoEngineState, BackgroundVideoEngineContext> {\n /**\n * Track picker handed to `selectVideoTrack`. Default:\n * `pickHighestResolutionVideoTrack` — picks the highest-resolution variant on\n * presentation resolve and pins it for the session. Override for\n * mobile-aware or content-aware caps.\n *\n * Adapters (e.g. `BackgroundVideoMediaElement`) install their own\n * picker; this default applies when the engine is constructed directly.\n */\n picker?: TrackPicker<SelectVideoTrackConfig>;\n /**\n * Manifest parser handed to `resolvePresentation`. Defaults to the HLS\n * multivariant-playlist parser.\n */\n parsePresentation?: ParsePresentation;\n}\n\n// ============================================================================\n// Background-video playback engine\n// ============================================================================\n\nconst shareSignals = makeShareSignals<BackgroundVideoEngineState, BackgroundVideoEngineContext>();\n\n/**\n * Create a background-video playback engine.\n *\n * Subtractive composition over the HLS engine baseline:\n * audio-side, text-side, ABR-driven, preload-monitoring, and play/seek\n * load-trigger behaviors are removed. `selectVideoTrack` (with a\n * max-resolution picker by default) replaces `switchVideoQuality`, pinning\n * a single rendition for the session. The initial state seeds\n * `loadActivated: true` so the composition behaves as if preload has\n * already been activated — appropriate for ambient / hero / GIF-replacement\n * surfaces that should start loading the moment a src is set.\n *\n * Native `loop` / `muted` / `autoplay` are adapter concerns and live on\n * `BackgroundVideoMediaElement` rather than the engine.\n *\n * @example\n * ```ts\n * let signals: BackgroundVideoEngineSignals;\n * const engine = createBackgroundVideoEngine({\n * onSignalsReady: (refs) => {\n * signals = refs;\n * },\n * });\n *\n * signals.context.mediaElement.set(videoEl);\n * signals.state.presentation.set({ url: 'https://example.com/stream.m3u8' });\n *\n * await engine.destroy();\n * ```\n */\nexport function createBackgroundVideoEngine(\n config: BackgroundVideoEngineConfig = {}\n): Composition<BackgroundVideoEngineState, BackgroundVideoEngineContext> {\n const finalConfig = {\n ...config,\n picker: config.picker ?? pickHighestResolutionVideoTrack,\n parsePresentation: config.parsePresentation ?? parseMultivariantPlaylist,\n resolveDuration: getResolvedSelectedTrackDuration,\n };\n\n return createComposition(\n [\n resolvePresentation,\n // Presentation duration\n calculatePresentationDuration,\n\n // Track selection - pinned single-rendition pick on presentation resolve.\n selectVideoTrack,\n // Resolve selected video track (fetch its media playlist)\n resolveVideoTrack,\n // Segment loading — video-only.\n loadVideoSegments,\n\n // MSE setup — video-only.\n setupMediaSource,\n updateMediaSourceDuration,\n setupVideoBufferActors,\n\n // Playback tracking\n trackCurrentTime,\n\n // End of stream coordination\n endOfStream,\n\n // Behavior whose sole purpose is to expose signal refs via a callback\n // (e.g. to an adapter). Listed last so initial signal setup has run\n // before the callback fires.\n shareSignals,\n ],\n {\n config: finalConfig,\n initialState: {\n // Note: Set to true until we add preload configuration\n loadActivated: true,\n },\n }\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAoGA,MAAM,eAAe,iBAA2E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgChG,SAAgB,4BACd,SAAsC,CAAC,GACgC;CACvE,MAAM,cAAc;EAClB,GAAG;EACH,QAAQ,OAAO,UAAU;EACzB,mBAAmB,OAAO,qBAAqB;EAC/C,iBAAiB;CACnB;CAEA,OAAO,kBACL;EACE;EAEA;EAGA;EAEA;EAEA;EAGA;EACA;EACA;EAGA;EAGA;EAKA;CACF,GACA;EACE,QAAQ;EACR,cAAc,EAEZ,eAAe,KACjB;CACF,CACF;AACF"}
@@ -0,0 +1,46 @@
1
+ import { Composition } from "../../../core/composition/create-composition.js";
2
+ import { SimpleHlsAudioOnlyEngineContext, SimpleHlsAudioOnlyEngineState } from "./engine-audio-only.js";
3
+ import { Constructor, MixinReturn } from "@videojs/utils/types";
4
+ //#region src/playback/engines/hls/adapter-audio-only.d.ts
5
+ interface SimpleHlsAudioOnlyMediaProps {
6
+ src: string;
7
+ preload: '' | 'none' | 'metadata' | 'auto';
8
+ disableRemotePlayback: boolean;
9
+ }
10
+ declare const simpleHlsAudioOnlyMediaDefaultProps: SimpleHlsAudioOnlyMediaProps;
11
+ interface SimpleHlsAudioOnlyMediaAPI extends SimpleHlsAudioOnlyMediaProps {
12
+ readonly engine: Composition<SimpleHlsAudioOnlyEngineState, SimpleHlsAudioOnlyEngineContext>;
13
+ attach(mediaElement: HTMLMediaElement): void;
14
+ detach(): void;
15
+ destroy(): void;
16
+ play(): Promise<void>;
17
+ }
18
+ /**
19
+ * Mixin that adds SPF audio-only HLS playback to any base class.
20
+ *
21
+ * Parallel to `SimpleHlsMediaMixin` with one substantive difference: the
22
+ * underlying engine is the audio-only variant (`createHlsAudioOnlyEngine`),
23
+ * which omits video and text-track behaviors. The src / preload /
24
+ * disableRemotePlayback / play() contract per the WHATWG HTML spec is identical
25
+ * to the default adapter.
26
+ *
27
+ * Selecting this adapter is the variant decision: instantiating
28
+ * `SimpleHlsAudioOnlyMediaElement` opts the consumer into audio-only
29
+ * delivery even when the source is a mixed-AV HLS manifest.
30
+ *
31
+ * @example
32
+ * class SimpleHlsAudioOnlyMedia extends SimpleHlsAudioOnlyMediaMixin(HTMLVideoElementHost) {}
33
+ *
34
+ * const media = new SimpleHlsAudioOnlyMedia();
35
+ * media.attach(document.querySelector('video'));
36
+ * media.src = 'https://stream.mux.com/abc123.m3u8';
37
+ */
38
+ declare function SimpleHlsAudioOnlyMediaMixin<Base extends Constructor<any>>(BaseClass: Base): MixinReturn<Base, SimpleHlsAudioOnlyMediaAPI>;
39
+ declare const SimpleHlsAudioOnlyMediaElement_base: MixinReturn<{
40
+ new (): {};
41
+ }, SimpleHlsAudioOnlyMediaAPI>;
42
+ /** Standalone SPF audio-only media adapter with no base class. */
43
+ declare class SimpleHlsAudioOnlyMediaElement extends SimpleHlsAudioOnlyMediaElement_base {}
44
+ //#endregion
45
+ export { SimpleHlsAudioOnlyMediaAPI, SimpleHlsAudioOnlyMediaElement, SimpleHlsAudioOnlyMediaMixin, SimpleHlsAudioOnlyMediaProps, simpleHlsAudioOnlyMediaDefaultProps };
46
+ //# sourceMappingURL=adapter-audio-only.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-audio-only.d.ts","names":[],"sources":["../../../../../src/playback/engines/hls/adapter-audio-only.ts"],"mappings":";;;;UAUiB;EACf;EACA;EACA;;cAGW,qCAAqC;UAMjC,mCAAmC;WACzC,QAAQ,YAAY,+BAA+B;EAC5D,OAAO,cAAc;EACrB;EACA;EACA,QAAQ;;;;;;;;;;;;;;;;;;;;;;iBAuBM,6BAA6B,aAAa,kBAAkB,WAAW,OAuJpC,YAAY,MAAM;;;;;cAIxD,uCAAuC"}
@@ -0,0 +1,124 @@
1
+ import { createHlsAudioOnlyEngine } from "./engine-audio-only.js";
2
+ //#region src/playback/engines/hls/adapter-audio-only.ts
3
+ const simpleHlsAudioOnlyMediaDefaultProps = {
4
+ src: "",
5
+ preload: "",
6
+ disableRemotePlayback: false
7
+ };
8
+ /**
9
+ * Mixin that adds SPF audio-only HLS playback to any base class.
10
+ *
11
+ * Parallel to `SimpleHlsMediaMixin` with one substantive difference: the
12
+ * underlying engine is the audio-only variant (`createHlsAudioOnlyEngine`),
13
+ * which omits video and text-track behaviors. The src / preload /
14
+ * disableRemotePlayback / play() contract per the WHATWG HTML spec is identical
15
+ * to the default adapter.
16
+ *
17
+ * Selecting this adapter is the variant decision: instantiating
18
+ * `SimpleHlsAudioOnlyMediaElement` opts the consumer into audio-only
19
+ * delivery even when the source is a mixed-AV HLS manifest.
20
+ *
21
+ * @example
22
+ * class SimpleHlsAudioOnlyMedia extends SimpleHlsAudioOnlyMediaMixin(HTMLVideoElementHost) {}
23
+ *
24
+ * const media = new SimpleHlsAudioOnlyMedia();
25
+ * media.attach(document.querySelector('video'));
26
+ * media.src = 'https://stream.mux.com/abc123.m3u8';
27
+ */
28
+ function SimpleHlsAudioOnlyMediaMixin(BaseClass) {
29
+ class SimpleHlsAudioOnlyMediaImpl extends BaseClass {
30
+ #engine;
31
+ #config;
32
+ #signals;
33
+ #preload = simpleHlsAudioOnlyMediaDefaultProps.preload;
34
+ #disableRemotePlayback = simpleHlsAudioOnlyMediaDefaultProps.disableRemotePlayback;
35
+ /** Pending loadstart listener from a deferred play() retry, if any. */
36
+ #loadstartListener = null;
37
+ constructor(...args) {
38
+ super(...args);
39
+ const { config } = args?.[0] ?? {};
40
+ this.#config = config;
41
+ this.#engine = this.#createEngine();
42
+ }
43
+ /**
44
+ * Underlying playback engine — the low-level SPF reactive composition that
45
+ * drives playback. An advanced escape hatch for direct engine access;
46
+ * normal playback is driven through this element's own properties and
47
+ * methods.
48
+ */
49
+ get engine() {
50
+ return this.#engine;
51
+ }
52
+ attach(mediaElement) {
53
+ super.attach?.(mediaElement);
54
+ this.#signals.context.mediaElement.set(mediaElement);
55
+ }
56
+ detach() {
57
+ this.#cancelPendingPlay();
58
+ this.#signals.context.mediaElement.set(void 0);
59
+ super.detach?.();
60
+ }
61
+ destroy() {
62
+ this.#cancelPendingPlay();
63
+ this.#engine.destroy();
64
+ }
65
+ /** Preload type (`'none'` / `'metadata'` / `'auto'`). */
66
+ get preload() {
67
+ return this.#preload;
68
+ }
69
+ set preload(value) {
70
+ this.#preload = value;
71
+ if (value) this.#signals.state.preload.set(value);
72
+ }
73
+ get disableRemotePlayback() {
74
+ return this.#disableRemotePlayback;
75
+ }
76
+ set disableRemotePlayback(value) {
77
+ this.#disableRemotePlayback = value;
78
+ this.#signals.state.disableRemotePlayback.set(value);
79
+ }
80
+ get src() {
81
+ return this.#signals.state.presentation.get()?.url ?? "";
82
+ }
83
+ set src(value) {
84
+ this.#cancelPendingPlay();
85
+ this.#signals.state.presentation.set(value ? { url: value } : void 0);
86
+ }
87
+ play() {
88
+ const mediaElement = this.#signals.context.mediaElement.get();
89
+ if (!mediaElement) return Promise.reject(/* @__PURE__ */ new Error("SimpleHlsAudioOnlyMediaElement: no media element attached"));
90
+ this.#signals.state.loadActivated.set(true);
91
+ return mediaElement.play().catch((err) => {
92
+ if (this.src) return new Promise((resolve, reject) => {
93
+ const listener = () => {
94
+ this.#loadstartListener = null;
95
+ mediaElement.play().then(resolve, reject);
96
+ };
97
+ this.#loadstartListener = listener;
98
+ mediaElement.addEventListener("loadstart", listener, { once: true });
99
+ });
100
+ throw err;
101
+ });
102
+ }
103
+ #createEngine() {
104
+ return createHlsAudioOnlyEngine({
105
+ ...this.#config,
106
+ onSignalsReady: (signals) => {
107
+ this.#signals = signals;
108
+ }
109
+ });
110
+ }
111
+ #cancelPendingPlay() {
112
+ if (!this.#loadstartListener) return;
113
+ this.#signals.context.mediaElement.get()?.removeEventListener("loadstart", this.#loadstartListener);
114
+ this.#loadstartListener = null;
115
+ }
116
+ }
117
+ return SimpleHlsAudioOnlyMediaImpl;
118
+ }
119
+ /** Standalone SPF audio-only media adapter with no base class. */
120
+ var SimpleHlsAudioOnlyMediaElement = class extends SimpleHlsAudioOnlyMediaMixin(class {}) {};
121
+ //#endregion
122
+ export { SimpleHlsAudioOnlyMediaElement, SimpleHlsAudioOnlyMediaMixin, simpleHlsAudioOnlyMediaDefaultProps };
123
+
124
+ //# sourceMappingURL=adapter-audio-only.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-audio-only.js","names":["#engine","#config","#createEngine","#signals","#cancelPendingPlay","#preload","#disableRemotePlayback","#loadstartListener"],"sources":["../../../../../src/playback/engines/hls/adapter-audio-only.ts"],"sourcesContent":["import type { Constructor, MixinReturn } from '@videojs/utils/types';\nimport type { Composition } from '../../../core/composition/create-composition';\nimport {\n createHlsAudioOnlyEngine,\n type SimpleHlsAudioOnlyEngineConfig,\n type SimpleHlsAudioOnlyEngineContext,\n type SimpleHlsAudioOnlyEngineSignals,\n type SimpleHlsAudioOnlyEngineState,\n} from './engine-audio-only';\n\nexport interface SimpleHlsAudioOnlyMediaProps {\n src: string;\n preload: '' | 'none' | 'metadata' | 'auto';\n disableRemotePlayback: boolean;\n}\n\nexport const simpleHlsAudioOnlyMediaDefaultProps: SimpleHlsAudioOnlyMediaProps = {\n src: '',\n preload: '',\n disableRemotePlayback: false,\n};\n\nexport interface SimpleHlsAudioOnlyMediaAPI extends SimpleHlsAudioOnlyMediaProps {\n readonly engine: Composition<SimpleHlsAudioOnlyEngineState, SimpleHlsAudioOnlyEngineContext>;\n attach(mediaElement: HTMLMediaElement): void;\n detach(): void;\n destroy(): void;\n play(): Promise<void>;\n}\n\n/**\n * Mixin that adds SPF audio-only HLS playback to any base class.\n *\n * Parallel to `SimpleHlsMediaMixin` with one substantive difference: the\n * underlying engine is the audio-only variant (`createHlsAudioOnlyEngine`),\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 * `SimpleHlsAudioOnlyMediaElement` opts the consumer into audio-only\n * delivery even when the source is a mixed-AV HLS manifest.\n *\n * @example\n * class SimpleHlsAudioOnlyMedia extends SimpleHlsAudioOnlyMediaMixin(HTMLVideoElementHost) {}\n *\n * const media = new SimpleHlsAudioOnlyMedia();\n * media.attach(document.querySelector('video'));\n * media.src = 'https://stream.mux.com/abc123.m3u8';\n */\nexport function SimpleHlsAudioOnlyMediaMixin<Base extends Constructor<any>>(BaseClass: Base) {\n class SimpleHlsAudioOnlyMediaImpl extends BaseClass {\n readonly #engine: Composition<SimpleHlsAudioOnlyEngineState, SimpleHlsAudioOnlyEngineContext>;\n #config: SimpleHlsAudioOnlyEngineConfig;\n #signals!: SimpleHlsAudioOnlyEngineSignals;\n #preload: '' | 'none' | 'metadata' | 'auto' = simpleHlsAudioOnlyMediaDefaultProps.preload;\n #disableRemotePlayback: boolean = simpleHlsAudioOnlyMediaDefaultProps.disableRemotePlayback;\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\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<SimpleHlsAudioOnlyEngineState, SimpleHlsAudioOnlyEngineContext> {\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.#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 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('SimpleHlsAudioOnlyMediaElement: 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 #createEngine(): Composition<SimpleHlsAudioOnlyEngineState, SimpleHlsAudioOnlyEngineContext> {\n return createHlsAudioOnlyEngine({\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 SimpleHlsAudioOnlyMediaImpl as unknown as MixinReturn<Base, SimpleHlsAudioOnlyMediaAPI>;\n}\n\n/** Standalone SPF audio-only media adapter with no base class. */\nexport class SimpleHlsAudioOnlyMediaElement extends SimpleHlsAudioOnlyMediaMixin(class {}) {}\n"],"mappings":";;AAgBA,MAAa,sCAAoE;CAC/E,KAAK;CACL,SAAS;CACT,uBAAuB;AACzB;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAgB,6BAA4D,WAAiB;CAC3F,MAAM,oCAAoC,UAAU;EAClD;EACA;EACA;EACA,WAA8C,oCAAoC;EAClF,yBAAkC,oCAAoC;;EAGtE,qBAA0C;EAE1C,YAAY,GAAG,MAAa;GAC1B,MAAM,GAAG,IAAI;GAEb,MAAM,EAAE,WAAW,OAAO,MAAM,CAAC;GACjC,KAAKC,UAAU;GACf,KAAKD,UAAU,KAAKE,cAAc;EACpC;;;;;;;EAQA,IAAI,SAAsF;GACxF,OAAO,KAAKF;EACd;EAMA,OAAO,cAAsC;GAC3C,MAAM,SAAS,YAAY;GAC3B,KAAKG,SAAS,QAAQ,aAAa,IAAI,YAAY;EACrD;EAEA,SAAe;GACb,KAAKC,mBAAmB;GACxB,KAAKD,SAAS,QAAQ,aAAa,IAAI,KAAA,CAAS;GAChD,MAAM,SAAS;EACjB;EAEA,UAAgB;GACd,KAAKC,mBAAmB;GACxB,KAAKJ,QAAQ,QAAQ;EACvB;;EAOA,IAAI,UAA6C;GAC/C,OAAO,KAAKK;EACd;EAEA,IAAI,QAAQ,OAA0C;GACpD,KAAKA,WAAW;GAChB,IAAI,OACF,KAAKF,SAAS,MAAM,QAAQ,IAAI,KAAK;EAEzC;EAYA,IAAI,wBAAiC;GACnC,OAAO,KAAKG;EACd;EAEA,IAAI,sBAAsB,OAAgB;GACxC,KAAKA,yBAAyB;GAC9B,KAAKH,SAAS,MAAM,sBAAsB,IAAI,KAAK;EACrD;EAYA,IAAI,MAAc;GAChB,OAAO,KAAKA,SAAS,MAAM,aAAa,IAAI,CAAC,EAAE,OAAO;EACxD;EAEA,IAAI,IAAI,OAAe;GACrB,KAAKC,mBAAmB;GACxB,KAAKD,SAAS,MAAM,aAAa,IAAI,QAAQ,EAAE,KAAK,MAAM,IAAI,KAAA,CAAS;EACzE;EAMA,OAAsB;GACpB,MAAM,eAAe,KAAKA,SAAS,QAAQ,aAAa,IAAI;GAC5D,IAAI,CAAC,cACH,OAAO,QAAQ,uBAAO,IAAI,MAAM,2DAA2D,CAAC;GAG9F,KAAKA,SAAS,MAAM,cAAc,IAAI,IAAI;GAE1C,OAAO,aAAa,KAAK,CAAC,CAAC,OAAO,QAAiB;IACjD,IAAI,KAAK,KACP,OAAO,IAAI,SAAe,SAAS,WAAW;KAC5C,MAAM,iBAAiB;MACrB,KAAKI,qBAAqB;MAC1B,aAAa,KAAK,CAAC,CAAC,KAAK,SAAS,MAAM;KAC1C;KACA,KAAKA,qBAAqB;KAC1B,aAAa,iBAAiB,aAAa,UAAU,EAAE,MAAM,KAAK,CAAC;IACrE,CAAC;IAEH,MAAM;GACR,CAAC;EACH;EAMA,gBAA6F;GAC3F,OAAO,yBAAyB;IAC9B,GAAG,KAAKN;IACR,iBAAiB,YAAY;KAC3B,KAAKE,WAAW;IAClB;GACF,CAAC;EACH;EAEA,qBAA2B;GACzB,IAAI,CAAC,KAAKI,oBAAoB;GAE9B,KAD0BJ,SAAS,QAAQ,aAAa,IAC7C,CAAC,EAAE,oBAAoB,aAAa,KAAKI,kBAAkB;GACtE,KAAKA,qBAAqB;EAC5B;CACF;CAEA,OAAO;AACT;;AAGA,IAAa,iCAAb,cAAoD,6BAA6B,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC"}
@@ -1,11 +1,11 @@
1
1
  import { Composition } from "../../../core/composition/create-composition.js";
2
2
  import { SimpleHlsEngineContext, SimpleHlsEngineState } from "./engine.js";
3
3
  import { Constructor, MixinReturn } from "@videojs/utils/types";
4
-
5
4
  //#region src/playback/engines/hls/adapter.d.ts
6
5
  interface SimpleHlsMediaProps {
7
6
  src: string;
8
7
  preload: '' | 'none' | 'metadata' | 'auto';
8
+ disableRemotePlayback: boolean;
9
9
  }
10
10
  declare const simpleHlsMediaDefaultProps: SimpleHlsMediaProps;
11
11
  interface SimpleHlsMediaAPI extends SimpleHlsMediaProps {
@@ -21,10 +21,8 @@ interface SimpleHlsMediaAPI extends SimpleHlsMediaProps {
21
21
  * Implements the src/play() contract per the WHATWG HTML spec so that SPF can
22
22
  * be used anywhere a media element API is expected.
23
23
  *
24
- * A new engine is created on every src assignment this fully tears down all
25
- * state, SourceBuffers, and in-flight requests from the previous source before
26
- * the next one begins. The media element reference is preserved across src
27
- * changes and re-applied to the new engine automatically.
24
+ * A single engine instance is created at construction and recycled across src
25
+ * changes.
28
26
  *
29
27
  * @example
30
28
  * class SimpleHlsMedia extends SimpleHlsMediaMixin(HTMLVideoElementHost) {}
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","names":[],"sources":["../../../../../src/playback/engines/hls/adapter.ts"],"mappings":";;;;;UAUiB,mBAAA;EACf,GAAA;EACA,OAAA;AAAA;AAAA,cAGW,0BAAA,EAA4B,mBAAA;AAAA,UAKxB,iBAAA,SAA0B,mBAAA;EAAA,SAChC,MAAA,EAAQ,WAAA,CAAY,oBAAA,EAAsB,sBAAA;EACnD,MAAA,CAAO,YAAA,EAAc,gBAAA;EACrB,MAAA;EACA,OAAA;EACA,IAAA,IAAQ,OAAA;AAAA;AALV;;;;;;;;;;;;;;;;;;AAAA,iBA0BgB,mBAAA,cAAiC,WAAA,MAAA,CAAkB,SAAA,EAAW,IAAA,GAmJpC,WAAA,CAAY,IAAA,EAAM,iBAAA;AAAA,cAC3D,0BAAA;;;;cAGY,qBAAA,SAA8B,0BAAA"}
1
+ {"version":3,"file":"adapter.d.ts","names":[],"sources":["../../../../../src/playback/engines/hls/adapter.ts"],"mappings":";;;;UAUiB;EACf;EACA;EACA;;cAGW,4BAA4B;UAMxB,0BAA0B;WAChC,QAAQ,YAAY,sBAAsB;EACnD,OAAO,cAAc;EACrB;EACA;EACA,QAAQ;;;;;;;;;;;;;;;;;;iBAmBM,oBAAoB,aAAa,kBAAkB,WAAW,OA+JpC,YAAY,MAAM;;;;;cAI/C,8BAA8B"}