@videojs/spf 10.0.0-beta.3 → 10.0.0-beta.30

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 (580) hide show
  1. package/README.md +19 -38
  2. package/dist/default/core/actors/create-machine-actor.js +91 -0
  3. package/dist/default/core/actors/create-machine-actor.js.map +1 -0
  4. package/dist/default/core/actors/create-transition-actor.js +46 -0
  5. package/dist/default/core/actors/create-transition-actor.js.map +1 -0
  6. package/dist/default/core/composition/create-composition.js +85 -0
  7. package/dist/default/core/composition/create-composition.js.map +1 -0
  8. package/dist/default/core/composition/share-signals.js +39 -0
  9. package/dist/default/core/composition/share-signals.js.map +1 -0
  10. package/dist/default/core/machine.js +26 -0
  11. package/dist/default/core/machine.js.map +1 -0
  12. package/dist/default/core/reactors/create-machine-reactor.js +83 -0
  13. package/dist/default/core/reactors/create-machine-reactor.js.map +1 -0
  14. package/dist/default/core/signals/effect.js +41 -0
  15. package/dist/default/core/signals/effect.js.map +1 -0
  16. package/dist/default/core/signals/primitives.js +54 -0
  17. package/dist/default/core/signals/primitives.js.map +1 -0
  18. package/dist/default/core/signals/when.js +38 -0
  19. package/dist/default/core/signals/when.js.map +1 -0
  20. package/dist/default/core/tasks/delayed-reschedule.js +31 -0
  21. package/dist/default/core/tasks/delayed-reschedule.js.map +1 -0
  22. package/dist/default/core/tasks/task.js +321 -0
  23. package/dist/default/core/tasks/task.js.map +1 -0
  24. package/dist/default/dom.js +9 -0
  25. package/dist/default/hls-audio.js +3 -0
  26. package/dist/default/hls-background-video.js +3 -0
  27. package/dist/default/hls-video.js +4 -0
  28. package/dist/default/hls.js +8 -0
  29. package/dist/default/index.js +23 -0
  30. package/dist/default/index.js.map +1 -0
  31. package/dist/default/media/abr/quality-selection.js +21 -0
  32. package/dist/default/media/abr/quality-selection.js.map +1 -0
  33. package/dist/default/media/buffer/back-buffer.js +46 -0
  34. package/dist/default/media/buffer/back-buffer.js.map +1 -0
  35. package/dist/default/media/buffer/forward-buffer.js +119 -0
  36. package/dist/default/media/buffer/forward-buffer.js.map +1 -0
  37. package/dist/default/media/dom/capabilities.js +72 -0
  38. package/dist/default/media/dom/capabilities.js.map +1 -0
  39. package/dist/default/media/dom/mse/append-segment.js +60 -0
  40. package/dist/default/media/dom/mse/append-segment.js.map +1 -0
  41. package/dist/default/media/dom/mse/buffer-flusher.js +55 -0
  42. package/dist/default/media/dom/mse/buffer-flusher.js.map +1 -0
  43. package/dist/default/media/dom/mse/duration.js +95 -0
  44. package/dist/default/media/dom/mse/duration.js.map +1 -0
  45. package/dist/default/media/dom/mse/end-of-stream.js +20 -0
  46. package/dist/default/media/dom/mse/end-of-stream.js.map +1 -0
  47. package/dist/default/media/dom/mse/mediasource-setup.js +242 -0
  48. package/dist/default/media/dom/mse/mediasource-setup.js.map +1 -0
  49. package/dist/default/media/dom/screen.js +112 -0
  50. package/dist/default/media/dom/screen.js.map +1 -0
  51. package/dist/default/media/dom/text/resolve-vtt-segment.js +50 -0
  52. package/dist/default/media/dom/text/resolve-vtt-segment.js.map +1 -0
  53. package/dist/default/media/dom/text/text-track-slots.js +69 -0
  54. package/dist/default/media/dom/text/text-track-slots.js.map +1 -0
  55. package/dist/default/media/errors.js +69 -0
  56. package/dist/default/media/errors.js.map +1 -0
  57. package/dist/default/media/hls/parse-attributes.js +148 -0
  58. package/dist/default/media/hls/parse-attributes.js.map +1 -0
  59. package/dist/default/media/hls/parse-media-playlist.js +261 -0
  60. package/dist/default/media/hls/parse-media-playlist.js.map +1 -0
  61. package/dist/default/media/hls/parse-multivariant.js +234 -0
  62. package/dist/default/media/hls/parse-multivariant.js.map +1 -0
  63. package/dist/default/media/hls/reload-policy.js +71 -0
  64. package/dist/default/media/hls/reload-policy.js.map +1 -0
  65. package/dist/default/media/hls/resolve-url.js +11 -0
  66. package/dist/default/media/hls/resolve-url.js.map +1 -0
  67. package/dist/default/media/live-window.js +36 -0
  68. package/dist/default/media/live-window.js.map +1 -0
  69. package/dist/default/media/media-tracks/media-tracks.js +101 -0
  70. package/dist/default/media/media-tracks/media-tracks.js.map +1 -0
  71. package/dist/default/media/mp4/box.js +58 -0
  72. package/dist/default/media/mp4/box.js.map +1 -0
  73. package/dist/default/media/mp4/timestamp-origin.js +107 -0
  74. package/dist/default/media/mp4/timestamp-origin.js.map +1 -0
  75. package/dist/default/media/primitives/resolution.js +29 -0
  76. package/dist/default/media/primitives/resolution.js.map +1 -0
  77. package/dist/default/media/primitives/select-tracks.js +107 -0
  78. package/dist/default/media/primitives/select-tracks.js.map +1 -0
  79. package/dist/default/media/text/parse-vtt-timestamp-map.js +42 -0
  80. package/dist/default/media/text/parse-vtt-timestamp-map.js.map +1 -0
  81. package/dist/default/media/text/resolve-vtt-metadata.js +23 -0
  82. package/dist/default/media/text/resolve-vtt-metadata.js.map +1 -0
  83. package/dist/default/media/types/index.js +50 -0
  84. package/dist/default/media/types/index.js.map +1 -0
  85. package/dist/default/media/utils/cdn.js +56 -0
  86. package/dist/default/media/utils/cdn.js.map +1 -0
  87. package/dist/default/media/utils/preload.js +22 -0
  88. package/dist/default/media/utils/preload.js.map +1 -0
  89. package/dist/default/media/utils/track-selection.js +47 -0
  90. package/dist/default/media/utils/track-selection.js.map +1 -0
  91. package/dist/default/media/utils/tracks.js +144 -0
  92. package/dist/default/media/utils/tracks.js.map +1 -0
  93. package/dist/default/media-tracks.js +2 -0
  94. package/dist/default/mux-audio.js +3 -0
  95. package/dist/default/mux-background-video.js +3 -0
  96. package/dist/default/mux-video.js +3 -0
  97. package/dist/default/network/bandwidth-estimator.js +96 -0
  98. package/dist/default/network/bandwidth-estimator.js.map +1 -0
  99. package/dist/default/network/chunked-stream-iterable.js +49 -0
  100. package/dist/default/network/chunked-stream-iterable.js.map +1 -0
  101. package/dist/default/network/ewma.js +71 -0
  102. package/dist/default/network/ewma.js.map +1 -0
  103. package/dist/default/network/fetch.js +115 -0
  104. package/dist/default/network/fetch.js.map +1 -0
  105. package/dist/default/playback/actors/dom/segment-loader.js +249 -0
  106. package/dist/default/playback/actors/dom/segment-loader.js.map +1 -0
  107. package/dist/default/playback/actors/dom/source-buffer.js +139 -0
  108. package/dist/default/playback/actors/dom/source-buffer.js.map +1 -0
  109. package/dist/default/playback/actors/dom/text-tracks.js +46 -0
  110. package/dist/default/playback/actors/dom/text-tracks.js.map +1 -0
  111. package/dist/default/playback/actors/text-track-segment-loader.js +149 -0
  112. package/dist/default/playback/actors/text-track-segment-loader.js.map +1 -0
  113. package/dist/default/playback/adapters/hls-audio/adapter.js +186 -0
  114. package/dist/default/playback/adapters/hls-audio/adapter.js.map +1 -0
  115. package/dist/default/playback/adapters/hls-audio/media.js +9 -0
  116. package/dist/default/playback/adapters/hls-audio/media.js.map +1 -0
  117. package/dist/default/playback/adapters/hls-background-video/adapter.js +211 -0
  118. package/dist/default/playback/adapters/hls-background-video/adapter.js.map +1 -0
  119. package/dist/default/playback/adapters/hls-background-video/host.js +60 -0
  120. package/dist/default/playback/adapters/hls-background-video/host.js.map +1 -0
  121. package/dist/default/playback/adapters/hls-background-video/media.js +21 -0
  122. package/dist/default/playback/adapters/hls-background-video/media.js.map +1 -0
  123. package/dist/default/playback/adapters/hls-video/adapter.js +316 -0
  124. package/dist/default/playback/adapters/hls-video/adapter.js.map +1 -0
  125. package/dist/default/playback/adapters/hls-video/error-surface.js +51 -0
  126. package/dist/default/playback/adapters/hls-video/error-surface.js.map +1 -0
  127. package/dist/default/playback/adapters/hls-video/media-tracks.js +126 -0
  128. package/dist/default/playback/adapters/hls-video/media-tracks.js.map +1 -0
  129. package/dist/default/playback/adapters/hls-video/media.js +11 -0
  130. package/dist/default/playback/adapters/hls-video/media.js.map +1 -0
  131. package/dist/default/playback/adapters/mux-audio/media.js +26 -0
  132. package/dist/default/playback/adapters/mux-audio/media.js.map +1 -0
  133. package/dist/default/playback/adapters/mux-video/adapter.js +105 -0
  134. package/dist/default/playback/adapters/mux-video/adapter.js.map +1 -0
  135. package/dist/default/playback/adapters/mux-video/media.js +23 -0
  136. package/dist/default/playback/adapters/mux-video/media.js.map +1 -0
  137. package/dist/default/playback/behaviors/calculate-presentation-duration.js +36 -0
  138. package/dist/default/playback/behaviors/calculate-presentation-duration.js.map +1 -0
  139. package/dist/default/playback/behaviors/collect-errors.js +111 -0
  140. package/dist/default/playback/behaviors/collect-errors.js.map +1 -0
  141. package/dist/default/playback/behaviors/derive-cdn-priority.js +68 -0
  142. package/dist/default/playback/behaviors/derive-cdn-priority.js.map +1 -0
  143. package/dist/default/playback/behaviors/dom/airplay.js +211 -0
  144. package/dist/default/playback/behaviors/dom/airplay.js.map +1 -0
  145. package/dist/default/playback/behaviors/dom/apply-start-position.js +93 -0
  146. package/dist/default/playback/behaviors/dom/apply-start-position.js.map +1 -0
  147. package/dist/default/playback/behaviors/dom/end-of-stream.js +102 -0
  148. package/dist/default/playback/behaviors/dom/end-of-stream.js.map +1 -0
  149. package/dist/default/playback/behaviors/dom/load-segments.js +181 -0
  150. package/dist/default/playback/behaviors/dom/load-segments.js.map +1 -0
  151. package/dist/default/playback/behaviors/dom/recover-end-stall.js +77 -0
  152. package/dist/default/playback/behaviors/dom/recover-end-stall.js.map +1 -0
  153. package/dist/default/playback/behaviors/dom/seek-to-live-edge.js +132 -0
  154. package/dist/default/playback/behaviors/dom/seek-to-live-edge.js.map +1 -0
  155. package/dist/default/playback/behaviors/dom/setup-buffer-actors.js +205 -0
  156. package/dist/default/playback/behaviors/dom/setup-buffer-actors.js.map +1 -0
  157. package/dist/default/playback/behaviors/dom/setup-mediasource.js +114 -0
  158. package/dist/default/playback/behaviors/dom/setup-mediasource.js.map +1 -0
  159. package/dist/default/playback/behaviors/dom/setup-text-track-actors.js +40 -0
  160. package/dist/default/playback/behaviors/dom/setup-text-track-actors.js.map +1 -0
  161. package/dist/default/playback/behaviors/dom/sync-live-seekable-range.js +26 -0
  162. package/dist/default/playback/behaviors/dom/sync-live-seekable-range.js.map +1 -0
  163. package/dist/default/playback/behaviors/dom/sync-text-tracks.js +124 -0
  164. package/dist/default/playback/behaviors/dom/sync-text-tracks.js.map +1 -0
  165. package/dist/default/playback/behaviors/dom/track-current-time.js +52 -0
  166. package/dist/default/playback/behaviors/dom/track-current-time.js.map +1 -0
  167. package/dist/default/playback/behaviors/dom/track-load-triggers.js +94 -0
  168. package/dist/default/playback/behaviors/dom/track-load-triggers.js.map +1 -0
  169. package/dist/default/playback/behaviors/dom/track-playback-rate.js +37 -0
  170. package/dist/default/playback/behaviors/dom/track-playback-rate.js.map +1 -0
  171. package/dist/default/playback/behaviors/dom/track-player-resolution.js +57 -0
  172. package/dist/default/playback/behaviors/dom/track-player-resolution.js.map +1 -0
  173. package/dist/default/playback/behaviors/dom/track-screen-resolution.js +29 -0
  174. package/dist/default/playback/behaviors/dom/track-screen-resolution.js.map +1 -0
  175. package/dist/default/playback/behaviors/dom/update-mediasource-duration.js +113 -0
  176. package/dist/default/playback/behaviors/dom/update-mediasource-duration.js.map +1 -0
  177. package/dist/default/playback/behaviors/establish-start-media-time.js +197 -0
  178. package/dist/default/playback/behaviors/establish-start-media-time.js.map +1 -0
  179. package/dist/default/playback/behaviors/resolve-presentation.js +85 -0
  180. package/dist/default/playback/behaviors/resolve-presentation.js.map +1 -0
  181. package/dist/default/playback/behaviors/resolve-track.js +141 -0
  182. package/dist/default/playback/behaviors/resolve-track.js.map +1 -0
  183. package/dist/default/playback/behaviors/select-tracks.js +216 -0
  184. package/dist/default/playback/behaviors/select-tracks.js.map +1 -0
  185. package/dist/default/playback/behaviors/setup-failover-monitor.js +66 -0
  186. package/dist/default/playback/behaviors/setup-failover-monitor.js.map +1 -0
  187. package/dist/default/playback/behaviors/sync-preload.js +59 -0
  188. package/dist/default/playback/behaviors/sync-preload.js.map +1 -0
  189. package/dist/default/playback/behaviors/track-switching.js +391 -0
  190. package/dist/default/playback/behaviors/track-switching.js.map +1 -0
  191. package/dist/default/playback/engines/hls/engine-audio-only.js +98 -0
  192. package/dist/default/playback/engines/hls/engine-audio-only.js.map +1 -0
  193. package/dist/default/playback/engines/hls/engine-background-video.js +92 -0
  194. package/dist/default/playback/engines/hls/engine-background-video.js.map +1 -0
  195. package/dist/default/playback/engines/hls/engine.js +147 -0
  196. package/dist/default/playback/engines/hls/engine.js.map +1 -0
  197. package/dist/default/playback/primitives/error-messages.js +51 -0
  198. package/dist/default/playback/primitives/error-messages.js.map +1 -0
  199. package/dist/default/playback/primitives/failover-fetch.js +42 -0
  200. package/dist/default/playback/primitives/failover-fetch.js.map +1 -0
  201. package/dist/default/playback/primitives/head-peek.js +44 -0
  202. package/dist/default/playback/primitives/head-peek.js.map +1 -0
  203. package/dist/default/playback/primitives/live-window.js +66 -0
  204. package/dist/default/playback/primitives/live-window.js.map +1 -0
  205. package/dist/default/playback/primitives/relocation-pipelines.js +203 -0
  206. package/dist/default/playback/primitives/relocation-pipelines.js.map +1 -0
  207. package/dist/default/playback/primitives/report-track-conditions.js +86 -0
  208. package/dist/default/playback/primitives/report-track-conditions.js.map +1 -0
  209. package/dist/default/playback/primitives/segment-load-pipeline.js +96 -0
  210. package/dist/default/playback/primitives/segment-load-pipeline.js.map +1 -0
  211. package/dist/default/playback/primitives/selection-rules.js +86 -0
  212. package/dist/default/playback/primitives/selection-rules.js.map +1 -0
  213. package/dist/default/playback/primitives/text-segment-load-pipeline.js +37 -0
  214. package/dist/default/playback/primitives/text-segment-load-pipeline.js.map +1 -0
  215. package/dist/default/playback/primitives/track-types.js +61 -0
  216. package/dist/default/playback/primitives/track-types.js.map +1 -0
  217. package/dist/dev/core/actors/actor.d.ts +26 -0
  218. package/dist/dev/core/actors/actor.d.ts.map +1 -0
  219. package/dist/dev/core/actors/create-machine-actor.d.ts +128 -0
  220. package/dist/dev/core/actors/create-machine-actor.d.ts.map +1 -0
  221. package/dist/dev/core/actors/create-machine-actor.js +91 -0
  222. package/dist/dev/core/actors/create-machine-actor.js.map +1 -0
  223. package/dist/dev/core/actors/create-transition-actor.d.ts +41 -0
  224. package/dist/dev/core/actors/create-transition-actor.d.ts.map +1 -0
  225. package/dist/dev/core/actors/create-transition-actor.js +46 -0
  226. package/dist/dev/core/actors/create-transition-actor.js.map +1 -0
  227. package/dist/dev/core/composition/create-composition.d.ts +273 -0
  228. package/dist/dev/core/composition/create-composition.d.ts.map +1 -0
  229. package/dist/dev/core/composition/create-composition.js +85 -0
  230. package/dist/dev/core/composition/create-composition.js.map +1 -0
  231. package/dist/dev/core/composition/share-signals.d.ts +46 -0
  232. package/dist/dev/core/composition/share-signals.d.ts.map +1 -0
  233. package/dist/dev/core/composition/share-signals.js +39 -0
  234. package/dist/dev/core/composition/share-signals.js.map +1 -0
  235. package/dist/dev/core/machine.d.ts +21 -0
  236. package/dist/dev/core/machine.d.ts.map +1 -0
  237. package/dist/dev/core/machine.js +26 -0
  238. package/dist/dev/core/machine.js.map +1 -0
  239. package/dist/dev/core/reactors/create-machine-reactor.d.ts +93 -0
  240. package/dist/dev/core/reactors/create-machine-reactor.d.ts.map +1 -0
  241. package/dist/dev/core/reactors/create-machine-reactor.js +83 -0
  242. package/dist/dev/core/reactors/create-machine-reactor.js.map +1 -0
  243. package/dist/dev/core/signals/effect.d.ts +15 -0
  244. package/dist/dev/core/signals/effect.d.ts.map +1 -0
  245. package/dist/dev/core/signals/effect.js +41 -0
  246. package/dist/dev/core/signals/effect.js.map +1 -0
  247. package/dist/dev/core/signals/primitives.d.ts +46 -0
  248. package/dist/dev/core/signals/primitives.d.ts.map +1 -0
  249. package/dist/dev/core/signals/primitives.js +54 -0
  250. package/dist/dev/core/signals/primitives.js.map +1 -0
  251. package/dist/dev/core/signals/when.js +38 -0
  252. package/dist/dev/core/signals/when.js.map +1 -0
  253. package/dist/dev/core/tasks/delayed-reschedule.js +31 -0
  254. package/dist/dev/core/tasks/delayed-reschedule.js.map +1 -0
  255. package/dist/dev/core/tasks/task.d.ts +166 -0
  256. package/dist/dev/core/tasks/task.d.ts.map +1 -0
  257. package/dist/dev/core/tasks/task.js +321 -0
  258. package/dist/dev/core/tasks/task.js.map +1 -0
  259. package/dist/dev/dom.d.ts +9 -0
  260. package/dist/dev/dom.js +9 -0
  261. package/dist/dev/hls-audio.d.ts +3 -0
  262. package/dist/dev/hls-audio.js +3 -0
  263. package/dist/dev/hls-background-video.d.ts +4 -0
  264. package/dist/dev/hls-background-video.js +3 -0
  265. package/dist/dev/hls-video.d.ts +5 -0
  266. package/dist/dev/hls-video.js +4 -0
  267. package/dist/dev/hls.d.ts +9 -0
  268. package/dist/dev/hls.js +8 -0
  269. package/dist/dev/index.d.ts +24 -0
  270. package/dist/dev/index.d.ts.map +1 -0
  271. package/dist/dev/index.js +23 -0
  272. package/dist/dev/index.js.map +1 -0
  273. package/dist/dev/media/abr/quality-selection.d.ts +22 -0
  274. package/dist/dev/media/abr/quality-selection.d.ts.map +1 -0
  275. package/dist/dev/media/abr/quality-selection.js +21 -0
  276. package/dist/dev/media/abr/quality-selection.js.map +1 -0
  277. package/dist/dev/media/buffer/back-buffer.d.ts +14 -0
  278. package/dist/dev/media/buffer/back-buffer.d.ts.map +1 -0
  279. package/dist/dev/media/buffer/back-buffer.js +46 -0
  280. package/dist/dev/media/buffer/back-buffer.js.map +1 -0
  281. package/dist/dev/media/buffer/forward-buffer.d.ts +14 -0
  282. package/dist/dev/media/buffer/forward-buffer.d.ts.map +1 -0
  283. package/dist/dev/media/buffer/forward-buffer.js +119 -0
  284. package/dist/dev/media/buffer/forward-buffer.js.map +1 -0
  285. package/dist/dev/media/dom/capabilities.js +72 -0
  286. package/dist/dev/media/dom/capabilities.js.map +1 -0
  287. package/dist/dev/media/dom/mse/append-segment.d.ts +18 -0
  288. package/dist/dev/media/dom/mse/append-segment.d.ts.map +1 -0
  289. package/dist/dev/media/dom/mse/append-segment.js +60 -0
  290. package/dist/dev/media/dom/mse/append-segment.js.map +1 -0
  291. package/dist/dev/media/dom/mse/buffer-flusher.d.ts +24 -0
  292. package/dist/dev/media/dom/mse/buffer-flusher.d.ts.map +1 -0
  293. package/dist/dev/media/dom/mse/buffer-flusher.js +55 -0
  294. package/dist/dev/media/dom/mse/buffer-flusher.js.map +1 -0
  295. package/dist/dev/media/dom/mse/duration.js +95 -0
  296. package/dist/dev/media/dom/mse/duration.js.map +1 -0
  297. package/dist/dev/media/dom/mse/end-of-stream.js +20 -0
  298. package/dist/dev/media/dom/mse/end-of-stream.js.map +1 -0
  299. package/dist/dev/media/dom/mse/mediasource-setup.js +242 -0
  300. package/dist/dev/media/dom/mse/mediasource-setup.js.map +1 -0
  301. package/dist/dev/media/dom/screen.d.ts +7 -0
  302. package/dist/dev/media/dom/screen.d.ts.map +1 -0
  303. package/dist/dev/media/dom/screen.js +112 -0
  304. package/dist/dev/media/dom/screen.js.map +1 -0
  305. package/dist/dev/media/dom/text/resolve-vtt-segment.d.ts +6 -0
  306. package/dist/dev/media/dom/text/resolve-vtt-segment.d.ts.map +1 -0
  307. package/dist/dev/media/dom/text/resolve-vtt-segment.js +50 -0
  308. package/dist/dev/media/dom/text/resolve-vtt-segment.js.map +1 -0
  309. package/dist/dev/media/dom/text/text-track-slots.d.ts +30 -0
  310. package/dist/dev/media/dom/text/text-track-slots.d.ts.map +1 -0
  311. package/dist/dev/media/dom/text/text-track-slots.js +69 -0
  312. package/dist/dev/media/dom/text/text-track-slots.js.map +1 -0
  313. package/dist/dev/media/errors.d.ts +82 -0
  314. package/dist/dev/media/errors.d.ts.map +1 -0
  315. package/dist/dev/media/errors.js +69 -0
  316. package/dist/dev/media/errors.js.map +1 -0
  317. package/dist/dev/media/hls/parse-attributes.js +148 -0
  318. package/dist/dev/media/hls/parse-attributes.js.map +1 -0
  319. package/dist/dev/media/hls/parse-media-playlist.js +261 -0
  320. package/dist/dev/media/hls/parse-media-playlist.js.map +1 -0
  321. package/dist/dev/media/hls/parse-multivariant.js +234 -0
  322. package/dist/dev/media/hls/parse-multivariant.js.map +1 -0
  323. package/dist/dev/media/hls/reload-policy.js +71 -0
  324. package/dist/dev/media/hls/reload-policy.js.map +1 -0
  325. package/dist/dev/media/hls/resolve-url.js +11 -0
  326. package/dist/dev/media/hls/resolve-url.js.map +1 -0
  327. package/dist/dev/media/live-window.js +36 -0
  328. package/dist/dev/media/live-window.js.map +1 -0
  329. package/dist/dev/media/media-tracks/media-tracks.d.ts +51 -0
  330. package/dist/dev/media/media-tracks/media-tracks.d.ts.map +1 -0
  331. package/dist/dev/media/media-tracks/media-tracks.js +101 -0
  332. package/dist/dev/media/media-tracks/media-tracks.js.map +1 -0
  333. package/dist/dev/media/mp4/box.js +58 -0
  334. package/dist/dev/media/mp4/box.js.map +1 -0
  335. package/dist/dev/media/mp4/timestamp-origin.js +107 -0
  336. package/dist/dev/media/mp4/timestamp-origin.js.map +1 -0
  337. package/dist/dev/media/primitives/resolution.d.ts +24 -0
  338. package/dist/dev/media/primitives/resolution.d.ts.map +1 -0
  339. package/dist/dev/media/primitives/resolution.js +29 -0
  340. package/dist/dev/media/primitives/resolution.js.map +1 -0
  341. package/dist/dev/media/primitives/select-tracks.js +107 -0
  342. package/dist/dev/media/primitives/select-tracks.js.map +1 -0
  343. package/dist/dev/media/text/parse-vtt-timestamp-map.js +42 -0
  344. package/dist/dev/media/text/parse-vtt-timestamp-map.js.map +1 -0
  345. package/dist/dev/media/text/resolve-vtt-metadata.js +23 -0
  346. package/dist/dev/media/text/resolve-vtt-metadata.js.map +1 -0
  347. package/dist/dev/media/types/index.d.ts +377 -0
  348. package/dist/dev/media/types/index.d.ts.map +1 -0
  349. package/dist/dev/media/types/index.js +50 -0
  350. package/dist/dev/media/types/index.js.map +1 -0
  351. package/dist/dev/media/utils/cdn.d.ts +13 -0
  352. package/dist/dev/media/utils/cdn.d.ts.map +1 -0
  353. package/dist/dev/media/utils/cdn.js +56 -0
  354. package/dist/dev/media/utils/cdn.js.map +1 -0
  355. package/dist/dev/media/utils/preload.js +22 -0
  356. package/dist/dev/media/utils/preload.js.map +1 -0
  357. package/dist/dev/media/utils/track-selection.js +47 -0
  358. package/dist/dev/media/utils/track-selection.js.map +1 -0
  359. package/dist/dev/media/utils/tracks.js +144 -0
  360. package/dist/dev/media/utils/tracks.js.map +1 -0
  361. package/dist/dev/media-tracks.d.ts +3 -0
  362. package/dist/dev/media-tracks.js +2 -0
  363. package/dist/dev/mux-audio.d.ts +4 -0
  364. package/dist/dev/mux-audio.js +3 -0
  365. package/dist/dev/mux-background-video.d.ts +4 -0
  366. package/dist/dev/mux-background-video.js +3 -0
  367. package/dist/dev/mux-video.d.ts +4 -0
  368. package/dist/dev/mux-video.js +3 -0
  369. package/dist/dev/network/bandwidth-estimator.d.ts +50 -0
  370. package/dist/dev/network/bandwidth-estimator.d.ts.map +1 -0
  371. package/dist/dev/network/bandwidth-estimator.js +96 -0
  372. package/dist/dev/network/bandwidth-estimator.js.map +1 -0
  373. package/dist/dev/network/chunked-stream-iterable.js +49 -0
  374. package/dist/dev/network/chunked-stream-iterable.js.map +1 -0
  375. package/dist/dev/network/ewma.js +71 -0
  376. package/dist/dev/network/ewma.js.map +1 -0
  377. package/dist/dev/network/fetch.js +115 -0
  378. package/dist/dev/network/fetch.js.map +1 -0
  379. package/dist/dev/playback/actors/dom/segment-loader.d.ts +48 -0
  380. package/dist/dev/playback/actors/dom/segment-loader.d.ts.map +1 -0
  381. package/dist/dev/playback/actors/dom/segment-loader.js +249 -0
  382. package/dist/dev/playback/actors/dom/segment-loader.js.map +1 -0
  383. package/dist/dev/playback/actors/dom/source-buffer.d.ts +47 -0
  384. package/dist/dev/playback/actors/dom/source-buffer.d.ts.map +1 -0
  385. package/dist/dev/playback/actors/dom/source-buffer.js +139 -0
  386. package/dist/dev/playback/actors/dom/source-buffer.js.map +1 -0
  387. package/dist/dev/playback/actors/dom/text-tracks.d.ts +3 -0
  388. package/dist/dev/playback/actors/dom/text-tracks.js +46 -0
  389. package/dist/dev/playback/actors/dom/text-tracks.js.map +1 -0
  390. package/dist/dev/playback/actors/text-track-segment-loader.d.ts +54 -0
  391. package/dist/dev/playback/actors/text-track-segment-loader.d.ts.map +1 -0
  392. package/dist/dev/playback/actors/text-track-segment-loader.js +149 -0
  393. package/dist/dev/playback/actors/text-track-segment-loader.js.map +1 -0
  394. package/dist/dev/playback/actors/text-tracks.d.ts +33 -0
  395. package/dist/dev/playback/actors/text-tracks.d.ts.map +1 -0
  396. package/dist/dev/playback/adapters/hls-audio/adapter.d.ts +54 -0
  397. package/dist/dev/playback/adapters/hls-audio/adapter.d.ts.map +1 -0
  398. package/dist/dev/playback/adapters/hls-audio/adapter.js +186 -0
  399. package/dist/dev/playback/adapters/hls-audio/adapter.js.map +1 -0
  400. package/dist/dev/playback/adapters/hls-audio/media.d.ts +10 -0
  401. package/dist/dev/playback/adapters/hls-audio/media.d.ts.map +1 -0
  402. package/dist/dev/playback/adapters/hls-audio/media.js +9 -0
  403. package/dist/dev/playback/adapters/hls-audio/media.js.map +1 -0
  404. package/dist/dev/playback/adapters/hls-background-video/adapter.d.ts +77 -0
  405. package/dist/dev/playback/adapters/hls-background-video/adapter.d.ts.map +1 -0
  406. package/dist/dev/playback/adapters/hls-background-video/adapter.js +211 -0
  407. package/dist/dev/playback/adapters/hls-background-video/adapter.js.map +1 -0
  408. package/dist/dev/playback/adapters/hls-background-video/host.d.ts +38 -0
  409. package/dist/dev/playback/adapters/hls-background-video/host.d.ts.map +1 -0
  410. package/dist/dev/playback/adapters/hls-background-video/host.js +60 -0
  411. package/dist/dev/playback/adapters/hls-background-video/host.js.map +1 -0
  412. package/dist/dev/playback/adapters/hls-background-video/media.d.ts +20 -0
  413. package/dist/dev/playback/adapters/hls-background-video/media.d.ts.map +1 -0
  414. package/dist/dev/playback/adapters/hls-background-video/media.js +21 -0
  415. package/dist/dev/playback/adapters/hls-background-video/media.js.map +1 -0
  416. package/dist/dev/playback/adapters/hls-video/adapter.d.ts +63 -0
  417. package/dist/dev/playback/adapters/hls-video/adapter.d.ts.map +1 -0
  418. package/dist/dev/playback/adapters/hls-video/adapter.js +316 -0
  419. package/dist/dev/playback/adapters/hls-video/adapter.js.map +1 -0
  420. package/dist/dev/playback/adapters/hls-video/error-surface.d.ts +18 -0
  421. package/dist/dev/playback/adapters/hls-video/error-surface.d.ts.map +1 -0
  422. package/dist/dev/playback/adapters/hls-video/error-surface.js +51 -0
  423. package/dist/dev/playback/adapters/hls-video/error-surface.js.map +1 -0
  424. package/dist/dev/playback/adapters/hls-video/media-tracks.d.ts +22 -0
  425. package/dist/dev/playback/adapters/hls-video/media-tracks.d.ts.map +1 -0
  426. package/dist/dev/playback/adapters/hls-video/media-tracks.js +126 -0
  427. package/dist/dev/playback/adapters/hls-video/media-tracks.js.map +1 -0
  428. package/dist/dev/playback/adapters/hls-video/media.d.ts +10 -0
  429. package/dist/dev/playback/adapters/hls-video/media.d.ts.map +1 -0
  430. package/dist/dev/playback/adapters/hls-video/media.js +11 -0
  431. package/dist/dev/playback/adapters/hls-video/media.js.map +1 -0
  432. package/dist/dev/playback/adapters/mux-audio/media.d.ts +28 -0
  433. package/dist/dev/playback/adapters/mux-audio/media.d.ts.map +1 -0
  434. package/dist/dev/playback/adapters/mux-audio/media.js +26 -0
  435. package/dist/dev/playback/adapters/mux-audio/media.js.map +1 -0
  436. package/dist/dev/playback/adapters/mux-video/adapter.d.ts +34 -0
  437. package/dist/dev/playback/adapters/mux-video/adapter.d.ts.map +1 -0
  438. package/dist/dev/playback/adapters/mux-video/adapter.js +105 -0
  439. package/dist/dev/playback/adapters/mux-video/adapter.js.map +1 -0
  440. package/dist/dev/playback/adapters/mux-video/media.d.ts +24 -0
  441. package/dist/dev/playback/adapters/mux-video/media.d.ts.map +1 -0
  442. package/dist/dev/playback/adapters/mux-video/media.js +23 -0
  443. package/dist/dev/playback/adapters/mux-video/media.js.map +1 -0
  444. package/dist/dev/playback/behaviors/calculate-presentation-duration.d.ts +26 -0
  445. package/dist/dev/playback/behaviors/calculate-presentation-duration.d.ts.map +1 -0
  446. package/dist/dev/playback/behaviors/calculate-presentation-duration.js +36 -0
  447. package/dist/dev/playback/behaviors/calculate-presentation-duration.js.map +1 -0
  448. package/dist/dev/playback/behaviors/collect-errors.js +111 -0
  449. package/dist/dev/playback/behaviors/collect-errors.js.map +1 -0
  450. package/dist/dev/playback/behaviors/derive-cdn-priority.js +68 -0
  451. package/dist/dev/playback/behaviors/derive-cdn-priority.js.map +1 -0
  452. package/dist/dev/playback/behaviors/dom/airplay.js +211 -0
  453. package/dist/dev/playback/behaviors/dom/airplay.js.map +1 -0
  454. package/dist/dev/playback/behaviors/dom/apply-start-position.js +93 -0
  455. package/dist/dev/playback/behaviors/dom/apply-start-position.js.map +1 -0
  456. package/dist/dev/playback/behaviors/dom/end-of-stream.js +102 -0
  457. package/dist/dev/playback/behaviors/dom/end-of-stream.js.map +1 -0
  458. package/dist/dev/playback/behaviors/dom/load-segments.d.ts +72 -0
  459. package/dist/dev/playback/behaviors/dom/load-segments.d.ts.map +1 -0
  460. package/dist/dev/playback/behaviors/dom/load-segments.js +181 -0
  461. package/dist/dev/playback/behaviors/dom/load-segments.js.map +1 -0
  462. package/dist/dev/playback/behaviors/dom/recover-end-stall.js +77 -0
  463. package/dist/dev/playback/behaviors/dom/recover-end-stall.js.map +1 -0
  464. package/dist/dev/playback/behaviors/dom/seek-to-live-edge.js +132 -0
  465. package/dist/dev/playback/behaviors/dom/seek-to-live-edge.js.map +1 -0
  466. package/dist/dev/playback/behaviors/dom/setup-buffer-actors.js +205 -0
  467. package/dist/dev/playback/behaviors/dom/setup-buffer-actors.js.map +1 -0
  468. package/dist/dev/playback/behaviors/dom/setup-mediasource.js +114 -0
  469. package/dist/dev/playback/behaviors/dom/setup-mediasource.js.map +1 -0
  470. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.d.ts +28 -0
  471. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.d.ts.map +1 -0
  472. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.js +40 -0
  473. package/dist/dev/playback/behaviors/dom/setup-text-track-actors.js.map +1 -0
  474. package/dist/dev/playback/behaviors/dom/sync-live-seekable-range.js +26 -0
  475. package/dist/dev/playback/behaviors/dom/sync-live-seekable-range.js.map +1 -0
  476. package/dist/dev/playback/behaviors/dom/sync-text-tracks.js +124 -0
  477. package/dist/dev/playback/behaviors/dom/sync-text-tracks.js.map +1 -0
  478. package/dist/dev/playback/behaviors/dom/track-current-time.d.ts +33 -0
  479. package/dist/dev/playback/behaviors/dom/track-current-time.d.ts.map +1 -0
  480. package/dist/dev/playback/behaviors/dom/track-current-time.js +52 -0
  481. package/dist/dev/playback/behaviors/dom/track-current-time.js.map +1 -0
  482. package/dist/dev/playback/behaviors/dom/track-load-triggers.d.ts +47 -0
  483. package/dist/dev/playback/behaviors/dom/track-load-triggers.d.ts.map +1 -0
  484. package/dist/dev/playback/behaviors/dom/track-load-triggers.js +94 -0
  485. package/dist/dev/playback/behaviors/dom/track-load-triggers.js.map +1 -0
  486. package/dist/dev/playback/behaviors/dom/track-playback-rate.d.ts +33 -0
  487. package/dist/dev/playback/behaviors/dom/track-playback-rate.d.ts.map +1 -0
  488. package/dist/dev/playback/behaviors/dom/track-playback-rate.js +37 -0
  489. package/dist/dev/playback/behaviors/dom/track-playback-rate.js.map +1 -0
  490. package/dist/dev/playback/behaviors/dom/track-player-resolution.d.ts +8 -0
  491. package/dist/dev/playback/behaviors/dom/track-player-resolution.d.ts.map +1 -0
  492. package/dist/dev/playback/behaviors/dom/track-player-resolution.js +57 -0
  493. package/dist/dev/playback/behaviors/dom/track-player-resolution.js.map +1 -0
  494. package/dist/dev/playback/behaviors/dom/track-screen-resolution.js +29 -0
  495. package/dist/dev/playback/behaviors/dom/track-screen-resolution.js.map +1 -0
  496. package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js +113 -0
  497. package/dist/dev/playback/behaviors/dom/update-mediasource-duration.js.map +1 -0
  498. package/dist/dev/playback/behaviors/establish-start-media-time.d.ts +36 -0
  499. package/dist/dev/playback/behaviors/establish-start-media-time.d.ts.map +1 -0
  500. package/dist/dev/playback/behaviors/establish-start-media-time.js +197 -0
  501. package/dist/dev/playback/behaviors/establish-start-media-time.js.map +1 -0
  502. package/dist/dev/playback/behaviors/resolve-presentation.d.ts +8 -0
  503. package/dist/dev/playback/behaviors/resolve-presentation.d.ts.map +1 -0
  504. package/dist/dev/playback/behaviors/resolve-presentation.js +85 -0
  505. package/dist/dev/playback/behaviors/resolve-presentation.js.map +1 -0
  506. package/dist/dev/playback/behaviors/resolve-track.js +141 -0
  507. package/dist/dev/playback/behaviors/resolve-track.js.map +1 -0
  508. package/dist/dev/playback/behaviors/select-tracks.d.ts +72 -0
  509. package/dist/dev/playback/behaviors/select-tracks.d.ts.map +1 -0
  510. package/dist/dev/playback/behaviors/select-tracks.js +216 -0
  511. package/dist/dev/playback/behaviors/select-tracks.js.map +1 -0
  512. package/dist/dev/playback/behaviors/setup-failover-monitor.d.ts +14 -0
  513. package/dist/dev/playback/behaviors/setup-failover-monitor.d.ts.map +1 -0
  514. package/dist/dev/playback/behaviors/setup-failover-monitor.js +66 -0
  515. package/dist/dev/playback/behaviors/setup-failover-monitor.js.map +1 -0
  516. package/dist/dev/playback/behaviors/sync-preload.js +59 -0
  517. package/dist/dev/playback/behaviors/sync-preload.js.map +1 -0
  518. package/dist/dev/playback/behaviors/track-switching.js +391 -0
  519. package/dist/dev/playback/behaviors/track-switching.js.map +1 -0
  520. package/dist/dev/playback/engines/hls/engine-audio-only.d.ts +173 -0
  521. package/dist/dev/playback/engines/hls/engine-audio-only.d.ts.map +1 -0
  522. package/dist/dev/playback/engines/hls/engine-audio-only.js +98 -0
  523. package/dist/dev/playback/engines/hls/engine-audio-only.js.map +1 -0
  524. package/dist/dev/playback/engines/hls/engine-background-video.d.ts +158 -0
  525. package/dist/dev/playback/engines/hls/engine-background-video.d.ts.map +1 -0
  526. package/dist/dev/playback/engines/hls/engine-background-video.js +92 -0
  527. package/dist/dev/playback/engines/hls/engine-background-video.js.map +1 -0
  528. package/dist/dev/playback/engines/hls/engine.d.ts +329 -0
  529. package/dist/dev/playback/engines/hls/engine.d.ts.map +1 -0
  530. package/dist/dev/playback/engines/hls/engine.js +147 -0
  531. package/dist/dev/playback/engines/hls/engine.js.map +1 -0
  532. package/dist/dev/playback/primitives/derive-start-media-time.d.ts +16 -0
  533. package/dist/dev/playback/primitives/derive-start-media-time.d.ts.map +1 -0
  534. package/dist/dev/playback/primitives/error-messages.js +51 -0
  535. package/dist/dev/playback/primitives/error-messages.js.map +1 -0
  536. package/dist/dev/playback/primitives/failover-fetch.js +42 -0
  537. package/dist/dev/playback/primitives/failover-fetch.js.map +1 -0
  538. package/dist/dev/playback/primitives/head-peek.js +44 -0
  539. package/dist/dev/playback/primitives/head-peek.js.map +1 -0
  540. package/dist/dev/playback/primitives/live-window.js +66 -0
  541. package/dist/dev/playback/primitives/live-window.js.map +1 -0
  542. package/dist/dev/playback/primitives/relocation-pipelines.js +203 -0
  543. package/dist/dev/playback/primitives/relocation-pipelines.js.map +1 -0
  544. package/dist/dev/playback/primitives/report-track-conditions.d.ts +11 -0
  545. package/dist/dev/playback/primitives/report-track-conditions.d.ts.map +1 -0
  546. package/dist/dev/playback/primitives/report-track-conditions.js +86 -0
  547. package/dist/dev/playback/primitives/report-track-conditions.js.map +1 -0
  548. package/dist/dev/playback/primitives/segment-load-pipeline.d.ts +2 -0
  549. package/dist/dev/playback/primitives/segment-load-pipeline.js +96 -0
  550. package/dist/dev/playback/primitives/segment-load-pipeline.js.map +1 -0
  551. package/dist/dev/playback/primitives/selection-rules.d.ts +38 -0
  552. package/dist/dev/playback/primitives/selection-rules.d.ts.map +1 -0
  553. package/dist/dev/playback/primitives/selection-rules.js +86 -0
  554. package/dist/dev/playback/primitives/selection-rules.js.map +1 -0
  555. package/dist/dev/playback/primitives/source-buffer-messages.d.ts +43 -0
  556. package/dist/dev/playback/primitives/source-buffer-messages.d.ts.map +1 -0
  557. package/dist/dev/playback/primitives/text-segment-load-pipeline.d.ts +65 -0
  558. package/dist/dev/playback/primitives/text-segment-load-pipeline.d.ts.map +1 -0
  559. package/dist/dev/playback/primitives/text-segment-load-pipeline.js +37 -0
  560. package/dist/dev/playback/primitives/text-segment-load-pipeline.js.map +1 -0
  561. package/dist/dev/playback/primitives/text-track-messages.d.ts +14 -0
  562. package/dist/dev/playback/primitives/text-track-messages.d.ts.map +1 -0
  563. package/dist/dev/playback/primitives/track-types.js +61 -0
  564. package/dist/dev/playback/primitives/track-types.js.map +1 -0
  565. package/package.json +63 -26
  566. package/dist/adapter-CMw-rvbk.js +0 -3512
  567. package/dist/adapter-CMw-rvbk.js.map +0 -1
  568. package/dist/adapter-l8iJN_GI.d.ts +0 -689
  569. package/dist/adapter-l8iJN_GI.d.ts.map +0 -1
  570. package/dist/dom/index.d.ts +0 -243
  571. package/dist/dom/index.d.ts.map +0 -1
  572. package/dist/dom/index.js +0 -38
  573. package/dist/dom/index.js.map +0 -1
  574. package/dist/dom/playback-engine/index.d.ts +0 -2
  575. package/dist/dom/playback-engine/index.js +0 -4
  576. package/dist/index.d.ts +0 -13
  577. package/dist/index.d.ts.map +0 -1
  578. package/dist/index.js +0 -3
  579. package/dist/src-DRsS_H80.js +0 -14
  580. package/dist/src-DRsS_H80.js.map +0 -1
@@ -0,0 +1,82 @@
1
+ //#region src/media/errors.d.ts
2
+ /**
3
+ * SVTA 2070 (Standardized Error Codes) — the vocabulary for identifying a
4
+ * playback failure or notice, independent of how it's transported or who
5
+ * decides what to do about it.
6
+ *
7
+ * A code is a single integer: the leading digit(s) are the **category** (the
8
+ * error's domain) and the trailing three are the **index** (the specific error
9
+ * within it). Four digits for natively-defined errors, five when an external
10
+ * standard is embedded — `"03404"` is an HTTP 404 under the network category.
11
+ * Categories are `0` unknown, `1` media content, `2` playback, `3` network,
12
+ * `4` content protection, `5` accessibility, `6` remote play, `7` advertising,
13
+ * `99` custom.
14
+ *
15
+ * Two properties of the spec shape the types here:
16
+ *
17
+ * - **Severity is deliberately not part of a code.** Per §Approach, "impact
18
+ * varies with player implementation, breaking the consistency of a specific
19
+ * error mapping to single code." So an error carries no fatal flag — whether a
20
+ * condition is fatal depends on the composition observing it, and is decided
21
+ * downstream.
22
+ * - **Reporting is partial and stacked** (Principles 5–6). Errors are reported
23
+ * as encountered, most of them non-fatal, and the *sequence* carries causation
24
+ * a single value can't.
25
+ *
26
+ * See `internal/design/spf/features/errors.md`.
27
+ */
28
+ /**
29
+ * A reported condition, identified by its SVTA code.
30
+ *
31
+ * Named for the spec rather than the engine because the vocabulary is
32
+ * format- and player-neutral. Not `MediaError` — that name belongs to the
33
+ * `@videojs/media` DOM-facing class this eventually maps *onto*, and the mapping
34
+ * is the point at which severity and user-facing text get decided.
35
+ */
36
+ interface SvtaError {
37
+ /** The SVTA code — see {@link svtaCategory} / {@link svtaIndex}. */
38
+ code: number;
39
+ /** Engineer-facing detail. Optional; the code is the identity. */
40
+ message?: string;
41
+ /** Reporter-specific context (track type, url, the constraint that fired). */
42
+ data?: unknown;
43
+ }
44
+ /**
45
+ * SVTA 99 [Custom] 001 — this engine has no pipeline for something the source
46
+ * requires, so the source is unplayable *here* rather than broken.
47
+ *
48
+ * Custom rather than standard because the standard codes available describe
49
+ * either narrower or wider things. The causes (1004/1005 unsupported format,
50
+ * 4008 unsupported DRM) say what one rendition hit; the verdicts (2011/2012 no
51
+ * supported track) say a type emptied without saying why it's unfixable. And
52
+ * 2039 "Manifest feature unsupported" covers features that are unsupported but
53
+ * still *playable* — LL-HLS degrading to standard live is a 2039 — so
54
+ * overloading it for a fatal condition would make it useless for the notices it
55
+ * belongs on.
56
+ *
57
+ * Index `001`: the spec defines only `99000` (Unknown) for the custom category
58
+ * and leaves the rest to the publisher, so this is the first code we define.
59
+ *
60
+ * Five digits, and deliberately not special-cased anywhere: {@link svtaCategory}
61
+ * and {@link svtaIndex} decompose it correctly by arithmetic alone, because
62
+ * every standard category is below `8000` and custom starts at `99000`.
63
+ */
64
+ declare const SVTA_UNSUPPORTED_PLAYBACK_FEATURE = 99001;
65
+ /**
66
+ * The error's domain — `code / 1000`, per the spec's "divide by one thousand to
67
+ * obtain the error category". Works uniformly across the four-digit native form
68
+ * and the five-digit form embedding an external standard: `"03404"` is
69
+ * numerically 3404, which decomposes identically. That also makes a numeric code
70
+ * immune to the spec's inconsistent zero-padding (§Approach writes a
71
+ * category-unknown network error as `"0300"` where the error index implies
72
+ * category 3 / index 000).
73
+ */
74
+ declare function svtaCategory(code: number): number;
75
+ /**
76
+ * The specific error within its category — `code % 1000`. For a five-digit code
77
+ * this is the embedded external value (an HTTP status, a VAST code).
78
+ */
79
+ declare function svtaIndex(code: number): number;
80
+ //#endregion
81
+ export { SVTA_UNSUPPORTED_PLAYBACK_FEATURE, SvtaError, svtaCategory, svtaIndex };
82
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","names":[],"sources":["../../../src/media/errors.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAmCiB;;EAEf;;EAEA;;EAEA;;;;;;;;;;;;;;;;;;;;;;cAoDW;;;;;;;;;;iBAWG,aAAa;;;;;iBAQb,UAAU"}
@@ -0,0 +1,69 @@
1
+ //#region src/media/errors.ts
2
+ /** SVTA 1 [Media Content] 004 — the video is in a format we can't play (e.g. an MPEG-TS container). */
3
+ const SVTA_UNSUPPORTED_VIDEO_FORMAT = 1004;
4
+ /** SVTA 1 [Media Content] 005 — the audio counterpart of {@link SVTA_UNSUPPORTED_VIDEO_FORMAT}. */
5
+ const SVTA_UNSUPPORTED_AUDIO_FORMAT = 1005;
6
+ /**
7
+ * SVTA 4 [Content Protection] 008 — unsupported or unavailable DRM system. Used
8
+ * for "this source is encrypted and we have no decryption pipeline," which is
9
+ * detection, not a license failure.
10
+ */
11
+ const SVTA_UNSUPPORTED_DRM_SYSTEM = 4008;
12
+ /**
13
+ * SVTA 2 [Playback] 011 — no video track the environment can play.
14
+ *
15
+ * Covers both ways a composition can end up with nothing to select: renditions
16
+ * that existed and were all excluded as unplayable, and — where the composition
17
+ * composes `reportAbsentTrackType` to say it needs the type — a source carrying
18
+ * none to begin with. Deliberately one code for both, because they are the same
19
+ * answer to a viewer, and because the alternative is a code the SVTA spec doesn't
20
+ * define. Whether an absent type is a failure is the composition's to state,
21
+ * which is why it opts in rather than being read off the source.
22
+ */
23
+ const SVTA_NO_SUPPORTED_VIDEO_TRACK = 2011;
24
+ /** SVTA 2 [Playback] 012 — the audio counterpart of {@link SVTA_NO_SUPPORTED_VIDEO_TRACK}. */
25
+ const SVTA_NO_SUPPORTED_AUDIO_TRACK = 2012;
26
+ /**
27
+ * SVTA 99 [Custom] 001 — this engine has no pipeline for something the source
28
+ * requires, so the source is unplayable *here* rather than broken.
29
+ *
30
+ * Custom rather than standard because the standard codes available describe
31
+ * either narrower or wider things. The causes (1004/1005 unsupported format,
32
+ * 4008 unsupported DRM) say what one rendition hit; the verdicts (2011/2012 no
33
+ * supported track) say a type emptied without saying why it's unfixable. And
34
+ * 2039 "Manifest feature unsupported" covers features that are unsupported but
35
+ * still *playable* — LL-HLS degrading to standard live is a 2039 — so
36
+ * overloading it for a fatal condition would make it useless for the notices it
37
+ * belongs on.
38
+ *
39
+ * Index `001`: the spec defines only `99000` (Unknown) for the custom category
40
+ * and leaves the rest to the publisher, so this is the first code we define.
41
+ *
42
+ * Five digits, and deliberately not special-cased anywhere: {@link svtaCategory}
43
+ * and {@link svtaIndex} decompose it correctly by arithmetic alone, because
44
+ * every standard category is below `8000` and custom starts at `99000`.
45
+ */
46
+ const SVTA_UNSUPPORTED_PLAYBACK_FEATURE = 99001;
47
+ /**
48
+ * The error's domain — `code / 1000`, per the spec's "divide by one thousand to
49
+ * obtain the error category". Works uniformly across the four-digit native form
50
+ * and the five-digit form embedding an external standard: `"03404"` is
51
+ * numerically 3404, which decomposes identically. That also makes a numeric code
52
+ * immune to the spec's inconsistent zero-padding (§Approach writes a
53
+ * category-unknown network error as `"0300"` where the error index implies
54
+ * category 3 / index 000).
55
+ */
56
+ function svtaCategory(code) {
57
+ return Math.floor(code / 1e3);
58
+ }
59
+ /**
60
+ * The specific error within its category — `code % 1000`. For a five-digit code
61
+ * this is the embedded external value (an HTTP status, a VAST code).
62
+ */
63
+ function svtaIndex(code) {
64
+ return code % 1e3;
65
+ }
66
+ //#endregion
67
+ export { SVTA_NO_SUPPORTED_AUDIO_TRACK, SVTA_NO_SUPPORTED_VIDEO_TRACK, SVTA_UNSUPPORTED_AUDIO_FORMAT, SVTA_UNSUPPORTED_DRM_SYSTEM, SVTA_UNSUPPORTED_PLAYBACK_FEATURE, SVTA_UNSUPPORTED_VIDEO_FORMAT, svtaCategory, svtaIndex };
68
+
69
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../../../src/media/errors.ts"],"sourcesContent":["/**\n * SVTA 2070 (Standardized Error Codes) — the vocabulary for identifying a\n * playback failure or notice, independent of how it's transported or who\n * decides what to do about it.\n *\n * A code is a single integer: the leading digit(s) are the **category** (the\n * error's domain) and the trailing three are the **index** (the specific error\n * within it). Four digits for natively-defined errors, five when an external\n * standard is embedded — `\"03404\"` is an HTTP 404 under the network category.\n * Categories are `0` unknown, `1` media content, `2` playback, `3` network,\n * `4` content protection, `5` accessibility, `6` remote play, `7` advertising,\n * `99` custom.\n *\n * Two properties of the spec shape the types here:\n *\n * - **Severity is deliberately not part of a code.** Per §Approach, \"impact\n * varies with player implementation, breaking the consistency of a specific\n * error mapping to single code.\" So an error carries no fatal flag — whether a\n * condition is fatal depends on the composition observing it, and is decided\n * downstream.\n * - **Reporting is partial and stacked** (Principles 5–6). Errors are reported\n * as encountered, most of them non-fatal, and the *sequence* carries causation\n * a single value can't.\n *\n * See `internal/design/spf/features/errors.md`.\n */\n\n/**\n * A reported condition, identified by its SVTA code.\n *\n * Named for the spec rather than the engine because the vocabulary is\n * format- and player-neutral. Not `MediaError` — that name belongs to the\n * `@videojs/media` DOM-facing class this eventually maps *onto*, and the mapping\n * is the point at which severity and user-facing text get decided.\n */\nexport interface SvtaError {\n /** The SVTA code — see {@link svtaCategory} / {@link svtaIndex}. */\n code: number;\n /** Engineer-facing detail. Optional; the code is the identity. */\n message?: string;\n /** Reporter-specific context (track type, url, the constraint that fired). */\n data?: unknown;\n}\n\n/** SVTA 1 [Media Content] 004 — the video is in a format we can't play (e.g. an MPEG-TS container). */\nexport const SVTA_UNSUPPORTED_VIDEO_FORMAT = 1004;\n\n/** SVTA 1 [Media Content] 005 — the audio counterpart of {@link SVTA_UNSUPPORTED_VIDEO_FORMAT}. */\nexport const SVTA_UNSUPPORTED_AUDIO_FORMAT = 1005;\n\n/**\n * SVTA 4 [Content Protection] 008 — unsupported or unavailable DRM system. Used\n * for \"this source is encrypted and we have no decryption pipeline,\" which is\n * detection, not a license failure.\n */\nexport const SVTA_UNSUPPORTED_DRM_SYSTEM = 4008;\n\n/**\n * SVTA 2 [Playback] 011 — no video track the environment can play.\n *\n * Covers both ways a composition can end up with nothing to select: renditions\n * that existed and were all excluded as unplayable, and — where the composition\n * composes `reportAbsentTrackType` to say it needs the type — a source carrying\n * none to begin with. Deliberately one code for both, because they are the same\n * answer to a viewer, and because the alternative is a code the SVTA spec doesn't\n * define. Whether an absent type is a failure is the composition's to state,\n * which is why it opts in rather than being read off the source.\n */\nexport const SVTA_NO_SUPPORTED_VIDEO_TRACK = 2011;\n\n/** SVTA 2 [Playback] 012 — the audio counterpart of {@link SVTA_NO_SUPPORTED_VIDEO_TRACK}. */\nexport const SVTA_NO_SUPPORTED_AUDIO_TRACK = 2012;\n\n/**\n * SVTA 99 [Custom] 001 — this engine has no pipeline for something the source\n * requires, so the source is unplayable *here* rather than broken.\n *\n * Custom rather than standard because the standard codes available describe\n * either narrower or wider things. The causes (1004/1005 unsupported format,\n * 4008 unsupported DRM) say what one rendition hit; the verdicts (2011/2012 no\n * supported track) say a type emptied without saying why it's unfixable. And\n * 2039 \"Manifest feature unsupported\" covers features that are unsupported but\n * still *playable* — LL-HLS degrading to standard live is a 2039 — so\n * overloading it for a fatal condition would make it useless for the notices it\n * belongs on.\n *\n * Index `001`: the spec defines only `99000` (Unknown) for the custom category\n * and leaves the rest to the publisher, so this is the first code we define.\n *\n * Five digits, and deliberately not special-cased anywhere: {@link svtaCategory}\n * and {@link svtaIndex} decompose it correctly by arithmetic alone, because\n * every standard category is below `8000` and custom starts at `99000`.\n */\nexport const SVTA_UNSUPPORTED_PLAYBACK_FEATURE = 99001;\n\n/**\n * The error's domain — `code / 1000`, per the spec's \"divide by one thousand to\n * obtain the error category\". Works uniformly across the four-digit native form\n * and the five-digit form embedding an external standard: `\"03404\"` is\n * numerically 3404, which decomposes identically. That also makes a numeric code\n * immune to the spec's inconsistent zero-padding (§Approach writes a\n * category-unknown network error as `\"0300\"` where the error index implies\n * category 3 / index 000).\n */\nexport function svtaCategory(code: number): number {\n return Math.floor(code / 1000);\n}\n\n/**\n * The specific error within its category — `code % 1000`. For a five-digit code\n * this is the embedded external value (an HTTP status, a VAST code).\n */\nexport function svtaIndex(code: number): number {\n return code % 1000;\n}\n"],"mappings":";;AA6CA,MAAa,gCAAgC;;AAG7C,MAAa,gCAAgC;;;;;;AAO7C,MAAa,8BAA8B;;;;;;;;;;;;AAa3C,MAAa,gCAAgC;;AAG7C,MAAa,gCAAgC;;;;;;;;;;;;;;;;;;;;;AAsB7C,MAAa,oCAAoC;;;;;;;;;;AAWjD,SAAgB,aAAa,MAAsB;CACjD,OAAO,KAAK,MAAM,OAAO,GAAI;AAC/B;;;;;AAMA,SAAgB,UAAU,MAAsB;CAC9C,OAAO,OAAO;AAChB"}
@@ -0,0 +1,148 @@
1
+ //#region src/media/hls/parse-attributes.ts
2
+ /**
3
+ * Parse HLS attribute list from a tag line.
4
+ * Handles both quoted and unquoted values.
5
+ */
6
+ function parseAttributeList(line) {
7
+ const attributes = /* @__PURE__ */ new Map();
8
+ for (const match of line.matchAll(/([A-Z0-9-]+)=(?:"([^"]*)"|([^,]*))/g)) {
9
+ const key = match[1];
10
+ const value = match[2] ?? match[3] ?? "";
11
+ if (key) attributes.set(key, value);
12
+ }
13
+ return attributes;
14
+ }
15
+ /**
16
+ * Parse RESOLUTION attribute value (WIDTHxHEIGHT).
17
+ */
18
+ function parseResolution(value) {
19
+ const match = /^(\d+)x(\d+)$/.exec(value);
20
+ if (!match) return null;
21
+ return {
22
+ width: Number.parseInt(match[1], 10),
23
+ height: Number.parseInt(match[2], 10)
24
+ };
25
+ }
26
+ /**
27
+ * Parse FRAME-RATE attribute to rational frame rate.
28
+ */
29
+ function parseFrameRate(value) {
30
+ const fps = Number.parseFloat(value);
31
+ if (Number.isNaN(fps) || fps <= 0) return void 0;
32
+ if (Math.abs(fps - 23.976) < .01) return {
33
+ frameRateNumerator: 24e3,
34
+ frameRateDenominator: 1001
35
+ };
36
+ if (Math.abs(fps - 29.97) < .01) return {
37
+ frameRateNumerator: 3e4,
38
+ frameRateDenominator: 1001
39
+ };
40
+ if (Math.abs(fps - 59.94) < .01) return {
41
+ frameRateNumerator: 6e4,
42
+ frameRateDenominator: 1001
43
+ };
44
+ if (fps % 1 === 0) return { frameRateNumerator: Math.round(fps) };
45
+ return { frameRateNumerator: Math.round(fps) };
46
+ }
47
+ const AUDIO_CODEC_PREFIXES = [
48
+ "mp4a.",
49
+ "ac-3",
50
+ "ec-3",
51
+ "ac-4",
52
+ "opus",
53
+ "flac",
54
+ "dts",
55
+ "alac",
56
+ "vorbis"
57
+ ];
58
+ /**
59
+ * Parse CODECS attribute into separate video and audio codecs.
60
+ */
61
+ function parseCodecs(codecs) {
62
+ const parts = codecs.split(",").map((s) => s.trim());
63
+ const result = {};
64
+ for (const codec of parts) {
65
+ const lower = codec.toLowerCase();
66
+ if (codec.startsWith("avc1.") || codec.startsWith("hvc1.") || codec.startsWith("hev1.")) result.video = codec;
67
+ else if (AUDIO_CODEC_PREFIXES.some((prefix) => lower.startsWith(prefix))) result.audio = codec;
68
+ }
69
+ return result;
70
+ }
71
+ /**
72
+ * Parse #EXTINF duration value.
73
+ */
74
+ function parseExtInfDuration(value) {
75
+ const durationPart = value.split(",")[0] ?? value;
76
+ const duration = Number.parseFloat(durationPart);
77
+ return Number.isNaN(duration) ? 0 : duration;
78
+ }
79
+ /**
80
+ * Parse BYTERANGE attribute value.
81
+ * Format: "length[@offset]"
82
+ * If offset is omitted, it continues from the previous byte range end.
83
+ */
84
+ function parseByteRange(value, previousEnd) {
85
+ const match = /^(\d+)(?:@(\d+))?$/.exec(value);
86
+ if (!match) return null;
87
+ const length = Number.parseInt(match[1], 10);
88
+ if (Number.isNaN(length)) return null;
89
+ let start;
90
+ if (match[2] !== void 0) {
91
+ start = Number.parseInt(match[2], 10);
92
+ if (Number.isNaN(start)) return null;
93
+ } else if (previousEnd !== void 0) start = previousEnd;
94
+ else return null;
95
+ return {
96
+ start,
97
+ end: start + length - 1
98
+ };
99
+ }
100
+ /**
101
+ * Create AttributeList from raw attribute string.
102
+ */
103
+ function createAttributeList(line) {
104
+ const map = parseAttributeList(line);
105
+ return {
106
+ get(key) {
107
+ return map.get(key);
108
+ },
109
+ getInt(key, defaultValue) {
110
+ const value = map.get(key);
111
+ if (value === void 0) return defaultValue;
112
+ const parsed = Number.parseInt(value, 10);
113
+ return Number.isNaN(parsed) ? defaultValue : parsed;
114
+ },
115
+ getFloat(key, defaultValue) {
116
+ const value = map.get(key);
117
+ if (value === void 0) return defaultValue;
118
+ const parsed = Number.parseFloat(value);
119
+ return Number.isNaN(parsed) ? defaultValue : parsed;
120
+ },
121
+ getBool(key) {
122
+ return map.get(key) === "YES";
123
+ },
124
+ getResolution(key) {
125
+ const value = map.get(key);
126
+ if (!value) return void 0;
127
+ return parseResolution(value) ?? void 0;
128
+ },
129
+ getFrameRate(key) {
130
+ const value = map.get(key);
131
+ if (!value) return void 0;
132
+ return parseFrameRate(value);
133
+ }
134
+ };
135
+ }
136
+ /**
137
+ * Match a tag and extract its attributes.
138
+ * Returns null if the line doesn't match the tag.
139
+ */
140
+ function matchTag(line, tag) {
141
+ const prefix = `#${tag}:`;
142
+ if (!line.startsWith(prefix)) return null;
143
+ return createAttributeList(line.slice(prefix.length));
144
+ }
145
+ //#endregion
146
+ export { createAttributeList, matchTag, parseAttributeList, parseByteRange, parseCodecs, parseExtInfDuration, parseFrameRate, parseResolution };
147
+
148
+ //# sourceMappingURL=parse-attributes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-attributes.js","names":[],"sources":["../../../../src/media/hls/parse-attributes.ts"],"sourcesContent":["import type { FrameRate } from '../types';\n\n/**\n * Parse HLS attribute list from a tag line.\n * Handles both quoted and unquoted values.\n */\nexport function parseAttributeList(line: string): Map<string, string> {\n const attributes = new Map<string, string>();\n const regex = /([A-Z0-9-]+)=(?:\"([^\"]*)\"|([^,]*))/g;\n\n for (const match of line.matchAll(regex)) {\n const key = match[1];\n const value = match[2] ?? match[3] ?? '';\n if (key) {\n attributes.set(key, value);\n }\n }\n\n return attributes;\n}\n\n/**\n * Parse RESOLUTION attribute value (WIDTHxHEIGHT).\n */\nexport function parseResolution(value: string): { width: number; height: number } | null {\n const match = /^(\\d+)x(\\d+)$/.exec(value);\n if (!match) return null;\n\n const width = Number.parseInt(match[1]!, 10);\n const height = Number.parseInt(match[2]!, 10);\n\n return { width, height };\n}\n\n/**\n * Parse FRAME-RATE attribute to rational frame rate.\n */\nexport function parseFrameRate(value: string): FrameRate | undefined {\n const fps = Number.parseFloat(value);\n if (Number.isNaN(fps) || fps <= 0) return undefined;\n\n // Common frame rates with tolerance for floating point precision\n if (Math.abs(fps - 23.976) < 0.01) {\n return { frameRateNumerator: 24000, frameRateDenominator: 1001 };\n }\n if (Math.abs(fps - 29.97) < 0.01) {\n return { frameRateNumerator: 30000, frameRateDenominator: 1001 };\n }\n if (Math.abs(fps - 59.94) < 0.01) {\n return { frameRateNumerator: 60000, frameRateDenominator: 1001 };\n }\n\n // Integer frame rates\n if (fps % 1 === 0) {\n return { frameRateNumerator: Math.round(fps) };\n }\n\n // Default: use rounded value\n return { frameRateNumerator: Math.round(fps) };\n}\n\n// Audio codec identifiers, matched case-insensitively against each CODECS\n// entry's prefix. Beyond AAC (`mp4a.*`): Dolby (`ac-3`, `ec-3`, `ac-4`), Opus,\n// FLAC (`fLaC`), DTS (`dts*`), ALAC, and Vorbis. Recognizing these is what lets\n// capability probing filter undecodable audio renditions (e.g. an AC-3 5.1\n// track on a browser without AC-3) — an unrecognized codec parses empty and is\n// treated as unprobeable, so it would never be pruned.\nconst AUDIO_CODEC_PREFIXES = ['mp4a.', 'ac-3', 'ec-3', 'ac-4', 'opus', 'flac', 'dts', 'alac', 'vorbis'];\n\n/**\n * Parse CODECS attribute into separate video and audio codecs.\n */\nexport function parseCodecs(codecs: string): { video?: string; audio?: string } {\n const parts = codecs.split(',').map((s) => s.trim());\n const result: { video?: string; audio?: string } = {};\n\n for (const codec of parts) {\n const lower = codec.toLowerCase();\n if (codec.startsWith('avc1.') || codec.startsWith('hvc1.') || codec.startsWith('hev1.')) {\n result.video = codec;\n } else if (AUDIO_CODEC_PREFIXES.some((prefix) => lower.startsWith(prefix))) {\n result.audio = codec;\n }\n }\n\n return result;\n}\n\n/**\n * Parse #EXTINF duration value.\n */\nexport function parseExtInfDuration(value: string): number {\n const durationPart = value.split(',')[0] ?? value;\n const duration = Number.parseFloat(durationPart);\n return Number.isNaN(duration) ? 0 : duration;\n}\n\n/**\n * Parse BYTERANGE attribute value.\n * Format: \"length[@offset]\"\n * If offset is omitted, it continues from the previous byte range end.\n */\nexport function parseByteRange(value: string, previousEnd?: number): { start: number; end: number } | null {\n const match = /^(\\d+)(?:@(\\d+))?$/.exec(value);\n if (!match) return null;\n\n const length = Number.parseInt(match[1]!, 10);\n if (Number.isNaN(length)) return null;\n\n let start: number;\n if (match[2] !== undefined) {\n start = Number.parseInt(match[2], 10);\n if (Number.isNaN(start)) return null;\n } else if (previousEnd !== undefined) {\n start = previousEnd;\n } else {\n return null;\n }\n\n return { start, end: start + length - 1 };\n}\n\n/**\n * AttributeList - Typed attribute access wrapper.\n */\nexport interface AttributeList {\n get: (key: string) => string | undefined;\n getInt: (key: string, defaultValue?: number) => number | undefined;\n getFloat: (key: string, defaultValue?: number) => number | undefined;\n getBool: (key: string) => boolean;\n getResolution: (key: string) => { width: number; height: number } | undefined;\n getFrameRate: (key: string) => FrameRate | undefined;\n}\n\n/**\n * Create AttributeList from raw attribute string.\n */\nexport function createAttributeList(line: string): AttributeList {\n const map = parseAttributeList(line);\n\n return {\n get(key: string): string | undefined {\n return map.get(key);\n },\n\n getInt(key: string, defaultValue?: number): number | undefined {\n const value = map.get(key);\n if (value === undefined) return defaultValue;\n const parsed = Number.parseInt(value, 10);\n return Number.isNaN(parsed) ? defaultValue : parsed;\n },\n\n getFloat(key: string, defaultValue?: number): number | undefined {\n const value = map.get(key);\n if (value === undefined) return defaultValue;\n const parsed = Number.parseFloat(value);\n return Number.isNaN(parsed) ? defaultValue : parsed;\n },\n\n getBool(key: string): boolean {\n return map.get(key) === 'YES';\n },\n\n getResolution(key: string): { width: number; height: number } | undefined {\n const value = map.get(key);\n if (!value) return undefined;\n return parseResolution(value) ?? undefined;\n },\n\n getFrameRate(key: string): FrameRate | undefined {\n const value = map.get(key);\n if (!value) return undefined;\n return parseFrameRate(value);\n },\n };\n}\n\n/**\n * Match a tag and extract its attributes.\n * Returns null if the line doesn't match the tag.\n */\nexport function matchTag(line: string, tag: string): AttributeList | null {\n const prefix = `#${tag}:`;\n if (!line.startsWith(prefix)) return null;\n return createAttributeList(line.slice(prefix.length));\n}\n"],"mappings":"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"}
@@ -0,0 +1,261 @@
1
+ import { MEDIA_PLAYLIST_METADATA_KEY, getMediaPlaylistMetadata, isResolvedTrack } from "../types/index.js";
2
+ import { matchTag, parseByteRange, parseExtInfDuration } from "./parse-attributes.js";
3
+ import { resolveUrl } from "./resolve-url.js";
4
+ import { isUndefined } from "@videojs/utils/predicate";
5
+ //#region src/media/hls/parse-media-playlist.ts
6
+ /** MPEG-2 Transport Stream (IANA `video/MP2T`, lowercased for `isTypeSupported`). Video + audio TS — there is no `audio/mp2t`. */
7
+ const MPEG_TS_MIME = "video/mp2t";
8
+ /** Raw ADTS AAC packed-audio (HLS `.aac` segments; IANA `audio/aac`). */
9
+ const RAW_AAC_MIME = "audio/aac";
10
+ const CONTAINER_MIME_BY_EXTENSION = {
11
+ ".ts": MPEG_TS_MIME,
12
+ ".aac": RAW_AAC_MIME
13
+ };
14
+ /** The non-fMP4 container MIMEs the parser detects — all currently treated as unplayable. */
15
+ const NON_FMP4_CONTAINER_MIMES = new Set(Object.values(CONTAINER_MIME_BY_EXTENSION));
16
+ /**
17
+ * Non-fMP4 container MIME for a (resolved, absolute) segment URL, by file
18
+ * extension, ignoring the query string. `undefined` for fMP4 / unrecognized.
19
+ */
20
+ function containerMimeFromSegment(url) {
21
+ if (!url) return void 0;
22
+ let path;
23
+ try {
24
+ path = new URL(url).pathname.toLowerCase();
25
+ } catch {
26
+ path = url.toLowerCase().split("?")[0] ?? "";
27
+ }
28
+ const dot = path.lastIndexOf(".");
29
+ return dot === -1 ? void 0 : CONTAINER_MIME_BY_EXTENSION[path.slice(dot)];
30
+ }
31
+ /**
32
+ * Position a freshly-parsed window (whose segment `startTime`s are snapshot-
33
+ * local, i.e. from 0) onto the timeline established by the previous resolved
34
+ * snapshot. Carries the timeline forward using the media-sequence overlap and
35
+ * the previous window's *actual* segment durations — see
36
+ * `internal/design/spf/live-presentation-timeline-model.md`.
37
+ *
38
+ * - **Overlap** (`0 <= offset < previous.segments.length`): the new window's
39
+ * first segment is the same segment as `previous.segments[offset]`; anchor to
40
+ * its start (URLs checked — a mismatch warns).
41
+ * - **Sequence went backwards** (non-conformant): reset to the local base.
42
+ * - **Full turnover** (no overlap): estimate forward from the previous window's
43
+ * end across the unseen gap. This is the *only* place EXT-X-TARGETDURATION is
44
+ * used for timing — an upper-bound estimate, since the actual rolled-off
45
+ * durations are gone (exact recovery is the deferred PDT decision).
46
+ *
47
+ * Returns the rebased segments (the window edge is `segments[0].startTime`,
48
+ * derived — never stored on the track).
49
+ */
50
+ function placeOnPreviousTimeline(previous, segments, mediaSequence, targetDuration) {
51
+ const prevSegments = previous.segments;
52
+ const localBase = segments[0]?.startTime ?? 0;
53
+ if (prevSegments.length === 0 || segments.length === 0) return segments;
54
+ const offset = mediaSequence - (getMediaPlaylistMetadata(previous)?.mediaSequence ?? 0);
55
+ let anchor;
56
+ if (offset >= 0 && offset < prevSegments.length) {
57
+ const overlap = prevSegments[offset];
58
+ if (overlap.url !== segments[0].url) console.warn(`[parseMediaPlaylist] media-sequence aligns previous[${offset}] with the new window's first segment, but URLs differ (${overlap.url} vs ${segments[0].url}); sequence numbers may be unreliable.`);
59
+ anchor = overlap.startTime;
60
+ } else if (offset < 0) {
61
+ console.warn(`[parseMediaPlaylist] media-sequence went backwards (offset ${offset}); resetting timeline.`);
62
+ anchor = localBase;
63
+ } else {
64
+ const last = prevSegments[prevSegments.length - 1];
65
+ const newFirst = segments[0];
66
+ if (last.startDate !== void 0 && newFirst.startDate !== void 0) anchor = last.startTime + (newFirst.startDate - last.startDate);
67
+ else {
68
+ anchor = last.startTime + last.duration + (offset - prevSegments.length) * targetDuration;
69
+ console.warn(`[parseMediaPlaylist] full window turnover (offset ${offset} >= ${prevSegments.length}); no PDT to bridge — estimating from previous end.`);
70
+ }
71
+ }
72
+ const shift = anchor - localBase;
73
+ return shift === 0 ? segments : segments.map((segment) => ({
74
+ ...segment,
75
+ startTime: segment.startTime + shift
76
+ }));
77
+ }
78
+ /**
79
+ * Place a window on the frozen wall-clock anchor — the track's `startDate`
80
+ * (wall clock at media-time 0). The anchoring PDT-bearing segment lands at
81
+ * `segment.startDate − anchor`, so the window sits on the shared presentation
82
+ * timeline rather than a local-from-zero one (the `startDate` recomputed
83
+ * afterwards then reads back as the anchor — idempotent). This is the **main
84
+ * live path on every parse**: first resolves place against the pre-stamped
85
+ * shell anchor, and reloads re-place from PDT so drift can't accumulate and a
86
+ * long-stall turnover re-places with no overlap bridging (the HLS authoring
87
+ * spec's §8.1 EXTINF-accuracy rule bounds the per-reload correction to ~one
88
+ * video frame). Falls back to the local base when no segment carries PDT —
89
+ * there's nothing to anchor against (callers guard this for reloads, where the
90
+ * local base would reset the timeline).
91
+ */
92
+ function placeOnAnchor(segments, anchor) {
93
+ const anchorSegment = segments.find((segment) => !isUndefined(segment.startDate));
94
+ if (!anchorSegment || isUndefined(anchorSegment.startDate)) return segments;
95
+ const shift = anchorSegment.startDate - anchor - anchorSegment.startTime;
96
+ if (shift === 0) return segments;
97
+ return segments.map((segment) => ({
98
+ ...segment,
99
+ startTime: segment.startTime + shift
100
+ }));
101
+ }
102
+ /**
103
+ * Parse HLS media playlist and resolve track with segments.
104
+ *
105
+ * `previous` is what was known about this track before this parse: the
106
+ * partially-resolved track from the multivariant playlist on the first resolve,
107
+ * or the previously-resolved snapshot on a live reload. Its metadata is carried
108
+ * onto the result either way; when it's already resolved (has segments), its
109
+ * timeline is carried forward so the new window lands on a stable, advancing
110
+ * timeline (see {@link placeOnPreviousTimeline}).
111
+ *
112
+ * @param text - Media playlist text content
113
+ * @param previous - Prior track state (unresolved shell, or previous resolved snapshot)
114
+ * @returns Resolved track with segments (type inferred from input)
115
+ */
116
+ function parseMediaPlaylist(text, previous) {
117
+ const lines = text.split(/\r?\n/);
118
+ const baseUrl = previous.url;
119
+ const segments = [];
120
+ let initSegmentUrl;
121
+ let initSegmentByteRange;
122
+ let currentDuration = 0;
123
+ let currentByteRange;
124
+ let currentTime = 0;
125
+ let segmentIndex = 0;
126
+ let previousByteRangeEnd;
127
+ let currentStartDate;
128
+ let targetDuration = 0;
129
+ let mediaSequence = 0;
130
+ let playlistType;
131
+ let endList = false;
132
+ let holdBack;
133
+ let lowLatency = false;
134
+ let encrypted = false;
135
+ for (const line of lines) {
136
+ const trimmed = line.trim();
137
+ if (!trimmed || trimmed.startsWith("#") && !trimmed.startsWith("#EXT")) continue;
138
+ if (trimmed.startsWith("#EXT-X-TARGETDURATION:")) {
139
+ targetDuration = Number.parseInt(trimmed.slice(22), 10) || 0;
140
+ continue;
141
+ }
142
+ if (trimmed.startsWith("#EXT-X-MEDIA-SEQUENCE:")) {
143
+ mediaSequence = Number.parseInt(trimmed.slice(22), 10) || 0;
144
+ continue;
145
+ }
146
+ if (trimmed.startsWith("#EXT-X-PROGRAM-DATE-TIME:")) {
147
+ const parsed = Date.parse(trimmed.slice(25).trim());
148
+ currentStartDate = Number.isNaN(parsed) ? currentStartDate : parsed / 1e3;
149
+ continue;
150
+ }
151
+ if (trimmed.startsWith("#EXT-X-PLAYLIST-TYPE:")) {
152
+ const value = trimmed.slice(21).trim();
153
+ playlistType = value === "VOD" || value === "EVENT" ? value : void 0;
154
+ continue;
155
+ }
156
+ const key = matchTag(trimmed, "EXT-X-KEY");
157
+ if (key) {
158
+ const method = key.get("METHOD");
159
+ if (method !== void 0 && method !== "NONE") encrypted = true;
160
+ continue;
161
+ }
162
+ const serverControl = matchTag(trimmed, "EXT-X-SERVER-CONTROL");
163
+ if (serverControl) {
164
+ const value = serverControl.get("HOLD-BACK");
165
+ if (value !== void 0) {
166
+ const parsed = Number.parseFloat(value);
167
+ if (Number.isFinite(parsed) && parsed > 0) holdBack = parsed;
168
+ }
169
+ if (serverControl.get("PART-HOLD-BACK") !== void 0) lowLatency = true;
170
+ continue;
171
+ }
172
+ if (trimmed.startsWith("#EXT-X-PART-INF") || trimmed.startsWith("#EXT-X-PART:")) {
173
+ lowLatency = true;
174
+ continue;
175
+ }
176
+ if (trimmed === "#EXTM3U" || trimmed.startsWith("#EXT-X-VERSION:") || trimmed.startsWith("#EXT-X-INDEPENDENT-SEGMENTS")) continue;
177
+ const mapAttrs = matchTag(trimmed, "EXT-X-MAP");
178
+ if (mapAttrs) {
179
+ const uri = mapAttrs.get("URI");
180
+ if (uri) {
181
+ initSegmentUrl = resolveUrl(uri, baseUrl);
182
+ const byteRangeStr = mapAttrs.get("BYTERANGE");
183
+ if (byteRangeStr) initSegmentByteRange = parseByteRange(byteRangeStr, 0) ?? void 0;
184
+ }
185
+ continue;
186
+ }
187
+ if (trimmed.startsWith("#EXTINF:")) {
188
+ currentDuration = parseExtInfDuration(trimmed.slice(8));
189
+ continue;
190
+ }
191
+ if (trimmed.startsWith("#EXT-X-BYTERANGE:")) {
192
+ currentByteRange = parseByteRange(trimmed.slice(17), previousByteRangeEnd) ?? void 0;
193
+ continue;
194
+ }
195
+ if (trimmed === "#EXT-X-ENDLIST") {
196
+ endList = true;
197
+ continue;
198
+ }
199
+ if (!trimmed.startsWith("#") && currentDuration > 0) {
200
+ const segment = {
201
+ id: `segment-${mediaSequence + segmentIndex}`,
202
+ url: resolveUrl(trimmed, baseUrl),
203
+ duration: currentDuration,
204
+ startTime: currentTime
205
+ };
206
+ if (!isUndefined(currentStartDate)) {
207
+ segment.startDate = currentStartDate;
208
+ currentStartDate += currentDuration;
209
+ }
210
+ if (currentByteRange) {
211
+ segment.byteRange = currentByteRange;
212
+ previousByteRangeEnd = currentByteRange.end + 1;
213
+ } else previousByteRangeEnd = void 0;
214
+ segments.push(segment);
215
+ currentTime += currentDuration;
216
+ segmentIndex++;
217
+ currentDuration = 0;
218
+ currentByteRange = void 0;
219
+ }
220
+ }
221
+ const complete = endList || playlistType === "VOD";
222
+ const anchor = previous.startDate;
223
+ const hasPdt = segments.some((segment) => !isUndefined(segment.startDate));
224
+ const placed = !isUndefined(anchor) && hasPdt ? placeOnAnchor(segments, anchor) : isResolvedTrack(previous) ? placeOnPreviousTimeline(previous, segments, mediaSequence, targetDuration) : segments;
225
+ const lastPlaced = placed[placed.length - 1];
226
+ const placedEnd = lastPlaced ? lastPlaced.startTime + lastPlaced.duration : 0;
227
+ const trackDuration = complete ? placedEnd : Number.POSITIVE_INFINITY;
228
+ const anchorSegment = placed.find((segment) => !isUndefined(segment.startDate));
229
+ const startDate = anchorSegment && !isUndefined(anchorSegment.startDate) ? anchorSegment.startDate - anchorSegment.startTime : void 0;
230
+ const initialization = previous.type === "text" && !initSegmentUrl ? void 0 : initSegmentUrl ? {
231
+ url: initSegmentUrl,
232
+ ...initSegmentByteRange ? { byteRange: initSegmentByteRange } : {}
233
+ } : { url: "" };
234
+ const detectedContainer = initSegmentUrl ? void 0 : containerMimeFromSegment(placed[0]?.url);
235
+ const mimeType = previous.type !== "text" && detectedContainer ? detectedContainer : previous.mimeType;
236
+ return {
237
+ ...previous,
238
+ mimeType,
239
+ startTime: 0,
240
+ startDate,
241
+ duration: trackDuration,
242
+ segments: placed,
243
+ initialization,
244
+ metadata: {
245
+ ...previous.metadata,
246
+ [MEDIA_PLAYLIST_METADATA_KEY]: {
247
+ targetDuration,
248
+ mediaSequence,
249
+ playlistType,
250
+ lowLatency,
251
+ endList,
252
+ holdBack,
253
+ encrypted
254
+ }
255
+ }
256
+ };
257
+ }
258
+ //#endregion
259
+ export { MPEG_TS_MIME, NON_FMP4_CONTAINER_MIMES, RAW_AAC_MIME, parseMediaPlaylist };
260
+
261
+ //# sourceMappingURL=parse-media-playlist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-media-playlist.js","names":[],"sources":["../../../../src/media/hls/parse-media-playlist.ts"],"sourcesContent":["import { isUndefined } from '@videojs/utils/predicate';\nimport {\n type AudioTrack,\n getMediaPlaylistMetadata,\n isResolvedTrack,\n MEDIA_PLAYLIST_METADATA_KEY,\n type MediaPlaylistMetadata,\n type PartiallyResolvedAudioTrack,\n type PartiallyResolvedTextTrack,\n type PartiallyResolvedTrack,\n type PartiallyResolvedVideoTrack,\n type ResolvedTrack,\n type Segment,\n type TextTrack,\n type VideoTrack,\n} from '../types';\nimport { matchTag, parseByteRange, parseExtInfDuration } from './parse-attributes';\nimport { resolveUrl } from './resolve-url';\n\n/** MPEG-2 Transport Stream (IANA `video/MP2T`, lowercased for `isTypeSupported`). Video + audio TS — there is no `audio/mp2t`. */\nexport const MPEG_TS_MIME = 'video/mp2t';\n/** Raw ADTS AAC packed-audio (HLS `.aac` segments; IANA `audio/aac`). */\nexport const RAW_AAC_MIME = 'audio/aac';\n\n// Non-fMP4 container MIMEs keyed by segment file extension. fMP4 (the MSE\n// default) always carries an EXT-X-MAP init segment, so a media playlist with\n// no init segment and one of these extensions is a non-fMP4 rendition,\n// relabeled from the fMP4 default. Extend with `.mp3` → 'audio/mpeg' etc.\nconst CONTAINER_MIME_BY_EXTENSION: Record<string, string> = {\n '.ts': MPEG_TS_MIME,\n '.aac': RAW_AAC_MIME,\n};\n\n/** The non-fMP4 container MIMEs the parser detects — all currently treated as unplayable. */\nexport const NON_FMP4_CONTAINER_MIMES = new Set(Object.values(CONTAINER_MIME_BY_EXTENSION));\n\n/**\n * Non-fMP4 container MIME for a (resolved, absolute) segment URL, by file\n * extension, ignoring the query string. `undefined` for fMP4 / unrecognized.\n */\nfunction containerMimeFromSegment(url: string | undefined): string | undefined {\n if (!url) return undefined;\n let path: string;\n try {\n path = new URL(url).pathname.toLowerCase();\n } catch {\n path = url.toLowerCase().split('?')[0] ?? '';\n }\n const dot = path.lastIndexOf('.');\n return dot === -1 ? undefined : CONTAINER_MIME_BY_EXTENSION[path.slice(dot)];\n}\n\n/**\n * Resolve unresolved track type to its resolved equivalent.\n */\ntype ResolveTrack<T> = T extends PartiallyResolvedVideoTrack\n ? VideoTrack\n : T extends PartiallyResolvedAudioTrack\n ? AudioTrack\n : T extends PartiallyResolvedTextTrack\n ? TextTrack\n : never;\n\n/**\n * Position a freshly-parsed window (whose segment `startTime`s are snapshot-\n * local, i.e. from 0) onto the timeline established by the previous resolved\n * snapshot. Carries the timeline forward using the media-sequence overlap and\n * the previous window's *actual* segment durations — see\n * `internal/design/spf/live-presentation-timeline-model.md`.\n *\n * - **Overlap** (`0 <= offset < previous.segments.length`): the new window's\n * first segment is the same segment as `previous.segments[offset]`; anchor to\n * its start (URLs checked — a mismatch warns).\n * - **Sequence went backwards** (non-conformant): reset to the local base.\n * - **Full turnover** (no overlap): estimate forward from the previous window's\n * end across the unseen gap. This is the *only* place EXT-X-TARGETDURATION is\n * used for timing — an upper-bound estimate, since the actual rolled-off\n * durations are gone (exact recovery is the deferred PDT decision).\n *\n * Returns the rebased segments (the window edge is `segments[0].startTime`,\n * derived — never stored on the track).\n */\nfunction placeOnPreviousTimeline(\n previous: ResolvedTrack,\n segments: Segment[],\n mediaSequence: number,\n targetDuration: number\n): Segment[] {\n const prevSegments = previous.segments;\n const localBase = segments[0]?.startTime ?? 0;\n\n if (prevSegments.length === 0 || segments.length === 0) {\n return segments;\n }\n\n const prevMediaSequence = getMediaPlaylistMetadata(previous)?.mediaSequence ?? 0;\n const offset = mediaSequence - prevMediaSequence;\n\n let anchor: number;\n if (offset >= 0 && offset < prevSegments.length) {\n const overlap = prevSegments[offset]!;\n if (overlap.url !== segments[0]!.url) {\n console.warn(\n `[parseMediaPlaylist] media-sequence aligns previous[${offset}] with the new window's first segment, ` +\n `but URLs differ (${overlap.url} vs ${segments[0]!.url}); sequence numbers may be unreliable.`\n );\n }\n anchor = overlap.startTime;\n } else if (offset < 0) {\n console.warn(`[parseMediaPlaylist] media-sequence went backwards (offset ${offset}); resetting timeline.`);\n anchor = localBase;\n } else {\n const last = prevSegments[prevSegments.length - 1]!;\n const newFirst = segments[0]!;\n if (last.startDate !== undefined && newFirst.startDate !== undefined) {\n // PDT bridges the gap exactly — the spec-consistent cross-reload reference,\n // immune to the target-duration over-estimate when actual segment durations\n // differ from the declared ceiling. (`startDate` is intrinsic PDT, unaffected\n // by the new window's local positioning.)\n anchor = last.startTime + (newFirst.startDate - last.startDate);\n } else {\n anchor = last.startTime + last.duration + (offset - prevSegments.length) * targetDuration;\n console.warn(\n `[parseMediaPlaylist] full window turnover (offset ${offset} >= ${prevSegments.length}); ` +\n 'no PDT to bridge — estimating from previous end.'\n );\n }\n }\n\n const shift = anchor - localBase;\n return shift === 0 ? segments : segments.map((segment) => ({ ...segment, startTime: segment.startTime + shift }));\n}\n\n/**\n * Place a window on the frozen wall-clock anchor — the track's `startDate`\n * (wall clock at media-time 0). The anchoring PDT-bearing segment lands at\n * `segment.startDate − anchor`, so the window sits on the shared presentation\n * timeline rather than a local-from-zero one (the `startDate` recomputed\n * afterwards then reads back as the anchor — idempotent). This is the **main\n * live path on every parse**: first resolves place against the pre-stamped\n * shell anchor, and reloads re-place from PDT so drift can't accumulate and a\n * long-stall turnover re-places with no overlap bridging (the HLS authoring\n * spec's §8.1 EXTINF-accuracy rule bounds the per-reload correction to ~one\n * video frame). Falls back to the local base when no segment carries PDT —\n * there's nothing to anchor against (callers guard this for reloads, where the\n * local base would reset the timeline).\n */\nfunction placeOnAnchor(segments: Segment[], anchor: number): Segment[] {\n const anchorSegment = segments.find((segment) => !isUndefined(segment.startDate));\n if (!anchorSegment || isUndefined(anchorSegment.startDate)) {\n return segments;\n }\n\n const shift = anchorSegment.startDate - anchor - anchorSegment.startTime;\n if (shift === 0) {\n return segments;\n }\n\n return segments.map((segment) => ({ ...segment, startTime: segment.startTime + shift }));\n}\n\n/**\n * Parse HLS media playlist and resolve track with segments.\n *\n * `previous` is what was known about this track before this parse: the\n * partially-resolved track from the multivariant playlist on the first resolve,\n * or the previously-resolved snapshot on a live reload. Its metadata is carried\n * onto the result either way; when it's already resolved (has segments), its\n * timeline is carried forward so the new window lands on a stable, advancing\n * timeline (see {@link placeOnPreviousTimeline}).\n *\n * @param text - Media playlist text content\n * @param previous - Prior track state (unresolved shell, or previous resolved snapshot)\n * @returns Resolved track with segments (type inferred from input)\n */\nexport function parseMediaPlaylist<T extends PartiallyResolvedTrack>(\n text: string,\n previous: T | ResolveTrack<T>\n): ResolveTrack<T> {\n const lines = text.split(/\\r?\\n/);\n\n // Segments and resources resolve relative to media playlist URL (per HLS spec)\n const baseUrl = previous.url;\n\n // Parse playlist\n const segments: Segment[] = [];\n let initSegmentUrl: string | undefined;\n let initSegmentByteRange: { start: number; end: number } | undefined;\n\n let currentDuration = 0;\n let currentByteRange: { start: number; end: number } | undefined;\n let currentTime = 0;\n let segmentIndex = 0;\n let previousByteRangeEnd: number | undefined;\n // Absolute wall-clock of the next segment's first sample, in epoch seconds.\n // Seeded by an explicit `#EXT-X-PROGRAM-DATE-TIME` (which re-anchors, e.g.\n // across a discontinuity) and advanced by each segment's duration so segments\n // without their own tag are interpolated forward (per RFC 8216).\n let currentStartDate: number | undefined;\n\n // Playlist-level metadata (surfaced for live reload pacing / merge / termination).\n let targetDuration = 0;\n let mediaSequence = 0;\n let playlistType: 'VOD' | 'EVENT' | undefined;\n let endList = false;\n let holdBack: number | undefined;\n // Low-Latency HLS delivery. Any of the partial-segment tags is enough: the\n // parser ignores parts and the loader fetches whole segments, so this records\n // that the publisher configured LL-HLS, not that we honour it.\n let lowLatency = false;\n // Any EXT-X-KEY with a real METHOD makes the rendition encrypted. Sticky: a\n // clear lead (METHOD=NONE first, a real key later) still counts, since we can\n // only report whether decryption is needed at all.\n let encrypted = false;\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n if (!trimmed || (trimmed.startsWith('#') && !trimmed.startsWith('#EXT'))) {\n continue;\n }\n\n if (trimmed.startsWith('#EXT-X-TARGETDURATION:')) {\n targetDuration = Number.parseInt(trimmed.slice('#EXT-X-TARGETDURATION:'.length), 10) || 0;\n continue;\n }\n\n if (trimmed.startsWith('#EXT-X-MEDIA-SEQUENCE:')) {\n mediaSequence = Number.parseInt(trimmed.slice('#EXT-X-MEDIA-SEQUENCE:'.length), 10) || 0;\n continue;\n }\n\n if (trimmed.startsWith('#EXT-X-PROGRAM-DATE-TIME:')) {\n const parsed = Date.parse(trimmed.slice('#EXT-X-PROGRAM-DATE-TIME:'.length).trim());\n currentStartDate = Number.isNaN(parsed) ? currentStartDate : parsed / 1000;\n continue;\n }\n\n if (trimmed.startsWith('#EXT-X-PLAYLIST-TYPE:')) {\n const value = trimmed.slice('#EXT-X-PLAYLIST-TYPE:'.length).trim();\n playlistType = value === 'VOD' || value === 'EVENT' ? value : undefined;\n continue;\n }\n\n const key = matchTag(trimmed, 'EXT-X-KEY');\n if (key) {\n const method = key.get('METHOD');\n if (method !== undefined && method !== 'NONE') encrypted = true;\n continue;\n }\n\n // #EXT-X-SERVER-CONTROL — HOLD-BACK supplies the latency target. PART-HOLD-BACK\n // is read for its presence only, as an LL-HLS signal; see MediaPlaylistMetadata\n // on why its value stays out of `holdBack` until LL-HLS support lands.\n const serverControl = matchTag(trimmed, 'EXT-X-SERVER-CONTROL');\n if (serverControl) {\n const value = serverControl.get('HOLD-BACK');\n if (value !== undefined) {\n const parsed = Number.parseFloat(value);\n if (Number.isFinite(parsed) && parsed > 0) holdBack = parsed;\n }\n // Advertised for clients playing partial segments — its presence is an\n // LL-HLS signal even though the value stays deliberately unread.\n if (serverControl.get('PART-HOLD-BACK') !== undefined) lowLatency = true;\n continue;\n }\n\n // Partial segments: noted, then skipped. `#EXT-X-PART` lines would otherwise\n // fall through as unrecognized `#EXT` tags, so LL-HLS delivery went unnoticed.\n if (trimmed.startsWith('#EXT-X-PART-INF') || trimmed.startsWith('#EXT-X-PART:')) {\n lowLatency = true;\n continue;\n }\n\n if (\n trimmed === '#EXTM3U' ||\n trimmed.startsWith('#EXT-X-VERSION:') ||\n trimmed.startsWith('#EXT-X-INDEPENDENT-SEGMENTS')\n ) {\n continue;\n }\n\n // #EXT-X-MAP - Init segment\n const mapAttrs = matchTag(trimmed, 'EXT-X-MAP');\n if (mapAttrs) {\n const uri = mapAttrs.get('URI');\n if (uri) {\n initSegmentUrl = resolveUrl(uri, baseUrl);\n const byteRangeStr = mapAttrs.get('BYTERANGE');\n if (byteRangeStr) {\n initSegmentByteRange = parseByteRange(byteRangeStr, 0) ?? undefined;\n }\n }\n continue;\n }\n\n // #EXTINF - Segment duration\n if (trimmed.startsWith('#EXTINF:')) {\n currentDuration = parseExtInfDuration(trimmed.slice(8));\n continue;\n }\n\n // #EXT-X-BYTERANGE - Segment byte range\n if (trimmed.startsWith('#EXT-X-BYTERANGE:')) {\n currentByteRange = parseByteRange(trimmed.slice(17), previousByteRangeEnd) ?? undefined;\n continue;\n }\n\n if (trimmed === '#EXT-X-ENDLIST') {\n endList = true;\n continue;\n }\n\n // Segment URI\n if (!trimmed.startsWith('#') && currentDuration > 0) {\n const segment: Segment = {\n id: `segment-${mediaSequence + segmentIndex}`,\n url: resolveUrl(trimmed, baseUrl),\n duration: currentDuration,\n startTime: currentTime,\n };\n\n if (!isUndefined(currentStartDate)) {\n segment.startDate = currentStartDate;\n // Interpolate forward: the next segment without an explicit tag inherits\n // this anchor plus this segment's duration.\n currentStartDate += currentDuration;\n }\n\n if (currentByteRange) {\n segment.byteRange = currentByteRange;\n previousByteRangeEnd = currentByteRange.end + 1;\n } else {\n previousByteRangeEnd = undefined;\n }\n\n segments.push(segment);\n currentTime += currentDuration;\n segmentIndex++;\n\n currentDuration = 0;\n currentByteRange = undefined;\n }\n }\n\n const complete = endList || playlistType === 'VOD';\n\n // Position this window on the timeline. PDT is primary: whenever the track\n // carries a wall-clock anchor (`startDate` — pre-stamped on the shell for a\n // first resolve, recomputed-and-stable for a reload) and the new window has\n // PDT to place with, place from PDT against that frozen anchor\n // (`placeOnAnchor`) — self-correcting across reloads, history-free across\n // turnovers. Media-sequence/EXTINF carry-forward is the fallback for\n // PDT-less windows; a first resolve with neither anchors at the local base 0.\n const anchor = previous.startDate;\n const hasPdt = segments.some((segment) => !isUndefined(segment.startDate));\n const placed =\n !isUndefined(anchor) && hasPdt\n ? placeOnAnchor(segments, anchor)\n : isResolvedTrack(previous)\n ? placeOnPreviousTimeline(previous, segments, mediaSequence, targetDuration)\n : segments;\n\n // `duration` is the track's duration: Infinity while the playlist can still\n // grow (unended live), finite once complete (VOD / ENDLIST). Paired with\n // `startTime: 0` below, it spans the presentation origin to the last placed\n // segment's end — so it's measured off `placed`, not the local EXTINF sum:\n // for a window that has slid, the sum is the window's length, not its span.\n // Never the target duration.\n const lastPlaced = placed[placed.length - 1];\n const placedEnd = lastPlaced ? lastPlaced.startTime + lastPlaced.duration : 0;\n const trackDuration = complete ? placedEnd : Number.POSITIVE_INFINITY;\n\n // Wall-clock anchor: `startDate − startTime` for the first PDT-bearing\n // segment (constant along a linear timeline). Maps this track's origin to\n // wall clock; recomputed each parse, so it stays stable as the window slides\n // and is comparable across tracks for A/V alignment.\n const anchorSegment = placed.find((segment) => !isUndefined(segment.startDate));\n const startDate =\n anchorSegment && !isUndefined(anchorSegment.startDate)\n ? anchorSegment.startDate - anchorSegment.startTime\n : undefined;\n\n // Build initialization (VTT may not have init segment)\n const initialization =\n previous.type === 'text' && !initSegmentUrl\n ? undefined\n : initSegmentUrl\n ? { url: initSegmentUrl, ...(initSegmentByteRange ? { byteRange: initSegmentByteRange } : {}) }\n : { url: '' };\n\n // Container detection: fMP4 always carries an EXT-X-MAP init segment, so its\n // absence plus a recognized non-fMP4 segment extension (`.ts` → MPEG-TS,\n // `.aac` → raw ADTS AAC) marks a non-fMP4 rendition (high-precision — never\n // trips on fMP4, which mandates the map). Relabel from the fMP4 default\n // `video/mp4` / `audio/mp4` to the container MIME so capability probing prunes\n // it (these containers are currently treated as unplayable; see `canPlayTrack`).\n const detectedContainer = initSegmentUrl ? undefined : containerMimeFromSegment(placed[0]?.url);\n const mimeType = previous.type !== 'text' && detectedContainer ? detectedContainer : previous.mimeType;\n\n // Generic resolution: All type-specific fields already on `previous` track\n // Just add parsed properties (startTime, duration, segments, initialization, metadata)\n return {\n ...previous,\n mimeType,\n startTime: 0,\n startDate,\n duration: trackDuration,\n segments: placed,\n initialization,\n metadata: {\n ...previous.metadata,\n [MEDIA_PLAYLIST_METADATA_KEY]: {\n targetDuration,\n mediaSequence,\n playlistType,\n lowLatency,\n endList,\n holdBack,\n encrypted,\n } satisfies MediaPlaylistMetadata,\n },\n } as unknown as ResolveTrack<T>;\n}\n"],"mappings":"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"}