@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
@@ -1 +0,0 @@
1
- {"version":3,"file":"track-playback-initiated.js","names":[],"sources":["../../../../src/dom/features/track-playback-initiated.ts"],"sourcesContent":["import { listen } from '@videojs/utils/dom';\nimport type { Reactor } from '../../core/create-machine-reactor';\nimport { createMachineReactor } from '../../core/create-machine-reactor';\nimport { computed, type Signal, update } from '../../core/signals/primitives';\n\n/**\n * State shape for playback initiation tracking.\n */\nexport interface PlaybackInitiatedState {\n /** True once play has been requested for the current presentation URL. */\n playbackInitiated?: boolean;\n /** Current presentation — URL is used to detect source changes. */\n presentation?: { url?: string };\n}\n\n/**\n * Owners shape for playback initiation tracking.\n */\nexport interface PlaybackInitiatedOwners {\n mediaElement?: HTMLMediaElement | undefined;\n}\n\n/**\n * FSM states for playback initiation tracking.\n *\n * ```\n * 'preconditions-unmet' ──── element + URL ────→ 'monitoring'\n * ↑ ↑ │\n * │ preconditions lost │ play / !paused\n * │ │ ↓\n * └────────────── 'playback-initiated' ←──────┘\n * (exit cleanup resets state.playbackInitiated → false)\n *\n * any state ──── destroy() ────→ 'destroying' ────→ 'destroyed'\n * ```\n */\nfunction deriveState(\n state: PlaybackInitiatedState,\n owners: PlaybackInitiatedOwners\n): 'preconditions-unmet' | 'monitoring' | 'playback-initiated' {\n if (!owners.mediaElement || !state.presentation?.url) return 'preconditions-unmet';\n if (state.playbackInitiated) return 'playback-initiated';\n return 'monitoring';\n}\n\n/**\n * Track whether playback has been initiated for the current presentation URL.\n *\n * A three-state Reactor FSM driven by `state.playbackInitiated` and the\n * `deriveState` pattern:\n * - `'preconditions-unmet'` — no element or URL yet; no effects.\n * - `'monitoring'` — checks `!el.paused` on entry; listens for `play`.\n * - `'playback-initiated'` — tracks element and URL; exit cleanup resets\n * `state.playbackInitiated` to `false` on any change or lost preconditions.\n *\n * @example\n * const reactor = trackPlaybackInitiated({ state, owners });\n * // later:\n * reactor.destroy();\n */\nexport function trackPlaybackInitiated<S extends PlaybackInitiatedState, O extends PlaybackInitiatedOwners>({\n state,\n owners,\n}: {\n state: Signal<S>;\n owners: Signal<O>;\n}): Reactor<'preconditions-unmet' | 'monitoring' | 'playback-initiated' | 'destroying' | 'destroyed'> {\n const derivedStateSignal = computed(() => deriveState(state.get(), owners.get()));\n const mediaElementSignal = computed(() => owners.get().mediaElement);\n const urlSignal = computed(() => state.get().presentation?.url);\n\n return createMachineReactor<'preconditions-unmet' | 'monitoring' | 'playback-initiated'>({\n initial: 'preconditions-unmet',\n monitor: () => derivedStateSignal.get(),\n states: {\n 'preconditions-unmet': {},\n\n monitoring: {\n // Entry: check if already playing; otherwise listen for play.\n // The fn body is automatically untracked — el is read at entry time only.\n entry: () => {\n const el = mediaElementSignal.get()!;\n update(state, { playbackInitiated: !el.paused } as Partial<S>);\n return listen(el, 'play', () => {\n update(state, { playbackInitiated: !el.paused } as Partial<S>);\n });\n },\n },\n\n 'playback-initiated': {\n // Reaction: tracks element and URL while initiated. When either changes,\n // the effect re-runs — the exit cleanup fires first, resetting\n // state.playbackInitiated to false. deriveState then returns 'monitoring'\n // on the next microtask, and the always monitor drives the transition.\n //\n // This covers both the preconditions-lost path (element/URL → undefined,\n // which also triggers a deriveState → 'preconditions-unmet' transition)\n // and the URL-change / element-swap path (preconditions still met but\n // values changed, handled entirely by this effect's cleanup).\n effects: () => {\n mediaElementSignal.get(); // tracked — re-run on element change\n urlSignal.get(); // tracked — re-run on URL change\n return () => update(state, { playbackInitiated: false } as Partial<S>);\n },\n },\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoCA,SAAS,YACP,OACA,QAC6D;AAC7D,KAAI,CAAC,OAAO,gBAAgB,CAAC,MAAM,cAAc,IAAK,QAAO;AAC7D,KAAI,MAAM,kBAAmB,QAAO;AACpC,QAAO;;;;;;;;;;;;;;;;;AAkBT,SAAgB,uBAA4F,EAC1G,OACA,UAIoG;CACpG,MAAM,qBAAqB,eAAe,YAAY,MAAM,KAAK,EAAE,OAAO,KAAK,CAAC,CAAC;CACjF,MAAM,qBAAqB,eAAe,OAAO,KAAK,CAAC,aAAa;CACpE,MAAM,YAAY,eAAe,MAAM,KAAK,CAAC,cAAc,IAAI;AAE/D,QAAO,qBAAkF;EACvF,SAAS;EACT,eAAe,mBAAmB,KAAK;EACvC,QAAQ;GACN,uBAAuB,EAAE;GAEzB,YAAY,EAGV,aAAa;IACX,MAAM,KAAK,mBAAmB,KAAK;AACnC,WAAO,OAAO,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAe;AAC9D,WAAO,OAAO,IAAI,cAAc;AAC9B,YAAO,OAAO,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAe;MAC9D;MAEL;GAED,sBAAsB,EAUpB,eAAe;AACb,uBAAmB,KAAK;AACxB,cAAU,KAAK;AACf,iBAAa,OAAO,OAAO,EAAE,mBAAmB,OAAO,CAAe;MAEzE;GACF;EACF,CAAC"}
@@ -1,34 +0,0 @@
1
- import { Signal } from "../../core/signals/primitives.js";
2
-
3
- //#region src/dom/features/track-playback-rate.d.ts
4
- /**
5
- * State shape for playback rate tracking.
6
- */
7
- interface PlaybackRateState {
8
- playbackRate?: number;
9
- }
10
- /**
11
- * Owners shape for playback rate tracking.
12
- */
13
- interface PlaybackRateOwners {
14
- mediaElement?: HTMLMediaElement | undefined;
15
- }
16
- /**
17
- * Track playback rate from the media element.
18
- *
19
- * Mirrors `mediaElement.playbackRate` into reactive state on each `ratechange`
20
- * event. Also syncs immediately when a media element becomes available.
21
- *
22
- * @example
23
- * const cleanup = trackPlaybackRate({ state, owners });
24
- */
25
- declare function trackPlaybackRate<O extends PlaybackRateOwners>({
26
- state,
27
- owners
28
- }: {
29
- state: Signal<PlaybackRateState>;
30
- owners: Signal<O>;
31
- }): () => void;
32
- //#endregion
33
- export { PlaybackRateOwners, PlaybackRateState, trackPlaybackRate };
34
- //# sourceMappingURL=track-playback-rate.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"track-playback-rate.d.ts","names":[],"sources":["../../../../src/dom/features/track-playback-rate.ts"],"mappings":";;;;;AAOA;UAAiB,iBAAA;EACf,YAAA;AAAA;;AAMF;;UAAiB,kBAAA;EACf,YAAA,GAAe,gBAAA;AAAA;AAYjB;;;;;;;;;AAAA,iBAAgB,iBAAA,WAA4B,kBAAA,CAAA,CAAA;EAC1C,KAAA;EACA;AAAA;EAEA,KAAA,EAAO,MAAA,CAAO,iBAAA;EACd,MAAA,EAAQ,MAAA,CAAO,CAAA;AAAA"}
@@ -1,32 +0,0 @@
1
- import { effect } from "../../core/signals/effect.js";
2
- import { computed, update } from "../../core/signals/primitives.js";
3
- import { listen } from "@videojs/utils/dom";
4
- //#region src/dom/features/track-playback-rate.ts
5
- /**
6
- * Track playback rate from the media element.
7
- *
8
- * Mirrors `mediaElement.playbackRate` into reactive state on each `ratechange`
9
- * event. Also syncs immediately when a media element becomes available.
10
- *
11
- * @example
12
- * const cleanup = trackPlaybackRate({ state, owners });
13
- */
14
- function trackPlaybackRate({ state, owners }) {
15
- const mediaElementSignal = computed(() => owners.get().mediaElement);
16
- const canTrackPlaybackRate = computed(() => !!mediaElementSignal.get());
17
- const cleanupEffect = effect(() => {
18
- if (!canTrackPlaybackRate.get()) return;
19
- const mediaElement = mediaElementSignal.get();
20
- update(state, { playbackRate: mediaElement.playbackRate });
21
- return listen(mediaElement, "ratechange", () => {
22
- update(state, { playbackRate: mediaElement.playbackRate });
23
- });
24
- });
25
- return () => {
26
- cleanupEffect();
27
- };
28
- }
29
- //#endregion
30
- export { trackPlaybackRate };
31
-
32
- //# sourceMappingURL=track-playback-rate.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"track-playback-rate.js","names":[],"sources":["../../../../src/dom/features/track-playback-rate.ts"],"sourcesContent":["import { listen } from '@videojs/utils/dom';\nimport { effect } from '../../core/signals/effect';\nimport { computed, type Signal, update } from '../../core/signals/primitives';\n\n/**\n * State shape for playback rate tracking.\n */\nexport interface PlaybackRateState {\n playbackRate?: number;\n}\n\n/**\n * Owners shape for playback rate tracking.\n */\nexport interface PlaybackRateOwners {\n mediaElement?: HTMLMediaElement | undefined;\n}\n\n/**\n * Track playback rate from the media element.\n *\n * Mirrors `mediaElement.playbackRate` into reactive state on each `ratechange`\n * event. Also syncs immediately when a media element becomes available.\n *\n * @example\n * const cleanup = trackPlaybackRate({ state, owners });\n */\nexport function trackPlaybackRate<O extends PlaybackRateOwners>({\n state,\n owners,\n}: {\n state: Signal<PlaybackRateState>;\n owners: Signal<O>;\n}): () => void {\n const mediaElementSignal = computed(() => owners.get().mediaElement);\n const canTrackPlaybackRate = computed(() => !!mediaElementSignal.get());\n\n const cleanupEffect = effect(() => {\n if (!canTrackPlaybackRate.get()) return;\n const mediaElement = mediaElementSignal.get() as HTMLMediaElement;\n\n update(state, { playbackRate: mediaElement.playbackRate });\n\n return listen(mediaElement, 'ratechange', () => {\n update(state, { playbackRate: mediaElement.playbackRate });\n });\n });\n\n return () => {\n cleanupEffect();\n };\n}\n"],"mappings":";;;;;;;;;;;;;AA2BA,SAAgB,kBAAgD,EAC9D,OACA,UAIa;CACb,MAAM,qBAAqB,eAAe,OAAO,KAAK,CAAC,aAAa;CACpE,MAAM,uBAAuB,eAAe,CAAC,CAAC,mBAAmB,KAAK,CAAC;CAEvE,MAAM,gBAAgB,aAAa;AACjC,MAAI,CAAC,qBAAqB,KAAK,CAAE;EACjC,MAAM,eAAe,mBAAmB,KAAK;AAE7C,SAAO,OAAO,EAAE,cAAc,aAAa,cAAc,CAAC;AAE1D,SAAO,OAAO,cAAc,oBAAoB;AAC9C,UAAO,OAAO,EAAE,cAAc,aAAa,cAAc,CAAC;IAC1D;GACF;AAEF,cAAa;AACX,iBAAe"}
@@ -1,78 +0,0 @@
1
- import { effect } from "../../core/signals/effect.js";
2
- import { hasPresentationDuration } from "../../core/types/index.js";
3
- //#region src/dom/features/update-duration.ts
4
- /**
5
- * Check if we can update MediaSource duration (have required data).
6
- */
7
- function canUpdateDuration(state, owners) {
8
- return !!(owners.mediaSource && state.presentation && hasPresentationDuration(state.presentation));
9
- }
10
- /**
11
- * Get the maximum buffered end time across all SourceBuffers.
12
- */
13
- function getMaxBufferedEnd(owners) {
14
- let maxEnd = 0;
15
- const buffers = [owners.videoSourceBuffer, owners.audioSourceBuffer].filter((buf) => buf !== void 0);
16
- for (const buffer of buffers) {
17
- const { buffered } = buffer;
18
- if (buffered.length > 0) {
19
- const end = buffered.end(buffered.length - 1);
20
- if (end > maxEnd) maxEnd = end;
21
- }
22
- }
23
- return maxEnd;
24
- }
25
- /**
26
- * Check if we should update MediaSource duration (conditions met).
27
- */
28
- function shouldUpdateDuration(state, owners) {
29
- if (!canUpdateDuration(state, owners)) return false;
30
- const { mediaSource } = owners;
31
- const { presentation } = state;
32
- if ((owners.mediaSourceReadyState?.get() ?? owners.mediaSource?.readyState) !== "open") return false;
33
- const duration = presentation.duration;
34
- if (!Number.isFinite(duration) || Number.isNaN(duration) || duration <= 0) return false;
35
- return Number.isNaN(mediaSource.duration);
36
- }
37
- /**
38
- * Wait for all currently-updating SourceBuffers to finish.
39
- *
40
- * The MSE spec forbids setting MediaSource.duration while any attached
41
- * SourceBuffer has updating === true. This defers until all are idle.
42
- */
43
- function waitForSourceBuffersReady(owners) {
44
- const updating = [owners.videoSourceBuffer, owners.audioSourceBuffer].filter((buf) => buf?.updating === true);
45
- if (updating.length === 0) return Promise.resolve();
46
- return Promise.all(updating.map((buf) => new Promise((resolve) => buf.addEventListener("updateend", () => resolve(), { once: true })))).then(() => void 0);
47
- }
48
- /**
49
- * Update MediaSource duration when presentation duration becomes available.
50
- */
51
- function updateDuration({ state, owners }) {
52
- let destroyed = false;
53
- let running = false;
54
- const cleanupEffect = effect(() => {
55
- const currentState = state.get();
56
- const currentOwners = owners.get();
57
- if (!shouldUpdateDuration(currentState, currentOwners) || running) return;
58
- const { mediaSource } = currentOwners;
59
- running = true;
60
- waitForSourceBuffersReady(currentOwners).then(() => {
61
- if (destroyed || mediaSource.readyState !== "open") return;
62
- let duration = currentState.presentation.duration;
63
- const maxBufferedEnd = getMaxBufferedEnd(currentOwners);
64
- if (maxBufferedEnd > duration) duration = maxBufferedEnd;
65
- mediaSource.duration = duration;
66
- }).finally(() => {
67
- running = false;
68
- });
69
- });
70
- return () => {
71
- destroyed = true;
72
- cleanupEffect();
73
- };
74
- }
75
- //#endregion
76
- export { updateDuration };
77
-
78
- //# sourceMappingURL=update-duration.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"update-duration.js","names":[],"sources":["../../../../src/dom/features/update-duration.ts"],"sourcesContent":["import { effect } from '../../core/signals/effect';\nimport type { ReadonlySignal, Signal } from '../../core/signals/primitives';\nimport type { Presentation } from '../../core/types';\nimport { hasPresentationDuration } from '../../core/types';\n\nexport interface DurationUpdateState {\n presentation?: Presentation;\n}\n\nexport interface DurationUpdateOwners {\n mediaSource?: MediaSource;\n /** Reactive mirror of `mediaSource.readyState` — updated via DOM events. */\n mediaSourceReadyState?: ReadonlySignal<MediaSource['readyState']>;\n videoSourceBuffer?: SourceBuffer;\n audioSourceBuffer?: SourceBuffer;\n}\n\n/**\n * Check if we can update MediaSource duration (have required data).\n */\nexport function canUpdateDuration(state: DurationUpdateState, owners: DurationUpdateOwners): boolean {\n return !!(owners.mediaSource && state.presentation && hasPresentationDuration(state.presentation));\n}\n\n/**\n * Get the maximum buffered end time across all SourceBuffers.\n */\nexport function getMaxBufferedEnd(owners: DurationUpdateOwners): number {\n let maxEnd = 0;\n\n const buffers = [owners.videoSourceBuffer, owners.audioSourceBuffer].filter(\n (buf): buf is SourceBuffer => buf !== undefined\n );\n\n for (const buffer of buffers) {\n const { buffered } = buffer;\n if (buffered.length > 0) {\n const end = buffered.end(buffered.length - 1);\n if (end > maxEnd) {\n maxEnd = end;\n }\n }\n }\n\n return maxEnd;\n}\n\n/**\n * Check if we should update MediaSource duration (conditions met).\n */\nexport function shouldUpdateDuration(state: DurationUpdateState, owners: DurationUpdateOwners): boolean {\n if (!canUpdateDuration(state, owners)) return false;\n\n const { mediaSource } = owners;\n const { presentation } = state;\n\n // MediaSource must be open — use reactive readyState signal when available\n // so the effect re-evaluates when readyState changes from 'closed' to 'open'.\n const readyState = owners.mediaSourceReadyState?.get() ?? owners.mediaSource?.readyState;\n if (readyState !== 'open') return false;\n\n const duration = presentation!.duration!;\n\n // Validate duration: finite, positive, not NaN\n if (!Number.isFinite(duration) || Number.isNaN(duration) || duration <= 0) return false;\n\n // Only set duration on initial MediaSource setup, when it hasn't been set yet.\n // A freshly opened MediaSource has duration === NaN. Once set (either by this\n // task or by endOfStreamTask from buffered.end()), we leave it alone — attempting\n // to re-sync a slight drift between mediaSource.duration and presentation.duration\n // races with concurrent appendBuffer() calls from loadSegmentsTask.\n return Number.isNaN(mediaSource!.duration);\n}\n\n/**\n * Wait for all currently-updating SourceBuffers to finish.\n *\n * The MSE spec forbids setting MediaSource.duration while any attached\n * SourceBuffer has updating === true. This defers until all are idle.\n */\nfunction waitForSourceBuffersReady(owners: DurationUpdateOwners): Promise<void> {\n const updating = [owners.videoSourceBuffer, owners.audioSourceBuffer].filter(\n (buf): buf is SourceBuffer => buf?.updating === true\n );\n\n if (updating.length === 0) return Promise.resolve();\n\n return Promise.all(\n updating.map(\n (buf) => new Promise<void>((resolve) => buf.addEventListener('updateend', () => resolve(), { once: true }))\n )\n ).then(() => undefined);\n}\n\n/**\n * Update MediaSource duration when presentation duration becomes available.\n */\nexport function updateDuration<S extends DurationUpdateState, O extends DurationUpdateOwners>({\n state,\n owners,\n}: {\n state: Signal<S>;\n owners: Signal<O>;\n}): () => void {\n let destroyed = false;\n let running = false;\n\n const cleanupEffect = effect(() => {\n const currentState = state.get();\n const currentOwners = owners.get();\n\n if (!shouldUpdateDuration(currentState, currentOwners) || running) return;\n\n const { mediaSource } = currentOwners;\n running = true;\n\n // MSE spec: duration cannot be set while any SourceBuffer is updating.\n // Capture the snapshot; the async helper does not read signals.\n waitForSourceBuffersReady(currentOwners)\n .then(() => {\n // Re-check after async wait: destroyed, or readyState changed (e.g. endOfStream\n // already called endOfStream(), transitioning 'open' → 'ended').\n if (destroyed || mediaSource!.readyState !== 'open') return;\n\n let duration = currentState.presentation!.duration!;\n\n // MSE spec: duration cannot be less than any buffered range.\n // If buffered ranges exceed calculated duration, extend to match.\n const maxBufferedEnd = getMaxBufferedEnd(currentOwners);\n if (maxBufferedEnd > duration) {\n duration = maxBufferedEnd;\n }\n\n mediaSource!.duration = duration;\n })\n .finally(() => {\n running = false;\n });\n });\n\n return () => {\n destroyed = true;\n cleanupEffect();\n };\n}\n"],"mappings":";;;;;;AAoBA,SAAgB,kBAAkB,OAA4B,QAAuC;AACnG,QAAO,CAAC,EAAE,OAAO,eAAe,MAAM,gBAAgB,wBAAwB,MAAM,aAAa;;;;;AAMnG,SAAgB,kBAAkB,QAAsC;CACtE,IAAI,SAAS;CAEb,MAAM,UAAU,CAAC,OAAO,mBAAmB,OAAO,kBAAkB,CAAC,QAClE,QAA6B,QAAQ,KAAA,EACvC;AAED,MAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,EAAE,aAAa;AACrB,MAAI,SAAS,SAAS,GAAG;GACvB,MAAM,MAAM,SAAS,IAAI,SAAS,SAAS,EAAE;AAC7C,OAAI,MAAM,OACR,UAAS;;;AAKf,QAAO;;;;;AAMT,SAAgB,qBAAqB,OAA4B,QAAuC;AACtG,KAAI,CAAC,kBAAkB,OAAO,OAAO,CAAE,QAAO;CAE9C,MAAM,EAAE,gBAAgB;CACxB,MAAM,EAAE,iBAAiB;AAKzB,MADmB,OAAO,uBAAuB,KAAK,IAAI,OAAO,aAAa,gBAC3D,OAAQ,QAAO;CAElC,MAAM,WAAW,aAAc;AAG/B,KAAI,CAAC,OAAO,SAAS,SAAS,IAAI,OAAO,MAAM,SAAS,IAAI,YAAY,EAAG,QAAO;AAOlF,QAAO,OAAO,MAAM,YAAa,SAAS;;;;;;;;AAS5C,SAAS,0BAA0B,QAA6C;CAC9E,MAAM,WAAW,CAAC,OAAO,mBAAmB,OAAO,kBAAkB,CAAC,QACnE,QAA6B,KAAK,aAAa,KACjD;AAED,KAAI,SAAS,WAAW,EAAG,QAAO,QAAQ,SAAS;AAEnD,QAAO,QAAQ,IACb,SAAS,KACN,QAAQ,IAAI,SAAe,YAAY,IAAI,iBAAiB,mBAAmB,SAAS,EAAE,EAAE,MAAM,MAAM,CAAC,CAAC,CAC5G,CACF,CAAC,WAAW,KAAA,EAAU;;;;;AAMzB,SAAgB,eAA8E,EAC5F,OACA,UAIa;CACb,IAAI,YAAY;CAChB,IAAI,UAAU;CAEd,MAAM,gBAAgB,aAAa;EACjC,MAAM,eAAe,MAAM,KAAK;EAChC,MAAM,gBAAgB,OAAO,KAAK;AAElC,MAAI,CAAC,qBAAqB,cAAc,cAAc,IAAI,QAAS;EAEnE,MAAM,EAAE,gBAAgB;AACxB,YAAU;AAIV,4BAA0B,cAAc,CACrC,WAAW;AAGV,OAAI,aAAa,YAAa,eAAe,OAAQ;GAErD,IAAI,WAAW,aAAa,aAAc;GAI1C,MAAM,iBAAiB,kBAAkB,cAAc;AACvD,OAAI,iBAAiB,SACnB,YAAW;AAGb,eAAa,WAAW;IACxB,CACD,cAAc;AACb,aAAU;IACV;GACJ;AAEF,cAAa;AACX,cAAY;AACZ,iBAAe"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"append-segment.d.ts","names":[],"sources":["../../../../src/dom/media/append-segment.ts"],"mappings":";;AASA;;;;;;;KAAY,UAAA,GAAa,WAAA,GAAc,aAAA,CAAc,UAAA;;;;;;AAYrD;;;;;iBAAsB,aAAA,CAAc,YAAA,EAAc,YAAA,EAAc,IAAA,EAAM,UAAA,EAAY,MAAA,GAAS,WAAA,GAAc,OAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"append-segment.js","names":[],"sources":["../../../../src/dom/media/append-segment.ts"],"sourcesContent":["/**\n * Segment appender helper.\n *\n * Appends media data (ArrayBuffer or AsyncIterable<Uint8Array> stream) to a\n * SourceBuffer, waiting for `updateend` between calls so the browser can\n * process each append before the next one arrives.\n */\n\n/** Data accepted by appendSegment — a full buffer or an async chunk stream. */\nexport type AppendData = ArrayBuffer | AsyncIterable<Uint8Array>;\n\n/**\n * Append media data to a SourceBuffer.\n *\n * Accepts either a full ArrayBuffer (single append) or an AsyncIterable of\n * Uint8Array chunks (one append per chunk, in order). Waits for `updateend`\n * between each call so appends are serialized correctly.\n *\n * Errors from the SourceBuffer (`error` event) or from the iterable are\n * propagated as rejections.\n */\nexport async function appendSegment(sourceBuffer: SourceBuffer, data: AppendData, signal?: AbortSignal): Promise<void> {\n if (data instanceof ArrayBuffer) {\n await appendChunk(sourceBuffer, data);\n } else {\n try {\n for await (const chunk of data) {\n // Check between chunks so an abort can stop streaming before the next\n // appendBuffer call. The current chunk (if any) has already landed in the\n // SourceBuffer; the partial: true flag in the actor model reflects this.\n if (signal?.aborted) throw signal.reason ?? new DOMException('Aborted', 'AbortError');\n await appendChunk(sourceBuffer, chunk);\n }\n } catch (e) {\n // Reset the MSE segment parser on any abort to discard partial fMP4 box\n // data from the SourceBuffer's internal byte buffer. Two paths reach here:\n //\n // 1. Explicit abort check above (signal.aborted between chunks) — the\n // last appended chunk may have left the parser mid-fragment.\n //\n // 2. The fetch was cancelled (signal fired), causing the underlying\n // ReadableStream to error and the for-await loop to throw directly\n // without ever passing through the signal check above. Same cleanup\n // is needed: partial box data must be cleared before the next append.\n //\n // Without this, the next appendBuffer call sees stale partial data and\n // Chrome throws CHUNK_DEMUXER_ERROR_APPEND_FAILED.\n if (e instanceof DOMException && e.name === 'AbortError' && !sourceBuffer.updating) {\n try {\n sourceBuffer.abort();\n } catch {\n // Thrown if the MediaSource is not \"open\" (e.g. during teardown).\n }\n }\n throw e;\n }\n }\n}\n\nasync function appendChunk(sourceBuffer: SourceBuffer, data: ArrayBuffer | Uint8Array<ArrayBufferLike>): Promise<void> {\n if (sourceBuffer.updating) {\n await new Promise<void>((resolve) => {\n const onUpdateEnd = () => {\n sourceBuffer.removeEventListener('updateend', onUpdateEnd);\n resolve();\n };\n sourceBuffer.addEventListener('updateend', onUpdateEnd);\n });\n }\n\n return new Promise<void>((resolve, reject) => {\n const onUpdateEnd = () => {\n cleanup();\n resolve();\n };\n\n const onError = (event: Event) => {\n cleanup();\n reject(new Error(`SourceBuffer append error: ${event.type}`));\n };\n\n const cleanup = () => {\n sourceBuffer.removeEventListener('updateend', onUpdateEnd);\n sourceBuffer.removeEventListener('error', onError);\n };\n\n sourceBuffer.addEventListener('updateend', onUpdateEnd);\n sourceBuffer.addEventListener('error', onError);\n\n try {\n sourceBuffer.appendBuffer(data as ArrayBuffer);\n } catch (error) {\n cleanup();\n reject(error);\n }\n });\n}\n"],"mappings":";;;;;;;;;;;AAqBA,eAAsB,cAAc,cAA4B,MAAkB,QAAqC;AACrH,KAAI,gBAAgB,YAClB,OAAM,YAAY,cAAc,KAAK;KAErC,KAAI;AACF,aAAW,MAAM,SAAS,MAAM;AAI9B,OAAI,QAAQ,QAAS,OAAM,OAAO,UAAU,IAAI,aAAa,WAAW,aAAa;AACrF,SAAM,YAAY,cAAc,MAAM;;UAEjC,GAAG;AAcV,MAAI,aAAa,gBAAgB,EAAE,SAAS,gBAAgB,CAAC,aAAa,SACxE,KAAI;AACF,gBAAa,OAAO;UACd;AAIV,QAAM;;;AAKZ,eAAe,YAAY,cAA4B,MAAgE;AACrH,KAAI,aAAa,SACf,OAAM,IAAI,SAAe,YAAY;EACnC,MAAM,oBAAoB;AACxB,gBAAa,oBAAoB,aAAa,YAAY;AAC1D,YAAS;;AAEX,eAAa,iBAAiB,aAAa,YAAY;GACvD;AAGJ,QAAO,IAAI,SAAe,SAAS,WAAW;EAC5C,MAAM,oBAAoB;AACxB,YAAS;AACT,YAAS;;EAGX,MAAM,WAAW,UAAiB;AAChC,YAAS;AACT,0BAAO,IAAI,MAAM,8BAA8B,MAAM,OAAO,CAAC;;EAG/D,MAAM,gBAAgB;AACpB,gBAAa,oBAAoB,aAAa,YAAY;AAC1D,gBAAa,oBAAoB,SAAS,QAAQ;;AAGpD,eAAa,iBAAiB,aAAa,YAAY;AACvD,eAAa,iBAAiB,SAAS,QAAQ;AAE/C,MAAI;AACF,gBAAa,aAAa,KAAoB;WACvC,OAAO;AACd,YAAS;AACT,UAAO,MAAM;;GAEf"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"buffer-flusher.d.ts","names":[],"sources":["../../../../src/dom/media/buffer-flusher.ts"],"mappings":";;AAoBA;;;;;;;;;;;;;;;;;;iBAAsB,WAAA,CAAY,YAAA,EAAc,YAAA,EAAc,KAAA,UAAe,GAAA,WAAc,OAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"buffer-flusher.js","names":[],"sources":["../../../../src/dom/media/buffer-flusher.ts"],"sourcesContent":["/**\n * Buffer flusher helper (P12)\n *\n * Removes a time range from a SourceBuffer to manage memory.\n */\n\n/**\n * Remove a time range from a SourceBuffer.\n *\n * Waits for the SourceBuffer to be ready (not updating), then removes\n * the specified range. Returns a promise that resolves when removal completes.\n *\n * @param sourceBuffer - The SourceBuffer to remove data from\n * @param start - Start of the time range to remove (seconds)\n * @param end - End of the time range to remove (seconds)\n * @returns Promise that resolves when removal completes\n *\n * @example\n * await flushBuffer(videoSourceBuffer, 0, 30);\n */\nexport async function flushBuffer(sourceBuffer: SourceBuffer, start: number, end: number): Promise<void> {\n // Wait for SourceBuffer to be ready (not currently updating)\n if (sourceBuffer.updating) {\n await new Promise<void>((resolve) => {\n const onUpdateEnd = () => {\n sourceBuffer.removeEventListener('updateend', onUpdateEnd);\n resolve();\n };\n sourceBuffer.addEventListener('updateend', onUpdateEnd);\n });\n }\n\n return new Promise<void>((resolve, reject) => {\n const onUpdateEnd = () => {\n cleanup();\n resolve();\n };\n\n const onError = (event: Event) => {\n cleanup();\n reject(new Error(`SourceBuffer remove error: ${event.type}`));\n };\n\n const cleanup = () => {\n sourceBuffer.removeEventListener('updateend', onUpdateEnd);\n sourceBuffer.removeEventListener('error', onError);\n };\n\n sourceBuffer.addEventListener('updateend', onUpdateEnd);\n sourceBuffer.addEventListener('error', onError);\n\n try {\n sourceBuffer.remove(start, end);\n } catch (error) {\n cleanup();\n reject(error);\n }\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAoBA,eAAsB,YAAY,cAA4B,OAAe,KAA4B;AAEvG,KAAI,aAAa,SACf,OAAM,IAAI,SAAe,YAAY;EACnC,MAAM,oBAAoB;AACxB,gBAAa,oBAAoB,aAAa,YAAY;AAC1D,YAAS;;AAEX,eAAa,iBAAiB,aAAa,YAAY;GACvD;AAGJ,QAAO,IAAI,SAAe,SAAS,WAAW;EAC5C,MAAM,oBAAoB;AACxB,YAAS;AACT,YAAS;;EAGX,MAAM,WAAW,UAAiB;AAChC,YAAS;AACT,0BAAO,IAAI,MAAM,8BAA8B,MAAM,OAAO,CAAC;;EAG/D,MAAM,gBAAgB;AACpB,gBAAa,oBAAoB,aAAa,YAAY;AAC1D,gBAAa,oBAAoB,SAAS,QAAQ;;AAGpD,eAAa,iBAAiB,aAAa,YAAY;AACvD,eAAa,iBAAiB,SAAS,QAAQ;AAE/C,MAAI;AACF,gBAAa,OAAO,OAAO,IAAI;WACxB,OAAO;AACd,YAAS;AACT,UAAO,MAAM;;GAEf"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"mediasource-setup.js","names":[],"sources":["../../../../src/dom/media/mediasource-setup.ts"],"sourcesContent":["/**\n * MediaSource Setup\n *\n * Utilities for creating and configuring MediaSource/ManagedMediaSource\n * for MSE (Media Source Extensions) playback.\n *\n * Global ManagedMediaSource types are defined in ./mediasource.d.ts\n */\n\nimport { type ReadonlySignal, signal } from '../../core/signals/primitives';\n\n/**\n * Check if MediaSource API is supported.\n */\nexport function supportsMediaSource(): boolean {\n return typeof MediaSource !== 'undefined';\n}\n\n/**\n * Check if ManagedMediaSource API is supported.\n * ManagedMediaSource is a newer Safari API with better lifecycle management.\n */\nexport function supportsManagedMediaSource(): boolean {\n return typeof ManagedMediaSource !== 'undefined';\n}\n\n/**\n * Options for creating a MediaSource.\n */\nexport interface CreateMediaSourceOptions {\n /** Prefer ManagedMediaSource when available (default: false for broader compatibility). */\n preferManaged?: boolean;\n}\n\n/**\n * Create a MediaSource or ManagedMediaSource instance.\n *\n * @param options - Creation options\n * @returns A MediaSource or ManagedMediaSource instance\n * @throws Error if no MediaSource API is available\n *\n * @example\n * const mediaSource = createMediaSource();\n * const mediaElement = document.querySelector('video');\n * attachMediaSource(mediaSource, mediaElement);\n */\nexport function createMediaSource(options: CreateMediaSourceOptions = {}): MediaSource {\n const { preferManaged = false } = options;\n\n if (preferManaged && supportsManagedMediaSource()) {\n return new ManagedMediaSource!();\n }\n\n if (supportsMediaSource()) {\n return new MediaSource();\n }\n\n throw new Error('MediaSource API is not supported');\n}\n\n/**\n * Result of attaching a MediaSource to a media element.\n */\nexport interface AttachMediaSourceResult {\n /** The object URL created for the MediaSource (empty string for ManagedMediaSource). */\n url: string;\n /** Detach the MediaSource and clean up resources. */\n detach: () => void;\n}\n\n/**\n * Attach a MediaSource to an HTMLMediaElement.\n *\n * Uses srcObject for ManagedMediaSource (Safari), or createObjectURL for regular MediaSource.\n *\n * @param mediaSource - The MediaSource to attach\n * @param mediaElement - The media element to attach to\n * @returns Object with URL and detach function\n *\n * @example\n * const mediaSource = createMediaSource();\n * const { detach } = attachMediaSource(mediaSource, videoElement);\n * // Use mediaSource...\n * // Later, to clean up:\n * detach();\n */\nexport function attachMediaSource(mediaSource: MediaSource, mediaElement: HTMLMediaElement): AttachMediaSourceResult {\n // ManagedMediaSource requires srcObject instead of createObjectURL\n const isManagedMediaSource = supportsManagedMediaSource() && mediaSource instanceof ManagedMediaSource!;\n\n if (isManagedMediaSource) {\n // ManagedMediaSource requires disableRemotePlayback — without it Safari\n // will not fire sourceopen.\n (mediaElement as HTMLMediaElement & { disableRemotePlayback: boolean }).disableRemotePlayback = true;\n\n // Use srcObject for ManagedMediaSource\n (mediaElement as HTMLMediaElement & { srcObject: MediaSource | null }).srcObject = mediaSource;\n\n const detach = (): void => {\n (mediaElement as HTMLMediaElement & { srcObject: MediaSource | null }).srcObject = null;\n mediaElement.load(); // Reset the element\n };\n\n return { url: '', detach };\n }\n\n // Use createObjectURL for regular MediaSource\n const url = URL.createObjectURL(mediaSource);\n mediaElement.src = url;\n\n const detach = (): void => {\n mediaElement.removeAttribute('src');\n mediaElement.load(); // Reset the element\n URL.revokeObjectURL(url);\n };\n\n return { url, detach };\n}\n\n/**\n * Create a SourceBuffer on a MediaSource.\n *\n * @param mediaSource - The MediaSource (must be in 'open' state)\n * @param mimeCodec - MIME type with codecs (e.g., 'video/mp4; codecs=\"avc1.42E01E\"')\n * @returns The created SourceBuffer\n * @throws Error if MediaSource is not open or codec is unsupported\n *\n * @example\n * const buffer = createSourceBuffer(mediaSource, 'video/mp4; codecs=\"avc1.42E01E\"');\n */\nexport function createSourceBuffer(mediaSource: MediaSource, mimeCodec: string): SourceBuffer {\n if (mediaSource.readyState !== 'open') {\n throw new Error('MediaSource is not open');\n }\n\n if (!isCodecSupported(mimeCodec)) {\n throw new Error(`Codec not supported: ${mimeCodec}`);\n }\n\n return mediaSource.addSourceBuffer(mimeCodec);\n}\n\n/**\n * Check if a codec is supported.\n *\n * @param mimeCodec - MIME type with codecs string\n * @returns True if the codec is supported\n *\n * @example\n * if (isCodecSupported('video/mp4; codecs=\"avc1.42E01E\"')) {\n * // Create source buffer\n * }\n */\nexport function isCodecSupported(mimeCodec: string): boolean {\n if (!supportsMediaSource()) {\n return false;\n }\n\n return MediaSource.isTypeSupported(mimeCodec);\n}\n\n/**\n * Create a reactive signal that mirrors `mediaSource.readyState`.\n *\n * Listens to `sourceopen`, `sourceended`, and `sourceclose` events and updates\n * the signal accordingly, making readyState visible to the TC39 signal graph.\n * Listeners are automatically removed when `signal` is aborted.\n *\n * @param mediaSource - The MediaSource to observe\n * @param signal - AbortSignal that controls listener lifetime\n * @returns A `Signal.ReadonlyState` that reflects the current `readyState`\n *\n * @example\n * const controller = new AbortController();\n * const readyState = observeMediaSourceReadyState(mediaSource, controller.signal);\n * effect(() => {\n * if (readyState.get() === 'open') { ... }\n * });\n * // Later:\n * controller.abort();\n */\nexport function observeMediaSourceReadyState(\n mediaSource: MediaSource,\n abortSignal: AbortSignal\n): ReadonlySignal<MediaSource['readyState']> {\n const readyState = signal<MediaSource['readyState']>(mediaSource.readyState);\n const update = () => readyState.set(mediaSource.readyState);\n const options = { signal: abortSignal };\n mediaSource.addEventListener('sourceopen', update, options);\n mediaSource.addEventListener('sourceended', update, options);\n mediaSource.addEventListener('sourceclose', update, options);\n return readyState;\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,SAAgB,sBAA+B;AAC7C,QAAO,OAAO,gBAAgB;;;;;;AAOhC,SAAgB,6BAAsC;AACpD,QAAO,OAAO,uBAAuB;;;;;;;;;;;;;;AAuBvC,SAAgB,kBAAkB,UAAoC,EAAE,EAAe;CACrF,MAAM,EAAE,gBAAgB,UAAU;AAElC,KAAI,iBAAiB,4BAA4B,CAC/C,QAAO,IAAI,oBAAqB;AAGlC,KAAI,qBAAqB,CACvB,QAAO,IAAI,aAAa;AAG1B,OAAM,IAAI,MAAM,mCAAmC;;;;;;;;;;;;;;;;;;AA6BrD,SAAgB,kBAAkB,aAA0B,cAAyD;AAInH,KAF6B,4BAA4B,IAAI,uBAAuB,oBAE1D;AAGvB,eAAuE,wBAAwB;AAG/F,eAAsE,YAAY;EAEnF,MAAM,eAAqB;AACxB,gBAAsE,YAAY;AACnF,gBAAa,MAAM;;AAGrB,SAAO;GAAE,KAAK;GAAI;GAAQ;;CAI5B,MAAM,MAAM,IAAI,gBAAgB,YAAY;AAC5C,cAAa,MAAM;CAEnB,MAAM,eAAqB;AACzB,eAAa,gBAAgB,MAAM;AACnC,eAAa,MAAM;AACnB,MAAI,gBAAgB,IAAI;;AAG1B,QAAO;EAAE;EAAK;EAAQ;;;;;;;;;;;;;AAcxB,SAAgB,mBAAmB,aAA0B,WAAiC;AAC5F,KAAI,YAAY,eAAe,OAC7B,OAAM,IAAI,MAAM,0BAA0B;AAG5C,KAAI,CAAC,iBAAiB,UAAU,CAC9B,OAAM,IAAI,MAAM,wBAAwB,YAAY;AAGtD,QAAO,YAAY,gBAAgB,UAAU;;;;;;;;;;;;;AAc/C,SAAgB,iBAAiB,WAA4B;AAC3D,KAAI,CAAC,qBAAqB,CACxB,QAAO;AAGT,QAAO,YAAY,gBAAgB,UAAU;;;;;;;;;;;;;;;;;;;;;;AAuB/C,SAAgB,6BACd,aACA,aAC2C;CAC3C,MAAM,aAAa,OAAkC,YAAY,WAAW;CAC5E,MAAM,eAAe,WAAW,IAAI,YAAY,WAAW;CAC3D,MAAM,UAAU,EAAE,QAAQ,aAAa;AACvC,aAAY,iBAAiB,cAAc,QAAQ,QAAQ;AAC3D,aAAY,iBAAiB,eAAe,QAAQ,QAAQ;AAC5D,aAAY,iBAAiB,eAAe,QAAQ,QAAQ;AAC5D,QAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"source-buffer-actor.d.ts","names":[],"sources":["../../../../src/dom/media/source-buffer-actor.ts"],"mappings":";;;;;UAUiB,aAAA;EACf,KAAA;EACA,GAAA;AAAA;AAAA,KAGU,iBAAA,GAAoB,IAAA,CAAK,OAAA;EACnC,OAAA,EAAS,KAAA,QAJN;EAMH,cAAA;AAAA;AAAA,KAKU,iBAAA;EAAsB,IAAA;EAAqB,IAAA,EAAM,UAAA;EAAY,IAAA;IAAQ,OAAA,EAAS,KAAA;EAAA;AAAA;AAAA,KAC9E,oBAAA;EAAyB,IAAA;EAAwB,IAAA,EAAM,UAAA;EAAY,IAAA,EAAM,iBAAA;AAAA;AAAA,KACzE,aAAA;EAAkB,IAAA;EAAgB,KAAA;EAAe,GAAA;AAAA;AAAA,KACjD,6BAAA,GAAgC,iBAAA,GAAoB,oBAAA,GAAuB,aAAA;AAAA,KAC3E,YAAA;EAAiB,IAAA;EAAe,QAAA,EAAU,6BAAA;AAAA;AAAA,KAC1C,aAAA;EAAkB,IAAA;AAAA;;KAGlB,mBAAA,GAAsB,6BAAA,GAAgC,YAAA,GAAe,aAAA;;KAGrE,sBAAA;;UAGK,wBAAA;EACf,WAAA;EACA,QAAA,EAAU,KAAA,CACR,IAAA,CAAK,OAAA;IACH,OAAA,EAAS,KAAA;IACT,cAAA;IAjBM;;;;;IAuBN,OAAA;EAAA;EAGJ,cAAA,EAAgB,aAAA;AAAA;AAzBlB;AAAA,KA6BY,iBAAA,GAAoB,YAAA,CAAa,sBAAA,EAAwB,wBAAA,EAA0B,mBAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"source-buffer-actor.js","names":[],"sources":["../../../../src/dom/media/source-buffer-actor.ts"],"sourcesContent":["import { createMachineActor, type HandlerContext, type MessageActor } from '../../core/create-machine-actor';\nimport { SerialRunner, Task } from '../../core/task';\nimport type { Segment, Track } from '../../core/types';\nimport { type AppendData, appendSegment } from './append-segment';\nimport { flushBuffer } from './buffer-flusher';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface BufferedRange {\n start: number;\n end: number;\n}\n\nexport type AppendSegmentMeta = Pick<Segment, 'id' | 'startTime' | 'duration'> & {\n trackId: Track['id'];\n /** Declared track bandwidth in bps (from playlist BANDWIDTH attribute). */\n trackBandwidth?: number;\n};\n\nexport type { AppendData };\n\nexport type AppendInitMessage = { type: 'append-init'; data: AppendData; meta: { trackId: Track['id'] } };\nexport type AppendSegmentMessage = { type: 'append-segment'; data: AppendData; meta: AppendSegmentMeta };\nexport type RemoveMessage = { type: 'remove'; start: number; end: number };\nexport type IndividualSourceBufferMessage = AppendInitMessage | AppendSegmentMessage | RemoveMessage;\nexport type BatchMessage = { type: 'batch'; messages: IndividualSourceBufferMessage[] };\nexport type CancelMessage = { type: 'cancel' };\n\n/** All messages accepted by a SourceBufferActor. */\nexport type SourceBufferMessage = IndividualSourceBufferMessage | BatchMessage | CancelMessage;\n\n/** Finite states of the actor. */\nexport type SourceBufferActorState = 'idle' | 'updating' | 'destroyed';\n\n/** Non-finite (extended) data managed by the actor — the XState \"context\". */\nexport interface SourceBufferActorContext {\n initTrackId?: string | undefined;\n segments: Array<\n Pick<Segment, 'id' | 'startTime' | 'duration'> & {\n trackId: Track['id'];\n trackBandwidth?: number;\n /**\n * True while a streaming append is in progress for this segment.\n * The segment's data is partially present in the SourceBuffer.\n * Downstream code must not treat a partial segment as fully buffered.\n */\n partial?: boolean;\n }\n >;\n bufferedRanges: BufferedRange[];\n}\n\n/** SourceBuffer actor: queues operations, owns its snapshot. */\nexport type SourceBufferActor = MessageActor<SourceBufferActorState, SourceBufferActorContext, SourceBufferMessage>;\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nfunction snapshotBuffered(buffered: TimeRanges): BufferedRange[] {\n const ranges: BufferedRange[] = [];\n for (let i = 0; i < buffered.length; i++) {\n ranges.push({ start: buffered.start(i), end: buffered.end(i) });\n }\n return ranges;\n}\n\n// =============================================================================\n// Message task factories\n// =============================================================================\n\n// Context is read lazily via getContext at task execution time — not at creation\n// time — so each task always operates on the most recent context regardless of\n// when it was scheduled.\n\ninterface MessageTaskOptions {\n getContext: () => SourceBufferActorContext;\n sourceBuffer: SourceBuffer;\n setContext: (ctx: SourceBufferActorContext) => void;\n}\n\nfunction appendInitTask(\n message: AppendInitMessage,\n { getContext, sourceBuffer }: MessageTaskOptions\n): Task<SourceBufferActorContext> {\n return new Task(async (taskSignal) => {\n const ctx = getContext();\n if (taskSignal.aborted) return ctx;\n await appendSegment(sourceBuffer, message.data);\n // No abort check here: the physical SourceBuffer has been modified, so\n // the model must be updated to match regardless of signal state.\n return { ...ctx, initTrackId: message.meta.trackId };\n });\n}\n\nfunction appendSegmentTask(\n message: AppendSegmentMessage,\n { getContext, sourceBuffer, setContext }: MessageTaskOptions\n): Task<SourceBufferActorContext> {\n return new Task(async (taskSignal) => {\n const ctx = getContext();\n if (taskSignal.aborted) return ctx;\n\n const { meta } = message;\n // Remove any existing entry at the same start time (same \"slot\" in the\n // timeline), then record the new segment. Assumes time-aligned segments\n // across playlists. The epsilon guards against floating-point drift in\n // parsed timestamps.\n const EPSILON = 0.0001;\n const filtered = ctx.segments.filter((s) => Math.abs(s.startTime - meta.startTime) >= EPSILON);\n\n // For streaming data: emit partial state before the first chunk so\n // downstream code can see the in-progress segment and treat it as\n // incomplete. ArrayBuffer appends are atomic so no partial state is\n // needed — context is updated once at task completion.\n if (!(message.data instanceof ArrayBuffer)) {\n setContext({\n ...ctx,\n segments: [\n ...filtered,\n {\n id: meta.id,\n startTime: meta.startTime,\n duration: meta.duration,\n trackId: meta.trackId,\n ...(meta.trackBandwidth !== undefined && { trackBandwidth: meta.trackBandwidth }),\n partial: true,\n },\n ],\n bufferedRanges: ctx.bufferedRanges,\n });\n }\n\n await appendSegment(sourceBuffer, message.data, taskSignal);\n // No abort check here: the physical SourceBuffer has been modified, so\n // the model must be updated to match regardless of signal state.\n return {\n ...ctx,\n segments: [\n ...filtered,\n {\n id: meta.id,\n startTime: meta.startTime,\n duration: meta.duration,\n trackId: meta.trackId,\n ...(meta.trackBandwidth !== undefined && { trackBandwidth: meta.trackBandwidth }),\n },\n ],\n bufferedRanges: snapshotBuffered(sourceBuffer.buffered),\n };\n });\n}\n\nfunction removeTask(\n message: RemoveMessage,\n { getContext, sourceBuffer }: MessageTaskOptions\n): Task<SourceBufferActorContext> {\n return new Task(async (taskSignal) => {\n const ctx = getContext();\n if (taskSignal.aborted) return ctx;\n await flushBuffer(sourceBuffer, message.start, message.end);\n // No abort check here: the physical SourceBuffer has been modified, so\n // the model must be updated to match regardless of signal state.\n //\n // Use the post-flush buffered ranges as ground truth. A segment is kept\n // in the model only if its midpoint falls within a buffered range.\n // Midpoint-based membership handles flush boundaries that don't align\n // exactly with segment edges without over-removing adjacent segments.\n const bufferedRanges = snapshotBuffered(sourceBuffer.buffered);\n const filtered = ctx.segments.filter((s) => {\n const midpoint = s.startTime + s.duration / 2;\n return bufferedRanges.some((r) => midpoint >= r.start && midpoint < r.end);\n });\n return { ...ctx, segments: filtered, bufferedRanges };\n });\n}\n\ntype MessageTaskFactory<T extends IndividualSourceBufferMessage> = (\n message: T,\n options: MessageTaskOptions\n) => Task<SourceBufferActorContext>;\n\nconst messageTaskFactories = {\n 'append-init': appendInitTask,\n 'append-segment': appendSegmentTask,\n remove: removeTask,\n} satisfies {\n [K in IndividualSourceBufferMessage['type']]: MessageTaskFactory<Extract<IndividualSourceBufferMessage, { type: K }>>;\n};\n\nfunction messageToTask(\n message: IndividualSourceBufferMessage,\n options: MessageTaskOptions\n): Task<SourceBufferActorContext> {\n const factory = messageTaskFactories[message.type] as MessageTaskFactory<typeof message>;\n return factory(message, options);\n}\n\n// =============================================================================\n// Implementation\n// =============================================================================\n\nexport function createSourceBufferActor(\n sourceBuffer: SourceBuffer,\n initialContext?: Partial<SourceBufferActorContext>\n): SourceBufferActor {\n type UserState = Exclude<SourceBufferActorState, 'destroyed'>;\n\n const handleError = (e: unknown): void => {\n if (!(e instanceof Error && e.name === 'AbortError')) {\n console.error('SourceBuffer operation failed:', e);\n }\n };\n\n type Ctx = HandlerContext<UserState, SourceBufferActorContext, () => SerialRunner>;\n\n const onMessage = (msg: IndividualSourceBufferMessage, { transition, setContext, getContext, runner }: Ctx): void => {\n transition('updating');\n const task = messageToTask(msg, { getContext, sourceBuffer, setContext });\n runner.schedule(task).then(setContext, handleError);\n };\n\n return createMachineActor<UserState, SourceBufferActorContext, SourceBufferMessage, () => SerialRunner>({\n runner: () => new SerialRunner(),\n initial: 'idle',\n context: { segments: [], bufferedRanges: [], initTrackId: undefined, ...initialContext },\n states: {\n idle: {\n on: {\n 'append-init': onMessage,\n 'append-segment': onMessage,\n remove: onMessage,\n batch: (msg, { transition, setContext, getContext, runner }) => {\n const { messages } = msg;\n if (messages.length === 0) return;\n\n transition('updating');\n messages.forEach((msg) => {\n const task = messageToTask(msg, { getContext, sourceBuffer, setContext });\n runner.schedule(task).then(setContext, handleError);\n });\n },\n },\n },\n updating: {\n // Automatically return to idle once all scheduled tasks settle.\n onSettled: 'idle',\n on: {\n // Abort all in-progress and pending tasks. onSettled handles → 'idle'\n // once the aborted tasks drain.\n cancel: (_, { runner }) => {\n runner.abortAll();\n },\n },\n },\n },\n });\n}\n"],"mappings":";;;;;AA6DA,SAAS,iBAAiB,UAAuC;CAC/D,MAAM,SAA0B,EAAE;AAClC,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,IACnC,QAAO,KAAK;EAAE,OAAO,SAAS,MAAM,EAAE;EAAE,KAAK,SAAS,IAAI,EAAE;EAAE,CAAC;AAEjE,QAAO;;AAiBT,SAAS,eACP,SACA,EAAE,YAAY,gBACkB;AAChC,QAAO,IAAI,KAAK,OAAO,eAAe;EACpC,MAAM,MAAM,YAAY;AACxB,MAAI,WAAW,QAAS,QAAO;AAC/B,QAAM,cAAc,cAAc,QAAQ,KAAK;AAG/C,SAAO;GAAE,GAAG;GAAK,aAAa,QAAQ,KAAK;GAAS;GACpD;;AAGJ,SAAS,kBACP,SACA,EAAE,YAAY,cAAc,cACI;AAChC,QAAO,IAAI,KAAK,OAAO,eAAe;EACpC,MAAM,MAAM,YAAY;AACxB,MAAI,WAAW,QAAS,QAAO;EAE/B,MAAM,EAAE,SAAS;EAKjB,MAAM,UAAU;EAChB,MAAM,WAAW,IAAI,SAAS,QAAQ,MAAM,KAAK,IAAI,EAAE,YAAY,KAAK,UAAU,IAAI,QAAQ;AAM9F,MAAI,EAAE,QAAQ,gBAAgB,aAC5B,YAAW;GACT,GAAG;GACH,UAAU,CACR,GAAG,UACH;IACE,IAAI,KAAK;IACT,WAAW,KAAK;IAChB,UAAU,KAAK;IACf,SAAS,KAAK;IACd,GAAI,KAAK,mBAAmB,KAAA,KAAa,EAAE,gBAAgB,KAAK,gBAAgB;IAChF,SAAS;IACV,CACF;GACD,gBAAgB,IAAI;GACrB,CAAC;AAGJ,QAAM,cAAc,cAAc,QAAQ,MAAM,WAAW;AAG3D,SAAO;GACL,GAAG;GACH,UAAU,CACR,GAAG,UACH;IACE,IAAI,KAAK;IACT,WAAW,KAAK;IAChB,UAAU,KAAK;IACf,SAAS,KAAK;IACd,GAAI,KAAK,mBAAmB,KAAA,KAAa,EAAE,gBAAgB,KAAK,gBAAgB;IACjF,CACF;GACD,gBAAgB,iBAAiB,aAAa,SAAS;GACxD;GACD;;AAGJ,SAAS,WACP,SACA,EAAE,YAAY,gBACkB;AAChC,QAAO,IAAI,KAAK,OAAO,eAAe;EACpC,MAAM,MAAM,YAAY;AACxB,MAAI,WAAW,QAAS,QAAO;AAC/B,QAAM,YAAY,cAAc,QAAQ,OAAO,QAAQ,IAAI;EAQ3D,MAAM,iBAAiB,iBAAiB,aAAa,SAAS;EAC9D,MAAM,WAAW,IAAI,SAAS,QAAQ,MAAM;GAC1C,MAAM,WAAW,EAAE,YAAY,EAAE,WAAW;AAC5C,UAAO,eAAe,MAAM,MAAM,YAAY,EAAE,SAAS,WAAW,EAAE,IAAI;IAC1E;AACF,SAAO;GAAE,GAAG;GAAK,UAAU;GAAU;GAAgB;GACrD;;AAQJ,MAAM,uBAAuB;CAC3B,eAAe;CACf,kBAAkB;CAClB,QAAQ;CACT;AAID,SAAS,cACP,SACA,SACgC;CAChC,MAAM,UAAU,qBAAqB,QAAQ;AAC7C,QAAO,QAAQ,SAAS,QAAQ;;AAOlC,SAAgB,wBACd,cACA,gBACmB;CAGnB,MAAM,eAAe,MAAqB;AACxC,MAAI,EAAE,aAAa,SAAS,EAAE,SAAS,cACrC,SAAQ,MAAM,kCAAkC,EAAE;;CAMtD,MAAM,aAAa,KAAoC,EAAE,YAAY,YAAY,YAAY,aAAwB;AACnH,aAAW,WAAW;EACtB,MAAM,OAAO,cAAc,KAAK;GAAE;GAAY;GAAc;GAAY,CAAC;AACzE,SAAO,SAAS,KAAK,CAAC,KAAK,YAAY,YAAY;;AAGrD,QAAO,mBAAiG;EACtG,cAAc,IAAI,cAAc;EAChC,SAAS;EACT,SAAS;GAAE,UAAU,EAAE;GAAE,gBAAgB,EAAE;GAAE,aAAa,KAAA;GAAW,GAAG;GAAgB;EACxF,QAAQ;GACN,MAAM,EACJ,IAAI;IACF,eAAe;IACf,kBAAkB;IAClB,QAAQ;IACR,QAAQ,KAAK,EAAE,YAAY,YAAY,YAAY,aAAa;KAC9D,MAAM,EAAE,aAAa;AACrB,SAAI,SAAS,WAAW,EAAG;AAE3B,gBAAW,WAAW;AACtB,cAAS,SAAS,QAAQ;MACxB,MAAM,OAAO,cAAc,KAAK;OAAE;OAAY;OAAc;OAAY,CAAC;AACzE,aAAO,SAAS,KAAK,CAAC,KAAK,YAAY,YAAY;OACnD;;IAEL,EACF;GACD,UAAU;IAER,WAAW;IACX,IAAI,EAGF,SAAS,GAAG,EAAE,aAAa;AACzB,YAAO,UAAU;OAEpB;IACF;GACF;EACF,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"chunked-stream-iterable.js","names":["#readableStream"],"sources":["../../../../src/dom/network/chunked-stream-iterable.ts"],"sourcesContent":["const DEFAULT_MIN_CHUNK_SIZE = 2 ** 17; // 128 KB\n\nexport interface ChunkedStreamIterableOptions {\n minChunkSize?: number;\n}\n\n/**\n * Adapts a `ReadableStream<Uint8Array>` (e.g. `response.body`) into an\n * `AsyncIterable<Uint8Array>` that yields chunks no smaller than\n * `minChunkSize` bytes. Smaller network chunks are accumulated and yielded\n * together once the threshold is met. Any remainder is flushed on stream end.\n *\n * Errors from the underlying stream propagate naturally — the reader lock is\n * always released via `finally`.\n */\nexport class ChunkedStreamIterable implements AsyncIterable<Uint8Array> {\n readonly minChunkSize: number;\n #readableStream: ReadableStream<Uint8Array>;\n\n constructor(\n readableStream: ReadableStream<Uint8Array>,\n { minChunkSize = DEFAULT_MIN_CHUNK_SIZE }: ChunkedStreamIterableOptions = {}\n ) {\n this.#readableStream = readableStream;\n this.minChunkSize = minChunkSize;\n }\n\n async *[Symbol.asyncIterator](): AsyncGenerator<Uint8Array> {\n let pending: Uint8Array | undefined;\n const reader = this.#readableStream.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n if (pending) yield pending;\n break;\n }\n\n pending = pending ? concat(pending, value) : value;\n\n if (pending.length >= this.minChunkSize) {\n yield pending;\n pending = undefined;\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n const result = new Uint8Array(a.length + b.length);\n result.set(a);\n result.set(b, a.length);\n return result;\n}\n"],"mappings":";AAAA,MAAM,yBAAyB,KAAK;;;;;;;;;;AAepC,IAAa,wBAAb,MAAwE;CACtE;CACA;CAEA,YACE,gBACA,EAAE,eAAe,2BAAyD,EAAE,EAC5E;AACA,QAAA,iBAAuB;AACvB,OAAK,eAAe;;CAGtB,QAAQ,OAAO,iBAA6C;EAC1D,IAAI;EACJ,MAAM,SAAS,MAAA,eAAqB,WAAW;AAC/C,MAAI;AACF,UAAO,MAAM;IACX,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAC3C,QAAI,MAAM;AACR,SAAI,QAAS,OAAM;AACnB;;AAGF,cAAU,UAAU,OAAO,SAAS,MAAM,GAAG;AAE7C,QAAI,QAAQ,UAAU,KAAK,cAAc;AACvC,WAAM;AACN,eAAU,KAAA;;;YAGN;AACR,UAAO,aAAa;;;;AAK1B,SAAS,OAAO,GAAe,GAA2B;CACxD,MAAM,SAAS,IAAI,WAAW,EAAE,SAAS,EAAE,OAAO;AAClD,QAAO,IAAI,EAAE;AACb,QAAO,IAAI,GAAG,EAAE,OAAO;AACvB,QAAO"}
@@ -1,54 +0,0 @@
1
- //#region src/dom/network/fetch.ts
2
- /**
3
- * Fetch resolvable from AddressableObject.
4
- *
5
- * Handles byte range requests if byteRange is present.
6
- * Returns native fetch Response for composability (can extract text, stream, etc.).
7
- *
8
- * @param addressable - Resource to fetch (url + optional byteRange)
9
- * @returns Promise resolving to Response
10
- *
11
- * @example
12
- * const response = await fetchResolvable({ url: 'https://example.com/segment.m4s' });
13
- * const text = await getResponseText(response);
14
- *
15
- * @example
16
- * // With byte range
17
- * const response = await fetchResolvable({
18
- * url: 'https://example.com/file.mp4',
19
- * byteRange: { start: 1000, end: 1999 }
20
- * });
21
- */
22
- async function fetchResolvable(addressable, options) {
23
- const headers = new Headers(options?.headers);
24
- if (addressable.byteRange) {
25
- const { start, end } = addressable.byteRange;
26
- headers.set("Range", `bytes=${start}-${end}`);
27
- }
28
- const request = new Request(addressable.url, {
29
- method: "GET",
30
- headers,
31
- ...options
32
- });
33
- return fetch(request);
34
- }
35
- /**
36
- * Extract text from Response.
37
- *
38
- * Accepts minimal Response-like object (just needs text() method).
39
- * Returns promise from response.text().
40
- *
41
- * @param response - Response-like object with text() method
42
- * @returns Promise resolving to text content
43
- *
44
- * @example
45
- * const response = await fetchResolvable(addressable);
46
- * const text = await getResponseText(response);
47
- */
48
- function getResponseText(response) {
49
- return response.text();
50
- }
51
- //#endregion
52
- export { fetchResolvable, getResponseText };
53
-
54
- //# sourceMappingURL=fetch.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fetch.js","names":[],"sources":["../../../../src/dom/network/fetch.ts"],"sourcesContent":["/**\n * HTTP Fetch Wrapper\n *\n * Two-function approach for composability:\n * 1. fetchResolvable() - Fetch AddressableObject (handles byte ranges)\n * 2. getResponseText() - Extract text from Response\n * 3. fetchResolvableStream() - Stream body as Uint8Array chunks\n */\n\nimport type { AddressableObject } from '../../core/types';\nimport { ChunkedStreamIterable, type ChunkedStreamIterableOptions } from './chunked-stream-iterable';\n\n/**\n * Minimal Response-like interface for text extraction.\n * Allows testing without full Response object.\n */\nexport interface ResponseLike {\n text(): Promise<string>;\n}\n\n/**\n * Fetch resolvable from AddressableObject.\n *\n * Handles byte range requests if byteRange is present.\n * Returns native fetch Response for composability (can extract text, stream, etc.).\n *\n * @param addressable - Resource to fetch (url + optional byteRange)\n * @returns Promise resolving to Response\n *\n * @example\n * const response = await fetchResolvable({ url: 'https://example.com/segment.m4s' });\n * const text = await getResponseText(response);\n *\n * @example\n * // With byte range\n * const response = await fetchResolvable({\n * url: 'https://example.com/file.mp4',\n * byteRange: { start: 1000, end: 1999 }\n * });\n */\nexport async function fetchResolvable(addressable: AddressableObject, options?: RequestInit): Promise<Response> {\n const headers = new Headers(options?.headers);\n\n // Add Range header for byte range requests\n if (addressable.byteRange) {\n const { start, end } = addressable.byteRange;\n headers.set('Range', `bytes=${start}-${end}`);\n }\n\n const request = new Request(addressable.url, {\n method: 'GET',\n headers,\n ...options,\n });\n\n return fetch(request);\n}\n\n/**\n * Fetch resolvable as bytes.\n *\n * Convenience wrapper around fetchResolvable that resolves the body as an\n * ArrayBuffer. Use this when you need the raw bytes (e.g. segment appends).\n * For text or streaming consumption, use fetchResolvable directly.\n */\nexport async function fetchResolvableBytes(\n addressable: AddressableObject,\n options?: RequestInit\n): Promise<ArrayBuffer> {\n const response = await fetchResolvable(addressable, options);\n return response.arrayBuffer();\n}\n\n/**\n * Fetch resolvable as a stream of Uint8Array chunks.\n *\n * Convenience wrapper around fetchResolvable that yields the body as chunks\n * via ChunkedStreamIterable. Headers are awaited before the first chunk is\n * yielded (TTFB is accounted for before iteration begins).\n *\n * Throws if the response body is null (e.g. non-body HTTP status).\n * Errors from the underlying stream propagate naturally as thrown errors.\n */\nexport async function* fetchResolvableStream(\n addressable: AddressableObject,\n options?: RequestInit & ChunkedStreamIterableOptions\n): AsyncGenerator<Uint8Array> {\n const { minChunkSize, ...fetchOptions } = options ?? {};\n const response = await fetchResolvable(addressable, fetchOptions);\n if (!response.body) throw new Error('Response has no body');\n yield* new ChunkedStreamIterable(response.body, ...(minChunkSize !== undefined ? [{ minChunkSize }] : []));\n}\n\n/**\n * Extract text from Response.\n *\n * Accepts minimal Response-like object (just needs text() method).\n * Returns promise from response.text().\n *\n * @param response - Response-like object with text() method\n * @returns Promise resolving to text content\n *\n * @example\n * const response = await fetchResolvable(addressable);\n * const text = await getResponseText(response);\n */\nexport function getResponseText(response: ResponseLike): Promise<string> {\n return response.text();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwCA,eAAsB,gBAAgB,aAAgC,SAA0C;CAC9G,MAAM,UAAU,IAAI,QAAQ,SAAS,QAAQ;AAG7C,KAAI,YAAY,WAAW;EACzB,MAAM,EAAE,OAAO,QAAQ,YAAY;AACnC,UAAQ,IAAI,SAAS,SAAS,MAAM,GAAG,MAAM;;CAG/C,MAAM,UAAU,IAAI,QAAQ,YAAY,KAAK;EAC3C,QAAQ;EACR;EACA,GAAG;EACJ,CAAC;AAEF,QAAO,MAAM,QAAQ;;;;;;;;;;;;;;;AAmDvB,SAAgB,gBAAgB,UAAyC;AACvE,QAAO,SAAS,MAAM"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"adapter.d.ts","names":[],"sources":["../../../../src/dom/playback-engine/adapter.ts"],"mappings":";;;;UAKiB,WAAA;EAAA,SACN,MAAA,EAAQ,cAAA;EACjB,GAAA;EACA,OAAA;EACA,MAAA,CAAO,YAAA,EAAc,gBAAA;EACrB,MAAA;EACA,OAAA;EACA,IAAA,IAAQ,OAAA;AAAA;;;;;;;;;;;;;;;AAqBV;;;;iBAAgB,aAAA,cAA2B,WAAA,MAAA,CAAkB,SAAA,EAAW,IAAA,GAuIpC,WAAA,CAAY,IAAA,EAAM,WAAA;AAAA,cACrD,aAAA;;;;cAGY,QAAA,SAAiB,aAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"adapter.js","names":["#config","#engine","#cancelPendingPlay","#preload","#loadstartListener"],"sources":["../../../../src/dom/playback-engine/adapter.ts"],"sourcesContent":["import type { Constructor, MixinReturn } from '@videojs/utils/types';\nimport { update } from '../../core/signals/primitives';\nimport type { PlaybackEngineConfig } from './engine';\nimport { createPlaybackEngine, type PlaybackEngine } from './engine';\n\nexport interface SpfMediaAPI {\n readonly engine: PlaybackEngine;\n src: string;\n preload: '' | 'none' | 'metadata' | 'auto';\n attach(mediaElement: HTMLMediaElement): void;\n detach(): void;\n destroy(): void;\n play(): Promise<void>;\n}\n\n/**\n * Mixin that adds SPF playback engine behavior to any base class.\n *\n * Implements the src/play() contract per the WHATWG HTML spec so that SPF can\n * be used anywhere a media element API is expected.\n *\n * A new engine is created on every src assignment — this fully tears down all\n * state, SourceBuffers, and in-flight requests from the previous source before\n * the next one begins. The media element reference is preserved across src\n * changes and re-applied to the new engine automatically.\n *\n * @example\n * class SimpleHlsMedia extends SpfMediaMixin(HTMLVideoElementHost) {}\n *\n * const media = new SimpleHlsMedia();\n * media.attach(document.querySelector('video'));\n * media.src = 'https://stream.mux.com/abc123.m3u8';\n */\nexport function SpfMediaMixin<Base extends Constructor<any>>(BaseClass: Base) {\n class SpfMediaImpl extends BaseClass {\n #engine: PlaybackEngine;\n #config: PlaybackEngineConfig;\n #preload: '' | 'none' | 'metadata' | 'auto' = '';\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 = createPlaybackEngine(config);\n }\n\n get engine(): PlaybackEngine {\n return this.#engine;\n }\n\n // -------------------------------------------------------------------------\n // Media element lifecycle\n // -------------------------------------------------------------------------\n\n attach(mediaElement: HTMLMediaElement): void {\n super.attach?.(mediaElement);\n update(this.#engine.owners, { mediaElement });\n }\n\n detach(): void {\n this.#cancelPendingPlay();\n update(this.#engine.owners, { mediaElement: 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 this.#preload = value;\n if (value) {\n update(this.#engine.state, { preload: value });\n }\n // value = '' clears #preload (so the next engine recreation won't re-apply\n // an explicit value) but does not patch current state — the existing preload\n // stays in effect until the next src change creates a fresh engine.\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, exactly\n // as the browser's load algorithm resets all media element state on src change.\n // -------------------------------------------------------------------------\n\n get src(): string {\n return this.#engine.state.get().presentation?.url ?? '';\n }\n\n set src(value: string) {\n const prevMediaElement = this.#engine.owners.get().mediaElement;\n\n this.#cancelPendingPlay();\n this.#engine.destroy();\n this.#engine = createPlaybackEngine(this.#config);\n\n // Apply explicit preload before setting owners so syncPreloadAttribute skips\n // element inference and the explicit value is preserved across src changes.\n if (this.#preload) {\n update(this.#engine.state, { preload: this.#preload });\n }\n\n if (prevMediaElement) {\n update(this.#engine.owners, { mediaElement: prevMediaElement });\n }\n\n if (value) {\n update(this.#engine.state, { presentation: { url: value } });\n }\n }\n\n // -------------------------------------------------------------------------\n // play() — WHATWG §4.8.11.8\n // Delegates to the attached media element's native play().\n // -------------------------------------------------------------------------\n\n play(): Promise<void> {\n const { mediaElement } = this.#engine.owners.get();\n if (!mediaElement) {\n return Promise.reject(new Error('SpfMedia: no media element attached'));\n }\n\n // Signal play intent — enables loading even with preload=\"none\"\n update(this.#engine.state, { playbackInitiated: true });\n\n return mediaElement.play().catch((err: unknown) => {\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 #cancelPendingPlay(): void {\n if (!this.#loadstartListener) return;\n const { mediaElement } = this.#engine.owners.get();\n mediaElement?.removeEventListener('loadstart', this.#loadstartListener);\n this.#loadstartListener = null;\n }\n }\n\n return SpfMediaImpl as unknown as MixinReturn<Base, SpfMediaAPI>;\n}\n\n/** Standalone SPF media adapter with no base class. */\nexport class SpfMedia extends SpfMediaMixin(class {}) {}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAiCA,SAAgB,cAA6C,WAAiB;CAC5E,MAAM,qBAAqB,UAAU;EACnC;EACA;EACA,WAA8C;;EAG9C,qBAA0C;EAE1C,YAAY,GAAG,MAAa;AAC1B,SAAM,GAAG,KAAK;GAEd,MAAM,EAAE,WAAW,OAAO,MAAM,EAAE;AAClC,SAAA,SAAe;AACf,SAAA,SAAe,qBAAqB,OAAO;;EAG7C,IAAI,SAAyB;AAC3B,UAAO,MAAA;;EAOT,OAAO,cAAsC;AAC3C,SAAM,SAAS,aAAa;AAC5B,UAAO,MAAA,OAAa,QAAQ,EAAE,cAAc,CAAC;;EAG/C,SAAe;AACb,SAAA,mBAAyB;AACzB,UAAO,MAAA,OAAa,QAAQ,EAAE,cAAc,KAAA,GAAW,CAAC;AACxD,SAAM,UAAU;;EAGlB,UAAgB;AACd,SAAA,mBAAyB;AACzB,SAAA,OAAa,SAAS;;EAOxB,IAAI,UAA6C;AAC/C,UAAO,MAAA;;EAGT,IAAI,QAAQ,OAA0C;AACpD,SAAA,UAAgB;AAChB,OAAI,MACF,QAAO,MAAA,OAAa,OAAO,EAAE,SAAS,OAAO,CAAC;;EAalD,IAAI,MAAc;AAChB,UAAO,MAAA,OAAa,MAAM,KAAK,CAAC,cAAc,OAAO;;EAGvD,IAAI,IAAI,OAAe;GACrB,MAAM,mBAAmB,MAAA,OAAa,OAAO,KAAK,CAAC;AAEnD,SAAA,mBAAyB;AACzB,SAAA,OAAa,SAAS;AACtB,SAAA,SAAe,qBAAqB,MAAA,OAAa;AAIjD,OAAI,MAAA,QACF,QAAO,MAAA,OAAa,OAAO,EAAE,SAAS,MAAA,SAAe,CAAC;AAGxD,OAAI,iBACF,QAAO,MAAA,OAAa,QAAQ,EAAE,cAAc,kBAAkB,CAAC;AAGjE,OAAI,MACF,QAAO,MAAA,OAAa,OAAO,EAAE,cAAc,EAAE,KAAK,OAAO,EAAE,CAAC;;EAShE,OAAsB;GACpB,MAAM,EAAE,iBAAiB,MAAA,OAAa,OAAO,KAAK;AAClD,OAAI,CAAC,aACH,QAAO,QAAQ,uBAAO,IAAI,MAAM,sCAAsC,CAAC;AAIzE,UAAO,MAAA,OAAa,OAAO,EAAE,mBAAmB,MAAM,CAAC;AAEvD,UAAO,aAAa,MAAM,CAAC,OAAO,QAAiB;AAIjD,QAAI,KAAK,IACP,QAAO,IAAI,SAAe,SAAS,WAAW;KAC5C,MAAM,iBAAiB;AACrB,YAAA,oBAA0B;AAC1B,mBAAa,MAAM,CAAC,KAAK,SAAS,OAAO;;AAE3C,WAAA,oBAA0B;AAC1B,kBAAa,iBAAiB,aAAa,UAAU,EAAE,MAAM,MAAM,CAAC;MACpE;AAEJ,UAAM;KACN;;EAOJ,qBAA2B;AACzB,OAAI,CAAC,MAAA,kBAAyB;GAC9B,MAAM,EAAE,iBAAiB,MAAA,OAAa,OAAO,KAAK;AAClD,iBAAc,oBAAoB,aAAa,MAAA,kBAAwB;AACvE,SAAA,oBAA0B;;;AAI9B,QAAO;;;AAIT,IAAa,WAAb,cAA8B,cAAc,MAAM,GAAG,CAAC"}
@@ -1,124 +0,0 @@
1
- import { BandwidthState } from "../../core/abr/bandwidth-estimator.js";
2
- import { ReadonlySignal, Signal } from "../../core/signals/primitives.js";
3
- import { SourceBufferActor } from "../media/source-buffer-actor.js";
4
- import { TextTracksActor } from "../features/text-tracks-actor.js";
5
- import { TextTrackSegmentLoaderActor } from "../features/text-track-segment-loader-actor.js";
6
-
7
- //#region src/dom/playback-engine/engine.d.ts
8
- /**
9
- * Configuration for the playback engine.
10
- */
11
- interface PlaybackEngineConfig {
12
- /**
13
- * Initial bandwidth estimate for cold start (bits per second).
14
- * Default: 1 Mbps (conservative).
15
- */
16
- initialBandwidth?: number;
17
- /**
18
- * Preferred audio language (ISO 639 code, e.g., "en", "es").
19
- * If not specified, selects first audio track.
20
- */
21
- preferredAudioLanguage?: string;
22
- /**
23
- * Preferred subtitle language (ISO 639 code, e.g., "en", "es").
24
- * If specified, selects matching text track if available.
25
- */
26
- preferredSubtitleLanguage?: string;
27
- /**
28
- * Include FORCED subtitle tracks in selection.
29
- * Default: false (follows hls.js/http-streaming pattern)
30
- */
31
- includeForcedTracks?: boolean;
32
- /**
33
- * Auto-select DEFAULT track (requires DEFAULT=YES + AUTOSELECT=YES in HLS).
34
- * Default: false (user opt-in, matches hls.js/http-streaming)
35
- */
36
- enableDefaultTrack?: boolean;
37
- }
38
- /**
39
- * Combined state shape for the playback engine.
40
- * Includes all state needed by orchestrations.
41
- */
42
- interface PlaybackEngineState {
43
- presentation?: any;
44
- preload?: 'auto' | 'metadata' | 'none';
45
- selectedVideoTrackId?: string;
46
- selectedAudioTrackId?: string;
47
- selectedTextTrackId?: string;
48
- bandwidthState?: BandwidthState;
49
- abrDisabled?: boolean;
50
- currentTime?: number;
51
- playbackInitiated?: boolean;
52
- }
53
- /**
54
- * Combined owners shape for the playback engine.
55
- * Includes all mutable platform objects.
56
- */
57
- interface PlaybackEngineOwners {
58
- mediaElement?: HTMLMediaElement | undefined;
59
- mediaSource?: MediaSource;
60
- /** Reactive mirror of `mediaSource.readyState` — updated via DOM events. */
61
- mediaSourceReadyState?: ReadonlySignal<MediaSource['readyState']>;
62
- videoBuffer?: SourceBuffer;
63
- audioBuffer?: SourceBuffer;
64
- videoBufferActor?: SourceBufferActor;
65
- audioBufferActor?: SourceBufferActor;
66
- textTracksActor?: TextTracksActor;
67
- segmentLoaderActor?: TextTrackSegmentLoaderActor;
68
- }
69
- /**
70
- * Playback engine instance.
71
- */
72
- interface PlaybackEngine {
73
- /**
74
- * Reactive state signal (for inspection/testing).
75
- */
76
- state: Signal<PlaybackEngineState>;
77
- /**
78
- * Mutable owners signal (for inspection/testing).
79
- */
80
- owners: Signal<PlaybackEngineOwners>;
81
- /**
82
- * Cleanup function to destroy all orchestrations.
83
- */
84
- destroy: () => void;
85
- }
86
- /**
87
- * Create a POC playback engine.
88
- *
89
- * Wires together all orchestrations to create a reactive playback pipeline:
90
- * 1. Resolve presentation (multivariant playlist)
91
- * 2. Select initial video and audio tracks
92
- * 3. Resolve selected tracks (media playlists)
93
- * 4. Setup MediaSource
94
- * 5. Setup SourceBuffers for video and audio
95
- *
96
- * Note: This is a POC - does not yet load/append segments.
97
- *
98
- * @param config - Playback engine configuration
99
- * @returns Playback engine instance with state, owners, and destroy function
100
- *
101
- * @example
102
- * const engine = createPlaybackEngine({
103
- * initialBandwidth: 2_000_000,
104
- * preferredAudioLanguage: 'en',
105
- * });
106
- *
107
- * // Initialize by setting state and owners
108
- * engine.owners.set({ ...engine.owners.get(), mediaElement: document.querySelector('video') });
109
- * engine.state.set({
110
- * ...engine.state.get(),
111
- * presentation: { url: 'https://example.com/playlist.m3u8' },
112
- * preload: 'auto',
113
- * });
114
- *
115
- * // Inspect state
116
- * console.log(engine.state.get());
117
- *
118
- * // Cleanup
119
- * engine.destroy();
120
- */
121
- declare function createPlaybackEngine(config?: PlaybackEngineConfig): PlaybackEngine;
122
- //#endregion
123
- export { PlaybackEngine, PlaybackEngineConfig, PlaybackEngineOwners, PlaybackEngineState, createPlaybackEngine };
124
- //# sourceMappingURL=engine.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"engine.d.ts","names":[],"sources":["../../../../src/dom/playback-engine/engine.ts"],"mappings":";;;;;;;;;AA0BA;UAAiB,oBAAA;;;;;EAKf,gBAAA;EAkBA;;;;EAZA,sBAAA;EAyBkC;;;;EAnBlC,yBAAA;EAyBA;;;;EAnBA,mBAAA;EA8BA;;;;EAxBA,kBAAA;AAAA;;;;;UAOe,mBAAA;EAEf,YAAA;EACA,OAAA;EAGA,oBAAA;EACA,oBAAA;EAEA,mBAAA;EAGA,cAAA,GAAiB,cAAA;EAKjB,WAAA;EAGA,WAAA;EAGA,iBAAA;AAAA;;;;;UAOe,oBAAA;EAEf,YAAA,GAAe,gBAAA;EAGf,WAAA,GAAc,WAAA;EAKA;EAHd,qBAAA,GAAwB,cAAA,CAAe,WAAA;EAGvC,WAAA,GAAc,YAAA;EACd,WAAA,GAAc,YAAA;EACd,gBAAA,GAAmB,iBAAA;EACnB,gBAAA,GAAmB,iBAAA;EAGnB,eAAA,GAAkB,eAAA;EAClB,kBAAA,GAAqB,2BAAA;AAAA;;;;UAMN,cAAA;EAAA;;;EAIf,KAAA,EAAO,MAAA,CAAO,mBAAA;EAAP;;;EAKP,MAAA,EAAQ,MAAA,CAAO,oBAAA;EAAD;;;EAKd,OAAA;AAAA;;;;;;AAsCF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAgB,oBAAA,CAAqB,MAAA,GAAQ,oBAAA,GAA4B,cAAA"}