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

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 (461) hide show
  1. package/dist/{dev/core → default/core/actors}/create-machine-actor.js +3 -3
  2. package/dist/default/core/actors/create-machine-actor.js.map +1 -0
  3. package/dist/default/core/{create-transition-actor.js → actors/create-transition-actor.js} +3 -3
  4. package/dist/default/core/actors/create-transition-actor.js.map +1 -0
  5. package/dist/default/core/composition/create-composition.js +85 -0
  6. package/dist/default/core/composition/create-composition.js.map +1 -0
  7. package/dist/default/core/composition/share-signals.js +37 -0
  8. package/dist/default/core/composition/share-signals.js.map +1 -0
  9. package/dist/{dev/core → default/core/reactors}/create-machine-reactor.js +4 -4
  10. package/dist/default/core/reactors/create-machine-reactor.js.map +1 -0
  11. package/dist/default/core/signals/primitives.js +33 -11
  12. package/dist/default/core/signals/primitives.js.map +1 -1
  13. package/dist/default/core/{task.js → tasks/task.js} +2 -2
  14. package/dist/default/core/tasks/task.js.map +1 -0
  15. package/dist/default/dom.js +9 -10
  16. package/dist/default/hls.js +3 -0
  17. package/dist/default/index.js +12 -3
  18. package/dist/default/index.js.map +1 -1
  19. package/dist/default/media/abr/quality-selection.js +83 -0
  20. package/dist/default/media/abr/quality-selection.js.map +1 -0
  21. package/dist/default/{core → media}/buffer/back-buffer.js +2 -2
  22. package/dist/default/media/buffer/back-buffer.js.map +1 -0
  23. package/dist/{dev/core → default/media}/buffer/forward-buffer.js +14 -2
  24. package/dist/default/media/buffer/forward-buffer.js.map +1 -0
  25. package/dist/{dev/dom/media → default/media/dom/mse}/append-segment.js +1 -1
  26. package/dist/default/media/dom/mse/append-segment.js.map +1 -0
  27. package/dist/default/{dom/media → media/dom/mse}/buffer-flusher.js +1 -1
  28. package/dist/default/media/dom/mse/buffer-flusher.js.map +1 -0
  29. package/dist/default/media/dom/mse/duration.js +78 -0
  30. package/dist/default/media/dom/mse/duration.js.map +1 -0
  31. package/dist/default/media/dom/mse/end-of-stream.js +20 -0
  32. package/dist/default/media/dom/mse/end-of-stream.js.map +1 -0
  33. package/dist/default/{dom/media → media/dom/mse}/mediasource-setup.js +63 -18
  34. package/dist/default/media/dom/mse/mediasource-setup.js.map +1 -0
  35. package/dist/default/{dom/text/parse-vtt-segment.js → media/dom/text/resolve-vtt-segment.js} +5 -5
  36. package/dist/default/media/dom/text/resolve-vtt-segment.js.map +1 -0
  37. package/dist/default/media/dom/text/text-track-slots.js +69 -0
  38. package/dist/default/media/dom/text/text-track-slots.js.map +1 -0
  39. package/dist/{dev/core → default/media}/hls/parse-attributes.js +1 -1
  40. package/dist/default/media/hls/parse-attributes.js.map +1 -0
  41. package/dist/{dev/core → default/media}/hls/parse-media-playlist.js +1 -1
  42. package/dist/default/media/hls/parse-media-playlist.js.map +1 -0
  43. package/dist/{dev/core → default/media}/hls/parse-multivariant.js +2 -2
  44. package/dist/default/media/hls/parse-multivariant.js.map +1 -0
  45. package/dist/default/{core → media}/hls/resolve-url.js +1 -1
  46. package/dist/default/media/hls/resolve-url.js.map +1 -0
  47. package/dist/default/media/primitives/select-tracks.js +45 -0
  48. package/dist/default/media/primitives/select-tracks.js.map +1 -0
  49. package/dist/default/media/types/index.js +36 -0
  50. package/dist/default/media/types/index.js.map +1 -0
  51. package/dist/default/media/utils/preload.js +22 -0
  52. package/dist/default/media/utils/preload.js.map +1 -0
  53. package/dist/default/media/utils/track-selection.js +47 -0
  54. package/dist/default/media/utils/track-selection.js.map +1 -0
  55. package/dist/default/media/utils/tracks.js +103 -0
  56. package/dist/default/media/utils/tracks.js.map +1 -0
  57. package/dist/default/{core/abr → network}/bandwidth-estimator.js +6 -5
  58. package/dist/default/network/bandwidth-estimator.js.map +1 -0
  59. package/dist/{dev/dom → default}/network/chunked-stream-iterable.js +1 -1
  60. package/dist/default/network/chunked-stream-iterable.js.map +1 -0
  61. package/dist/{dev/core/abr → default/network}/ewma.js +1 -1
  62. package/dist/default/network/ewma.js.map +1 -0
  63. package/dist/default/network/fetch.js +109 -0
  64. package/dist/default/network/fetch.js.map +1 -0
  65. package/dist/{dev/dom/features/segment-loader-actor.js → default/playback/actors/dom/segment-loader.js} +24 -15
  66. package/dist/default/playback/actors/dom/segment-loader.js.map +1 -0
  67. package/dist/{dev/dom/media/source-buffer-actor.js → default/playback/actors/dom/source-buffer.js} +8 -8
  68. package/dist/default/playback/actors/dom/source-buffer.js.map +1 -0
  69. package/dist/{dev/dom/features/text-tracks-actor.js → default/playback/actors/dom/text-tracks.js} +7 -3
  70. package/dist/default/playback/actors/dom/text-tracks.js.map +1 -0
  71. package/dist/default/playback/actors/text-track-segment-loader.js +135 -0
  72. package/dist/default/playback/actors/text-track-segment-loader.js.map +1 -0
  73. package/dist/default/playback/behaviors/calculate-presentation-duration.js +58 -0
  74. package/dist/default/playback/behaviors/calculate-presentation-duration.js.map +1 -0
  75. package/dist/default/playback/behaviors/dom/end-of-stream.js +178 -0
  76. package/dist/default/playback/behaviors/dom/end-of-stream.js.map +1 -0
  77. package/dist/default/playback/behaviors/dom/load-segments.js +177 -0
  78. package/dist/default/playback/behaviors/dom/load-segments.js.map +1 -0
  79. package/dist/default/playback/behaviors/dom/setup-buffer-actors.js +173 -0
  80. package/dist/default/playback/behaviors/dom/setup-buffer-actors.js.map +1 -0
  81. package/dist/default/playback/behaviors/dom/setup-mediasource.js +89 -0
  82. package/dist/default/playback/behaviors/dom/setup-mediasource.js.map +1 -0
  83. package/dist/default/playback/behaviors/dom/setup-text-track-actors.js +54 -0
  84. package/dist/default/playback/behaviors/dom/setup-text-track-actors.js.map +1 -0
  85. package/dist/default/playback/behaviors/dom/sync-text-tracks.js +99 -0
  86. package/dist/default/playback/behaviors/dom/sync-text-tracks.js.map +1 -0
  87. package/dist/default/playback/behaviors/dom/track-current-time.js +46 -0
  88. package/dist/default/playback/behaviors/dom/track-current-time.js.map +1 -0
  89. package/dist/default/playback/behaviors/dom/track-load-triggers.js +94 -0
  90. package/dist/default/playback/behaviors/dom/track-load-triggers.js.map +1 -0
  91. package/dist/default/playback/behaviors/dom/track-playback-rate.js +37 -0
  92. package/dist/default/playback/behaviors/dom/track-playback-rate.js.map +1 -0
  93. package/dist/default/playback/behaviors/dom/update-mediasource-duration.js +90 -0
  94. package/dist/default/playback/behaviors/dom/update-mediasource-duration.js.map +1 -0
  95. package/dist/default/playback/behaviors/quality-switching.js +96 -0
  96. package/dist/default/playback/behaviors/quality-switching.js.map +1 -0
  97. package/dist/default/playback/behaviors/resolve-presentation.js +85 -0
  98. package/dist/default/playback/behaviors/resolve-presentation.js.map +1 -0
  99. package/dist/default/playback/behaviors/resolve-track.js +97 -0
  100. package/dist/default/playback/behaviors/resolve-track.js.map +1 -0
  101. package/dist/default/playback/behaviors/select-tracks.js +132 -0
  102. package/dist/default/playback/behaviors/select-tracks.js.map +1 -0
  103. package/dist/default/playback/behaviors/sync-preload.js +59 -0
  104. package/dist/default/playback/behaviors/sync-preload.js.map +1 -0
  105. package/dist/default/playback/behaviors/track-types.js +61 -0
  106. package/dist/default/playback/behaviors/track-types.js.map +1 -0
  107. package/dist/default/{dom/playback-engine → playback/engines/hls}/adapter.js +36 -25
  108. package/dist/default/playback/engines/hls/adapter.js.map +1 -0
  109. package/dist/default/playback/engines/hls/engine.js +102 -0
  110. package/dist/default/playback/engines/hls/engine.js.map +1 -0
  111. package/dist/dev/core/{actor.d.ts → actors/actor.d.ts} +2 -2
  112. package/dist/dev/core/actors/actor.d.ts.map +1 -0
  113. package/dist/dev/core/actors/create-machine-actor.d.ts +125 -0
  114. package/dist/dev/core/actors/create-machine-actor.d.ts.map +1 -0
  115. package/dist/{default/core → dev/core/actors}/create-machine-actor.js +3 -3
  116. package/dist/dev/core/actors/create-machine-actor.js.map +1 -0
  117. package/dist/dev/core/actors/create-transition-actor.d.ts +42 -0
  118. package/dist/dev/core/actors/create-transition-actor.d.ts.map +1 -0
  119. package/dist/dev/core/{create-transition-actor.js → actors/create-transition-actor.js} +3 -3
  120. package/dist/dev/core/actors/create-transition-actor.js.map +1 -0
  121. package/dist/dev/core/composition/create-composition.d.ts +274 -0
  122. package/dist/dev/core/composition/create-composition.d.ts.map +1 -0
  123. package/dist/dev/core/composition/create-composition.js +85 -0
  124. package/dist/dev/core/composition/create-composition.js.map +1 -0
  125. package/dist/dev/core/composition/share-signals.d.ts +45 -0
  126. package/dist/dev/core/composition/share-signals.d.ts.map +1 -0
  127. package/dist/dev/core/composition/share-signals.js +37 -0
  128. package/dist/dev/core/composition/share-signals.js.map +1 -0
  129. package/dist/dev/core/machine.d.ts +0 -1
  130. package/dist/dev/core/machine.d.ts.map +1 -1
  131. package/dist/dev/core/reactors/create-machine-reactor.d.ts +93 -0
  132. package/dist/dev/core/reactors/create-machine-reactor.d.ts.map +1 -0
  133. package/dist/{default/core → dev/core/reactors}/create-machine-reactor.js +4 -4
  134. package/dist/dev/core/reactors/create-machine-reactor.js.map +1 -0
  135. package/dist/dev/core/signals/primitives.d.ts +38 -1
  136. package/dist/dev/core/signals/primitives.d.ts.map +1 -1
  137. package/dist/dev/core/signals/primitives.js +33 -11
  138. package/dist/dev/core/signals/primitives.js.map +1 -1
  139. package/dist/dev/core/tasks/task.d.ts +115 -0
  140. package/dist/dev/core/tasks/task.d.ts.map +1 -0
  141. package/dist/dev/core/{task.js → tasks/task.js} +2 -2
  142. package/dist/dev/core/tasks/task.js.map +1 -0
  143. package/dist/dev/dom.d.ts +9 -10
  144. package/dist/dev/dom.js +9 -10
  145. package/dist/dev/hls.d.ts +3 -0
  146. package/dist/dev/hls.js +3 -0
  147. package/dist/dev/index.d.ts +15 -3
  148. package/dist/dev/index.d.ts.map +1 -1
  149. package/dist/dev/index.js +12 -3
  150. package/dist/dev/index.js.map +1 -1
  151. package/dist/dev/media/abr/quality-selection.d.ts +22 -0
  152. package/dist/dev/media/abr/quality-selection.d.ts.map +1 -0
  153. package/dist/dev/media/abr/quality-selection.js +83 -0
  154. package/dist/dev/media/abr/quality-selection.js.map +1 -0
  155. package/dist/dev/media/buffer/back-buffer.d.ts +14 -0
  156. package/dist/dev/media/buffer/back-buffer.d.ts.map +1 -0
  157. package/dist/dev/{core → media}/buffer/back-buffer.js +2 -2
  158. package/dist/dev/media/buffer/back-buffer.js.map +1 -0
  159. package/dist/dev/media/buffer/forward-buffer.d.ts +14 -0
  160. package/dist/dev/media/buffer/forward-buffer.d.ts.map +1 -0
  161. package/dist/{default/core → dev/media}/buffer/forward-buffer.js +14 -2
  162. package/dist/dev/media/buffer/forward-buffer.js.map +1 -0
  163. package/dist/dev/{dom/media → media/dom/mse}/append-segment.d.ts +1 -1
  164. package/dist/dev/media/dom/mse/append-segment.d.ts.map +1 -0
  165. package/dist/{default/dom/media → dev/media/dom/mse}/append-segment.js +1 -1
  166. package/dist/dev/media/dom/mse/append-segment.js.map +1 -0
  167. package/dist/dev/{dom/media → media/dom/mse}/buffer-flusher.d.ts +1 -1
  168. package/dist/dev/media/dom/mse/buffer-flusher.d.ts.map +1 -0
  169. package/dist/dev/{dom/media → media/dom/mse}/buffer-flusher.js +1 -1
  170. package/dist/dev/media/dom/mse/buffer-flusher.js.map +1 -0
  171. package/dist/dev/media/dom/mse/duration.js +78 -0
  172. package/dist/dev/media/dom/mse/duration.js.map +1 -0
  173. package/dist/dev/media/dom/mse/end-of-stream.js +20 -0
  174. package/dist/dev/media/dom/mse/end-of-stream.js.map +1 -0
  175. package/dist/dev/{dom/media → media/dom/mse}/mediasource-setup.js +63 -18
  176. package/dist/dev/media/dom/mse/mediasource-setup.js.map +1 -0
  177. package/dist/dev/media/dom/text/resolve-vtt-segment.d.ts +12 -0
  178. package/dist/dev/media/dom/text/resolve-vtt-segment.d.ts.map +1 -0
  179. package/dist/dev/{dom/text/parse-vtt-segment.js → media/dom/text/resolve-vtt-segment.js} +5 -5
  180. package/dist/dev/media/dom/text/resolve-vtt-segment.js.map +1 -0
  181. package/dist/dev/media/dom/text/text-track-slots.d.ts +31 -0
  182. package/dist/dev/media/dom/text/text-track-slots.d.ts.map +1 -0
  183. package/dist/dev/media/dom/text/text-track-slots.js +69 -0
  184. package/dist/dev/media/dom/text/text-track-slots.js.map +1 -0
  185. package/dist/{default/core → dev/media}/hls/parse-attributes.js +1 -1
  186. package/dist/dev/media/hls/parse-attributes.js.map +1 -0
  187. package/dist/{default/core → dev/media}/hls/parse-media-playlist.js +1 -1
  188. package/dist/dev/media/hls/parse-media-playlist.js.map +1 -0
  189. package/dist/{default/core → dev/media}/hls/parse-multivariant.js +2 -2
  190. package/dist/dev/media/hls/parse-multivariant.js.map +1 -0
  191. package/dist/dev/{core → media}/hls/resolve-url.js +1 -1
  192. package/dist/dev/media/hls/resolve-url.js.map +1 -0
  193. package/dist/dev/media/primitives/select-tracks.js +45 -0
  194. package/dist/dev/media/primitives/select-tracks.js.map +1 -0
  195. package/dist/dev/{core → media}/types/index.d.ts +30 -2
  196. package/dist/dev/media/types/index.d.ts.map +1 -0
  197. package/dist/dev/media/types/index.js +36 -0
  198. package/dist/dev/media/types/index.js.map +1 -0
  199. package/dist/dev/media/utils/preload.js +22 -0
  200. package/dist/dev/media/utils/preload.js.map +1 -0
  201. package/dist/dev/media/utils/track-selection.js +47 -0
  202. package/dist/dev/media/utils/track-selection.js.map +1 -0
  203. package/dist/dev/media/utils/tracks.js +103 -0
  204. package/dist/dev/media/utils/tracks.js.map +1 -0
  205. package/dist/dev/{core/abr → network}/bandwidth-estimator.d.ts +17 -2
  206. package/dist/dev/network/bandwidth-estimator.d.ts.map +1 -0
  207. package/dist/dev/{core/abr → network}/bandwidth-estimator.js +6 -5
  208. package/dist/dev/network/bandwidth-estimator.js.map +1 -0
  209. package/dist/{default/dom → dev}/network/chunked-stream-iterable.js +1 -1
  210. package/dist/dev/network/chunked-stream-iterable.js.map +1 -0
  211. package/dist/{default/core/abr → dev/network}/ewma.js +1 -1
  212. package/dist/dev/network/ewma.js.map +1 -0
  213. package/dist/dev/network/fetch.js +109 -0
  214. package/dist/dev/network/fetch.js.map +1 -0
  215. package/dist/dev/playback/actors/dom/segment-loader.d.ts +36 -0
  216. package/dist/dev/playback/actors/dom/segment-loader.d.ts.map +1 -0
  217. package/dist/{default/dom/features/segment-loader-actor.js → dev/playback/actors/dom/segment-loader.js} +24 -15
  218. package/dist/dev/playback/actors/dom/segment-loader.js.map +1 -0
  219. package/dist/dev/{dom/media/source-buffer-actor.d.ts → playback/actors/dom/source-buffer.d.ts} +5 -5
  220. package/dist/dev/playback/actors/dom/source-buffer.d.ts.map +1 -0
  221. package/dist/{default/dom/media/source-buffer-actor.js → dev/playback/actors/dom/source-buffer.js} +8 -8
  222. package/dist/dev/playback/actors/dom/source-buffer.js.map +1 -0
  223. package/dist/dev/playback/actors/dom/text-tracks.d.ts +1 -0
  224. package/dist/{default/dom/features/text-tracks-actor.js → dev/playback/actors/dom/text-tracks.js} +7 -3
  225. package/dist/dev/playback/actors/dom/text-tracks.js.map +1 -0
  226. package/dist/dev/playback/actors/text-track-segment-loader.d.ts +59 -0
  227. package/dist/dev/playback/actors/text-track-segment-loader.d.ts.map +1 -0
  228. package/dist/dev/playback/actors/text-track-segment-loader.js +135 -0
  229. package/dist/dev/playback/actors/text-track-segment-loader.js.map +1 -0
  230. package/dist/dev/playback/actors/text-tracks.d.ts +42 -0
  231. package/dist/dev/playback/actors/text-tracks.d.ts.map +1 -0
  232. package/dist/dev/playback/behaviors/calculate-presentation-duration.d.ts +17 -0
  233. package/dist/dev/playback/behaviors/calculate-presentation-duration.d.ts.map +1 -0
  234. package/dist/dev/playback/behaviors/calculate-presentation-duration.js +58 -0
  235. package/dist/dev/playback/behaviors/calculate-presentation-duration.js.map +1 -0
  236. package/dist/dev/playback/behaviors/dom/end-of-stream.js +178 -0
  237. package/dist/dev/playback/behaviors/dom/end-of-stream.js.map +1 -0
  238. package/dist/dev/playback/behaviors/dom/load-segments.d.ts +62 -0
  239. package/dist/dev/playback/behaviors/dom/load-segments.d.ts.map +1 -0
  240. package/dist/dev/playback/behaviors/dom/load-segments.js +177 -0
  241. package/dist/dev/playback/behaviors/dom/load-segments.js.map +1 -0
  242. package/dist/dev/playback/behaviors/dom/setup-buffer-actors.js +173 -0
  243. package/dist/dev/playback/behaviors/dom/setup-buffer-actors.js.map +1 -0
  244. package/dist/dev/playback/behaviors/dom/setup-mediasource.js +89 -0
  245. package/dist/dev/playback/behaviors/dom/setup-mediasource.js.map +1 -0
  246. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.d.ts +31 -0
  247. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.d.ts.map +1 -0
  248. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.js +54 -0
  249. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.js.map +1 -0
  250. package/dist/dev/playback/behaviors/dom/sync-text-tracks.js +99 -0
  251. package/dist/dev/playback/behaviors/dom/sync-text-tracks.js.map +1 -0
  252. package/dist/dev/playback/behaviors/dom/track-current-time.d.ts +34 -0
  253. package/dist/dev/playback/behaviors/dom/track-current-time.d.ts.map +1 -0
  254. package/dist/dev/playback/behaviors/dom/track-current-time.js +46 -0
  255. package/dist/dev/playback/behaviors/dom/track-current-time.js.map +1 -0
  256. package/dist/dev/playback/behaviors/dom/track-load-triggers.d.ts +48 -0
  257. package/dist/dev/playback/behaviors/dom/track-load-triggers.d.ts.map +1 -0
  258. package/dist/dev/playback/behaviors/dom/track-load-triggers.js +94 -0
  259. package/dist/dev/playback/behaviors/dom/track-load-triggers.js.map +1 -0
  260. package/dist/dev/playback/behaviors/dom/track-playback-rate.d.ts +34 -0
  261. package/dist/dev/playback/behaviors/dom/track-playback-rate.d.ts.map +1 -0
  262. package/dist/dev/playback/behaviors/dom/track-playback-rate.js +37 -0
  263. package/dist/dev/playback/behaviors/dom/track-playback-rate.js.map +1 -0
  264. package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js +90 -0
  265. package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js.map +1 -0
  266. package/dist/dev/playback/behaviors/quality-switching.js +96 -0
  267. package/dist/dev/playback/behaviors/quality-switching.js.map +1 -0
  268. package/dist/dev/playback/behaviors/resolve-presentation.d.ts +7 -0
  269. package/dist/dev/playback/behaviors/resolve-presentation.d.ts.map +1 -0
  270. package/dist/dev/playback/behaviors/resolve-presentation.js +85 -0
  271. package/dist/dev/playback/behaviors/resolve-presentation.js.map +1 -0
  272. package/dist/dev/playback/behaviors/resolve-track.js +97 -0
  273. package/dist/dev/playback/behaviors/resolve-track.js.map +1 -0
  274. package/dist/dev/playback/behaviors/select-tracks.js +132 -0
  275. package/dist/dev/playback/behaviors/select-tracks.js.map +1 -0
  276. package/dist/dev/playback/behaviors/sync-preload.js +59 -0
  277. package/dist/dev/playback/behaviors/sync-preload.js.map +1 -0
  278. package/dist/dev/playback/behaviors/track-types.js +61 -0
  279. package/dist/dev/playback/behaviors/track-types.js.map +1 -0
  280. package/dist/dev/{dom/playback-engine → playback/engines/hls}/adapter.d.ts +14 -10
  281. package/dist/dev/playback/engines/hls/adapter.d.ts.map +1 -0
  282. package/dist/dev/{dom/playback-engine → playback/engines/hls}/adapter.js +36 -25
  283. package/dist/dev/playback/engines/hls/adapter.js.map +1 -0
  284. package/dist/dev/playback/engines/hls/engine.d.ts +177 -0
  285. package/dist/dev/playback/engines/hls/engine.d.ts.map +1 -0
  286. package/dist/dev/playback/engines/hls/engine.js +102 -0
  287. package/dist/dev/playback/engines/hls/engine.js.map +1 -0
  288. package/package.json +8 -9
  289. package/dist/default/core/abr/bandwidth-estimator.js.map +0 -1
  290. package/dist/default/core/abr/ewma.js.map +0 -1
  291. package/dist/default/core/abr/quality-selection.js +0 -53
  292. package/dist/default/core/abr/quality-selection.js.map +0 -1
  293. package/dist/default/core/buffer/back-buffer.js.map +0 -1
  294. package/dist/default/core/buffer/forward-buffer.js.map +0 -1
  295. package/dist/default/core/create-machine-actor.js.map +0 -1
  296. package/dist/default/core/create-machine-reactor.js.map +0 -1
  297. package/dist/default/core/create-transition-actor.js.map +0 -1
  298. package/dist/default/core/features/calculate-presentation-duration.js +0 -53
  299. package/dist/default/core/features/calculate-presentation-duration.js.map +0 -1
  300. package/dist/default/core/features/quality-switching.js +0 -69
  301. package/dist/default/core/features/quality-switching.js.map +0 -1
  302. package/dist/default/core/features/resolve-presentation.js +0 -73
  303. package/dist/default/core/features/resolve-presentation.js.map +0 -1
  304. package/dist/default/core/features/resolve-track.js +0 -66
  305. package/dist/default/core/features/resolve-track.js.map +0 -1
  306. package/dist/default/core/features/select-tracks.js +0 -130
  307. package/dist/default/core/features/select-tracks.js.map +0 -1
  308. package/dist/default/core/features/sync-preload-attribute.js +0 -26
  309. package/dist/default/core/features/sync-preload-attribute.js.map +0 -1
  310. package/dist/default/core/hls/parse-attributes.js.map +0 -1
  311. package/dist/default/core/hls/parse-media-playlist.js.map +0 -1
  312. package/dist/default/core/hls/parse-multivariant.js.map +0 -1
  313. package/dist/default/core/hls/resolve-url.js.map +0 -1
  314. package/dist/default/core/task.js.map +0 -1
  315. package/dist/default/core/types/index.js +0 -15
  316. package/dist/default/core/types/index.js.map +0 -1
  317. package/dist/default/core/utils/generate-id.js +0 -21
  318. package/dist/default/core/utils/generate-id.js.map +0 -1
  319. package/dist/default/core/utils/track-selection.js +0 -39
  320. package/dist/default/core/utils/track-selection.js.map +0 -1
  321. package/dist/default/dom/features/end-of-stream.js +0 -145
  322. package/dist/default/dom/features/end-of-stream.js.map +0 -1
  323. package/dist/default/dom/features/load-segments.js +0 -192
  324. package/dist/default/dom/features/load-segments.js.map +0 -1
  325. package/dist/default/dom/features/load-text-track-cues.js +0 -104
  326. package/dist/default/dom/features/load-text-track-cues.js.map +0 -1
  327. package/dist/default/dom/features/segment-loader-actor.js.map +0 -1
  328. package/dist/default/dom/features/setup-mediasource.js +0 -48
  329. package/dist/default/dom/features/setup-mediasource.js.map +0 -1
  330. package/dist/default/dom/features/setup-sourcebuffer.js +0 -78
  331. package/dist/default/dom/features/setup-sourcebuffer.js.map +0 -1
  332. package/dist/default/dom/features/sync-text-tracks.js +0 -95
  333. package/dist/default/dom/features/sync-text-tracks.js.map +0 -1
  334. package/dist/default/dom/features/text-track-segment-loader-actor.js +0 -55
  335. package/dist/default/dom/features/text-track-segment-loader-actor.js.map +0 -1
  336. package/dist/default/dom/features/text-tracks-actor.js.map +0 -1
  337. package/dist/default/dom/features/track-current-time.js +0 -49
  338. package/dist/default/dom/features/track-current-time.js.map +0 -1
  339. package/dist/default/dom/features/track-playback-initiated.js +0 -66
  340. package/dist/default/dom/features/track-playback-initiated.js.map +0 -1
  341. package/dist/default/dom/features/track-playback-rate.js +0 -32
  342. package/dist/default/dom/features/track-playback-rate.js.map +0 -1
  343. package/dist/default/dom/features/update-duration.js +0 -78
  344. package/dist/default/dom/features/update-duration.js.map +0 -1
  345. package/dist/default/dom/media/append-segment.js.map +0 -1
  346. package/dist/default/dom/media/buffer-flusher.js.map +0 -1
  347. package/dist/default/dom/media/mediasource-setup.js.map +0 -1
  348. package/dist/default/dom/media/source-buffer-actor.js.map +0 -1
  349. package/dist/default/dom/network/chunked-stream-iterable.js.map +0 -1
  350. package/dist/default/dom/network/fetch.js +0 -54
  351. package/dist/default/dom/network/fetch.js.map +0 -1
  352. package/dist/default/dom/playback-engine/adapter.js.map +0 -1
  353. package/dist/default/dom/playback-engine/engine.js +0 -142
  354. package/dist/default/dom/playback-engine/engine.js.map +0 -1
  355. package/dist/default/dom/playback-engine.js +0 -4
  356. package/dist/default/dom/text/parse-vtt-segment.js.map +0 -1
  357. package/dist/dev/core/abr/bandwidth-estimator.d.ts.map +0 -1
  358. package/dist/dev/core/abr/bandwidth-estimator.js.map +0 -1
  359. package/dist/dev/core/abr/ewma.js.map +0 -1
  360. package/dist/dev/core/abr/quality-selection.js +0 -53
  361. package/dist/dev/core/abr/quality-selection.js.map +0 -1
  362. package/dist/dev/core/actor.d.ts.map +0 -1
  363. package/dist/dev/core/buffer/back-buffer.js.map +0 -1
  364. package/dist/dev/core/buffer/forward-buffer.js.map +0 -1
  365. package/dist/dev/core/create-machine-actor.d.ts +0 -12
  366. package/dist/dev/core/create-machine-actor.d.ts.map +0 -1
  367. package/dist/dev/core/create-machine-actor.js.map +0 -1
  368. package/dist/dev/core/create-machine-reactor.d.ts +0 -8
  369. package/dist/dev/core/create-machine-reactor.d.ts.map +0 -1
  370. package/dist/dev/core/create-machine-reactor.js.map +0 -1
  371. package/dist/dev/core/create-transition-actor.d.ts +0 -23
  372. package/dist/dev/core/create-transition-actor.d.ts.map +0 -1
  373. package/dist/dev/core/create-transition-actor.js.map +0 -1
  374. package/dist/dev/core/features/calculate-presentation-duration.js +0 -53
  375. package/dist/dev/core/features/calculate-presentation-duration.js.map +0 -1
  376. package/dist/dev/core/features/quality-switching.js +0 -69
  377. package/dist/dev/core/features/quality-switching.js.map +0 -1
  378. package/dist/dev/core/features/resolve-presentation.js +0 -73
  379. package/dist/dev/core/features/resolve-presentation.js.map +0 -1
  380. package/dist/dev/core/features/resolve-track.js +0 -66
  381. package/dist/dev/core/features/resolve-track.js.map +0 -1
  382. package/dist/dev/core/features/select-tracks.js +0 -130
  383. package/dist/dev/core/features/select-tracks.js.map +0 -1
  384. package/dist/dev/core/features/sync-preload-attribute.js +0 -26
  385. package/dist/dev/core/features/sync-preload-attribute.js.map +0 -1
  386. package/dist/dev/core/hls/parse-attributes.js.map +0 -1
  387. package/dist/dev/core/hls/parse-media-playlist.js.map +0 -1
  388. package/dist/dev/core/hls/parse-multivariant.js.map +0 -1
  389. package/dist/dev/core/hls/resolve-url.js.map +0 -1
  390. package/dist/dev/core/task.js.map +0 -1
  391. package/dist/dev/core/types/index.d.ts.map +0 -1
  392. package/dist/dev/core/types/index.js +0 -15
  393. package/dist/dev/core/types/index.js.map +0 -1
  394. package/dist/dev/core/utils/generate-id.js +0 -21
  395. package/dist/dev/core/utils/generate-id.js.map +0 -1
  396. package/dist/dev/core/utils/track-selection.d.ts +0 -16
  397. package/dist/dev/core/utils/track-selection.d.ts.map +0 -1
  398. package/dist/dev/core/utils/track-selection.js +0 -39
  399. package/dist/dev/core/utils/track-selection.js.map +0 -1
  400. package/dist/dev/dom/features/end-of-stream.js +0 -145
  401. package/dist/dev/dom/features/end-of-stream.js.map +0 -1
  402. package/dist/dev/dom/features/load-segments.d.ts +0 -72
  403. package/dist/dev/dom/features/load-segments.d.ts.map +0 -1
  404. package/dist/dev/dom/features/load-segments.js +0 -192
  405. package/dist/dev/dom/features/load-segments.js.map +0 -1
  406. package/dist/dev/dom/features/load-text-track-cues.d.ts +0 -85
  407. package/dist/dev/dom/features/load-text-track-cues.d.ts.map +0 -1
  408. package/dist/dev/dom/features/load-text-track-cues.js +0 -104
  409. package/dist/dev/dom/features/load-text-track-cues.js.map +0 -1
  410. package/dist/dev/dom/features/segment-loader-actor.d.ts +0 -1
  411. package/dist/dev/dom/features/segment-loader-actor.js.map +0 -1
  412. package/dist/dev/dom/features/setup-mediasource.js +0 -48
  413. package/dist/dev/dom/features/setup-mediasource.js.map +0 -1
  414. package/dist/dev/dom/features/setup-sourcebuffer.d.ts +0 -9
  415. package/dist/dev/dom/features/setup-sourcebuffer.d.ts.map +0 -1
  416. package/dist/dev/dom/features/setup-sourcebuffer.js +0 -78
  417. package/dist/dev/dom/features/setup-sourcebuffer.js.map +0 -1
  418. package/dist/dev/dom/features/sync-text-tracks.js +0 -95
  419. package/dist/dev/dom/features/sync-text-tracks.js.map +0 -1
  420. package/dist/dev/dom/features/text-track-segment-loader-actor.d.ts +0 -12
  421. package/dist/dev/dom/features/text-track-segment-loader-actor.d.ts.map +0 -1
  422. package/dist/dev/dom/features/text-track-segment-loader-actor.js +0 -55
  423. package/dist/dev/dom/features/text-track-segment-loader-actor.js.map +0 -1
  424. package/dist/dev/dom/features/text-tracks-actor.d.ts +0 -31
  425. package/dist/dev/dom/features/text-tracks-actor.d.ts.map +0 -1
  426. package/dist/dev/dom/features/text-tracks-actor.js.map +0 -1
  427. package/dist/dev/dom/features/track-current-time.d.ts +0 -40
  428. package/dist/dev/dom/features/track-current-time.d.ts.map +0 -1
  429. package/dist/dev/dom/features/track-current-time.js +0 -49
  430. package/dist/dev/dom/features/track-current-time.js.map +0 -1
  431. package/dist/dev/dom/features/track-playback-initiated.d.ts +0 -46
  432. package/dist/dev/dom/features/track-playback-initiated.d.ts.map +0 -1
  433. package/dist/dev/dom/features/track-playback-initiated.js +0 -66
  434. package/dist/dev/dom/features/track-playback-initiated.js.map +0 -1
  435. package/dist/dev/dom/features/track-playback-rate.d.ts +0 -34
  436. package/dist/dev/dom/features/track-playback-rate.d.ts.map +0 -1
  437. package/dist/dev/dom/features/track-playback-rate.js +0 -32
  438. package/dist/dev/dom/features/track-playback-rate.js.map +0 -1
  439. package/dist/dev/dom/features/update-duration.js +0 -78
  440. package/dist/dev/dom/features/update-duration.js.map +0 -1
  441. package/dist/dev/dom/media/append-segment.d.ts.map +0 -1
  442. package/dist/dev/dom/media/append-segment.js.map +0 -1
  443. package/dist/dev/dom/media/buffer-flusher.d.ts.map +0 -1
  444. package/dist/dev/dom/media/buffer-flusher.js.map +0 -1
  445. package/dist/dev/dom/media/mediasource-setup.js.map +0 -1
  446. package/dist/dev/dom/media/source-buffer-actor.d.ts.map +0 -1
  447. package/dist/dev/dom/media/source-buffer-actor.js.map +0 -1
  448. package/dist/dev/dom/network/chunked-stream-iterable.js.map +0 -1
  449. package/dist/dev/dom/network/fetch.js +0 -54
  450. package/dist/dev/dom/network/fetch.js.map +0 -1
  451. package/dist/dev/dom/playback-engine/adapter.d.ts.map +0 -1
  452. package/dist/dev/dom/playback-engine/adapter.js.map +0 -1
  453. package/dist/dev/dom/playback-engine/engine.d.ts +0 -124
  454. package/dist/dev/dom/playback-engine/engine.d.ts.map +0 -1
  455. package/dist/dev/dom/playback-engine/engine.js +0 -142
  456. package/dist/dev/dom/playback-engine/engine.js.map +0 -1
  457. package/dist/dev/dom/playback-engine.d.ts +0 -4
  458. package/dist/dev/dom/playback-engine.js +0 -4
  459. package/dist/dev/dom/text/parse-vtt-segment.d.ts +0 -12
  460. package/dist/dev/dom/text/parse-vtt-segment.d.ts.map +0 -1
  461. package/dist/dev/dom/text/parse-vtt-segment.js.map +0 -1
@@ -0,0 +1,46 @@
1
+ import { defineBehavior } from "../../../core/composition/create-composition.js";
2
+ import { effect } from "../../../core/signals/effect.js";
3
+ import { listen } from "@videojs/utils/dom";
4
+ //#region src/playback/behaviors/dom/track-current-time.ts
5
+ /**
6
+ * Mirror `mediaElement.currentTime` into reactive state. Listens for:
7
+ * - `timeupdate` — fires during playback (~4 Hz)
8
+ * - `seeking` — fires when a seek begins; per spec, `currentTime` is already
9
+ * at the new position when this event dispatches, so buffer management can
10
+ * react immediately rather than waiting for `timeupdate`, which does not
11
+ * fire while paused.
12
+ *
13
+ * Also syncs immediately when a media element becomes available.
14
+ *
15
+ * When no media element is attached, writes `config.defaultCurrentTime`
16
+ * (default-default `0`, matching the HTMLMediaElement spec) so consumers
17
+ * always see a defined position. Read-only mirror; does not push
18
+ * `state.currentTime` back to the element.
19
+ */
20
+ function trackCurrentTimeSetup({ state, context, config }) {
21
+ const defaultCurrentTime = config?.defaultCurrentTime ?? 0;
22
+ return effect(() => {
23
+ const mediaElement = context.mediaElement.get();
24
+ if (!mediaElement) {
25
+ state.currentTime.set(defaultCurrentTime);
26
+ return;
27
+ }
28
+ const sync = () => state.currentTime.set(mediaElement.currentTime);
29
+ sync();
30
+ const removeTimeupdate = listen(mediaElement, "timeupdate", sync);
31
+ const removeSeeking = listen(mediaElement, "seeking", sync);
32
+ return () => {
33
+ removeTimeupdate();
34
+ removeSeeking();
35
+ };
36
+ });
37
+ }
38
+ const trackCurrentTime = defineBehavior({
39
+ stateKeys: ["currentTime"],
40
+ contextKeys: ["mediaElement"],
41
+ setup: trackCurrentTimeSetup
42
+ });
43
+ //#endregion
44
+ export { trackCurrentTime };
45
+
46
+ //# sourceMappingURL=track-current-time.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track-current-time.js","names":[],"sources":["../../../../../src/playback/behaviors/dom/track-current-time.ts"],"sourcesContent":["/**\n * Mirror `mediaElement.currentTime` into reactive state. Listens for:\n * - `timeupdate` — fires during playback (~4 Hz)\n * - `seeking` — fires when a seek begins; per spec, `currentTime` is already\n * at the new position when this event dispatches, so buffer management can\n * react immediately rather than waiting for `timeupdate`, which does not\n * fire while paused.\n *\n * Also syncs immediately when a media element becomes available.\n *\n * When no media element is attached, writes `config.defaultCurrentTime`\n * (default-default `0`, matching the HTMLMediaElement spec) so consumers\n * always see a defined position. Read-only mirror; does not push\n * `state.currentTime` back to the element.\n */\nimport { listen } from '@videojs/utils/dom';\nimport { defineBehavior } from '../../../core/composition/create-composition';\nimport { effect } from '../../../core/signals/effect';\nimport type { ReadonlySignal, Signal } from '../../../core/signals/primitives';\n\nexport interface CurrentTimeState {\n currentTime?: number;\n}\n\nexport interface CurrentTimeContext {\n mediaElement?: HTMLMediaElement | undefined;\n}\n\nexport interface TrackCurrentTimeConfig {\n /**\n * Value written to `state.currentTime` when no media element is attached.\n * Defaults to `0` — the HTMLMediaElement spec default.\n */\n defaultCurrentTime?: number;\n}\n\nfunction trackCurrentTimeSetup({\n state,\n context,\n config,\n}: {\n state: { currentTime: Signal<CurrentTimeState['currentTime']> };\n context: { mediaElement: ReadonlySignal<CurrentTimeContext['mediaElement']> };\n config?: TrackCurrentTimeConfig;\n}): () => void {\n const defaultCurrentTime = config?.defaultCurrentTime ?? 0;\n\n return effect(() => {\n const mediaElement = context.mediaElement.get();\n if (!mediaElement) {\n state.currentTime.set(defaultCurrentTime);\n return;\n }\n\n const sync = () => state.currentTime.set(mediaElement.currentTime);\n sync();\n const removeTimeupdate = listen(mediaElement, 'timeupdate', sync);\n const removeSeeking = listen(mediaElement, 'seeking', sync);\n return () => {\n removeTimeupdate();\n removeSeeking();\n };\n });\n}\n\nexport const trackCurrentTime = defineBehavior({\n stateKeys: ['currentTime'],\n contextKeys: ['mediaElement'],\n setup: trackCurrentTimeSetup,\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoCA,SAAS,sBAAsB,EAC7B,OACA,SACA,UAKa;CACb,MAAM,qBAAqB,QAAQ,sBAAsB;AAEzD,QAAO,aAAa;EAClB,MAAM,eAAe,QAAQ,aAAa,KAAK;AAC/C,MAAI,CAAC,cAAc;AACjB,SAAM,YAAY,IAAI,mBAAmB;AACzC;;EAGF,MAAM,aAAa,MAAM,YAAY,IAAI,aAAa,YAAY;AAClE,QAAM;EACN,MAAM,mBAAmB,OAAO,cAAc,cAAc,KAAK;EACjE,MAAM,gBAAgB,OAAO,cAAc,WAAW,KAAK;AAC3D,eAAa;AACX,qBAAkB;AAClB,kBAAe;;GAEjB;;AAGJ,MAAa,mBAAmB,eAAe;CAC7C,WAAW,CAAC,cAAc;CAC1B,aAAa,CAAC,eAAe;CAC7B,OAAO;CACR,CAAC"}
@@ -0,0 +1,48 @@
1
+ import { ReadonlySignal, Signal } from "../../../core/signals/primitives.js";
2
+ import { Reactor } from "../../../core/reactors/create-machine-reactor.js";
3
+ import { MaybeResolvedPresentation } from "../../../media/types/index.js";
4
+
5
+ //#region src/playback/behaviors/dom/track-load-triggers.d.ts
6
+ /**
7
+ * State shape for load-trigger tracking.
8
+ */
9
+ interface LoadTriggersState {
10
+ /**
11
+ * Sticky-true per source. Flips to `true` the first time an event occurs
12
+ * that should switch loading behavior from preload-based to standard load
13
+ * (currently DOM `play` / `seeking`). Reset to `false` on source change.
14
+ *
15
+ * Read by `resolvePresentation` and `loadVideoSegments` / `loadAudioSegments`
16
+ * to mirror native `HTMLMediaElement` preload semantics — only meaningful
17
+ * when `preload !== 'auto'`, which already loads fully regardless.
18
+ */
19
+ loadActivated?: boolean;
20
+ /** Current presentation — URL is used to detect source changes. */
21
+ presentation?: MaybeResolvedPresentation;
22
+ }
23
+ /**
24
+ * Context shape for load-trigger tracking.
25
+ */
26
+ interface LoadTriggersContext {
27
+ mediaElement?: HTMLMediaElement | undefined;
28
+ }
29
+ type LoadTriggersFsmState = 'preconditions-unmet' | 'monitoring' | 'load-active';
30
+ declare const trackLoadTriggers: {
31
+ stateKeys: readonly ["loadActivated", "presentation"];
32
+ contextKeys: readonly ["mediaElement"];
33
+ setup: (deps: {
34
+ state: {
35
+ loadActivated: Signal<LoadTriggersState['loadActivated']>;
36
+ presentation: ReadonlySignal<LoadTriggersState['presentation']>;
37
+ };
38
+ } & {
39
+ context: {
40
+ mediaElement: ReadonlySignal<LoadTriggersContext['mediaElement']>;
41
+ };
42
+ } & {
43
+ config?: {};
44
+ }) => Reactor<"destroyed" | "destroying" | LoadTriggersFsmState>;
45
+ };
46
+ //#endregion
47
+ export { LoadTriggersContext, LoadTriggersState, trackLoadTriggers };
48
+ //# sourceMappingURL=track-load-triggers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track-load-triggers.d.ts","names":[],"sources":["../../../../../src/playback/behaviors/dom/track-load-triggers.ts"],"mappings":";;;;;;;AAUA;UAAiB,iBAAA;;;;;;;;AAkBjB;;EARE,aAAA;EASA;EAPA,YAAA,GAAe,yBAAA;AAAA;;;;UAMA,mBAAA;EACf,YAAA,GAAe,gBAAA;AAAA;AAAA,KAGZ,oBAAA;AAAA,cA6HQ,iBAAA;;;;;qBA/DM,MAAA,CAAO,iBAAA;oBACR,cAAA,CAAe,iBAAA;IAAA;EAAA;;oBAEN,cAAA,CAAe,mBAAA;IAAA;EAAA"}
@@ -0,0 +1,94 @@
1
+ import { computed } from "../../../core/signals/primitives.js";
2
+ import { defineBehavior } from "../../../core/composition/create-composition.js";
3
+ import { createMachineReactor } from "../../../core/reactors/create-machine-reactor.js";
4
+ import { listen } from "@videojs/utils/dom";
5
+ //#region src/playback/behaviors/dom/track-load-triggers.ts
6
+ /**
7
+ * Slot-driven FSM. The slot `loadActivated` is the canonical externally-
8
+ * observable state; `deriveState` reads it (and the preconditions) to
9
+ * derive the local FSM state. The slot is *both* the state and the data —
10
+ * no separate internal bookkeeping.
11
+ *
12
+ * ```
13
+ * 'preconditions-unmet' ⟷ 'monitoring' ⟷ 'load-active'
14
+ *
15
+ * preconditions-unmet → monitoring element + URL appear
16
+ * monitoring → load-active slot flips true (listener fires
17
+ * or external write)
18
+ * load-active → monitoring within-state cleanup resets slot
19
+ * (URL or element identity change)
20
+ * any → preconditions-unmet element or URL → undefined
21
+ *
22
+ * any state → destroying → destroyed on destroy()
23
+ * ```
24
+ */
25
+ function deriveState(presentation, mediaElement, loadActivated) {
26
+ if (!mediaElement || !presentation?.url) return "preconditions-unmet";
27
+ if (loadActivated) return "load-active";
28
+ return "monitoring";
29
+ }
30
+ /**
31
+ * Track preload-overriding events per source.
32
+ *
33
+ * Writes `state.loadActivated = true` the first time a `play` or `seeking`
34
+ * event fires on the attached media element for the current source — or
35
+ * immediately on entry if the element is already in such a state
36
+ * (`!el.paused` or `el.seeking`), mirroring autoplay / native-controls /
37
+ * direct-DOM-`play()` scenarios.
38
+ *
39
+ * Sticky-true *within a source identity*: subsequent play/pause/seek
40
+ * cycles don't flip back. Source identity = (mediaElement, presentation
41
+ * URL). Either changing — including direct in-place swap with no
42
+ * `undefined` intermediate — resets the slot to `false`.
43
+ *
44
+ * Multi-writer with `hls/adapter.ts:play()` (which writes `true` directly
45
+ * on programmatic play) is intentional — different domains. The adapter
46
+ * records programmatic intent; this behavior is the DOM-side observer.
47
+ * Pre-existing `true` writes are honored because `deriveState` reads the
48
+ * slot — a `true` value routes directly to `'load-active'` without
49
+ * entering `'monitoring'`.
50
+ *
51
+ * @example
52
+ * const reactor = trackLoadTriggers.setup({ state, context });
53
+ * // later:
54
+ * reactor.destroy();
55
+ */
56
+ function trackLoadTriggersSetup({ state, context }) {
57
+ const derivedStateSignal = computed(() => deriveState(state.presentation.get(), context.mediaElement.get(), state.loadActivated.get()));
58
+ const urlSignal = computed(() => state.presentation.get()?.url);
59
+ return createMachineReactor({
60
+ initial: "preconditions-unmet",
61
+ monitor: () => derivedStateSignal.get(),
62
+ states: {
63
+ "preconditions-unmet": {},
64
+ monitoring: { effects: () => {
65
+ const el = context.mediaElement.get();
66
+ const setLoadActivated = () => state.loadActivated.set(true);
67
+ if (!el.paused || el.seeking) {
68
+ setLoadActivated();
69
+ return;
70
+ }
71
+ const cleanupPlay = listen(el, "play", setLoadActivated);
72
+ const cleanupSeeking = listen(el, "seeking", setLoadActivated);
73
+ return () => {
74
+ cleanupPlay();
75
+ cleanupSeeking();
76
+ };
77
+ } },
78
+ "load-active": { effects: () => {
79
+ context.mediaElement.get();
80
+ urlSignal.get();
81
+ return () => state.loadActivated.set(false);
82
+ } }
83
+ }
84
+ });
85
+ }
86
+ const trackLoadTriggers = defineBehavior({
87
+ stateKeys: ["loadActivated", "presentation"],
88
+ contextKeys: ["mediaElement"],
89
+ setup: trackLoadTriggersSetup
90
+ });
91
+ //#endregion
92
+ export { trackLoadTriggers };
93
+
94
+ //# sourceMappingURL=track-load-triggers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track-load-triggers.js","names":[],"sources":["../../../../../src/playback/behaviors/dom/track-load-triggers.ts"],"sourcesContent":["import { listen } from '@videojs/utils/dom';\nimport { defineBehavior } from '../../../core/composition/create-composition';\nimport type { Reactor } from '../../../core/reactors/create-machine-reactor';\nimport { createMachineReactor } from '../../../core/reactors/create-machine-reactor';\nimport { computed, type ReadonlySignal, type Signal } from '../../../core/signals/primitives';\nimport type { MaybeResolvedPresentation } from '../../../media/types';\n\n/**\n * State shape for load-trigger tracking.\n */\nexport interface LoadTriggersState {\n /**\n * Sticky-true per source. Flips to `true` the first time an event occurs\n * that should switch loading behavior from preload-based to standard load\n * (currently DOM `play` / `seeking`). Reset to `false` on source change.\n *\n * Read by `resolvePresentation` and `loadVideoSegments` / `loadAudioSegments`\n * to mirror native `HTMLMediaElement` preload semantics — only meaningful\n * when `preload !== 'auto'`, which already loads fully regardless.\n */\n loadActivated?: boolean;\n /** Current presentation — URL is used to detect source changes. */\n presentation?: MaybeResolvedPresentation;\n}\n\n/**\n * Context shape for load-trigger tracking.\n */\nexport interface LoadTriggersContext {\n mediaElement?: HTMLMediaElement | undefined;\n}\n\ntype LoadTriggersFsmState = 'preconditions-unmet' | 'monitoring' | 'load-active';\n\n/**\n * Slot-driven FSM. The slot `loadActivated` is the canonical externally-\n * observable state; `deriveState` reads it (and the preconditions) to\n * derive the local FSM state. The slot is *both* the state and the data —\n * no separate internal bookkeeping.\n *\n * ```\n * 'preconditions-unmet' ⟷ 'monitoring' ⟷ 'load-active'\n *\n * preconditions-unmet → monitoring element + URL appear\n * monitoring → load-active slot flips true (listener fires\n * or external write)\n * load-active → monitoring within-state cleanup resets slot\n * (URL or element identity change)\n * any → preconditions-unmet element or URL → undefined\n *\n * any state → destroying → destroyed on destroy()\n * ```\n */\nfunction deriveState(\n presentation: MaybeResolvedPresentation | undefined,\n mediaElement: HTMLMediaElement | undefined,\n loadActivated: boolean | undefined\n): LoadTriggersFsmState {\n if (!mediaElement || !presentation?.url) return 'preconditions-unmet';\n if (loadActivated) return 'load-active';\n return 'monitoring';\n}\n\n/**\n * Track preload-overriding events per source.\n *\n * Writes `state.loadActivated = true` the first time a `play` or `seeking`\n * event fires on the attached media element for the current source — or\n * immediately on entry if the element is already in such a state\n * (`!el.paused` or `el.seeking`), mirroring autoplay / native-controls /\n * direct-DOM-`play()` scenarios.\n *\n * Sticky-true *within a source identity*: subsequent play/pause/seek\n * cycles don't flip back. Source identity = (mediaElement, presentation\n * URL). Either changing — including direct in-place swap with no\n * `undefined` intermediate — resets the slot to `false`.\n *\n * Multi-writer with `hls/adapter.ts:play()` (which writes `true` directly\n * on programmatic play) is intentional — different domains. The adapter\n * records programmatic intent; this behavior is the DOM-side observer.\n * Pre-existing `true` writes are honored because `deriveState` reads the\n * slot — a `true` value routes directly to `'load-active'` without\n * entering `'monitoring'`.\n *\n * @example\n * const reactor = trackLoadTriggers.setup({ state, context });\n * // later:\n * reactor.destroy();\n */\nfunction trackLoadTriggersSetup({\n state,\n context,\n}: {\n state: {\n loadActivated: Signal<LoadTriggersState['loadActivated']>;\n presentation: ReadonlySignal<LoadTriggersState['presentation']>;\n };\n context: { mediaElement: ReadonlySignal<LoadTriggersContext['mediaElement']> };\n}): Reactor<LoadTriggersFsmState | 'destroying' | 'destroyed'> {\n const derivedStateSignal = computed(() =>\n deriveState(state.presentation.get(), context.mediaElement.get(), state.loadActivated.get())\n );\n // Sparse-firing source-URL signal. Emits whenever `presentation?.url`\n // resolves to a different value — covering both URL string changes\n // (url_a → url_b) and transitions where the URL becomes defined or\n // undefined (presentation set, cleared, or replaced without a URL\n // field). Does NOT emit when `state.presentation` is rewritten with\n // the same URL: manifest parsing, duration calc, track resolution,\n // and other enrichment paths re-write the presentation object\n // frequently — tracking raw `state.presentation` here would spuriously\n // reset the 'load-active' slot.\n const urlSignal = computed(() => state.presentation.get()?.url);\n\n return createMachineReactor<LoadTriggersFsmState>({\n initial: 'preconditions-unmet',\n monitor: () => derivedStateSignal.get(),\n states: {\n 'preconditions-unmet': {},\n\n monitoring: {\n // effects (not entry) so element-identity change within this state\n // re-fires and re-attaches listeners to the new element. The monitor\n // guarantees mediaElement is truthy while we're in this state.\n effects: () => {\n const el = context.mediaElement.get()!;\n\n const setLoadActivated = () => state.loadActivated.set(true);\n if (!el.paused || el.seeking) {\n setLoadActivated();\n return;\n }\n const cleanupPlay = listen(el, 'play', setLoadActivated);\n const cleanupSeeking = listen(el, 'seeking', setLoadActivated);\n return () => {\n cleanupPlay();\n cleanupSeeking();\n };\n },\n },\n\n 'load-active': {\n // effects-based cleanup (not entry) because the cleanup must fire on\n // BOTH state exit AND within-state identity change (url_a → url_b,\n // element_a → element_b — both truthy, no state transition).\n // Re-firing tracked reads → cleanup writes loadActivated=false →\n // deriveState (which reads loadActivated) returns 'monitoring' →\n // state transitions → fresh listeners attached for the new source.\n effects: () => {\n context.mediaElement.get();\n urlSignal.get();\n return () => state.loadActivated.set(false);\n },\n },\n },\n });\n}\n\nexport const trackLoadTriggers = defineBehavior({\n stateKeys: ['loadActivated', 'presentation'],\n contextKeys: ['mediaElement'],\n setup: trackLoadTriggersSetup,\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAqDA,SAAS,YACP,cACA,cACA,eACsB;AACtB,KAAI,CAAC,gBAAgB,CAAC,cAAc,IAAK,QAAO;AAChD,KAAI,cAAe,QAAO;AAC1B,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BT,SAAS,uBAAuB,EAC9B,OACA,WAO6D;CAC7D,MAAM,qBAAqB,eACzB,YAAY,MAAM,aAAa,KAAK,EAAE,QAAQ,aAAa,KAAK,EAAE,MAAM,cAAc,KAAK,CAAC,CAC7F;CAUD,MAAM,YAAY,eAAe,MAAM,aAAa,KAAK,EAAE,IAAI;AAE/D,QAAO,qBAA2C;EAChD,SAAS;EACT,eAAe,mBAAmB,KAAK;EACvC,QAAQ;GACN,uBAAuB,EAAE;GAEzB,YAAY,EAIV,eAAe;IACb,MAAM,KAAK,QAAQ,aAAa,KAAK;IAErC,MAAM,yBAAyB,MAAM,cAAc,IAAI,KAAK;AAC5D,QAAI,CAAC,GAAG,UAAU,GAAG,SAAS;AAC5B,uBAAkB;AAClB;;IAEF,MAAM,cAAc,OAAO,IAAI,QAAQ,iBAAiB;IACxD,MAAM,iBAAiB,OAAO,IAAI,WAAW,iBAAiB;AAC9D,iBAAa;AACX,kBAAa;AACb,qBAAgB;;MAGrB;GAED,eAAe,EAOb,eAAe;AACb,YAAQ,aAAa,KAAK;AAC1B,cAAU,KAAK;AACf,iBAAa,MAAM,cAAc,IAAI,MAAM;MAE9C;GACF;EACF,CAAC;;AAGJ,MAAa,oBAAoB,eAAe;CAC9C,WAAW,CAAC,iBAAiB,eAAe;CAC5C,aAAa,CAAC,eAAe;CAC7B,OAAO;CACR,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { ReadonlySignal, Signal } from "../../../core/signals/primitives.js";
2
+
3
+ //#region src/playback/behaviors/dom/track-playback-rate.d.ts
4
+ interface PlaybackRateState {
5
+ playbackRate?: number;
6
+ }
7
+ interface PlaybackRateContext {
8
+ mediaElement?: HTMLMediaElement | undefined;
9
+ }
10
+ interface TrackPlaybackRateConfig {
11
+ /**
12
+ * Value written to `state.playbackRate` when no media element is attached.
13
+ * Defaults to `1` — the HTMLMediaElement spec default.
14
+ */
15
+ defaultPlaybackRate?: number;
16
+ }
17
+ declare const trackPlaybackRate: {
18
+ stateKeys: readonly ["playbackRate"];
19
+ contextKeys: readonly ["mediaElement"];
20
+ setup: (deps: {
21
+ state: {
22
+ playbackRate: Signal<PlaybackRateState['playbackRate']>;
23
+ };
24
+ } & {
25
+ context: {
26
+ mediaElement: ReadonlySignal<PlaybackRateContext['mediaElement']>;
27
+ };
28
+ } & {
29
+ config: TrackPlaybackRateConfig;
30
+ }) => () => void;
31
+ };
32
+ //#endregion
33
+ export { PlaybackRateContext, PlaybackRateState, trackPlaybackRate };
34
+ //# sourceMappingURL=track-playback-rate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track-playback-rate.d.ts","names":[],"sources":["../../../../../src/playback/behaviors/dom/track-playback-rate.ts"],"mappings":";;;UAgBiB,iBAAA;EACf,YAAA;AAAA;AAAA,UAGe,mBAAA;EACf,YAAA,GAAe,gBAAA;AAAA;AAAA,UAGA,uBAAA;EAJA;;;;EASf,mBAAA;AAAA;AAAA,cA2BW,iBAAA;;;;;oBAnBY,MAAA,CAAO,iBAAA;IAAA;EAAA;;oBACL,cAAA,CAAe,mBAAA;IAAA;EAAA"}
@@ -0,0 +1,37 @@
1
+ import { defineBehavior } from "../../../core/composition/create-composition.js";
2
+ import { effect } from "../../../core/signals/effect.js";
3
+ import { listen } from "@videojs/utils/dom";
4
+ //#region src/playback/behaviors/dom/track-playback-rate.ts
5
+ /**
6
+ * Mirror `mediaElement.playbackRate` into reactive state. On each `ratechange`
7
+ * event, write the new value to `state.playbackRate`. Also syncs immediately
8
+ * when a media element becomes available so consumers don't wait for the first
9
+ * event.
10
+ *
11
+ * When no media element is attached, writes `config.defaultPlaybackRate`
12
+ * (default-default `1`, matching the HTMLMediaElement spec) so consumers
13
+ * always see the rate a freshly attached element would have. Read-only mirror;
14
+ * does not push `state.playbackRate` back to the element.
15
+ */
16
+ function trackPlaybackRateSetup({ state, context, config }) {
17
+ const defaultPlaybackRate = config?.defaultPlaybackRate ?? 1;
18
+ return effect(() => {
19
+ const mediaElement = context.mediaElement.get();
20
+ if (!mediaElement) {
21
+ state.playbackRate.set(defaultPlaybackRate);
22
+ return;
23
+ }
24
+ const sync = () => state.playbackRate.set(mediaElement.playbackRate);
25
+ sync();
26
+ return listen(mediaElement, "ratechange", sync);
27
+ });
28
+ }
29
+ const trackPlaybackRate = defineBehavior({
30
+ stateKeys: ["playbackRate"],
31
+ contextKeys: ["mediaElement"],
32
+ setup: trackPlaybackRateSetup
33
+ });
34
+ //#endregion
35
+ export { trackPlaybackRate };
36
+
37
+ //# sourceMappingURL=track-playback-rate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track-playback-rate.js","names":[],"sources":["../../../../../src/playback/behaviors/dom/track-playback-rate.ts"],"sourcesContent":["/**\n * Mirror `mediaElement.playbackRate` into reactive state. On each `ratechange`\n * event, write the new value to `state.playbackRate`. Also syncs immediately\n * when a media element becomes available so consumers don't wait for the first\n * event.\n *\n * When no media element is attached, writes `config.defaultPlaybackRate`\n * (default-default `1`, matching the HTMLMediaElement spec) so consumers\n * always see the rate a freshly attached element would have. Read-only mirror;\n * does not push `state.playbackRate` back to the element.\n */\nimport { listen } from '@videojs/utils/dom';\nimport { defineBehavior } from '../../../core/composition/create-composition';\nimport { effect } from '../../../core/signals/effect';\nimport type { ReadonlySignal, Signal } from '../../../core/signals/primitives';\n\nexport interface PlaybackRateState {\n playbackRate?: number;\n}\n\nexport interface PlaybackRateContext {\n mediaElement?: HTMLMediaElement | undefined;\n}\n\nexport interface TrackPlaybackRateConfig {\n /**\n * Value written to `state.playbackRate` when no media element is attached.\n * Defaults to `1` — the HTMLMediaElement spec default.\n */\n defaultPlaybackRate?: number;\n}\n\nfunction trackPlaybackRateSetup({\n state,\n context,\n config,\n}: {\n state: { playbackRate: Signal<PlaybackRateState['playbackRate']> };\n context: { mediaElement: ReadonlySignal<PlaybackRateContext['mediaElement']> };\n config?: TrackPlaybackRateConfig;\n}): () => void {\n const defaultPlaybackRate = config?.defaultPlaybackRate ?? 1;\n\n return effect(() => {\n const mediaElement = context.mediaElement.get();\n if (!mediaElement) {\n state.playbackRate.set(defaultPlaybackRate);\n return;\n }\n\n const sync = () => state.playbackRate.set(mediaElement.playbackRate);\n sync();\n return listen(mediaElement, 'ratechange', sync);\n });\n}\n\nexport const trackPlaybackRate = defineBehavior({\n stateKeys: ['playbackRate'],\n contextKeys: ['mediaElement'],\n setup: trackPlaybackRateSetup,\n});\n"],"mappings":";;;;;;;;;;;;;;;AAgCA,SAAS,uBAAuB,EAC9B,OACA,SACA,UAKa;CACb,MAAM,sBAAsB,QAAQ,uBAAuB;AAE3D,QAAO,aAAa;EAClB,MAAM,eAAe,QAAQ,aAAa,KAAK;AAC/C,MAAI,CAAC,cAAc;AACjB,SAAM,aAAa,IAAI,oBAAoB;AAC3C;;EAGF,MAAM,aAAa,MAAM,aAAa,IAAI,aAAa,aAAa;AACpE,QAAM;AACN,SAAO,OAAO,cAAc,cAAc,KAAK;GAC/C;;AAGJ,MAAa,oBAAoB,eAAe;CAC9C,WAAW,CAAC,eAAe;CAC3B,aAAa,CAAC,eAAe;CAC7B,OAAO;CACR,CAAC"}
@@ -0,0 +1,90 @@
1
+ import { computed } from "../../../core/signals/primitives.js";
2
+ import { defineBehavior } from "../../../core/composition/create-composition.js";
3
+ import { createMachineReactor } from "../../../core/reactors/create-machine-reactor.js";
4
+ import { getMaxBufferedEnd, shouldUpdateDuration, waitForSourceBuffersReady } from "../../../media/dom/mse/duration.js";
5
+ import { waitForMediaSourceOpen } from "../../../media/dom/mse/mediasource-setup.js";
6
+ //#region src/playback/behaviors/dom/update-mediasource-duration.ts
7
+ /**
8
+ * **Propagate `presentation.duration` to `mediaSource.duration` — exactly
9
+ * once per MediaSource.**
10
+ *
11
+ * When the presentation has a valid positive duration (including `Infinity`
12
+ * for live) and a MediaSource is in context, writes the value through to
13
+ * `mediaSource.duration` on initial setup — once, while `mediaSource.duration`
14
+ * is still `NaN`. Once any non-NaN value is present (set by us, or by
15
+ * `endOfStream` from the buffered end), the behavior leaves the property
16
+ * alone; re-syncing a drift against `presentation.duration` would race with
17
+ * concurrent `appendBuffer()` calls.
18
+ *
19
+ * The entry resolves three async preconditions in order before writing:
20
+ *
21
+ * 1. **MediaSource open** — `waitForMediaSourceOpen` defers until the first
22
+ * `sourceopen` event (or any readyState transition, since `'ended'` /
23
+ * `'closed'` mean we've missed the window and should bail).
24
+ * 2. **All SourceBuffers idle** — `waitForSourceBuffersReady` defers per
25
+ * the MSE-spec rule that `duration` cannot be set while any buffer has
26
+ * `updating === true`.
27
+ * 3. **Buffered-range clamp** — `getMaxBufferedEnd` ensures the written
28
+ * duration is at least the highest buffered end (MSE spec disallows
29
+ * a smaller `duration` than any buffered range).
30
+ *
31
+ * The buffer-set helpers operate across `mediaSource.sourceBuffers` (the
32
+ * canonical aggregate), so the behavior composes uniformly across
33
+ * audio-only, video-only, and mixed configurations.
34
+ *
35
+ * Single-positive-state reactor (`'preconditions-unmet'` ↔ `'duration-writable'`):
36
+ * state derivation is purely signal-driven (presentation validity +
37
+ * mediaSource existence). MediaSource lifecycle state (`readyState`) and
38
+ * the `duration` itself are non-signal DOM properties resolved inside the
39
+ * entry's async sequence. The state-exit cleanup aborts the in-flight
40
+ * wait, so source resets and behavior destroy structurally cancel the
41
+ * pending write. A post-await re-check of `mediaSource.readyState ===
42
+ * 'open'` covers the narrow race where `endOfStream()` synchronously
43
+ * transitions readyState to `'ended'` between our `waitForMediaSourceOpen`
44
+ * resolution and the `mediaSource.duration` write.
45
+ *
46
+ * Downstream of `calculatePresentationDuration` (which writes
47
+ * `presentation.duration`); concurrent with `endOfStream` (which may later
48
+ * write `mediaSource.duration` — the "exactly once" contract keeps us out
49
+ * of that path).
50
+ */
51
+ function deriveState(presentation, mediaSource) {
52
+ return shouldUpdateDuration(presentation, mediaSource) ? "duration-writable" : "preconditions-unmet";
53
+ }
54
+ function updateMediaSourceDurationSetup({ state, context }) {
55
+ const derivedStateSignal = computed(() => deriveState(state.presentation.get(), context.mediaSource.get()));
56
+ return createMachineReactor({
57
+ initial: "preconditions-unmet",
58
+ monitor: () => derivedStateSignal.get(),
59
+ states: {
60
+ "preconditions-unmet": {},
61
+ "duration-writable": { entry: () => {
62
+ const presentation = state.presentation.get();
63
+ const mediaSource = context.mediaSource.get();
64
+ if (!Number.isNaN(mediaSource.duration)) return;
65
+ const controller = new AbortController();
66
+ const writeWhenReady = async () => {
67
+ await waitForMediaSourceOpen(mediaSource, controller.signal);
68
+ if (controller.signal.aborted) return;
69
+ if (mediaSource.readyState !== "open") return;
70
+ await waitForSourceBuffersReady(mediaSource.sourceBuffers, controller.signal);
71
+ if (controller.signal.aborted) return;
72
+ if (mediaSource.readyState !== "open") return;
73
+ const maxBufferedEnd = getMaxBufferedEnd(mediaSource.sourceBuffers);
74
+ mediaSource.duration = maxBufferedEnd > presentation.duration ? maxBufferedEnd : presentation.duration;
75
+ };
76
+ writeWhenReady();
77
+ return () => controller.abort();
78
+ } }
79
+ }
80
+ });
81
+ }
82
+ const updateMediaSourceDuration = defineBehavior({
83
+ stateKeys: ["presentation"],
84
+ contextKeys: ["mediaSource"],
85
+ setup: updateMediaSourceDurationSetup
86
+ });
87
+ //#endregion
88
+ export { updateMediaSourceDuration };
89
+
90
+ //# sourceMappingURL=update-mediasource-duration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-mediasource-duration.js","names":[],"sources":["../../../../../src/playback/behaviors/dom/update-mediasource-duration.ts"],"sourcesContent":["/**\n * **Propagate `presentation.duration` to `mediaSource.duration` — exactly\n * once per MediaSource.**\n *\n * When the presentation has a valid positive duration (including `Infinity`\n * for live) and a MediaSource is in context, writes the value through to\n * `mediaSource.duration` on initial setup — once, while `mediaSource.duration`\n * is still `NaN`. Once any non-NaN value is present (set by us, or by\n * `endOfStream` from the buffered end), the behavior leaves the property\n * alone; re-syncing a drift against `presentation.duration` would race with\n * concurrent `appendBuffer()` calls.\n *\n * The entry resolves three async preconditions in order before writing:\n *\n * 1. **MediaSource open** — `waitForMediaSourceOpen` defers until the first\n * `sourceopen` event (or any readyState transition, since `'ended'` /\n * `'closed'` mean we've missed the window and should bail).\n * 2. **All SourceBuffers idle** — `waitForSourceBuffersReady` defers per\n * the MSE-spec rule that `duration` cannot be set while any buffer has\n * `updating === true`.\n * 3. **Buffered-range clamp** — `getMaxBufferedEnd` ensures the written\n * duration is at least the highest buffered end (MSE spec disallows\n * a smaller `duration` than any buffered range).\n *\n * The buffer-set helpers operate across `mediaSource.sourceBuffers` (the\n * canonical aggregate), so the behavior composes uniformly across\n * audio-only, video-only, and mixed configurations.\n *\n * Single-positive-state reactor (`'preconditions-unmet'` ↔ `'duration-writable'`):\n * state derivation is purely signal-driven (presentation validity +\n * mediaSource existence). MediaSource lifecycle state (`readyState`) and\n * the `duration` itself are non-signal DOM properties resolved inside the\n * entry's async sequence. The state-exit cleanup aborts the in-flight\n * wait, so source resets and behavior destroy structurally cancel the\n * pending write. A post-await re-check of `mediaSource.readyState ===\n * 'open'` covers the narrow race where `endOfStream()` synchronously\n * transitions readyState to `'ended'` between our `waitForMediaSourceOpen`\n * resolution and the `mediaSource.duration` write.\n *\n * Downstream of `calculatePresentationDuration` (which writes\n * `presentation.duration`); concurrent with `endOfStream` (which may later\n * write `mediaSource.duration` — the \"exactly once\" contract keeps us out\n * of that path).\n */\nimport { defineBehavior } from '../../../core/composition/create-composition';\nimport type { Reactor } from '../../../core/reactors/create-machine-reactor';\nimport { createMachineReactor } from '../../../core/reactors/create-machine-reactor';\nimport { computed, type ReadonlySignal } from '../../../core/signals/primitives';\nimport { getMaxBufferedEnd, shouldUpdateDuration, waitForSourceBuffersReady } from '../../../media/dom/mse/duration';\nimport { waitForMediaSourceOpen } from '../../../media/dom/mse/mediasource-setup';\nimport type { MaybeResolvedPresentation } from '../../../media/types';\n\ntype DurationFsmState = 'preconditions-unmet' | 'duration-writable';\n\nfunction deriveState(\n presentation: MaybeResolvedPresentation | undefined,\n mediaSource: MediaSource | undefined\n): DurationFsmState {\n return shouldUpdateDuration(presentation, mediaSource) ? 'duration-writable' : 'preconditions-unmet';\n}\n\nfunction updateMediaSourceDurationSetup({\n state,\n context,\n}: {\n state: { presentation: ReadonlySignal<MaybeResolvedPresentation | undefined> };\n context: { mediaSource: ReadonlySignal<MediaSource | undefined> };\n}): Reactor<DurationFsmState | 'destroying' | 'destroyed'> {\n // Purely signal-driven derivation: only `presentation` validity and\n // `mediaSource` existence. MediaSource lifecycle (`readyState`),\n // its attached `sourceBuffers`, and `mediaSource.duration` itself are\n // non-signal DOM properties consumed inside the entry — none of them\n // sneak into `computed(...)`.\n const derivedStateSignal = computed(() => deriveState(state.presentation.get(), context.mediaSource.get()));\n\n return createMachineReactor<DurationFsmState>({\n initial: 'preconditions-unmet',\n monitor: () => derivedStateSignal.get(),\n states: {\n 'preconditions-unmet': {},\n\n 'duration-writable': {\n // entry body is auto-untracked. The state machine handles source\n // resets via deriveState; this entry resolves the MediaSource\n // lifecycle preconditions in sequence and binds its cleanup\n // (abort) to state exit + destroy.\n entry: () => {\n const presentation = state.presentation.get()!;\n const mediaSource = context.mediaSource.get()!;\n\n // Idempotency: someone (us on a prior entry, or concurrent\n // `endOfStream`) has already written. No-op and leave the state\n // alone — the next source-reset transition will produce a fresh\n // entry against the new MediaSource (whose `duration` starts at\n // `NaN` again).\n if (!Number.isNaN(mediaSource.duration)) return;\n\n const controller = new AbortController();\n\n const writeWhenReady = async () => {\n await waitForMediaSourceOpen(mediaSource, controller.signal);\n if (controller.signal.aborted) return;\n // `waitForMediaSourceOpen` resolves on any readyState transition\n // out of 'closed'; if we landed in 'ended' / 'closed' instead of\n // 'open', the write window is gone.\n if (mediaSource.readyState !== 'open') return;\n\n await waitForSourceBuffersReady(mediaSource.sourceBuffers, controller.signal);\n if (controller.signal.aborted) return;\n\n // Narrow race: `endOfStream()` synchronously transitions\n // readyState to 'ended' AND writes `mediaSource.duration`\n // between our `waitForMediaSourceOpen` resolution and here.\n // Re-read the DOM property to catch this window.\n if (mediaSource.readyState !== 'open') return;\n\n // MSE spec: duration cannot be less than any buffered range.\n // Re-read sourceBuffers after the await so any buffer added\n // during the wait is included in the clamp.\n const maxBufferedEnd = getMaxBufferedEnd(mediaSource.sourceBuffers);\n const duration = maxBufferedEnd > presentation.duration! ? maxBufferedEnd : presentation.duration!;\n mediaSource.duration = duration;\n };\n\n writeWhenReady();\n\n return () => controller.abort();\n },\n },\n },\n });\n}\n\nexport const updateMediaSourceDuration = defineBehavior({\n stateKeys: ['presentation'],\n contextKeys: ['mediaSource'],\n setup: updateMediaSourceDurationSetup,\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDA,SAAS,YACP,cACA,aACkB;AAClB,QAAO,qBAAqB,cAAc,YAAY,GAAG,sBAAsB;;AAGjF,SAAS,+BAA+B,EACtC,OACA,WAIyD;CAMzD,MAAM,qBAAqB,eAAe,YAAY,MAAM,aAAa,KAAK,EAAE,QAAQ,YAAY,KAAK,CAAC,CAAC;AAE3G,QAAO,qBAAuC;EAC5C,SAAS;EACT,eAAe,mBAAmB,KAAK;EACvC,QAAQ;GACN,uBAAuB,EAAE;GAEzB,qBAAqB,EAKnB,aAAa;IACX,MAAM,eAAe,MAAM,aAAa,KAAK;IAC7C,MAAM,cAAc,QAAQ,YAAY,KAAK;AAO7C,QAAI,CAAC,OAAO,MAAM,YAAY,SAAS,CAAE;IAEzC,MAAM,aAAa,IAAI,iBAAiB;IAExC,MAAM,iBAAiB,YAAY;AACjC,WAAM,uBAAuB,aAAa,WAAW,OAAO;AAC5D,SAAI,WAAW,OAAO,QAAS;AAI/B,SAAI,YAAY,eAAe,OAAQ;AAEvC,WAAM,0BAA0B,YAAY,eAAe,WAAW,OAAO;AAC7E,SAAI,WAAW,OAAO,QAAS;AAM/B,SAAI,YAAY,eAAe,OAAQ;KAKvC,MAAM,iBAAiB,kBAAkB,YAAY,cAAc;AAEnE,iBAAY,WADK,iBAAiB,aAAa,WAAY,iBAAiB,aAAa;;AAI3F,oBAAgB;AAEhB,iBAAa,WAAW,OAAO;MAElC;GACF;EACF,CAAC;;AAGJ,MAAa,4BAA4B,eAAe;CACtD,WAAW,CAAC,eAAe;CAC3B,aAAa,CAAC,cAAc;CAC5B,OAAO;CACR,CAAC"}
@@ -0,0 +1,96 @@
1
+ import { computed, peek } from "../../core/signals/primitives.js";
2
+ import { defineBehavior } from "../../core/composition/create-composition.js";
3
+ import { createMachineReactor } from "../../core/reactors/create-machine-reactor.js";
4
+ import { isResolvedPresentation } from "../../media/types/index.js";
5
+ import { getTracksByType } from "../../media/utils/tracks.js";
6
+ import { DEFAULT_BANDWIDTH_CONFIG, getBandwidthEstimate } from "../../network/bandwidth-estimator.js";
7
+ import { DEFAULT_QUALITY_CONFIG, selectLowestQuality, selectQuality } from "../../media/abr/quality-selection.js";
8
+ function setupQualitySwitching({ state, config }) {
9
+ const safetyMargin = config.quality?.safetyMargin ?? DEFAULT_QUALITY_CONFIG.safetyMargin;
10
+ const upgradeMargin = config.quality?.upgradeMargin ?? DEFAULT_QUALITY_CONFIG.upgradeMargin;
11
+ const initialBandwidth = config.initialBandwidth ?? 5e6;
12
+ const bandwidthConfig = {
13
+ ...DEFAULT_BANDWIDTH_CONFIG,
14
+ ...config.bandwidth
15
+ };
16
+ const { selectionKey, userSelectionKey, getTracks, selectOptimal } = config;
17
+ const derivedStateSignal = computed(() => isResolvedPresentation(state.presentation.get()) ? "presentation-resolved" : "presentation-unresolved");
18
+ return createMachineReactor({
19
+ initial: "presentation-unresolved",
20
+ monitor: () => derivedStateSignal.get(),
21
+ states: {
22
+ "presentation-unresolved": {},
23
+ "presentation-resolved": {
24
+ entry: () => () => state[selectionKey].set(void 0),
25
+ effects: [() => {
26
+ const presentation = peek(state.presentation);
27
+ if (!presentation) return;
28
+ const allTracks = getTracks(presentation);
29
+ const [firstAllTrack] = allTracks;
30
+ if (!firstAllTrack) return;
31
+ const userFilter = state[userSelectionKey].get();
32
+ const matching = userFilter ? allTracks.filter((track) => {
33
+ for (const key in userFilter) {
34
+ const filterValue = userFilter[key];
35
+ if (filterValue !== void 0 && track[key] !== filterValue) return false;
36
+ }
37
+ return true;
38
+ }) : allTracks;
39
+ const candidates = matching.length > 0 ? matching : allTracks;
40
+ if (!candidates.length) return;
41
+ const selectedId = state[selectionKey].get();
42
+ if (candidates.length === 1) {
43
+ if (candidates[0].id !== selectedId) state[selectionKey].set(candidates[0].id);
44
+ return;
45
+ }
46
+ const bandwidth = getBandwidthEstimate(state.bandwidthState.get(), initialBandwidth, bandwidthConfig);
47
+ if (!selectedId && config.picker) {
48
+ const id = config.picker(presentation, config);
49
+ if (id) {
50
+ state[selectionKey].set(id);
51
+ return;
52
+ }
53
+ }
54
+ const optimal = selectOptimal(candidates, bandwidth, {
55
+ safetyMargin,
56
+ upgradeMargin,
57
+ currentTrack: candidates.find((t) => t.id === selectedId)
58
+ }) ?? selectLowestQuality(candidates);
59
+ if (optimal.id !== selectedId) state[selectionKey].set(optimal.id);
60
+ }]
61
+ }
62
+ }
63
+ });
64
+ }
65
+ /**
66
+ * Manage `selectedVideoTrackId`: pick a default on src load, dynamically
67
+ * adjust based on bandwidth, clear on src unload. Honors
68
+ * `userVideoTrackSelection` as a partial-track constraint on candidates;
69
+ * short-circuits ABR when the constraint narrows to a single track.
70
+ *
71
+ * @example
72
+ * const reactor = switchVideoQuality.setup({ state });
73
+ */
74
+ const switchVideoQuality = defineBehavior({
75
+ stateKeys: [
76
+ "presentation",
77
+ "bandwidthState",
78
+ "selectedVideoTrackId",
79
+ "userVideoTrackSelection"
80
+ ],
81
+ contextKeys: [],
82
+ setup: ({ state, config }) => setupQualitySwitching({
83
+ state,
84
+ config: {
85
+ ...config,
86
+ selectionKey: "selectedVideoTrackId",
87
+ userSelectionKey: "userVideoTrackSelection",
88
+ getTracks: (presentation) => getTracksByType(presentation, "video"),
89
+ selectOptimal: selectQuality
90
+ }
91
+ })
92
+ });
93
+ //#endregion
94
+ export { switchVideoQuality };
95
+
96
+ //# sourceMappingURL=quality-switching.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality-switching.js","names":[],"sources":["../../../../src/playback/behaviors/quality-switching.ts"],"sourcesContent":["/**\n * **Manage the per-type ABR-eligible track selection slot.** While a\n * presentation is resolved, owns the slot's lifecycle: pick a default,\n * dynamically adjust based on media metrics (today: bandwidth via\n * `selectQuality`), and clear on src unload. User intent is expressed as a\n * partial-track description in a sibling slot (e.g.\n * `userVideoTrackSelection`) which constrains the candidate set for\n * selection — when the constraint narrows candidates to exactly one, the\n * choice is fully determined and ABR is short-circuited (no bandwidth read,\n * no effect re-fire on bandwidth changes).\n *\n * Lifecycle: `'presentation-unresolved'` ↔ `'presentation-resolved'`. The\n * `'presentation-resolved'` state owns the selection slot; its\n * entry-returned cleanup clears the slot on exit (canonical\n * cleanup-binds-to-setup per `reactors.md`).\n *\n * Hysteresis: downgrades apply immediately; upgrades require the optimal\n * track's bandwidth to exceed the current track's by `upgradeMargin`. No\n * temporal state — short-term smoothing is the bandwidth estimator's job.\n *\n * Initial pick is configurable via `config.picker` — pass any `TrackPicker`\n * to override the bandwidth-aware default for the empty-slot case. ABR\n * re-evaluation (downgrade/upgrade) is unaffected. Composing\n * `switchVideoQuality` with `picker: (p) => pickFirstTrackId(p, 'video')`\n * yields \"first track at load, ABR adjusts from there\" — a non-bandwidth\n * initial pick paired with bandwidth-driven re-evaluation.\n */\n\nimport { defineBehavior } from '../../core/composition/create-composition';\nimport { createMachineReactor } from '../../core/reactors/create-machine-reactor';\nimport { computed, peek, type ReadonlySignal, type Signal } from '../../core/signals/primitives';\nimport {\n DEFAULT_QUALITY_CONFIG,\n type QualityConfig,\n selectLowestQuality,\n selectQuality,\n} from '../../media/abr/quality-selection';\nimport type { TrackPicker } from '../../media/primitives/select-tracks';\nimport {\n isResolvedPresentation,\n type MaybeResolvedPresentation,\n type PartiallyResolvedVideoTrack,\n type VideoTrack,\n} from '../../media/types';\nimport { getTracksByType } from '../../media/utils/tracks';\nimport type { BandwidthConfig, BandwidthState } from '../../network/bandwidth-estimator';\nimport { DEFAULT_BANDWIDTH_CONFIG, getBandwidthEstimate } from '../../network/bandwidth-estimator';\n\nexport interface QualitySwitchingState {\n presentation?: MaybeResolvedPresentation;\n bandwidthState?: BandwidthState;\n selectedVideoTrackId?: string;\n /**\n * Partial-track description expressing user intent. When set, narrows\n * the ABR candidate set to tracks matching every present field. The\n * common case is `{ id: 'specific-track-id' }` for a \"manual quality\"\n * pick, but other partial shapes work — e.g., `{ height: 720 }` would\n * constrain to 720p tracks; ABR continues to pick among them.\n *\n * When the narrowed candidates contain exactly one track, ABR is\n * short-circuited entirely (no bandwidth read, no effect re-fire).\n *\n * When the filter matches no tracks in the current presentation (e.g.,\n * user-picked id from a previous source doesn't exist here), falls back\n * to the unfiltered set rather than stalling playback.\n */\n userVideoTrackSelection?: Partial<VideoTrack>;\n}\n\nexport interface QualitySwitchingConfig {\n /**\n * Quality-selection tuning. `safetyMargin` is the bandwidth-headroom\n * multiplier; `upgradeMargin` is the hysteresis ratio gating upgrades.\n * Defaults: `DEFAULT_QUALITY_CONFIG` (0.85 / 1.15).\n */\n quality?: Partial<QualityConfig>;\n\n /**\n * Bandwidth-estimator tuning passed through to `getBandwidthEstimate`.\n * Merged over `DEFAULT_BANDWIDTH_CONFIG`.\n */\n bandwidth?: Partial<BandwidthConfig>;\n\n /**\n * Bandwidth estimate in bps to use before enough samples have been collected.\n * Default: 5_000_000 (5 Mbps).\n */\n initialBandwidth?: number;\n\n /**\n * Override the initial-pick algorithm. When set, the picker is called the\n * first time the slot is empty in the `'presentation-resolved'` state;\n * its returned id is set verbatim (no bandwidth-aware logic). Subsequent\n * ABR re-evaluation (downgrade/upgrade by bandwidth + hysteresis) is\n * unaffected and runs as usual.\n *\n * Default (no picker): a bandwidth-aware initial pick driven by\n * `initialBandwidth` and `quality.safetyMargin`, identical to ABR's\n * downgrade branch.\n *\n * Honors of `userVideoTrackSelection` are the picker's responsibility\n * when overridden. If the picker returns `undefined`, the bandwidth-aware\n * default pick fires (graceful fallback).\n */\n picker?: TrackPicker<QualitySwitchingConfig>;\n}\n\n/** Default initial-bandwidth value used by quality-switching variants before measurements arrive. */\nexport const DEFAULT_INITIAL_BANDWIDTH = 5_000_000;\n\n// ============================================================================\n// Specialization helper\n//\n// `setupQualitySwitching` has the same shape as a Behavior `setup` function:\n// `({ state, config }) => Reactor`. Each `switchXQuality` export below calls\n// it from inside its own `defineBehavior` setup, passing the per-type slot\n// keys, track type, and selection algorithm explicitly via three generic\n// parameters — `S` (selection slot key), `U` (user-selection slot key), `T`\n// (ABR track type). The per-type export is the single point that ties them\n// together; the helper stays slot-agnostic.\n//\n// -- Design note: why narrow `SelectionKey` / `UserSelectionKey` unions ----\n// Goal we did not reach: have callers \"fully pass in\" the slot keys, with\n// the helper enforcing zero internal knowledge of which literals are valid.\n// What blocks it: indexing a mapped-type intersection by a generic key.\n// When `S extends keyof QualitySwitchingState` (or `string`), TS conservatively\n// treats `state[selectionKey]` as the union of every possible match across\n// the intersected mapped portions — including the fixed-key signals\n// (`presentation`, `bandwidthState`) — and widens to their value-type union.\n// The sibling pattern hits the same constraint and answers it the same way:\n// `SelectedTrackKey` in `select-tracks.ts:43` is a hardcoded narrow union\n// for the same reason.\n//\n// Routes considered for \"fully passed in\", with trade-offs (left here for\n// the larger-group conversation):\n//\n// A. Derived constraint — `Exclude<keyof QualitySwitchingState, 'presentation'\n// | 'bandwidthState'>`. Removes the literal enumeration; same narrowness,\n// computed from the state shape. Still \"knows\" the fixed-key names.\n// B. Broad constraint (`S extends keyof QualitySwitchingState`) + access-site\n// casts (`state[selectionKey] as Signal<string | undefined>` at the top\n// of the helper). Caller passes any keys; the type system stops checking\n// S ≠ U or that the keys actually refer to selection slots. Once you\n// cast at the top, the body is structurally the original remap pattern\n// with extra ceremony.\n// C. Remap pattern (pre-refactor) — caller passes signals under logical\n// names (`selection`, `userSelection`); helper has no key generics.\n// Cleanest types; inconsistent with the sibling helpers.\n//\n// Current pick is the narrow-union route because it matches siblings and\n// the unions read as documentation (\"these are the slots this helper\n// manages\") rather than restriction. Extending for audio is one literal\n// per union.\n// --------------------------------------------------------------------------\n// ============================================================================\n\ntype AbrTrack = { id: string; bandwidth: number };\n\ntype SelectionKey = 'selectedVideoTrackId';\ntype UserSelectionKey = 'userVideoTrackSelection';\n\n// Each mapped value references `P` so TS keeps the per-key dependency and\n// resolves `state[selectionKey]` / `state[userSelectionKey]` to the right\n// arm. `T` (track type) deliberately stays out of the state map — pulling\n// it in detaches the user-selection mapped value from `P` and TS collapses\n// the intersection. T flows through `QualitySwitchingSetupConfig` instead;\n// the user-filter access casts at the read site (see below).\ntype QualitySwitchingStateMap<S extends SelectionKey, U extends UserSelectionKey> = {\n presentation: ReadonlySignal<QualitySwitchingState['presentation']>;\n bandwidthState: ReadonlySignal<QualitySwitchingState['bandwidthState']>;\n} & { [P in S]: Signal<QualitySwitchingState[P]> } & { [P in U]: ReadonlySignal<QualitySwitchingState[P]> };\n\ninterface QualitySwitchingSetupConfig<S extends SelectionKey, U extends UserSelectionKey, T extends AbrTrack>\n extends QualitySwitchingConfig {\n selectionKey: S;\n userSelectionKey: U;\n getTracks: (presentation: MaybeResolvedPresentation) => readonly T[];\n selectOptimal: (\n tracks: readonly T[],\n bandwidth: number,\n opts: { safetyMargin: number; upgradeMargin: number; currentTrack?: T }\n ) => T | undefined;\n}\n\nfunction setupQualitySwitching<S extends SelectionKey, U extends UserSelectionKey, T extends AbrTrack>({\n state,\n config,\n}: {\n state: QualitySwitchingStateMap<S, U>;\n config: QualitySwitchingSetupConfig<S, U, T>;\n}) {\n const safetyMargin = config.quality?.safetyMargin ?? DEFAULT_QUALITY_CONFIG.safetyMargin;\n const upgradeMargin = config.quality?.upgradeMargin ?? DEFAULT_QUALITY_CONFIG.upgradeMargin;\n const initialBandwidth = config.initialBandwidth ?? DEFAULT_INITIAL_BANDWIDTH;\n const bandwidthConfig: BandwidthConfig = { ...DEFAULT_BANDWIDTH_CONFIG, ...config.bandwidth };\n const { selectionKey, userSelectionKey, getTracks, selectOptimal } = config;\n\n const derivedStateSignal = computed(() =>\n isResolvedPresentation(state.presentation.get())\n ? ('presentation-resolved' as const)\n : ('presentation-unresolved' as const)\n );\n\n return createMachineReactor({\n initial: 'presentation-unresolved',\n monitor: () => derivedStateSignal.get(),\n states: {\n 'presentation-unresolved': {},\n 'presentation-resolved': {\n // Canonical cleanup-binds-to-setup: the selection slot's valid\n // lifespan is exactly 'presentation-resolved'. Clear fires on\n // 'presentation-resolved' exit, covering both src unload and\n // behavior destroy.\n entry: () => () => state[selectionKey].set(undefined),\n effects: [\n () => {\n const presentation = peek(state.presentation);\n if (!presentation) return;\n\n const allTracks = getTracks(presentation);\n const [firstAllTrack] = allTracks;\n if (!firstAllTrack) return;\n\n // State stores the filter as `Partial<VideoTrack>` (user-facing\n // shape — includes V-only fields like `height`); the helper\n // works against `Partial<T>` so filter and track access share\n // one index type. Filter keys absent on a partially-resolved\n // track read as `undefined` and just exclude that track.\n const userFilter = state[userSelectionKey].get() as Partial<T> | undefined;\n const matching = userFilter\n ? allTracks.filter((track) => {\n for (const key in userFilter) {\n const filterValue = userFilter[key as keyof T];\n if (filterValue !== undefined && track[key as keyof T] !== filterValue) return false;\n }\n return true;\n })\n : allTracks;\n // Fall back to all tracks when the filter excludes everything\n // (e.g., user-picked id doesn't exist in the current source).\n const candidates = matching.length > 0 ? matching : allTracks;\n if (!candidates.length) return;\n\n const selectedId = state[selectionKey].get();\n\n // Common case: user has fully constrained the choice (e.g.,\n // `{ id: 'specific-720p' }` narrows to a single track). Skip\n // the ABR path — and crucially, don't read `bandwidthState`\n // so the effect doesn't re-fire on bandwidth changes while\n // the user's selection holds.\n if (candidates.length === 1) {\n if (candidates[0]!.id !== selectedId) state[selectionKey].set(candidates[0]!.id);\n return;\n }\n\n // Read bandwidth up front to establish the signal subscription —\n // future bandwidth changes must re-fire this effect even when\n // the picker branch below takes the early-return path. (If the\n // picker bails out without ever touching `bandwidthState`, ABR\n // would otherwise be deaf to subsequent bandwidth changes.)\n //\n // Single path for pre-trust and post-trust:\n // `getBandwidthEstimate` returns `initialBandwidth` when state\n // is undefined or bytes sampled hasn't crossed `minTotalBytes`,\n // so the initial pick + early-ABR window run the same\n // `selectOptimal` path as a fully-trusted measurement.\n const bandwidth = getBandwidthEstimate(state.bandwidthState.get(), initialBandwidth, bandwidthConfig);\n\n // Picker-driven initial pick: when the slot is empty and the\n // caller supplied a `picker`, defer to it instead of the\n // bandwidth-aware default. The picker sees the full\n // presentation (not narrowed by `userVideoTrackSelection`) —\n // honoring the filter is the picker's responsibility when\n // overridden. Returning `undefined` falls through to the\n // bandwidth-aware default (graceful fallback).\n //\n // ABR re-evaluation (downgrade/upgrade by bandwidth) runs as\n // usual on subsequent effect re-runs once the slot is set.\n if (!selectedId && config.picker) {\n const id = config.picker(presentation, config);\n if (id) {\n state[selectionKey].set(id);\n return;\n }\n }\n // `selectOptimal` decides the track to apply now given current\n // selection + bandwidth + tuning. It returns:\n // - the optimal when no current track or on a downgrade\n // - the optimal when an upgrade clears `upgradeMargin`\n // - the current track itself when an upgrade doesn't clear margin\n // (caller's id-compare below no-ops in that case)\n // Outer `?? selectLowestQuality` is defensive — `selectQuality` falls\n // back to lowest internally; this catches future impls that don't.\n // `selectLowestQuality` returns `undefined` only on empty input,\n // and `candidates.length >= 2` here.\n const currentTrack = candidates.find((t) => t.id === selectedId);\n const optimal =\n selectOptimal(candidates, bandwidth, { safetyMargin, upgradeMargin, currentTrack }) ??\n selectLowestQuality(candidates)!;\n if (optimal.id !== selectedId) state[selectionKey].set(optimal.id);\n },\n ],\n },\n },\n });\n}\n\n// ============================================================================\n// Specialized exports — one per ABR-enabled track type\n// ============================================================================\n\n/**\n * Manage `selectedVideoTrackId`: pick a default on src load, dynamically\n * adjust based on bandwidth, clear on src unload. Honors\n * `userVideoTrackSelection` as a partial-track constraint on candidates;\n * short-circuits ABR when the constraint narrows to a single track.\n *\n * @example\n * const reactor = switchVideoQuality.setup({ state });\n */\nexport const switchVideoQuality = defineBehavior({\n stateKeys: ['presentation', 'bandwidthState', 'selectedVideoTrackId', 'userVideoTrackSelection'],\n contextKeys: [],\n setup: ({\n state,\n config,\n }: {\n state: QualitySwitchingStateMap<'selectedVideoTrackId', 'userVideoTrackSelection'>;\n config?: QualitySwitchingConfig;\n }) =>\n setupQualitySwitching<'selectedVideoTrackId', 'userVideoTrackSelection', PartiallyResolvedVideoTrack | VideoTrack>({\n state,\n config: {\n ...config,\n selectionKey: 'selectedVideoTrackId',\n userSelectionKey: 'userVideoTrackSelection',\n getTracks: (presentation) =>\n getTracksByType(presentation, 'video') as readonly (PartiallyResolvedVideoTrack | VideoTrack)[],\n selectOptimal: selectQuality,\n },\n }),\n});\n"],"mappings":";;;;;;;AAwLA,SAAS,sBAA8F,EACrG,OACA,UAIC;CACD,MAAM,eAAe,OAAO,SAAS,gBAAgB,uBAAuB;CAC5E,MAAM,gBAAgB,OAAO,SAAS,iBAAiB,uBAAuB;CAC9E,MAAM,mBAAmB,OAAO,oBAAA;CAChC,MAAM,kBAAmC;EAAE,GAAG;EAA0B,GAAG,OAAO;EAAW;CAC7F,MAAM,EAAE,cAAc,kBAAkB,WAAW,kBAAkB;CAErE,MAAM,qBAAqB,eACzB,uBAAuB,MAAM,aAAa,KAAK,CAAC,GAC3C,0BACA,0BACN;AAED,QAAO,qBAAqB;EAC1B,SAAS;EACT,eAAe,mBAAmB,KAAK;EACvC,QAAQ;GACN,2BAA2B,EAAE;GAC7B,yBAAyB;IAKvB,mBAAmB,MAAM,cAAc,IAAI,KAAA,EAAU;IACrD,SAAS,OACD;KACJ,MAAM,eAAe,KAAK,MAAM,aAAa;AAC7C,SAAI,CAAC,aAAc;KAEnB,MAAM,YAAY,UAAU,aAAa;KACzC,MAAM,CAAC,iBAAiB;AACxB,SAAI,CAAC,cAAe;KAOpB,MAAM,aAAa,MAAM,kBAAkB,KAAK;KAChD,MAAM,WAAW,aACb,UAAU,QAAQ,UAAU;AAC1B,WAAK,MAAM,OAAO,YAAY;OAC5B,MAAM,cAAc,WAAW;AAC/B,WAAI,gBAAgB,KAAA,KAAa,MAAM,SAAoB,YAAa,QAAO;;AAEjF,aAAO;OACP,GACF;KAGJ,MAAM,aAAa,SAAS,SAAS,IAAI,WAAW;AACpD,SAAI,CAAC,WAAW,OAAQ;KAExB,MAAM,aAAa,MAAM,cAAc,KAAK;AAO5C,SAAI,WAAW,WAAW,GAAG;AAC3B,UAAI,WAAW,GAAI,OAAO,WAAY,OAAM,cAAc,IAAI,WAAW,GAAI,GAAG;AAChF;;KAcF,MAAM,YAAY,qBAAqB,MAAM,eAAe,KAAK,EAAE,kBAAkB,gBAAgB;AAYrG,SAAI,CAAC,cAAc,OAAO,QAAQ;MAChC,MAAM,KAAK,OAAO,OAAO,cAAc,OAAO;AAC9C,UAAI,IAAI;AACN,aAAM,cAAc,IAAI,GAAG;AAC3B;;;KAcJ,MAAM,UACJ,cAAc,YAAY,WAAW;MAAE;MAAc;MAAe,cAFjD,WAAW,MAAM,MAAM,EAAE,OAAO,WAAW;MAEoB,CAAC,IACnF,oBAAoB,WAAW;AACjC,SAAI,QAAQ,OAAO,WAAY,OAAM,cAAc,IAAI,QAAQ,GAAG;MAErE;IACF;GACF;EACF,CAAC;;;;;;;;;;;AAgBJ,MAAa,qBAAqB,eAAe;CAC/C,WAAW;EAAC;EAAgB;EAAkB;EAAwB;EAA0B;CAChG,aAAa,EAAE;CACf,QAAQ,EACN,OACA,aAKA,sBAAmH;EACjH;EACA,QAAQ;GACN,GAAG;GACH,cAAc;GACd,kBAAkB;GAClB,YAAY,iBACV,gBAAgB,cAAc,QAAQ;GACxC,eAAe;GAChB;EACF,CAAC;CACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { MaybeResolvedPresentation, Presentation } from "../../media/types/index.js";
2
+
3
+ //#region src/playback/behaviors/resolve-presentation.d.ts
4
+ type ParsePresentation = (text: string, presentation: MaybeResolvedPresentation) => Presentation;
5
+ //#endregion
6
+ export { ParsePresentation };
7
+ //# sourceMappingURL=resolve-presentation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-presentation.d.ts","names":[],"sources":["../../../../src/playback/behaviors/resolve-presentation.ts"],"mappings":";;;KAiDY,iBAAA,IAAqB,IAAA,UAAc,YAAA,EAAc,yBAAA,KAA8B,YAAA"}