@amazon/vinyl 3.0.1 → 3.2.0

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 (268) hide show
  1. package/dist/index.cjs +1103 -1042
  2. package/dist/index.cjs.map +4 -4
  3. package/dist/index.js +810 -739
  4. package/dist/index.js.map +4 -4
  5. package/dist/test/benchmark.js.map +2 -2
  6. package/dist/test/integ.es5.js +394 -388
  7. package/dist/test/integ.js +2626 -2032
  8. package/dist/test/integ.js.map +4 -4
  9. package/dist/test/jasmine.css +50 -3
  10. package/dist/test/jasmineHtml.es5.js +195 -155
  11. package/dist/test/jasmineHtml.js +2938 -1833
  12. package/dist/test/jasmineHtml.js.map +3 -3
  13. package/dist/types/current/ad/AdControllerImpl.d.ts.map +1 -1
  14. package/dist/types/current/ad/AdControllerImpl.js +4 -1
  15. package/dist/types/current/ad/discoverHlsInterstitials.d.ts.map +1 -1
  16. package/dist/types/current/ad/discoverHlsInterstitials.js +2 -2
  17. package/dist/types/current/drm/DrmControllerImpl.d.ts +19 -1
  18. package/dist/types/current/drm/DrmControllerImpl.d.ts.map +1 -1
  19. package/dist/types/current/drm/DrmControllerImpl.js +101 -58
  20. package/dist/types/current/drm/licenseProvider/defaultLicenseProvider.d.ts.map +1 -1
  21. package/dist/types/current/drm/licenseProvider/defaultLicenseProvider.js +2 -2
  22. package/dist/types/current/index.d.ts +3 -6
  23. package/dist/types/current/index.d.ts.map +1 -1
  24. package/dist/types/current/index.js +3 -6
  25. package/dist/types/current/playback/PlaybackControllerImpl.d.ts +15 -0
  26. package/dist/types/current/playback/PlaybackControllerImpl.d.ts.map +1 -1
  27. package/dist/types/current/playback/PlaybackControllerImpl.js +100 -9
  28. package/dist/types/current/playback/ReadonlyPlaybackController.d.ts +27 -1
  29. package/dist/types/current/playback/ReadonlyPlaybackController.d.ts.map +1 -1
  30. package/dist/types/current/playback/ReadonlyPlaybackController.js +16 -0
  31. package/dist/types/current/playback/createStallDetector.d.ts +43 -0
  32. package/dist/types/current/playback/createStallDetector.d.ts.map +1 -0
  33. package/dist/types/current/playback/createStallDetector.js +101 -0
  34. package/dist/types/current/playback/createStallMonitor.d.ts +45 -0
  35. package/dist/types/current/playback/createStallMonitor.d.ts.map +1 -0
  36. package/dist/types/current/playback/createStallMonitor.js +94 -0
  37. package/dist/types/current/streaming/AudioOptions.d.ts +27 -0
  38. package/dist/types/current/streaming/AudioOptions.d.ts.map +1 -1
  39. package/dist/types/current/streaming/AudioOptions.js +5 -1
  40. package/dist/types/current/streaming/ContentStream.d.ts +0 -5
  41. package/dist/types/current/streaming/ContentStream.d.ts.map +1 -1
  42. package/dist/types/current/streaming/ContentStream.js +0 -4
  43. package/dist/types/current/streaming/LoadMetric.d.ts +15 -1
  44. package/dist/types/current/streaming/LoadMetric.d.ts.map +1 -1
  45. package/dist/types/current/streaming/StreamingEventMap.d.ts +1 -5
  46. package/dist/types/current/streaming/StreamingEventMap.d.ts.map +1 -1
  47. package/dist/types/current/streaming/StreamingEventMap.js +0 -1
  48. package/dist/types/current/streaming/buffering/BufferingController.d.ts +0 -11
  49. package/dist/types/current/streaming/buffering/BufferingController.d.ts.map +1 -1
  50. package/dist/types/current/streaming/buffering/BufferingController.js +0 -13
  51. package/dist/types/current/streaming/createDefaultMediaTimelineTransformer.d.ts.map +1 -1
  52. package/dist/types/current/streaming/createDefaultMediaTimelineTransformer.js +13 -4
  53. package/dist/types/current/streaming/mediaTimelineFilter.d.ts +4 -2
  54. package/dist/types/current/streaming/mediaTimelineFilter.d.ts.map +1 -1
  55. package/dist/types/current/streaming/mediaTimelineFilter.js +23 -8
  56. package/dist/types/current/text/SidecarTextTrackLoader.d.ts.map +1 -1
  57. package/dist/types/current/text/SidecarTextTrackLoader.js +4 -4
  58. package/dist/types/current/text/TextTrack.d.ts.map +1 -1
  59. package/dist/types/current/track/TrackController.d.ts.map +1 -1
  60. package/dist/types/current/track/TrackController.js +8 -2
  61. package/dist/types/current/track/createSegmentDataProvider.d.ts.map +1 -1
  62. package/dist/types/current/track/createSegmentDataProvider.js +6 -3
  63. package/dist/types/current/track/dash/DashMediaQualityMetadataResolver.d.ts +10 -6
  64. package/dist/types/current/track/dash/DashMediaQualityMetadataResolver.d.ts.map +1 -1
  65. package/dist/types/current/track/dash/DashMediaQualityMetadataResolver.js +13 -8
  66. package/dist/types/current/track/dash/createDashFactories.d.ts +1 -1
  67. package/dist/types/current/track/dash/timeline/DashRepresentationSegmentProvider.d.ts.map +1 -1
  68. package/dist/types/current/track/dash/timeline/DashRepresentationSegmentProvider.js +71 -3
  69. package/dist/types/current/track/dash/urlDashManifestProvider.js +2 -2
  70. package/dist/types/current/track/dash/util/mpd.d.ts +6 -0
  71. package/dist/types/current/track/dash/util/mpd.d.ts.map +1 -1
  72. package/dist/types/current/track/dash/util/mpd.js +24 -3
  73. package/dist/types/current/track/filters/resourceTypeFilter.d.ts +4 -0
  74. package/dist/types/current/track/filters/resourceTypeFilter.d.ts.map +1 -1
  75. package/dist/types/current/track/filters/resourceTypeFilter.js +4 -0
  76. package/dist/types/current/track/filters/sampleRateFilter.d.ts +25 -7
  77. package/dist/types/current/track/filters/sampleRateFilter.d.ts.map +1 -1
  78. package/dist/types/current/track/filters/sampleRateFilter.js +52 -24
  79. package/dist/types/current/track/hls/createHlsFactories.d.ts +1 -1
  80. package/dist/types/current/track/hls/createUrlHlsManifestProvider.d.ts.map +1 -1
  81. package/dist/types/current/track/hls/createUrlHlsManifestProvider.js +3 -3
  82. package/dist/types/current/track/mse/MseTrack.d.ts +0 -17
  83. package/dist/types/current/track/mse/MseTrack.d.ts.map +1 -1
  84. package/dist/types/current/track/mse/MseTrack.js +1 -45
  85. package/dist/types/current/tsconfig.tsbuildinfo +1 -1
  86. package/dist/types/current/util/media/mimeType.d.ts +8 -0
  87. package/dist/types/current/util/media/mimeType.d.ts.map +1 -0
  88. package/dist/types/current/util/media/mimeType.js +13 -0
  89. package/dist/types/current/vinyl/VinylPlayer.d.ts +5 -0
  90. package/dist/types/current/vinyl/VinylPlayer.d.ts.map +1 -1
  91. package/dist/types/current/vinyl/VinylPlayer.js +23 -1
  92. package/dist/types/current/vinyl/createVinylFactories.d.ts +7 -16
  93. package/dist/types/current/vinyl/createVinylFactories.d.ts.map +1 -1
  94. package/dist/types/current/vinyl/createVinylFactories.js +2 -12
  95. package/dist/types/ts3.7/drm/DrmControllerImpl.d.ts +19 -1
  96. package/dist/types/ts3.7/index.d.ts +3 -6
  97. package/dist/types/ts3.7/playback/PlaybackControllerImpl.d.ts +15 -0
  98. package/dist/types/ts3.7/playback/ReadonlyPlaybackController.d.ts +28 -0
  99. package/dist/types/ts3.7/playback/createStallDetector.d.ts +43 -0
  100. package/dist/types/ts3.7/playback/createStallMonitor.d.ts +45 -0
  101. package/dist/types/ts3.7/streaming/AudioOptions.d.ts +27 -0
  102. package/dist/types/ts3.7/streaming/ContentStream.d.ts +0 -5
  103. package/dist/types/ts3.7/streaming/LoadMetric.d.ts +15 -1
  104. package/dist/types/ts3.7/streaming/StreamingEventMap.d.ts +0 -5
  105. package/dist/types/ts3.7/streaming/buffering/BufferingController.d.ts +0 -11
  106. package/dist/types/ts3.7/streaming/mediaTimelineFilter.d.ts +4 -2
  107. package/dist/types/ts3.7/track/dash/DashMediaQualityMetadataResolver.d.ts +10 -6
  108. package/dist/types/ts3.7/track/dash/createDashFactories.d.ts +1 -1
  109. package/dist/types/ts3.7/track/dash/util/mpd.d.ts +6 -0
  110. package/dist/types/ts3.7/track/filters/resourceTypeFilter.d.ts +4 -0
  111. package/dist/types/ts3.7/track/filters/sampleRateFilter.d.ts +25 -7
  112. package/dist/types/ts3.7/track/hls/createHlsFactories.d.ts +1 -1
  113. package/dist/types/ts3.7/track/mse/MseTrack.d.ts +0 -17
  114. package/dist/types/ts3.7/util/media/mimeType.d.ts +8 -0
  115. package/dist/types/ts3.7/vinyl/VinylPlayer.d.ts +5 -0
  116. package/dist/types/ts3.7/vinyl/createVinylFactories.d.ts +7 -16
  117. package/dist/types/ts4.1/drm/DrmControllerImpl.d.ts +19 -1
  118. package/dist/types/ts4.1/index.d.ts +3 -6
  119. package/dist/types/ts4.1/playback/PlaybackControllerImpl.d.ts +15 -0
  120. package/dist/types/ts4.1/playback/ReadonlyPlaybackController.d.ts +28 -0
  121. package/dist/types/ts4.1/playback/createStallDetector.d.ts +43 -0
  122. package/dist/types/ts4.1/playback/createStallMonitor.d.ts +45 -0
  123. package/dist/types/ts4.1/streaming/AudioOptions.d.ts +27 -0
  124. package/dist/types/ts4.1/streaming/ContentStream.d.ts +0 -5
  125. package/dist/types/ts4.1/streaming/LoadMetric.d.ts +15 -1
  126. package/dist/types/ts4.1/streaming/StreamingEventMap.d.ts +0 -5
  127. package/dist/types/ts4.1/streaming/buffering/BufferingController.d.ts +0 -11
  128. package/dist/types/ts4.1/streaming/mediaTimelineFilter.d.ts +4 -2
  129. package/dist/types/ts4.1/track/dash/DashMediaQualityMetadataResolver.d.ts +10 -6
  130. package/dist/types/ts4.1/track/dash/createDashFactories.d.ts +1 -1
  131. package/dist/types/ts4.1/track/dash/util/mpd.d.ts +6 -0
  132. package/dist/types/ts4.1/track/filters/resourceTypeFilter.d.ts +4 -0
  133. package/dist/types/ts4.1/track/filters/sampleRateFilter.d.ts +25 -7
  134. package/dist/types/ts4.1/track/hls/createHlsFactories.d.ts +1 -1
  135. package/dist/types/ts4.1/track/mse/MseTrack.d.ts +0 -17
  136. package/dist/types/ts4.1/util/media/mimeType.d.ts +8 -0
  137. package/dist/types/ts4.1/vinyl/VinylPlayer.d.ts +5 -0
  138. package/dist/types/ts4.1/vinyl/createVinylFactories.d.ts +7 -16
  139. package/dist/types/ts4.7/drm/DrmControllerImpl.d.ts +19 -1
  140. package/dist/types/ts4.7/index.d.ts +3 -6
  141. package/dist/types/ts4.7/playback/PlaybackControllerImpl.d.ts +15 -0
  142. package/dist/types/ts4.7/playback/ReadonlyPlaybackController.d.ts +28 -0
  143. package/dist/types/ts4.7/playback/createStallDetector.d.ts +43 -0
  144. package/dist/types/ts4.7/playback/createStallMonitor.d.ts +45 -0
  145. package/dist/types/ts4.7/streaming/AudioOptions.d.ts +27 -0
  146. package/dist/types/ts4.7/streaming/ContentStream.d.ts +0 -5
  147. package/dist/types/ts4.7/streaming/LoadMetric.d.ts +15 -1
  148. package/dist/types/ts4.7/streaming/StreamingEventMap.d.ts +0 -5
  149. package/dist/types/ts4.7/streaming/buffering/BufferingController.d.ts +0 -11
  150. package/dist/types/ts4.7/streaming/mediaTimelineFilter.d.ts +4 -2
  151. package/dist/types/ts4.7/track/dash/DashMediaQualityMetadataResolver.d.ts +10 -6
  152. package/dist/types/ts4.7/track/dash/createDashFactories.d.ts +1 -1
  153. package/dist/types/ts4.7/track/dash/util/mpd.d.ts +6 -0
  154. package/dist/types/ts4.7/track/filters/resourceTypeFilter.d.ts +4 -0
  155. package/dist/types/ts4.7/track/filters/sampleRateFilter.d.ts +25 -7
  156. package/dist/types/ts4.7/track/hls/createHlsFactories.d.ts +1 -1
  157. package/dist/types/ts4.7/track/mse/MseTrack.d.ts +0 -17
  158. package/dist/types/ts4.7/util/media/mimeType.d.ts +8 -0
  159. package/dist/types/ts4.7/vinyl/VinylPlayer.d.ts +5 -0
  160. package/dist/types/ts4.7/vinyl/createVinylFactories.d.ts +7 -16
  161. package/dist/unit/types/current/ad/AdControllerImpl.test.js +27 -1
  162. package/dist/unit/types/current/drm/DrmControllerImpl.test.js +146 -9
  163. package/dist/unit/types/current/index.d.ts +3 -4
  164. package/dist/unit/types/current/index.d.ts.map +1 -1
  165. package/dist/unit/types/current/index.js +3 -4
  166. package/dist/unit/types/current/playback/PlaybackControllerImpl.test.js +165 -0
  167. package/dist/unit/types/current/playback/createStallDetector.test.d.ts +2 -0
  168. package/dist/unit/types/current/playback/createStallDetector.test.d.ts.map +1 -0
  169. package/dist/unit/types/current/playback/createStallDetector.test.js +163 -0
  170. package/dist/unit/types/current/playback/createStallMonitor.test.d.ts +2 -0
  171. package/dist/unit/types/current/playback/createStallMonitor.test.d.ts.map +1 -0
  172. package/dist/unit/types/current/playback/createStallMonitor.test.js +125 -0
  173. package/dist/unit/types/current/streaming/ContentStream.test.js +0 -11
  174. package/dist/unit/types/current/streaming/MseTrack.test.js +49 -73
  175. package/dist/unit/types/current/streaming/abr/QualitySelectorImpl.test.js +1 -1
  176. package/dist/unit/types/current/streaming/buffering/BufferingController.test.js +0 -21
  177. package/dist/unit/types/current/streaming/createDefaultMediaTimelineTransformer.test.js +133 -0
  178. package/dist/unit/types/current/streaming/mediaTimelineFilter.test.js +60 -54
  179. package/dist/unit/types/current/track/TrackController.test.js +61 -1
  180. package/dist/unit/types/current/track/createSegmentDataProvider.test.js +18 -0
  181. package/dist/unit/types/current/track/dash/DashMediaQualityMetadataResolver.test.js +46 -14
  182. package/dist/unit/types/current/track/dash/createSegmentControllerFactory.test.js +1 -0
  183. package/dist/unit/types/current/track/dash/timeline/DashRepresentationSegmentProvider.test.js +114 -0
  184. package/dist/unit/types/current/track/dash/util/mpd.test.js +37 -0
  185. package/dist/unit/types/current/track/filters/resourceTypeFilter.test.js +7 -0
  186. package/dist/unit/types/current/track/filters/sampleRateFilter.test.js +211 -34
  187. package/dist/unit/types/current/track/source/SourceObjectTrack.test.js +1 -1
  188. package/dist/unit/types/current/tsconfig.tsbuildinfo +1 -1
  189. package/dist/unit/types/current/util/media/mimeType.test.d.ts +2 -0
  190. package/dist/unit/types/current/util/media/mimeType.test.d.ts.map +1 -0
  191. package/dist/unit/types/current/util/media/mimeType.test.js +22 -0
  192. package/dist/unit/types/current/vinyl/VinylPlayer.test.js +33 -2
  193. package/dist/unit/types/current/vinyl/createVinylFactories.test.js +2 -36
  194. package/dist/vinylTestUtil/index.js +6 -4
  195. package/dist/vinylTestUtil/index.js.map +2 -2
  196. package/dist/vinylTestUtil/types/current/assets/vinylTestAssets.d.ts +1 -0
  197. package/dist/vinylTestUtil/types/current/assets/vinylTestAssets.d.ts.map +1 -1
  198. package/dist/vinylTestUtil/types/current/assets/vinylTestAssets.js +1 -0
  199. package/dist/vinylTestUtil/types/current/media/FrequencyAnalyzer.d.ts.map +1 -1
  200. package/dist/vinylTestUtil/types/current/mock/streaming/MockContentStream.d.ts +0 -1
  201. package/dist/vinylTestUtil/types/current/mock/streaming/MockContentStream.d.ts.map +1 -1
  202. package/dist/vinylTestUtil/types/current/mock/streaming/MockContentStream.js +0 -1
  203. package/dist/vinylTestUtil/types/current/mock/streaming/buffering/MockBufferingController.d.ts +0 -1
  204. package/dist/vinylTestUtil/types/current/mock/streaming/buffering/MockBufferingController.d.ts.map +1 -1
  205. package/dist/vinylTestUtil/types/current/mock/streaming/buffering/MockBufferingController.js +0 -1
  206. package/dist/vinylTestUtil/types/current/tsconfig.tsbuildinfo +1 -1
  207. package/dist/vinylTestUtil/types/current/util/playback/eventPromises.js +1 -1
  208. package/dist/vinylTestUtil/types/current/util/playback/expectTrackCanSeek.d.ts.map +1 -1
  209. package/dist/vinylTestUtil/types/current/util/playback/expectTrackCanSeek.js +9 -1
  210. package/dist/vinylTestUtil/types/ts3.7/assets/vinylTestAssets.d.ts +1 -0
  211. package/dist/vinylTestUtil/types/ts3.7/mock/streaming/MockContentStream.d.ts +0 -1
  212. package/dist/vinylTestUtil/types/ts3.7/mock/streaming/buffering/MockBufferingController.d.ts +0 -1
  213. package/dist/vinylTestUtil/types/ts4.1/assets/vinylTestAssets.d.ts +1 -0
  214. package/dist/vinylTestUtil/types/ts4.1/mock/streaming/MockContentStream.d.ts +0 -1
  215. package/dist/vinylTestUtil/types/ts4.1/mock/streaming/buffering/MockBufferingController.d.ts +0 -1
  216. package/dist/vinylTestUtil/types/ts4.7/assets/vinylTestAssets.d.ts +1 -0
  217. package/dist/vinylTestUtil/types/ts4.7/mock/streaming/MockContentStream.d.ts +0 -1
  218. package/dist/vinylTestUtil/types/ts4.7/mock/streaming/buffering/MockBufferingController.d.ts +0 -1
  219. package/docs/USAGE.md +29 -0
  220. package/package.json +11 -10
  221. package/dist/types/current/patch/media/HtmlMediaElementPatch.d.ts +0 -3
  222. package/dist/types/current/patch/media/HtmlMediaElementPatch.d.ts.map +0 -1
  223. package/dist/types/current/patch/media/HtmlMediaElementPatch.js +0 -5
  224. package/dist/types/current/patch/media/MediaElementPatchOptions.d.ts +0 -19
  225. package/dist/types/current/patch/media/MediaElementPatchOptions.d.ts.map +0 -1
  226. package/dist/types/current/patch/media/MediaElementPatchOptions.js +0 -16
  227. package/dist/types/current/patch/media/patchMediaElement.d.ts +0 -9
  228. package/dist/types/current/patch/media/patchMediaElement.d.ts.map +0 -1
  229. package/dist/types/current/patch/media/patchMediaElement.js +0 -15
  230. package/dist/types/current/patch/media/patches/createPreventStallsPatch.d.ts +0 -17
  231. package/dist/types/current/patch/media/patches/createPreventStallsPatch.d.ts.map +0 -1
  232. package/dist/types/current/patch/media/patches/createPreventStallsPatch.js +0 -55
  233. package/dist/types/current/patch/media/patches/createUnreliablePlaybackEventsPatch.d.ts +0 -26
  234. package/dist/types/current/patch/media/patches/createUnreliablePlaybackEventsPatch.d.ts.map +0 -1
  235. package/dist/types/current/patch/media/patches/createUnreliablePlaybackEventsPatch.js +0 -218
  236. package/dist/types/current/vinyl/VinylPatchOptions.d.ts +0 -10
  237. package/dist/types/current/vinyl/VinylPatchOptions.d.ts.map +0 -1
  238. package/dist/types/current/vinyl/VinylPatchOptions.js +0 -11
  239. package/dist/types/ts3.7/patch/media/HtmlMediaElementPatch.d.ts +0 -3
  240. package/dist/types/ts3.7/patch/media/MediaElementPatchOptions.d.ts +0 -19
  241. package/dist/types/ts3.7/patch/media/patchMediaElement.d.ts +0 -9
  242. package/dist/types/ts3.7/patch/media/patches/createPreventStallsPatch.d.ts +0 -17
  243. package/dist/types/ts3.7/patch/media/patches/createUnreliablePlaybackEventsPatch.d.ts +0 -26
  244. package/dist/types/ts3.7/vinyl/VinylPatchOptions.d.ts +0 -10
  245. package/dist/types/ts4.1/patch/media/HtmlMediaElementPatch.d.ts +0 -3
  246. package/dist/types/ts4.1/patch/media/MediaElementPatchOptions.d.ts +0 -19
  247. package/dist/types/ts4.1/patch/media/patchMediaElement.d.ts +0 -9
  248. package/dist/types/ts4.1/patch/media/patches/createPreventStallsPatch.d.ts +0 -17
  249. package/dist/types/ts4.1/patch/media/patches/createUnreliablePlaybackEventsPatch.d.ts +0 -26
  250. package/dist/types/ts4.1/vinyl/VinylPatchOptions.d.ts +0 -10
  251. package/dist/types/ts4.7/patch/media/HtmlMediaElementPatch.d.ts +0 -3
  252. package/dist/types/ts4.7/patch/media/MediaElementPatchOptions.d.ts +0 -19
  253. package/dist/types/ts4.7/patch/media/patchMediaElement.d.ts +0 -9
  254. package/dist/types/ts4.7/patch/media/patches/createPreventStallsPatch.d.ts +0 -17
  255. package/dist/types/ts4.7/patch/media/patches/createUnreliablePlaybackEventsPatch.d.ts +0 -26
  256. package/dist/types/ts4.7/vinyl/VinylPatchOptions.d.ts +0 -10
  257. package/dist/unit/types/current/patch/media/MediaElementPatchOptions.test.d.ts +0 -2
  258. package/dist/unit/types/current/patch/media/MediaElementPatchOptions.test.d.ts.map +0 -1
  259. package/dist/unit/types/current/patch/media/MediaElementPatchOptions.test.js +0 -17
  260. package/dist/unit/types/current/patch/media/patchMediaElement.test.d.ts +0 -2
  261. package/dist/unit/types/current/patch/media/patchMediaElement.test.d.ts.map +0 -1
  262. package/dist/unit/types/current/patch/media/patchMediaElement.test.js +0 -36
  263. package/dist/unit/types/current/patch/media/patches/createPreventStallsPatch.test.d.ts +0 -2
  264. package/dist/unit/types/current/patch/media/patches/createPreventStallsPatch.test.d.ts.map +0 -1
  265. package/dist/unit/types/current/patch/media/patches/createPreventStallsPatch.test.js +0 -93
  266. package/dist/unit/types/current/patch/media/patches/createUnreliablePlaybackEventsPatch.test.d.ts +0 -2
  267. package/dist/unit/types/current/patch/media/patches/createUnreliablePlaybackEventsPatch.test.d.ts.map +0 -1
  268. package/dist/unit/types/current/patch/media/patches/createUnreliablePlaybackEventsPatch.test.js +0 -423
package/dist/index.js CHANGED
@@ -236,7 +236,7 @@ var AdControllerImpl = class extends EventHostImpl {
236
236
  */
237
237
  providerInterrupted() {
238
238
  const provider = this.adsProvider;
239
- return () => provider !== this.adsProvider;
239
+ return () => this.disposed || provider !== this.adsProvider;
240
240
  }
241
241
  setAdsProvider(provider) {
242
242
  var _a;
@@ -615,7 +615,9 @@ var AdControllerImpl = class extends EventHostImpl {
615
615
  * Disposes this controller, removes all listeners.
616
616
  */
617
617
  dispose() {
618
+ var _a;
618
619
  super.dispose();
620
+ (_a = this.adsProviderSub) == null ? void 0 : _a.call(this);
619
621
  this.disposer.dispose();
620
622
  this.adBreakState = null;
621
623
  }
@@ -766,6 +768,7 @@ var UnresolvableAdError = class _UnresolvableAdError extends ReportableError2 {
766
768
  import { HLS_INTERSTITIAL_CLASS } from "@amazon/vinyl-hls-parser";
767
769
  import {
768
770
  memoize as memoize3,
771
+ readResponseBody,
769
772
  requestWithRetry as requestWithRetry2,
770
773
  resolveUrl
771
774
  } from "@amazon/vinyl-util";
@@ -928,7 +931,7 @@ async function resolveHlsAssetList({
928
931
  var _a;
929
932
  const url = resolveUrl(assetListUrl, baseUrl);
930
933
  const response = await requestWithRetry2(url);
931
- const json = await response.json();
934
+ const json = await readResponseBody(response, "json");
932
935
  const assets = (_a = json.ASSETS) != null ? _a : [];
933
936
  const ads = assets.map((asset, i) => {
934
937
  var _a2;
@@ -1805,7 +1808,11 @@ function parsePlayReadyKeyMessage(xmlStr) {
1805
1808
  }
1806
1809
 
1807
1810
  // src/drm/licenseProvider/defaultLicenseProvider.ts
1808
- import { requestWithRetry as requestWithRetry3, ValidationError } from "@amazon/vinyl-util";
1811
+ import {
1812
+ readResponseBody as readResponseBody2,
1813
+ requestWithRetry as requestWithRetry3,
1814
+ ValidationError
1815
+ } from "@amazon/vinyl-util";
1809
1816
  var defaultLicenseProvider = async (keySystem, serverOptions, challenge, abort) => {
1810
1817
  if (serverOptions.url == null) {
1811
1818
  throw new ValidationError(
@@ -1821,7 +1828,7 @@ var defaultLicenseProvider = async (keySystem, serverOptions, challenge, abort)
1821
1828
  }),
1822
1829
  { abort }
1823
1830
  );
1824
- return await res.arrayBuffer();
1831
+ return await readResponseBody2(res, "arrayBuffer");
1825
1832
  };
1826
1833
 
1827
1834
  // src/drm/util/extractContentId.ts
@@ -1885,6 +1892,10 @@ var DrmControllerImpl = class extends EventHostImpl5 {
1885
1892
  __publicField(this, "bufferingTrackUri", null);
1886
1893
  __publicField(this, "sessionAbort", null);
1887
1894
  __publicField(this, "pendingMessageProps", null);
1895
+ // Armed per track load; latches on the first session so only the
1896
+ // critical-path session's EME/CDM setup is measured.
1897
+ __publicField(this, "keySetupSpanArmed", true);
1898
+ __publicField(this, "keySetupSpanStart", null);
1888
1899
  __publicField(this, "disposer", /* @__PURE__ */ createDisposer2());
1889
1900
  __publicField(this, "checkIsSupportedCached", /* @__PURE__ */ memoize4(
1890
1901
  async (params) => {
@@ -1919,6 +1930,11 @@ var DrmControllerImpl = class extends EventHostImpl5 {
1919
1930
  ));
1920
1931
  __publicField(this, "handleEncryptedEvent", (event) => {
1921
1932
  if (this.disposed) return;
1933
+ if (this.manifestProvidesInitData()) {
1934
+ logDebug3(this, "ignoring encrypted event; manifest provides pssh");
1935
+ return;
1936
+ }
1937
+ ;
1922
1938
  (async () => {
1923
1939
  var _a;
1924
1940
  const { initData, initDataType } = event;
@@ -2040,11 +2056,12 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2040
2056
  * The new session will be added to the current sessions list.
2041
2057
  */
2042
2058
  async maybeCreateSession(options) {
2043
- var _a;
2059
+ var _a, _b;
2044
2060
  const { drmInfo, initDataType, initData, trackUri, abort } = options;
2045
2061
  if (!hasMimeType(drmInfo)) {
2046
2062
  throw new DrmError("Encrypted content must have a mimeType.");
2047
2063
  }
2064
+ this.markKeySetupStart();
2048
2065
  const mediaKeys = await this.attachMediaKeys(drmInfo);
2049
2066
  this.abortIfDisposed();
2050
2067
  const keySystemOptions = (_a = this.options.keySystems[mediaKeys.keySystem]) != null ? _a : this.options.keySystems["*"];
@@ -2053,33 +2070,63 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2053
2070
  licenseServerOptionsProvider != null ? licenseServerOptionsProvider : {}
2054
2071
  );
2055
2072
  this.abortIfDisposed();
2056
- const existingSession = this.getSessionByInitData(initData);
2073
+ const certBytes = toCertBytes(licenseServerOptions.serverCertificate);
2074
+ if (certBytes) {
2075
+ await mediaKeys.setServerCertificate(certBytes);
2076
+ this.abortIfDisposed();
2077
+ }
2078
+ const transform = (_b = keySystemOptions == null ? void 0 : keySystemOptions.initDataTransformer) != null ? _b : defaultInitDataTransformer(mediaKeys.keySystem, certBytes);
2079
+ const transformedInitData = transform(
2080
+ bufferToByteArray3(initData),
2081
+ initDataType,
2082
+ drmInfo
2083
+ );
2084
+ const existingSession = this.getSessionByInitData(transformedInitData);
2057
2085
  if (existingSession) {
2058
2086
  logDebug3(this, "reusing session");
2059
2087
  return existingSession;
2060
- } else {
2061
- const newSession = await this.createNewSession({
2062
- serverCertificate: licenseServerOptions.serverCertificate,
2063
- mediaKeys,
2064
- initData,
2065
- initDataType,
2066
- drmInfo,
2067
- trackUri,
2068
- initDataTransformer: keySystemOptions == null ? void 0 : keySystemOptions.initDataTransformer
2069
- });
2070
- this.sessions.push(newSession);
2071
- this.dispatch("sessionCreate", {
2072
- initDataType: newSession.initDataType,
2073
- mimeType: newSession.mimeType
2074
- });
2075
- newSession.on("closed", () => this.closeSession(newSession));
2076
- abort == null ? void 0 : abort.onAborted(() => {
2077
- if (this.disposed) return;
2078
- logDebug3(this, "abort session");
2079
- this.closeSession(newSession);
2080
- });
2081
- return newSession;
2082
2088
  }
2089
+ const newSession = this.createNewSession({
2090
+ mediaKeys,
2091
+ initData: transformedInitData,
2092
+ initDataType,
2093
+ drmInfo,
2094
+ trackUri
2095
+ });
2096
+ this.sessions.push(newSession);
2097
+ this.dispatch("sessionCreate", {
2098
+ initDataType: newSession.initDataType,
2099
+ mimeType: newSession.mimeType
2100
+ });
2101
+ newSession.on("closed", () => this.closeSession(newSession));
2102
+ abort == null ? void 0 : abort.onAborted(() => {
2103
+ if (this.disposed) return;
2104
+ logDebug3(this, "abort session");
2105
+ this.closeSession(newSession);
2106
+ });
2107
+ return newSession;
2108
+ }
2109
+ /**
2110
+ * Captures the key-setup span start at the top of the session-creation path
2111
+ * (before media keys are attached), latching so only the first session of
2112
+ * the current track load is measured.
2113
+ */
2114
+ markKeySetupStart() {
2115
+ if (!this.keySetupSpanArmed) return;
2116
+ this.keySetupSpanArmed = false;
2117
+ this.keySetupSpanStart = Date.now();
2118
+ }
2119
+ dispatchLoadSpan(kind, startTime, endTime, messageProps) {
2120
+ this.dispatch("loadSpanMeasured", __spreadValues(__spreadValues({
2121
+ kind,
2122
+ startTime,
2123
+ endTime,
2124
+ mimeType: messageProps.mimeType
2125
+ }, messageProps.trackUri != null && {
2126
+ trackUri: messageProps.trackUri
2127
+ }), messageProps.contentType != null && {
2128
+ contentType: messageProps.contentType
2129
+ }));
2083
2130
  }
2084
2131
  initializeForPlayback(drmInfo, options) {
2085
2132
  var _a;
@@ -2092,6 +2139,11 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2092
2139
  ).catch(this.handleError);
2093
2140
  }
2094
2141
  }
2142
+ /** True when the manifest carried pssh (sessions come from it, not events). */
2143
+ manifestProvidesInitData() {
2144
+ var _a, _b;
2145
+ return (_b = (_a = this.drmInfo) == null ? void 0 : _a.contentProtections.some((cP) => cP.pssh != null)) != null ? _b : false;
2146
+ }
2095
2147
  setBufferingDrmInfo(drmInfo, options) {
2096
2148
  var _a, _b;
2097
2149
  logDebug3(this, "setBufferingDrmInfo", drmInfo);
@@ -2099,6 +2151,8 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2099
2151
  this.drmInfo = drmInfo;
2100
2152
  this.bufferingTrackUri = (_a = options == null ? void 0 : options.trackUri) != null ? _a : null;
2101
2153
  this.sessionAbort = (_b = options == null ? void 0 : options.abort) != null ? _b : null;
2154
+ this.keySetupSpanArmed = true;
2155
+ this.keySetupSpanStart = null;
2102
2156
  }
2103
2157
  /**
2104
2158
  * If the drm metadata contains initialization data for the current key system, create a new session.
@@ -2110,6 +2164,7 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2110
2164
  this.handleError(new DrmError("DRM not supported."));
2111
2165
  return;
2112
2166
  }
2167
+ this.markKeySetupStart();
2113
2168
  const mediaKeys = await this.attachMediaKeys(drmInfo);
2114
2169
  const drmProtection = (_a = drmInfo.contentProtections.find((cP) => {
2115
2170
  return cP.keySystem === mediaKeys.keySystem;
@@ -2231,24 +2286,10 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2231
2286
  /**
2232
2287
  * Creates a new key session and adds a message handler.
2233
2288
  */
2234
- async createNewSession(options) {
2235
- const {
2236
- serverCertificate,
2237
- mediaKeys,
2238
- initDataType,
2239
- drmInfo,
2240
- trackUri,
2241
- initDataTransformer
2242
- } = options;
2243
- let initData = options.initData;
2244
- const certBytes = serverCertificate ? typeof serverCertificate === "string" ? base64ToByteArray2(serverCertificate) : bufferToByteArray3(serverCertificate) : null;
2245
- if (certBytes) {
2246
- await mediaKeys.setServerCertificate(certBytes);
2247
- }
2248
- const transform = initDataTransformer != null ? initDataTransformer : defaultInitDataTransformer(mediaKeys.keySystem, certBytes);
2249
- initData = transform(bufferToByteArray3(initData), initDataType, drmInfo);
2289
+ createNewSession(options) {
2290
+ const { mediaKeys, initData, initDataType, drmInfo, trackUri } = options;
2250
2291
  this.abortIfDisposed();
2251
- logDebug3(this, "createSession", drmInfo.mimeType, initDataType);
2292
+ logDebug3(this, "createSession", drmInfo.mimeType, initDataType, drmInfo);
2252
2293
  const session = mediaKeys.createSession(
2253
2294
  drmInfo.mimeType,
2254
2295
  initDataType,
@@ -2262,7 +2303,9 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2262
2303
  event,
2263
2304
  // Captured per session, so a concurrent preloaded track's
2264
2305
  // license exchange keeps its own attribution.
2265
- trackUri
2306
+ trackUri,
2307
+ mimeType: drmInfo.mimeType,
2308
+ contentType: drmInfo.contentType
2266
2309
  }),
2267
2310
  LICENSE_TIMEOUT,
2268
2311
  { message: LICENSE_TIMEOUT_MESSAGE }
@@ -2278,15 +2321,24 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2278
2321
  * Invoked when the content decryption module needs to interact with the license server.
2279
2322
  */
2280
2323
  async messageHandler(messageProps) {
2281
- var _a, _b;
2324
+ var _a, _b, _c;
2282
2325
  const { mediaKeys, session, event } = messageProps;
2283
2326
  messageEventValidator.assert(event);
2284
2327
  this.pendingMessageProps = messageProps;
2285
2328
  const keySystem = mediaKeys.keySystem;
2286
2329
  logDebug3(this, "message", keySystem, event.message.byteLength);
2287
- const keySystemOptions = this.options.keySystems[keySystem];
2330
+ if (this.keySetupSpanStart != null) {
2331
+ this.dispatchLoadSpan(
2332
+ "keySetup",
2333
+ this.keySetupSpanStart,
2334
+ Date.now(),
2335
+ messageProps
2336
+ );
2337
+ this.keySetupSpanStart = null;
2338
+ }
2339
+ const keySystemOptions = (_a = this.options.keySystems[keySystem]) != null ? _a : this.options.keySystems["*"];
2288
2340
  const licenseServerOptionsProvider = keySystemOptions == null ? void 0 : keySystemOptions.licenseServer;
2289
- const licenseServerOptions = (_a = clone(await resolveValueProvider2(licenseServerOptionsProvider))) != null ? _a : {};
2341
+ const licenseServerOptions = (_b = clone(await resolveValueProvider2(licenseServerOptionsProvider))) != null ? _b : {};
2290
2342
  this.abortIfDisposed();
2291
2343
  let challenge = event.message;
2292
2344
  if (isPlayReady(keySystem)) {
@@ -2295,7 +2347,7 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2295
2347
  if (licenseServerOptions.init == null)
2296
2348
  licenseServerOptions.init = {};
2297
2349
  licenseServerOptions.init.headers = __spreadValues(__spreadValues({}, normalizeHeadersInit(
2298
- (_b = licenseServerOptions.init.headers) != null ? _b : {}
2350
+ (_c = licenseServerOptions.init.headers) != null ? _c : {}
2299
2351
  )), unpacked.headers);
2300
2352
  }
2301
2353
  const licenseSpanStart = Date.now();
@@ -2304,13 +2356,13 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2304
2356
  licenseServerOptions,
2305
2357
  challenge
2306
2358
  );
2307
- this.dispatch("loadSpanMeasured", __spreadValues({
2308
- kind: "license",
2309
- startTime: licenseSpanStart,
2310
- endTime: Date.now()
2311
- }, messageProps.trackUri != null && {
2312
- trackUri: messageProps.trackUri
2313
- }));
2359
+ if (this.disposed) return;
2360
+ this.dispatchLoadSpan(
2361
+ "license",
2362
+ licenseSpanStart,
2363
+ Date.now(),
2364
+ messageProps
2365
+ );
2314
2366
  this.pendingMessageProps = null;
2315
2367
  if (session.disposed) return;
2316
2368
  logDebug3(this, "update");
@@ -2393,9 +2445,9 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2393
2445
  }
2394
2446
  getSessionByInitData(initData) {
2395
2447
  var _a;
2396
- return (_a = this.sessions.find((session) => {
2397
- return buffersEqual(session.initData, initData);
2398
- })) != null ? _a : null;
2448
+ return (_a = this.sessions.find(
2449
+ (session) => buffersEqual(session.initData, initData)
2450
+ )) != null ? _a : null;
2399
2451
  }
2400
2452
  };
2401
2453
  var messageEventValidator = /* @__PURE__ */ object3({
@@ -2404,6 +2456,10 @@ var messageEventValidator = /* @__PURE__ */ object3({
2404
2456
  function hasMimeType(drmInfo) {
2405
2457
  return drmInfo.mimeType != null;
2406
2458
  }
2459
+ function toCertBytes(serverCertificate) {
2460
+ if (!serverCertificate) return null;
2461
+ return typeof serverCertificate === "string" ? base64ToByteArray2(serverCertificate) : bufferToByteArray3(serverCertificate);
2462
+ }
2407
2463
  function defaultInitDataTransformer(keySystem, certBytes) {
2408
2464
  return (initData) => {
2409
2465
  if (keySystem === "com.apple.fps.1_0" /* FAIR_PLAY_1_0 */) {
@@ -2565,7 +2621,7 @@ function configureVinylGlobal(options) {
2565
2621
  import { parseVersion } from "@amazon/vinyl-util";
2566
2622
  var vinylVersion = /* @__PURE__ */ parseVersion(
2567
2623
  /* istanbul ignore next */
2568
- "3.0.1"
2624
+ "3.2.0"
2569
2625
  );
2570
2626
 
2571
2627
  // src/global/globalRef.ts
@@ -2620,237 +2676,220 @@ function initializeVinylGlobal() {
2620
2676
  vinylGlobalRef.initialize();
2621
2677
  }
2622
2678
 
2623
- // src/patch/media/MediaElementPatchOptions.ts
2624
- import { lazy as lazy2 } from "@amazon/vinyl-util";
2625
-
2626
- // src/patch/media/patches/createUnreliablePlaybackEventsPatch.ts
2627
- import { Browser, hasBrowser } from "@amazon/vinyl-util";
2628
- import {
2629
- closeTo,
2630
- createDisposer as createDisposer3,
2631
- DomEventHost,
2632
- onAny,
2633
- SignalImpl
2634
- } from "@amazon/vinyl-util";
2635
- var UNRELIABLE_EVENTS_POLL_INTERVAL = 0.2;
2636
- var MIN_STALLED_BEFORE_FAB = 0.8;
2637
- var MIN_PLAYING_BEFORE_FAB = 0.4;
2638
- var MIN_PLAYING_DELTA = 0.05;
2639
- var MIN_SEEKING_DELTA = 0.5;
2640
- function createUnreliablePlaybackEventsPatch(media) {
2641
- const { add, dispose } = createDisposer3();
2642
- const domEvents = add(new DomEventHost(media));
2643
- const eventFabricated = add(new SignalImpl());
2644
- let stateChangedAt = Date.now();
2645
- let currentApparentState = 1 /* STOPPED */;
2646
- function setApparentState(state, changedAt = Date.now()) {
2647
- if (currentApparentState !== state) {
2648
- currentApparentState = state;
2649
- stateChangedAt = changedAt;
2650
- }
2651
- }
2652
- function elapsedStateTime() {
2653
- return (Date.now() - stateChangedAt) / 1e3;
2654
- }
2655
- let lastTimestamp = Date.now();
2679
+ // src/playback/createStallDetector.ts
2680
+ function createStallDetector(media, options) {
2681
+ var _a, _b, _c, _d, _e, _f;
2682
+ const { fabricatePlaying } = options;
2683
+ const pollInterval = (_a = options.pollInterval) != null ? _a : 0.25;
2684
+ const stallThreshold = (_b = options.stallThreshold) != null ? _b : 0.75;
2685
+ const bufferEndMargin = (_c = options.bufferEndMargin) != null ? _c : 0.5;
2686
+ const stallSkip = (_d = options.stallSkip) != null ? _d : 0.1;
2687
+ const maxAttempts = (_e = options.maxAttempts) != null ? _e : 3;
2688
+ const nudgeUnbuffered = (_f = options.nudgeUnbuffered) != null ? _f : false;
2656
2689
  let lastTime = media.currentTime;
2657
- let waiting = false;
2658
- let seeking = false;
2659
- onAny(
2660
- domEvents,
2661
- ["emptied", "ended", "pause", "playing", "seeking"],
2662
- () => {
2663
- waiting = false;
2664
- }
2665
- );
2666
- let playing = false;
2667
- onAny(
2668
- domEvents,
2669
- ["emptied", "ended", "pause", "seeking", "waiting"],
2670
- () => {
2671
- playing = false;
2672
- }
2673
- );
2674
- domEvents.on("seeking", () => {
2675
- seeking = true;
2676
- });
2677
- domEvents.on("seeked", () => {
2678
- seeking = false;
2679
- setApparentState(2 /* SEEKING */);
2680
- });
2681
- domEvents.on("play", () => {
2682
- stateChangedAt = Date.now();
2683
- });
2684
- const readyStateEvents = [
2685
- "emptied",
2686
- "loadeddata",
2687
- "loadedmetadata",
2688
- "waiting"
2689
- ];
2690
- let lastReadyStateEvent = "emptied";
2691
- add(
2692
- onAny(domEvents, readyStateEvents, (_, type) => {
2693
- lastReadyStateEvent = type;
2694
- })
2695
- );
2696
- const checkApparentState = () => {
2697
- const progressed = (media.currentTime - lastTime) / media.playbackRate;
2698
- const now = Date.now();
2699
- if (Math.abs(progressed) > MIN_SEEKING_DELTA) {
2700
- setApparentState(2 /* SEEKING */, lastTimestamp);
2701
- } else if (progressed >= MIN_PLAYING_DELTA) {
2702
- setApparentState(0 /* PLAYING */, lastTimestamp);
2703
- } else if (closeTo(progressed, 0, MIN_PLAYING_DELTA)) {
2704
- setApparentState(1 /* STOPPED */, lastTimestamp);
2705
- }
2706
- lastTime = media.currentTime;
2707
- lastTimestamp = now;
2708
- if (!playing && !seeking && !media.paused && !media.ended && media.readyState >= media.HAVE_FUTURE_DATA && currentApparentState === 0 /* PLAYING */ && elapsedStateTime() >= MIN_PLAYING_BEFORE_FAB) {
2709
- waiting = false;
2710
- playing = true;
2711
- if (lastReadyStateEvent !== "canplay" && lastReadyStateEvent !== "canplaythrough") {
2712
- lastReadyStateEvent = "canplay";
2713
- eventFabricated.dispatch(new CustomEvent("canplay"));
2714
- }
2715
- if (media.readyState >= media.HAVE_ENOUGH_DATA) {
2716
- if (lastReadyStateEvent !== "canplaythrough") {
2717
- lastReadyStateEvent = "canplaythrough";
2718
- eventFabricated.dispatch(new CustomEvent("canplaythrough"));
2719
- }
2720
- }
2721
- eventFabricated.dispatch(new CustomEvent("playing"));
2722
- }
2723
- if (!waiting && !media.paused && !media.ended && currentApparentState === 1 /* STOPPED */ && elapsedStateTime() >= MIN_STALLED_BEFORE_FAB) {
2724
- waiting = true;
2725
- playing = false;
2726
- eventFabricated.dispatch(new CustomEvent("waiting"));
2727
- }
2690
+ let stalledFor = 0;
2691
+ let attempts = 0;
2692
+ let sawPlaying = false;
2693
+ let recovered = false;
2694
+ const onPlaying = () => {
2695
+ sawPlaying = true;
2728
2696
  };
2729
- const playbackWatchIntervalId = setInterval(
2730
- checkApparentState,
2731
- UNRELIABLE_EVENTS_POLL_INTERVAL * 1e3
2732
- );
2733
- add(() => {
2734
- clearInterval(playbackWatchIntervalId);
2735
- });
2736
- return {
2737
- eventFabricated,
2738
- properties: {
2739
- /**
2740
- * Platforms that have unreliable waiting events, also have unreliable ready state
2741
- * when the end of buffered data has been reached. If the media is in a waiting state,
2742
- * the highest ready state that is possible is HAVE_METADATA.
2743
- */
2744
- readyState: {
2745
- get() {
2746
- return waiting ? Math.min(media.readyState, media.HAVE_METADATA) : media.readyState;
2747
- }
2748
- }
2749
- },
2750
- events: {
2751
- canplay(event) {
2752
- const eventOrNull = lastReadyStateEvent === "canplay" ? null : event;
2753
- lastReadyStateEvent = "canplay";
2754
- return eventOrNull;
2755
- },
2756
- canplaythrough(event) {
2757
- const eventOrNull = lastReadyStateEvent === "canplaythrough" ? null : event;
2758
- lastReadyStateEvent = "canplaythrough";
2759
- return eventOrNull;
2760
- },
2761
- playing(event) {
2762
- if (playing) {
2763
- return null;
2764
- }
2765
- setApparentState(0 /* PLAYING */);
2766
- playing = true;
2767
- return event;
2768
- },
2769
- waiting(event) {
2770
- if (waiting) {
2771
- return null;
2772
- }
2773
- waiting = true;
2774
- setApparentState(1 /* STOPPED */);
2775
- return event;
2776
- }
2777
- },
2778
- dispose
2697
+ const onEmptied = () => stop();
2698
+ media.addEventListener("playing", onPlaying);
2699
+ media.addEventListener("emptied", onEmptied);
2700
+ const stop = () => {
2701
+ clearInterval(id);
2702
+ media.removeEventListener("playing", onPlaying);
2703
+ media.removeEventListener("emptied", onEmptied);
2779
2704
  };
2780
- }
2781
- function requiresUnreliablePlaybackEventsPatch() {
2782
- return hasBrowser(Browser.SAFARI) || hasBrowser(Browser.EDGE_LEGACY) || hasBrowser(Browser.CHROMIUM, null, "53");
2705
+ const id = setInterval(() => {
2706
+ if (media.paused || media.ended) return stop();
2707
+ if (media.currentTime !== lastTime) {
2708
+ lastTime = media.currentTime;
2709
+ if (!sawPlaying || recovered) fabricatePlaying();
2710
+ return stop();
2711
+ }
2712
+ if (!nudgeUnbuffered && !withinBufferedData(media, bufferEndMargin)) {
2713
+ stalledFor = 0;
2714
+ return;
2715
+ }
2716
+ stalledFor += pollInterval;
2717
+ if (stalledFor < stallThreshold) return;
2718
+ stalledFor = 0;
2719
+ if (attempts++ >= maxAttempts) return stop();
2720
+ recovered = true;
2721
+ media.currentTime += stallSkip;
2722
+ lastTime = media.currentTime;
2723
+ }, pollInterval * 1e3);
2724
+ return stop;
2725
+ }
2726
+ function withinBufferedData(media, endMargin) {
2727
+ const t = media.currentTime;
2728
+ const duration = media.duration;
2729
+ const buffered = media.buffered;
2730
+ for (let i = 0; i < buffered.length; i++) {
2731
+ const end = buffered.end(i);
2732
+ const isEndOfMedia = Number.isFinite(duration) && duration > 0 && end >= duration - endMargin;
2733
+ if (t >= buffered.start(i) && (t < end - endMargin || isEndOfMedia))
2734
+ return true;
2735
+ }
2736
+ return false;
2783
2737
  }
2784
2738
 
2785
- // src/patch/media/patches/createPreventStallsPatch.ts
2786
- import {
2787
- Browser as Browser2,
2788
- closeTo as closeTo2,
2789
- createDisposer as createDisposer4,
2790
- createLogPrefix as createLogPrefix2,
2791
- DomEventHost as DomEventHost2,
2792
- hasBrowser as hasBrowser2,
2793
- logInfo,
2794
- logWarn as logWarn2,
2795
- noop as noop4
2796
- } from "@amazon/vinyl-util";
2797
- var MAX_UNCHANGED_COUNT = 10;
2798
- function createPreventStallsPatch(media) {
2799
- const { add, dispose } = createDisposer4();
2800
- const domEvents = add(new DomEventHost2(media));
2801
- const pathTarget = {
2802
- logPrefix: createLogPrefix2("createPreventStallsPatch")
2739
+ // src/playback/createStallMonitor.ts
2740
+ import { createDisposer as createDisposer3 } from "@amazon/vinyl-util";
2741
+
2742
+ // src/playback/ReadonlyPlaybackController.ts
2743
+ var PlayedReason = /* @__PURE__ */ ((PlayedReason2) => {
2744
+ PlayedReason2["EMPTIED"] = "emptied";
2745
+ PlayedReason2["ENDED"] = "ended";
2746
+ PlayedReason2["PAUSE"] = "pause";
2747
+ PlayedReason2["SEEKING"] = "seeking";
2748
+ PlayedReason2["WAITING"] = "waiting";
2749
+ return PlayedReason2;
2750
+ })(PlayedReason || {});
2751
+ var playedReasons = [
2752
+ "emptied" /* EMPTIED */,
2753
+ "ended" /* ENDED */,
2754
+ "pause" /* PAUSE */,
2755
+ "seeking" /* SEEKING */,
2756
+ "waiting" /* WAITING */
2757
+ ];
2758
+ var WaitedReason = /* @__PURE__ */ ((WaitedReason2) => {
2759
+ WaitedReason2["PLAYING"] = "playing";
2760
+ WaitedReason2["PAUSE"] = "pause";
2761
+ WaitedReason2["EMPTIED"] = "emptied";
2762
+ WaitedReason2["SEEKING"] = "seeking";
2763
+ return WaitedReason2;
2764
+ })(WaitedReason || {});
2765
+ var waitedReasons = [
2766
+ "playing" /* PLAYING */,
2767
+ "pause" /* PAUSE */,
2768
+ "emptied" /* EMPTIED */,
2769
+ "seeking" /* SEEKING */
2770
+ ];
2771
+ var StallEndedReason = /* @__PURE__ */ ((StallEndedReason2) => {
2772
+ StallEndedReason2["PLAYING"] = "playing";
2773
+ StallEndedReason2["PAUSE"] = "pause";
2774
+ StallEndedReason2["SEEKING"] = "seeking";
2775
+ StallEndedReason2["EMPTIED"] = "emptied";
2776
+ return StallEndedReason2;
2777
+ })(StallEndedReason || {});
2778
+ var ALL_PLAYBACK_STATE_EVENTS = [
2779
+ "abort",
2780
+ "canPlay",
2781
+ "canPlayThrough",
2782
+ "durationChange",
2783
+ "emptied",
2784
+ "ended",
2785
+ "error",
2786
+ "playIsPendingChange",
2787
+ "loadedData",
2788
+ "loadedMetadata",
2789
+ "loadStart",
2790
+ "looped",
2791
+ "mutedChange",
2792
+ "pause",
2793
+ "play",
2794
+ "playRejected",
2795
+ "played",
2796
+ "playing",
2797
+ "progress",
2798
+ "rateChange",
2799
+ "readyStateChange",
2800
+ "reset",
2801
+ "resize",
2802
+ "seeked",
2803
+ "seeking",
2804
+ "stallEntered",
2805
+ "stallEnded",
2806
+ "timeUpdate",
2807
+ "volumeChange",
2808
+ "waited",
2809
+ "waiting",
2810
+ "waitingForKey"
2811
+ ];
2812
+ var PlaybackReadyState = /* @__PURE__ */ ((PlaybackReadyState2) => {
2813
+ PlaybackReadyState2[PlaybackReadyState2["HAVE_NOTHING"] = 0] = "HAVE_NOTHING";
2814
+ PlaybackReadyState2[PlaybackReadyState2["HAVE_METADATA"] = 1] = "HAVE_METADATA";
2815
+ PlaybackReadyState2[PlaybackReadyState2["HAVE_CURRENT_DATA"] = 2] = "HAVE_CURRENT_DATA";
2816
+ PlaybackReadyState2[PlaybackReadyState2["HAVE_FUTURE_DATA"] = 3] = "HAVE_FUTURE_DATA";
2817
+ PlaybackReadyState2[PlaybackReadyState2["HAVE_ENOUGH_DATA"] = 4] = "HAVE_ENOUGH_DATA";
2818
+ return PlaybackReadyState2;
2819
+ })(PlaybackReadyState || {});
2820
+ var PlaybackNetworkState = /* @__PURE__ */ ((PlaybackNetworkState2) => {
2821
+ PlaybackNetworkState2[PlaybackNetworkState2["NETWORK_EMPTY"] = 0] = "NETWORK_EMPTY";
2822
+ PlaybackNetworkState2[PlaybackNetworkState2["NETWORK_IDLE"] = 1] = "NETWORK_IDLE";
2823
+ PlaybackNetworkState2[PlaybackNetworkState2["NETWORK_LOADING"] = 2] = "NETWORK_LOADING";
2824
+ PlaybackNetworkState2[PlaybackNetworkState2["NETWORK_NO_SOURCE"] = 3] = "NETWORK_NO_SOURCE";
2825
+ return PlaybackNetworkState2;
2826
+ })(PlaybackNetworkState || {});
2827
+
2828
+ // src/playback/createStallMonitor.ts
2829
+ function createStallMonitor(controller, callbacks, options = {}) {
2830
+ var _a, _b;
2831
+ const stallThresholdMs = ((_a = options.stallThreshold) != null ? _a : 1) * 1e3;
2832
+ const pollIntervalMs = ((_b = options.pollInterval) != null ? _b : 0.25) * 1e3;
2833
+ let observedPlaying = false;
2834
+ let lastProgressAt = Date.now();
2835
+ let inStall = false;
2836
+ let pollId = null;
2837
+ const endStall = (reason) => {
2838
+ if (!inStall) return;
2839
+ inStall = false;
2840
+ const ended = Date.now();
2841
+ callbacks.onStallEnded({
2842
+ started: lastProgressAt,
2843
+ ended,
2844
+ duration: (ended - lastProgressAt) / 1e3,
2845
+ reason
2846
+ });
2803
2847
  };
2804
- let unchangedCount = 0;
2805
- let attemptedFix = false;
2806
- let previousTime = media.currentTime;
2807
- domEvents.on("timeupdate", () => {
2808
- if (media.paused) return;
2809
- if (closeTo2(media.currentTime, previousTime, 0.01)) {
2810
- if (++unchangedCount >= MAX_UNCHANGED_COUNT && !attemptedFix) {
2811
- logWarn2(
2812
- pathTarget,
2813
- `Detected stall at time ${media.currentTime}, attempting fix`
2814
- );
2815
- attemptedFix = true;
2816
- unchangedCount = 0;
2817
- media.pause();
2818
- media.play().catch(noop4);
2819
- }
2820
- } else {
2821
- if (attemptedFix) {
2822
- logInfo(pathTarget, "stall ended");
2823
- attemptedFix = false;
2848
+ const stopPoll = () => {
2849
+ if (pollId == null) return;
2850
+ clearInterval(pollId);
2851
+ pollId = null;
2852
+ };
2853
+ const startPoll = () => {
2854
+ if (pollId != null) return;
2855
+ pollId = setInterval(() => {
2856
+ if (inStall || !observedPlaying) return;
2857
+ if (Date.now() - lastProgressAt >= stallThresholdMs) {
2858
+ inStall = true;
2859
+ callbacks.onStallEntered();
2824
2860
  }
2825
- unchangedCount = 0;
2826
- previousTime = media.currentTime;
2827
- }
2828
- });
2829
- return {
2830
- dispose
2861
+ }, pollIntervalMs);
2831
2862
  };
2832
- }
2833
- function requiresPreventStallsPatch() {
2834
- return hasBrowser2(Browser2.EDGE_LEGACY);
2835
- }
2836
-
2837
- // src/patch/media/MediaElementPatchOptions.ts
2838
- var defaultMediaElementPatchOptions = /* @__PURE__ */ lazy2(() => {
2839
- return {
2840
- unreliablePlaybackEvents: requiresUnreliablePlaybackEventsPatch(),
2841
- preventStalls: requiresPreventStallsPatch()
2863
+ const suspend = (reason) => {
2864
+ endStall(reason);
2865
+ observedPlaying = false;
2866
+ stopPoll();
2842
2867
  };
2843
- });
2844
-
2845
- // src/patch/media/patchMediaElement.ts
2846
- import { patchTargetFromFlags } from "@amazon/vinyl-util";
2847
- function patchMediaElement(media, options) {
2848
- return patchTargetFromFlags(
2849
- media,
2850
- options,
2851
- ["unreliablePlaybackEvents", createUnreliablePlaybackEventsPatch],
2852
- ["preventStalls", createPreventStallsPatch]
2868
+ const { add, dispose } = createDisposer3();
2869
+ add(
2870
+ controller.on("playing", () => {
2871
+ if (inStall) endStall("playing" /* PLAYING */);
2872
+ else lastProgressAt = Date.now();
2873
+ observedPlaying = true;
2874
+ startPoll();
2875
+ })
2853
2876
  );
2877
+ add(
2878
+ controller.on("timeUpdate", () => {
2879
+ if (inStall) endStall("playing" /* PLAYING */);
2880
+ lastProgressAt = Date.now();
2881
+ })
2882
+ );
2883
+ add(controller.on("pause", () => suspend("pause" /* PAUSE */)));
2884
+ add(controller.on("seeking", () => suspend("seeking" /* SEEKING */)));
2885
+ add(controller.on("emptied", () => suspend("emptied" /* EMPTIED */)));
2886
+ let stopped = false;
2887
+ return () => {
2888
+ if (stopped) return;
2889
+ stopped = true;
2890
+ stopPoll();
2891
+ dispose();
2892
+ };
2854
2893
  }
2855
2894
 
2856
2895
  // src/playback/error/InvalidSeekError.ts
@@ -2953,90 +2992,11 @@ __publicField(_ReportableMediaError, "MEDIA_ERR_SRC_NOT_SUPPORTED", 4);
2953
2992
  var ReportableMediaError = _ReportableMediaError;
2954
2993
 
2955
2994
  // src/playback/logging/playbackStateLoggingHandler.ts
2956
- import { createDisposer as createDisposer5 } from "@amazon/vinyl-util";
2995
+ import { createDisposer as createDisposer4 } from "@amazon/vinyl-util";
2957
2996
  import { logDebug as logDebug4 } from "@amazon/vinyl-util";
2958
-
2959
- // src/playback/ReadonlyPlaybackController.ts
2960
- var PlayedReason = /* @__PURE__ */ ((PlayedReason2) => {
2961
- PlayedReason2["EMPTIED"] = "emptied";
2962
- PlayedReason2["ENDED"] = "ended";
2963
- PlayedReason2["PAUSE"] = "pause";
2964
- PlayedReason2["SEEKING"] = "seeking";
2965
- PlayedReason2["WAITING"] = "waiting";
2966
- return PlayedReason2;
2967
- })(PlayedReason || {});
2968
- var playedReasons = [
2969
- "emptied" /* EMPTIED */,
2970
- "ended" /* ENDED */,
2971
- "pause" /* PAUSE */,
2972
- "seeking" /* SEEKING */,
2973
- "waiting" /* WAITING */
2974
- ];
2975
- var WaitedReason = /* @__PURE__ */ ((WaitedReason2) => {
2976
- WaitedReason2["PLAYING"] = "playing";
2977
- WaitedReason2["PAUSE"] = "pause";
2978
- WaitedReason2["EMPTIED"] = "emptied";
2979
- WaitedReason2["SEEKING"] = "seeking";
2980
- return WaitedReason2;
2981
- })(WaitedReason || {});
2982
- var waitedReasons = [
2983
- "playing" /* PLAYING */,
2984
- "pause" /* PAUSE */,
2985
- "emptied" /* EMPTIED */,
2986
- "seeking" /* SEEKING */
2987
- ];
2988
- var ALL_PLAYBACK_STATE_EVENTS = [
2989
- "abort",
2990
- "canPlay",
2991
- "canPlayThrough",
2992
- "durationChange",
2993
- "emptied",
2994
- "ended",
2995
- "error",
2996
- "playIsPendingChange",
2997
- "loadedData",
2998
- "loadedMetadata",
2999
- "loadStart",
3000
- "looped",
3001
- "mutedChange",
3002
- "pause",
3003
- "play",
3004
- "playRejected",
3005
- "played",
3006
- "playing",
3007
- "progress",
3008
- "rateChange",
3009
- "readyStateChange",
3010
- "reset",
3011
- "resize",
3012
- "seeked",
3013
- "seeking",
3014
- "timeUpdate",
3015
- "volumeChange",
3016
- "waited",
3017
- "waiting",
3018
- "waitingForKey"
3019
- ];
3020
- var PlaybackReadyState = /* @__PURE__ */ ((PlaybackReadyState2) => {
3021
- PlaybackReadyState2[PlaybackReadyState2["HAVE_NOTHING"] = 0] = "HAVE_NOTHING";
3022
- PlaybackReadyState2[PlaybackReadyState2["HAVE_METADATA"] = 1] = "HAVE_METADATA";
3023
- PlaybackReadyState2[PlaybackReadyState2["HAVE_CURRENT_DATA"] = 2] = "HAVE_CURRENT_DATA";
3024
- PlaybackReadyState2[PlaybackReadyState2["HAVE_FUTURE_DATA"] = 3] = "HAVE_FUTURE_DATA";
3025
- PlaybackReadyState2[PlaybackReadyState2["HAVE_ENOUGH_DATA"] = 4] = "HAVE_ENOUGH_DATA";
3026
- return PlaybackReadyState2;
3027
- })(PlaybackReadyState || {});
3028
- var PlaybackNetworkState = /* @__PURE__ */ ((PlaybackNetworkState2) => {
3029
- PlaybackNetworkState2[PlaybackNetworkState2["NETWORK_EMPTY"] = 0] = "NETWORK_EMPTY";
3030
- PlaybackNetworkState2[PlaybackNetworkState2["NETWORK_IDLE"] = 1] = "NETWORK_IDLE";
3031
- PlaybackNetworkState2[PlaybackNetworkState2["NETWORK_LOADING"] = 2] = "NETWORK_LOADING";
3032
- PlaybackNetworkState2[PlaybackNetworkState2["NETWORK_NO_SOURCE"] = 3] = "NETWORK_NO_SOURCE";
3033
- return PlaybackNetworkState2;
3034
- })(PlaybackNetworkState || {});
3035
-
3036
- // src/playback/logging/playbackStateLoggingHandler.ts
3037
2997
  import { throttle } from "@amazon/vinyl-util";
3038
2998
  import { substitute as substitute2 } from "@amazon/vinyl-util";
3039
- import { createLogPrefix as createLogPrefix3 } from "@amazon/vinyl-util";
2999
+ import { createLogPrefix as createLogPrefix2 } from "@amazon/vinyl-util";
3040
3000
  var TIMEUPDATE_THROTTLE = 5;
3041
3001
  var locale2 = {
3042
3002
  /**
@@ -3050,9 +3010,9 @@ var locale2 = {
3050
3010
  };
3051
3011
  function playbackStateLoggingHandler(playbackState) {
3052
3012
  const target = {
3053
- logPrefix: createLogPrefix3("Playback")
3013
+ logPrefix: createLogPrefix2("Playback")
3054
3014
  };
3055
- const disposer = createDisposer5();
3015
+ const disposer = createDisposer4();
3056
3016
  const { add } = disposer;
3057
3017
  let timeUpdateCount = 0;
3058
3018
  let startTime = null;
@@ -3093,12 +3053,12 @@ function playbackStateLoggingHandler(playbackState) {
3093
3053
  }
3094
3054
 
3095
3055
  // src/playback/loudness/LoudnessNormalizationControllerImpl.ts
3096
- import { createDisposer as createDisposer6 } from "@amazon/vinyl-util";
3056
+ import { createDisposer as createDisposer5 } from "@amazon/vinyl-util";
3097
3057
  import {
3098
3058
  logDebug as logDebug5,
3099
- createLogPrefix as createLogPrefix4,
3059
+ createLogPrefix as createLogPrefix3,
3100
3060
  EventHostImpl as EventHostImpl6,
3101
- closeTo as closeTo3
3061
+ closeTo
3102
3062
  } from "@amazon/vinyl-util";
3103
3063
 
3104
3064
  // src/playback/loudness/LoudnessNormalizationControllerImplOptions.ts
@@ -3121,9 +3081,9 @@ var LoudnessNormalizationControllerImpl = class extends EventHostImpl6 {
3121
3081
  constructor(deps) {
3122
3082
  super();
3123
3083
  __publicField(this, "deps", deps);
3124
- __publicField(this, "logPrefix", /* @__PURE__ */ createLogPrefix4(this));
3084
+ __publicField(this, "logPrefix", /* @__PURE__ */ createLogPrefix3(this));
3125
3085
  __publicField(this, "_gain", MAX_GAIN_LEVEL);
3126
- __publicField(this, "disposer", /* @__PURE__ */ createDisposer6());
3086
+ __publicField(this, "disposer", /* @__PURE__ */ createDisposer5());
3127
3087
  __publicField(this, "trackLoudness", null);
3128
3088
  __publicField(this, "_options", defaultLoudnessNormalizationControllerImplOptions);
3129
3089
  const { add } = this.disposer;
@@ -3157,7 +3117,7 @@ var LoudnessNormalizationControllerImpl = class extends EventHostImpl6 {
3157
3117
  */
3158
3118
  set gain(value) {
3159
3119
  const previousGain = this._gain;
3160
- if (!closeTo3(previousGain, value)) {
3120
+ if (!closeTo(previousGain, value)) {
3161
3121
  this._gain = value;
3162
3122
  logDebug5(this, "loudness gain adjustment:", {
3163
3123
  trackLoudness: this.trackLoudness,
@@ -3211,22 +3171,22 @@ var LIVE_DURATION = 4294967296;
3211
3171
  import {
3212
3172
  Abort,
3213
3173
  AbortError as AbortError2,
3214
- Browser as Browser3,
3174
+ Browser,
3215
3175
  clamp,
3216
- closeTo as closeTo4,
3217
- createDisposer as createDisposer7,
3176
+ closeTo as closeTo2,
3177
+ createDisposer as createDisposer6,
3218
3178
  createTimeRangesReader,
3219
- DomEventHost as DomEventHost3,
3179
+ DomEventHost,
3220
3180
  ErrorLevel as ErrorLevel7,
3221
3181
  ErrorOrigin as ErrorOrigin12,
3222
3182
  EventHostImpl as EventHostImpl7,
3223
- getUserAgentInfo as getUserAgentInfo3,
3224
- hasBrowser as hasBrowser3,
3183
+ hasBrowser,
3225
3184
  logDebug as logDebug6,
3226
- logInfo as logInfo2,
3227
- logWarn as logWarn3,
3185
+ logInfo,
3186
+ logWarn as logWarn2,
3228
3187
  nextEventAsPromise as nextEventAsPromise2,
3229
- onAny as onAny2,
3188
+ noop as noop4,
3189
+ onAny,
3230
3190
  ownKeys,
3231
3191
  TimeoutSlot,
3232
3192
  toLowerCase,
@@ -3238,11 +3198,14 @@ var defaultPlaybackControllerImplOptions = {
3238
3198
  minSeekableBuffer: -1,
3239
3199
  // Default comes from getMinSeekableBufferDefault()
3240
3200
  playTimeout: 30,
3241
- seekTimeout: 30
3201
+ seekTimeout: 30,
3202
+ stallThreshold: 1
3242
3203
  };
3243
3204
  function getMinSeekableBufferDefault() {
3244
- return !hasBrowser3(Browser3.CHROMIUM) ? 5 : 2;
3205
+ return !hasBrowser(Browser.CHROMIUM) ? 5 : 2;
3245
3206
  }
3207
+ var SEEK_RETRY_LIMIT = 2;
3208
+ var SEEK_ATTEMPT_TIMEOUT = 4;
3246
3209
  var PlaybackControllerImpl = class extends EventHostImpl7 {
3247
3210
  constructor(deps, options) {
3248
3211
  super();
@@ -3250,12 +3213,14 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3250
3213
  __publicField(this, "_error", null);
3251
3214
  __publicField(this, "media");
3252
3215
  __publicField(this, "domEvents");
3253
- __publicField(this, "disposer", /* @__PURE__ */ createDisposer7());
3216
+ __publicField(this, "disposer", /* @__PURE__ */ createDisposer6());
3254
3217
  __publicField(this, "_playing", false);
3255
3218
  __publicField(this, "_seeking", false);
3256
3219
  __publicField(this, "_waiting", false);
3257
3220
  // Monotonic counter identifying the most recent seekTo call.
3258
3221
  __publicField(this, "_seekId", 0);
3222
+ // Stops the stall detector started after the last seek, if any.
3223
+ __publicField(this, "stopStallDetection", null);
3259
3224
  // default user volume (0.0 to 1.0 scale)
3260
3225
  __publicField(this, "userVolume", 1);
3261
3226
  __publicField(this, "_pendingPlay", null);
@@ -3266,21 +3231,23 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3266
3231
  minSeekableBuffer: getMinSeekableBufferDefault()
3267
3232
  }), options);
3268
3233
  this.loudnessNormalizationController = deps.loudnessNormalizationController;
3269
- logInfo2(this, "constructed", this.options);
3234
+ logInfo(this, "constructed", this.options);
3270
3235
  this.media = deps.media;
3271
3236
  const { add } = this.disposer;
3272
3237
  add(() => {
3238
+ var _a;
3273
3239
  this.disposeAbort.abort();
3274
3240
  this.disposeAbort.dispose();
3241
+ (_a = this.stopStallDetection) == null ? void 0 : _a.call(this);
3275
3242
  });
3276
3243
  this.domEvents = add(
3277
- new DomEventHost3(deps.media)
3244
+ new DomEventHost(deps.media)
3278
3245
  );
3279
3246
  add(playbackStateLoggingHandler(this));
3280
3247
  this.domEvents.on("error", (_) => {
3281
3248
  const error = new ReportableMediaError(this.media.error);
3282
3249
  if (error.level === ErrorLevel7.SILENT) {
3283
- logInfo2(this, error.message);
3250
+ logInfo(this, error.message);
3284
3251
  return;
3285
3252
  }
3286
3253
  this._error = error;
@@ -3290,6 +3257,16 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3290
3257
  });
3291
3258
  });
3292
3259
  this.initializeEvents();
3260
+ add(
3261
+ createStallMonitor(
3262
+ this,
3263
+ {
3264
+ onStallEntered: () => this.dispatch("stallEntered", {}),
3265
+ onStallEnded: (info) => this.dispatch("stallEnded", info)
3266
+ },
3267
+ { stallThreshold: this.options.stallThreshold }
3268
+ )
3269
+ );
3293
3270
  add(
3294
3271
  this.loudnessNormalizationController.on("change", () => {
3295
3272
  this.refreshVolume();
@@ -3447,7 +3424,7 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3447
3424
  started = true;
3448
3425
  startedAt = Date.now();
3449
3426
  });
3450
- onAny2(host, endEvents, (_, event) => {
3427
+ onAny(host, endEvents, (_, event) => {
3451
3428
  if (started) {
3452
3429
  started = false;
3453
3430
  const now = Date.now();
@@ -3496,9 +3473,8 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3496
3473
  initializeLoopedEvent() {
3497
3474
  let lastTime = 0;
3498
3475
  this.on("timeUpdate", () => {
3499
- var _a;
3500
3476
  if (this.loop && !this.paused && this.currentTime <= this.options.loopTimeAffordance && lastTime >= this.duration - this.options.loopTimeAffordance) {
3501
- if (((_a = getUserAgentInfo3().browserLike) == null ? void 0 : _a.name) === Browser3.FIREFOX) {
3477
+ if (hasBrowser(Browser.FIREFOX)) {
3502
3478
  logDebug6(this, "fabricating Firefox playing event on loop");
3503
3479
  this.dispatch("playing", {});
3504
3480
  }
@@ -3612,8 +3588,25 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3612
3588
  current: value != null
3613
3589
  });
3614
3590
  }
3591
+ /**
3592
+ * Starts (or restarts) the stall detector: recovers a play head that stays frozen when it
3593
+ * should be advancing — some WebKit versions never resume after a seek or a play, e.g. after a
3594
+ * buffer-flushing seek. Superseded by the next seek/play and stopped on dispose.
3595
+ * @private
3596
+ */
3597
+ startStallDetection() {
3598
+ var _a;
3599
+ (_a = this.stopStallDetection) == null ? void 0 : _a.call(this);
3600
+ this.stopStallDetection = createStallDetector(this.media, {
3601
+ fabricatePlaying: () => this.dispatch("playing", {}),
3602
+ // Safari/iOS can leave a seek on a freshly-attached source pending
3603
+ // with a stale empty `buffered`; re-issue the seek to un-stick it.
3604
+ nudgeUnbuffered: hasBrowser(Browser.WEBKIT)
3605
+ });
3606
+ }
3615
3607
  play() {
3616
3608
  logDebug6(this, "play");
3609
+ this.startStallDetection();
3617
3610
  if (!this.pendingPlay) {
3618
3611
  const playAbort = new Abort();
3619
3612
  this.playAbort = playAbort;
@@ -3655,16 +3648,20 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3655
3648
  return this.pendingPlay != null;
3656
3649
  }
3657
3650
  async seekTo(time, tolerance = 0.5) {
3651
+ var _a;
3658
3652
  logDebug6(this, `seekTo: ${time}`);
3659
3653
  const seekId = ++this._seekId;
3654
+ (_a = this.stopStallDetection) == null ? void 0 : _a.call(this);
3655
+ this.stopStallDetection = null;
3660
3656
  const superseded = () => {
3661
3657
  if (this._seekId === seekId) return false;
3662
3658
  logDebug6(this, `seekTo: ${time} superseded by a newer seek`);
3663
3659
  return true;
3664
3660
  };
3665
- const nextEvent = (type) => {
3661
+ const nextEvent = (type, options) => {
3662
+ var _a2;
3666
3663
  return nextEventAsPromise2(this, type, {
3667
- timeout: this.options.seekTimeout,
3664
+ timeout: (_a2 = options == null ? void 0 : options.timeout) != null ? _a2 : this.options.seekTimeout,
3668
3665
  timeoutMessage: `seek timed out on ${type} event after {time}s`,
3669
3666
  timeoutOrigin: ErrorOrigin12.INTERNAL,
3670
3667
  timeoutLevel: ErrorLevel7.WARN,
@@ -3681,7 +3678,7 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3681
3678
  tolerance
3682
3679
  );
3683
3680
  if (range == null) {
3684
- logWarn3(
3681
+ logWarn2(
3685
3682
  this,
3686
3683
  `seekTo: seek outside of seekable ranges, seek ignored`,
3687
3684
  seekable.ranges
@@ -3697,19 +3694,36 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3697
3694
  this,
3698
3695
  `seekTo operation, requested: ${time}, actual: ${clampedTime}`
3699
3696
  );
3700
- if (closeTo4(clampedTime, this.currentTime, tolerance)) {
3697
+ if (closeTo2(clampedTime, this.currentTime, tolerance)) {
3701
3698
  logDebug6(
3702
3699
  this,
3703
3700
  `seekTo: requested: ${time}, actual: ${clampedTime} no-op`
3704
3701
  );
3705
3702
  } else {
3706
- const seeking = nextEvent("seeking");
3707
- this.media.currentTime = clampedTime;
3708
- await seeking;
3709
- const seekedEvent = await nextEvent("seeked");
3710
- if (seekedEvent.reason === "emptied") {
3703
+ const nullIfStuck = (error) => {
3704
+ if (this.disposeAbort.aborted()) throw error;
3705
+ return null;
3706
+ };
3707
+ const seekOnce = async (reSeeking) => {
3708
+ const seeking = reSeeking ? nextEvent("seeking", {
3709
+ timeout: SEEK_ATTEMPT_TIMEOUT
3710
+ }).catch(nullIfStuck) : nextEvent("seeking");
3711
+ this.media.currentTime = clampedTime;
3712
+ if (await seeking === null) return null;
3713
+ return nextEvent("seeked", {
3714
+ timeout: SEEK_ATTEMPT_TIMEOUT
3715
+ }).catch(nullIfStuck);
3716
+ };
3717
+ let seekedEvent = await seekOnce(false);
3718
+ for (let attempt = 0; !superseded() && attempt < SEEK_RETRY_LIMIT && (seekedEvent === null || seekedEvent.reason === "seeked" && !closeTo2(clampedTime, this.currentTime, tolerance)); attempt++) {
3719
+ if (seekedEvent === null) void this.media.play().catch(noop4);
3720
+ logDebug6(this, `seekTo: re-seeking to ${clampedTime}`);
3721
+ seekedEvent = await seekOnce(true);
3722
+ }
3723
+ if ((seekedEvent == null ? void 0 : seekedEvent.reason) === "emptied") {
3711
3724
  throw new AbortError2();
3712
3725
  }
3726
+ if (!this.paused) this.startStallDetection();
3713
3727
  }
3714
3728
  }
3715
3729
  /**
@@ -3718,7 +3732,7 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3718
3732
  */
3719
3733
  initializeReadyStateChangeEvent() {
3720
3734
  let previous = this.readyState;
3721
- onAny2(
3735
+ onAny(
3722
3736
  this,
3723
3737
  [
3724
3738
  "canPlay",
@@ -3805,8 +3819,8 @@ var PlaybackSourceImpl = class {
3805
3819
  // src/streaming/abr/QualitySelectorImpl.ts
3806
3820
  import {
3807
3821
  clamp as clamp2,
3808
- createDisposer as createDisposer8,
3809
- createLogPrefix as createLogPrefix5,
3822
+ createDisposer as createDisposer7,
3823
+ createLogPrefix as createLogPrefix4,
3810
3824
  getNetworkMetrics as getNetworkMetrics2,
3811
3825
  lerp as lerp2
3812
3826
  } from "@amazon/vinyl-util";
@@ -3847,9 +3861,9 @@ var defaultQualitySelectorImplOptions = {
3847
3861
  };
3848
3862
  var QualitySelectorImpl = class {
3849
3863
  constructor(deps) {
3850
- __publicField(this, "logPrefix", /* @__PURE__ */ createLogPrefix5(this));
3864
+ __publicField(this, "logPrefix", /* @__PURE__ */ createLogPrefix4(this));
3851
3865
  __publicField(this, "_options", defaultQualitySelectorImplOptions);
3852
- __publicField(this, "disposer", /* @__PURE__ */ createDisposer8());
3866
+ __publicField(this, "disposer", /* @__PURE__ */ createDisposer7());
3853
3867
  const { add } = this.disposer;
3854
3868
  add(
3855
3869
  deps.options.onData((v) => {
@@ -3937,23 +3951,33 @@ var QualitySelectorImpl = class {
3937
3951
  };
3938
3952
 
3939
3953
  // src/streaming/AudioOptions.ts
3940
- import { array, boolean as boolean3, object as object7, string as string4 } from "@amazon/vinyl-validation";
3954
+ import {
3955
+ array,
3956
+ boolean as boolean3,
3957
+ number as number5,
3958
+ object as object7,
3959
+ string as string4
3960
+ } from "@amazon/vinyl-validation";
3941
3961
  var defaultAudioOptions = {
3942
- selection: { language: null, descriptive: false }
3962
+ selection: { language: null, descriptive: false },
3963
+ disableSampleRateFilter: false
3943
3964
  };
3944
3965
  var audioSelectionValidator = /* @__PURE__ */ object7({
3945
3966
  language: /* @__PURE__ */ string4().or(/* @__PURE__ */ array(/* @__PURE__ */ string4()).readonly()).orNull().optional(),
3946
3967
  descriptive: /* @__PURE__ */ boolean3().optional()
3947
3968
  });
3948
3969
  var audioOptionsValidator = /* @__PURE__ */ object7({
3949
- selection: /* @__PURE__ */ audioSelectionValidator.optional()
3970
+ selection: /* @__PURE__ */ audioSelectionValidator.optional(),
3971
+ disableSampleRateFilter: /* @__PURE__ */ boolean3().optional(),
3972
+ maxSampleRate: /* @__PURE__ */ number5().maybe().optional(),
3973
+ minSampleRate: /* @__PURE__ */ number5().maybe().optional()
3950
3974
  });
3951
3975
 
3952
3976
  // src/streaming/buffering/BufferingController.ts
3953
3977
  import {
3954
3978
  createAbortSlot,
3955
- createDisposer as createDisposer9,
3956
- createLogPrefix as createLogPrefix6,
3979
+ createDisposer as createDisposer8,
3980
+ createLogPrefix as createLogPrefix5,
3957
3981
  createTaskQueue,
3958
3982
  EventHostImpl as EventHostImpl8,
3959
3983
  getLogLevel,
@@ -3962,7 +3986,7 @@ import {
3962
3986
  logDebug as logDebug7,
3963
3987
  LogLevel as LogLevel2,
3964
3988
  logVerbose as logVerbose3,
3965
- logWarn as logWarn4,
3989
+ logWarn as logWarn3,
3966
3990
  throttle as throttle2
3967
3991
  } from "@amazon/vinyl-util";
3968
3992
 
@@ -4067,9 +4091,8 @@ var BufferingControllerImpl = class extends EventHostImpl8 {
4067
4091
  __publicField(this, "reopen", false);
4068
4092
  __publicField(this, "_error", null);
4069
4093
  __publicField(this, "_bufferingEnded", false);
4070
- __publicField(this, "_hasData", false);
4071
4094
  __publicField(this, "queue", /* @__PURE__ */ createTaskQueue());
4072
- __publicField(this, "disposer", /* @__PURE__ */ createDisposer9());
4095
+ __publicField(this, "disposer", /* @__PURE__ */ createDisposer8());
4073
4096
  __publicField(this, "_active", false);
4074
4097
  __publicField(this, "activateDisposer", null);
4075
4098
  __publicField(this, "segmentAbort", /* @__PURE__ */ createAbortSlot());
@@ -4123,7 +4146,7 @@ var BufferingControllerImpl = class extends EventHostImpl8 {
4123
4146
  const newAppendSize = this.getMaxAppendSize(contentType2) * QUOTA_REACHED_SCALE;
4124
4147
  if (newAppendSize >= MIN_APPEND_SIZE) {
4125
4148
  sourceBufferQuotas.set(contentType2, newAppendSize);
4126
- logWarn4(
4149
+ logWarn3(
4127
4150
  this,
4128
4151
  "QuotaExceededError, new source buffer limit:",
4129
4152
  (newAppendSize / 1024 / 1024).toFixed(1) + " MiB"
@@ -4156,7 +4179,7 @@ var BufferingControllerImpl = class extends EventHostImpl8 {
4156
4179
  await this.sourceBufferController.clear();
4157
4180
  logVerbose3(this, "finishAndClearBuffers complete");
4158
4181
  });
4159
- this.logPrefix = createLogPrefix6(`Buffering_${contentType2}`);
4182
+ this.logPrefix = createLogPrefix5(`Buffering_${contentType2}`);
4160
4183
  this.options = __spreadValues(__spreadValues({}, defaultBufferingControllerOptions), options);
4161
4184
  logDebug7(this, "constructed", this.options);
4162
4185
  this.mediaSourceController = deps.mediaSourceController;
@@ -4176,7 +4199,7 @@ var BufferingControllerImpl = class extends EventHostImpl8 {
4176
4199
  if (this._active) return;
4177
4200
  this._active = true;
4178
4201
  logDebug7(this, "activate");
4179
- this.activateDisposer = createDisposer9();
4202
+ this.activateDisposer = createDisposer8();
4180
4203
  const { add } = this.activateDisposer;
4181
4204
  this.sourceBufferController = add(
4182
4205
  this.deps.sourceBufferControllerFactory()
@@ -4316,7 +4339,6 @@ var BufferingControllerImpl = class extends EventHostImpl8 {
4316
4339
  this.buffered.push(streamingSegment);
4317
4340
  }
4318
4341
  if (!tail) this.refreshHead();
4319
- this.setHasData(true);
4320
4342
  }
4321
4343
  abortCurrentSegment() {
4322
4344
  this.segmentAbort.abort();
@@ -4400,15 +4422,6 @@ var BufferingControllerImpl = class extends EventHostImpl8 {
4400
4422
  get bufferingEnded() {
4401
4423
  return this._bufferingEnded;
4402
4424
  }
4403
- get hasData() {
4404
- return this._hasData;
4405
- }
4406
- setHasData(value) {
4407
- if (this._hasData === value) return;
4408
- const previous = this._hasData;
4409
- this._hasData = value;
4410
- this.dispatch("hasDataChange", { previous, current: value });
4411
- }
4412
4425
  /**
4413
4426
  * Attempts to recover from a SourceBuffer decode/append failure caused by a
4414
4427
  * codec the browser reported as supported but cannot actually decode.
@@ -4429,7 +4442,7 @@ var BufferingControllerImpl = class extends EventHostImpl8 {
4429
4442
  const contentType2 = quality == null ? void 0 : quality.contentType;
4430
4443
  if (!mimeType || !contentType2) return false;
4431
4444
  if (!denylistCodecsFromMimeType(mimeType)) return false;
4432
- logWarn4(
4445
+ logWarn3(
4433
4446
  this,
4434
4447
  "SourceBuffer append failed; denylisting codec and requesting reload:",
4435
4448
  mimeType
@@ -4483,7 +4496,6 @@ var BufferingControllerImpl = class extends EventHostImpl8 {
4483
4496
  this._bufferingEnded = false;
4484
4497
  this.bufferingQuality = null;
4485
4498
  this.playbackQuality = null;
4486
- this.setHasData(false);
4487
4499
  }
4488
4500
  get disposed() {
4489
4501
  return this.disposer.disposed;
@@ -4497,16 +4509,16 @@ var BufferingControllerImpl = class extends EventHostImpl8 {
4497
4509
 
4498
4510
  // src/streaming/buffering/MediaSourceController.ts
4499
4511
  import {
4500
- closeTo as closeTo5,
4501
- createDisposer as createDisposer10,
4502
- DomEventHost as DomEventHost4,
4512
+ closeTo as closeTo3,
4513
+ createDisposer as createDisposer9,
4514
+ DomEventHost as DomEventHost2,
4503
4515
  ErrorLevel as ErrorLevel8,
4504
4516
  ErrorOrigin as ErrorOrigin14,
4505
4517
  EventHostImpl as EventHostImpl9,
4506
4518
  IllegalStateError as IllegalStateError2,
4507
4519
  isSilentError as isSilentError3,
4508
4520
  logDebug as logDebug8,
4509
- logWarn as logWarn5,
4521
+ logWarn as logWarn4,
4510
4522
  ReportableError as ReportableError8,
4511
4523
  toJson as toJson2,
4512
4524
  toLowerCase as toLowerCase2
@@ -4581,12 +4593,12 @@ var MediaSourceControllerImpl = class extends EventHostImpl9 {
4581
4593
  return this.activateDisposer != null;
4582
4594
  }
4583
4595
  activate() {
4584
- this.activateDisposer = createDisposer10();
4596
+ this.activateDisposer = createDisposer9();
4585
4597
  const add = this.activateDisposer.add;
4586
4598
  const mediaSource = this.deps.mediaSourceFactory();
4587
4599
  this.mediaSource = mediaSource;
4588
4600
  const domEvents = add(
4589
- new DomEventHost4(mediaSource)
4601
+ new DomEventHost2(mediaSource)
4590
4602
  );
4591
4603
  domEvents.on("sourceopen", () => {
4592
4604
  this.refreshDuration().catch(this.errorHandler);
@@ -4629,7 +4641,7 @@ var MediaSourceControllerImpl = class extends EventHostImpl9 {
4629
4641
  try {
4630
4642
  URL.revokeObjectURL(this.objectUrl);
4631
4643
  } catch (error) {
4632
- logWarn5(this, "error revoking object url", error);
4644
+ logWarn4(this, "error revoking object url", error);
4633
4645
  }
4634
4646
  }
4635
4647
  get sourceBufferCount() {
@@ -4650,7 +4662,7 @@ var MediaSourceControllerImpl = class extends EventHostImpl9 {
4650
4662
  const duration = await timeline.getDuration();
4651
4663
  const value = duration === Infinity ? LIVE_DURATION : duration + DURATION_PADDING;
4652
4664
  await Promise.all(Array.from(this.sourceBuffers, nextSourceBufferIdle));
4653
- if (token !== this.durationToken || mediaSource.readyState !== "open" || closeTo5(mediaSource.duration, value, 0.1))
4665
+ if (token !== this.durationToken || mediaSource.readyState !== "open" || closeTo3(mediaSource.duration, value, 0.1))
4654
4666
  return;
4655
4667
  logDebug8(this, `setting duration: ${value}`);
4656
4668
  mediaSource.duration = value;
@@ -4733,7 +4745,7 @@ var MediaSourceError = class _MediaSourceError extends ReportableError8 {
4733
4745
 
4734
4746
  // src/streaming/buffering/SourceBufferController.ts
4735
4747
  import {
4736
- createLogPrefix as createLogPrefix7,
4748
+ createLogPrefix as createLogPrefix6,
4737
4749
  createTaskQueue as createTaskQueue2,
4738
4750
  createTimeRangesReader as createTimeRangesReader2,
4739
4751
  emptyRanges,
@@ -4767,7 +4779,7 @@ var SourceBufferControllerImpl = class {
4767
4779
  * @private
4768
4780
  */
4769
4781
  __publicField(this, "nextIdle", () => nextSourceBufferIdle(this.sourceBuffer).finally(this.clearBufferedCache));
4770
- this.logPrefix = createLogPrefix7(`SourceBuffer_${contentType2}`);
4782
+ this.logPrefix = createLogPrefix6(`SourceBuffer_${contentType2}`);
4771
4783
  logDebug9(this, "constructed, contentType:", contentType2);
4772
4784
  this.mediaSourceController = deps.mediaSourceController;
4773
4785
  }
@@ -4902,8 +4914,8 @@ var SourceBufferControllerImpl = class {
4902
4914
 
4903
4915
  // src/streaming/ContentStream.ts
4904
4916
  import {
4905
- createDisposer as createDisposer11,
4906
- createLogPrefix as createLogPrefix8,
4917
+ createDisposer as createDisposer10,
4918
+ createLogPrefix as createLogPrefix7,
4907
4919
  EventHostImpl as EventHostImpl10,
4908
4920
  logDebug as logDebug10,
4909
4921
  redispatchEvents
@@ -4916,10 +4928,10 @@ var ContentStreamImpl = class extends EventHostImpl10 {
4916
4928
  // Assigned in the constructor body: a field initializer runs before the
4917
4929
  // contentType param-property, so it would capture `undefined`.
4918
4930
  __publicField(this, "logPrefix");
4919
- __publicField(this, "disposer", /* @__PURE__ */ createDisposer11());
4931
+ __publicField(this, "disposer", /* @__PURE__ */ createDisposer10());
4920
4932
  __publicField(this, "segmentController");
4921
4933
  __publicField(this, "bufferingController");
4922
- this.logPrefix = createLogPrefix8(`ContentStream_${contentType2}`);
4934
+ this.logPrefix = createLogPrefix7(`ContentStream_${contentType2}`);
4923
4935
  const { add } = this.disposer;
4924
4936
  const deps = add(createContainer(dependencyFactories)).dependencies;
4925
4937
  this.segmentController = deps.segmentController;
@@ -4935,7 +4947,6 @@ var ContentStreamImpl = class extends EventHostImpl10 {
4935
4947
  "bufferingQualityChange",
4936
4948
  "playbackQualityChange",
4937
4949
  "bufferingEnded",
4938
- "hasDataChange",
4939
4950
  "error",
4940
4951
  "codecUnsupported"
4941
4952
  ]);
@@ -4965,9 +4976,6 @@ var ContentStreamImpl = class extends EventHostImpl10 {
4965
4976
  var _a;
4966
4977
  return (_a = this.bufferingController.playbackQuality) != null ? _a : null;
4967
4978
  }
4968
- get hasData() {
4969
- return this.bufferingController.hasData;
4970
- }
4971
4979
  get bufferingEnded() {
4972
4980
  return this.bufferingController.bufferingEnded;
4973
4981
  }
@@ -5030,20 +5038,121 @@ function createAllowedContentTypesValue(deps) {
5030
5038
  return filterContentTypes(await contentTypes, allowedContentTypes);
5031
5039
  });
5032
5040
  }
5033
- function filterContentTypes(contentTypes, allowedContentTypes) {
5034
- if (allowedContentTypes == null) return contentTypes;
5035
- const allowed = new Set(allowedContentTypes);
5036
- const filtered = /* @__PURE__ */ new Set();
5037
- for (const contentType2 of contentTypes) {
5038
- if (contentType2 === "text" || allowed.has(contentType2)) {
5039
- filtered.add(contentType2);
5040
- }
5041
- }
5042
- return filtered;
5043
- }
5044
-
5045
- // src/streaming/createDefaultMediaTimelineTransformer.ts
5046
- import { combineData as combineData2 } from "@amazon/vinyl-observable";
5041
+ function filterContentTypes(contentTypes, allowedContentTypes) {
5042
+ if (allowedContentTypes == null) return contentTypes;
5043
+ const allowed = new Set(allowedContentTypes);
5044
+ const filtered = /* @__PURE__ */ new Set();
5045
+ for (const contentType2 of contentTypes) {
5046
+ if (contentType2 === "text" || allowed.has(contentType2)) {
5047
+ filtered.add(contentType2);
5048
+ }
5049
+ }
5050
+ return filtered;
5051
+ }
5052
+
5053
+ // src/streaming/createDefaultMediaTimelineTransformer.ts
5054
+ import { combineData as combineData2 } from "@amazon/vinyl-observable";
5055
+
5056
+ // src/streaming/MediaQualityMetadata.ts
5057
+ import {
5058
+ createShortUid
5059
+ } from "@amazon/vinyl-util";
5060
+ import {
5061
+ array as array3,
5062
+ enumOf as enumOf3,
5063
+ isOneOf as isOneOf3,
5064
+ number as number6,
5065
+ object as object9,
5066
+ string as string6,
5067
+ tuple
5068
+ } from "@amazon/vinyl-validation";
5069
+
5070
+ // src/streaming/DescriptorRecord.ts
5071
+ import {
5072
+ array as array2,
5073
+ object as object8,
5074
+ record as record2,
5075
+ string as string5
5076
+ } from "@amazon/vinyl-validation";
5077
+ import { first } from "@amazon/vinyl-util";
5078
+ function getDescriptorValue(record4, uri, id) {
5079
+ var _a, _b;
5080
+ let arr = record4[uri];
5081
+ if (!arr) return null;
5082
+ if (id !== void 0) arr = arr.filter((descriptor) => descriptor.id === id);
5083
+ return (_b = (_a = first(arr)) == null ? void 0 : _a.value) != null ? _b : null;
5084
+ }
5085
+ var descriptorValidator = /* @__PURE__ */ object8({
5086
+ id: /* @__PURE__ */ string5().maybe().optional(),
5087
+ value: /* @__PURE__ */ string5().maybe().optional()
5088
+ });
5089
+ var descriptorRecordValidator = /* @__PURE__ */ record2(/* @__PURE__ */ string5(), /* @__PURE__ */ array2(descriptorValidator).readonly().orUndefined());
5090
+
5091
+ // src/streaming/MediaQualityMetadata.ts
5092
+ var ALL_CONTENT_TYPES = [
5093
+ "video",
5094
+ "audio",
5095
+ "text"
5096
+ ];
5097
+ var RESTRICTABLE_CONTENT_TYPES = [
5098
+ "video",
5099
+ "audio"
5100
+ ];
5101
+ var drmProtectionValidator = /* @__PURE__ */ descriptorValidator.extend({
5102
+ keySystem: /* @__PURE__ */ enumOf3(DrmKeySystem),
5103
+ pro: /* @__PURE__ */ string6().maybe().optional(),
5104
+ pssh: /* @__PURE__ */ string6().maybe().optional()
5105
+ });
5106
+ var mediaFormatMetadataValidator = /* @__PURE__ */ object9({
5107
+ contentProtections: /* @__PURE__ */ array3(drmProtectionValidator).readonly(),
5108
+ contentType: /* @__PURE__ */ isOneOf3("audio", "video", "text").orNull(),
5109
+ initDataType: /* @__PURE__ */ string6().orNull(),
5110
+ encryptionScheme: /* @__PURE__ */ string6().orNull(),
5111
+ mimeType: /* @__PURE__ */ string6().orNull()
5112
+ });
5113
+ function createEmptyMediaFormatMetadata() {
5114
+ return {
5115
+ contentType: null,
5116
+ mimeType: null,
5117
+ initDataType: null,
5118
+ encryptionScheme: null,
5119
+ contentProtections: []
5120
+ };
5121
+ }
5122
+ function createEmptyMediaQualityMetadata() {
5123
+ return __spreadProps(__spreadValues({}, createEmptyMediaFormatMetadata()), {
5124
+ decoderId: createShortUid(),
5125
+ qualityId: createShortUid(),
5126
+ codecs: null,
5127
+ bandwidth: null,
5128
+ bandwidthTotal: null,
5129
+ supplementalProperties: {},
5130
+ audioSamplingRate: null,
5131
+ frameRate: null,
5132
+ height: null,
5133
+ width: null,
5134
+ lang: null,
5135
+ characteristics: [],
5136
+ groupId: createShortUid(),
5137
+ switchingGroupIds: null
5138
+ });
5139
+ }
5140
+ var mediaQualityMetadataValidator = /* @__PURE__ */ mediaFormatMetadataValidator.extend({
5141
+ audioSamplingRate: /* @__PURE__ */ array3(/* @__PURE__ */ number6()).readonly().orNull(),
5142
+ bandwidth: /* @__PURE__ */ number6().orNull(),
5143
+ bandwidthTotal: /* @__PURE__ */ number6().orNull(),
5144
+ codecs: /* @__PURE__ */ string6().orNull(),
5145
+ decoderId: /* @__PURE__ */ string6(),
5146
+ frameRate: /* @__PURE__ */ tuple(/* @__PURE__ */ number6(), /* @__PURE__ */ number6()).readonly().orNull(),
5147
+ height: /* @__PURE__ */ number6().orNull(),
5148
+ qualityId: /* @__PURE__ */ string6(),
5149
+ supplementalProperties: descriptorRecordValidator,
5150
+ width: /* @__PURE__ */ number6().orNull(),
5151
+ lang: /* @__PURE__ */ string6().orNull(),
5152
+ characteristics: /* @__PURE__ */ array3(/* @__PURE__ */ string6()).readonly(),
5153
+ groupId: /* @__PURE__ */ string6(),
5154
+ switchingGroupIds: /* @__PURE__ */ array3(/* @__PURE__ */ string6()).readonly().orNull()
5155
+ });
5047
5156
 
5048
5157
  // src/streaming/mediaTimelineFilter.ts
5049
5158
  import { map, memoize as memoize6 } from "@amazon/vinyl-util";
@@ -5333,6 +5442,13 @@ function createLanguageFilter(preferredLanguage, contentType2) {
5333
5442
  }
5334
5443
 
5335
5444
  // src/streaming/mediaTimelineFilter.ts
5445
+ function assertMediaStreamsRetained(original, filtered, throwError) {
5446
+ for (const contentType2 of RESTRICTABLE_CONTENT_TYPES) {
5447
+ if (original.some((q) => q.metadata.contentType === contentType2) && !filtered.some((q) => q.metadata.contentType === contentType2)) {
5448
+ throwError();
5449
+ }
5450
+ }
5451
+ }
5336
5452
  function filterTimelineQualities(filter, throwError, timeline) {
5337
5453
  if (!filter) return timeline;
5338
5454
  const mapMetadataArray = memoize6(
@@ -5344,11 +5460,9 @@ function filterTimelineQualities(filter, throwError, timeline) {
5344
5460
  const filtered = period.qualities.filter(
5345
5461
  (q, index) => filter(q.metadata, index, mapMetadataArray(period.qualities))
5346
5462
  );
5463
+ assertMediaStreamsRetained(period.qualities, filtered, throwError);
5347
5464
  return __spreadProps(__spreadValues({}, period), { qualities: filtered });
5348
5465
  });
5349
- if (periods.some((p) => p.qualities.length === 0)) {
5350
- throwError();
5351
- }
5352
5466
  return __spreadProps(__spreadValues({}, timeline), { periods });
5353
5467
  }
5354
5468
  async function filterTimelineQualitiesAsync(filter, throwError, timeline) {
@@ -5366,11 +5480,9 @@ async function filterTimelineQualitiesAsync(filter, throwError, timeline) {
5366
5480
  filtered.push(period.qualities[i]);
5367
5481
  }
5368
5482
  }
5483
+ assertMediaStreamsRetained(period.qualities, filtered, throwError);
5369
5484
  periods.push(__spreadProps(__spreadValues({}, period), { qualities: filtered }));
5370
5485
  }
5371
- if (periods.some((p) => p.qualities.length === 0)) {
5372
- throwError();
5373
- }
5374
5486
  return __spreadProps(__spreadValues({}, timeline), { periods });
5375
5487
  }
5376
5488
 
@@ -5440,39 +5552,44 @@ async function canPlayKeySystem(deps, metadata) {
5440
5552
 
5441
5553
  // src/track/filters/sampleRateFilter.ts
5442
5554
  import {
5443
- hasBrowser as hasBrowser4,
5444
- Browser as Browser4,
5555
+ hasBrowser as hasBrowser2,
5556
+ Browser as Browser2,
5445
5557
  last,
5446
5558
  MediaUnsupportedError as MediaUnsupportedError6,
5447
- every,
5448
5559
  map as map2,
5560
+ max as max2,
5449
5561
  min
5450
5562
  } from "@amazon/vinyl-util";
5451
5563
  function throwSamplingRatesUnsupported() {
5452
5564
  throw new MediaUnsupportedError6("No supported sample rate", "sampling-rate");
5453
5565
  }
5454
- function supportsAudioSamplingRate(deps, metadata, _index, array6) {
5455
- const isFirefox = hasBrowser4(Browser4.FIREFOX);
5456
- const maxSampleRate = deps.capabilities.sampleRate;
5566
+ function withinAudioSampleRateRange(options, metadata, _index, array6) {
5567
+ var _a;
5568
+ if (metadata.contentType !== "audio") return true;
5457
5569
  const samplingRate = last(metadata.audioSamplingRate);
5458
- if (!samplingRate || !maxSampleRate) return true;
5459
- if (isFirefox) {
5570
+ if (!samplingRate) return true;
5571
+ const { minSampleRate } = options;
5572
+ const maxSampleRate = (_a = options.maxSampleRate) != null ? _a : options.capabilities.sampleRate;
5573
+ const audioRates = () => map2(
5574
+ array6,
5575
+ (item) => item.contentType === "audio" ? last(item.audioSamplingRate) : void 0
5576
+ ).filter((rate) => rate != null);
5577
+ const outOfBandFallback = () => {
5578
+ const rates = audioRates();
5579
+ const inBand = (rate) => (minSampleRate == null || rate >= minSampleRate) && (!maxSampleRate || rate <= maxSampleRate);
5580
+ if (rates.some(inBand)) return void 0;
5581
+ const decodable = maxSampleRate ? rates.filter((rate) => rate <= maxSampleRate) : rates;
5582
+ return decodable.length ? max2(decodable) : min(rates);
5583
+ };
5584
+ if (minSampleRate != null && samplingRate < minSampleRate) {
5585
+ return samplingRate === outOfBandFallback();
5586
+ }
5587
+ if (!maxSampleRate) return true;
5588
+ if (hasBrowser2(Browser2.FIREFOX)) {
5460
5589
  return samplingRate <= 48e3;
5461
5590
  }
5462
5591
  if (samplingRate <= maxSampleRate) return true;
5463
- const allAboveMax = every(array6, (item) => {
5464
- const itemSamplingRate = last(item.audioSamplingRate);
5465
- return itemSamplingRate != null && itemSamplingRate > maxSampleRate;
5466
- });
5467
- if (allAboveMax) {
5468
- const samplingRates = map2(
5469
- array6,
5470
- (item) => last(item.audioSamplingRate)
5471
- ).filter((rate) => rate != null);
5472
- const lowestSamplingRate = min(samplingRates);
5473
- return samplingRate === lowestSamplingRate;
5474
- }
5475
- return false;
5592
+ return samplingRate === outOfBandFallback();
5476
5593
  }
5477
5594
 
5478
5595
  // src/util/media/codecOverrides.ts
@@ -5508,8 +5625,8 @@ function createDefaultMediaTimelineTransformer(deps) {
5508
5625
  return canPlayMimeType(deps, quality);
5509
5626
  }
5510
5627
  async function transformTimeline(timeline) {
5511
- var _a, _b;
5512
- const codecOverrides = deps.options.value.codecOverrides;
5628
+ var _a, _b, _c, _d;
5629
+ const { audio, codecOverrides } = deps.options.value;
5513
5630
  let t = filterTimelineQualities(
5514
5631
  (quality) => canPlayWithOverrides(quality, codecOverrides),
5515
5632
  throwMimeTypesUnsupported,
@@ -5520,19 +5637,31 @@ function createDefaultMediaTimelineTransformer(deps) {
5520
5637
  throwKeySystemsUnsupported,
5521
5638
  t
5522
5639
  );
5640
+ if (!audio.disableSampleRateFilter) {
5641
+ const sampleRateOptions = {
5642
+ capabilities: deps.capabilities,
5643
+ maxSampleRate: (_a = audio.maxSampleRate) != null ? _a : null,
5644
+ minSampleRate: (_b = audio.minSampleRate) != null ? _b : null
5645
+ };
5646
+ t = filterTimelineQualities(
5647
+ (quality, index, array6) => withinAudioSampleRateRange(
5648
+ sampleRateOptions,
5649
+ quality,
5650
+ index,
5651
+ array6
5652
+ ),
5653
+ throwSamplingRatesUnsupported,
5654
+ t
5655
+ );
5656
+ }
5657
+ const selection = audio.selection;
5523
5658
  t = filterTimelineQualities(
5524
- (quality, index, array6) => supportsAudioSamplingRate(deps, quality, index, array6),
5525
- throwSamplingRatesUnsupported,
5526
- t
5527
- );
5528
- const selection = deps.options.value.audio.selection;
5529
- t = filterTimelineQualities(
5530
- createAudioDescriptionFilter((_a = selection == null ? void 0 : selection.descriptive) != null ? _a : false),
5659
+ createAudioDescriptionFilter((_c = selection == null ? void 0 : selection.descriptive) != null ? _c : false),
5531
5660
  throwNoPlayableAudio,
5532
5661
  t
5533
5662
  );
5534
5663
  t = filterTimelineQualities(
5535
- createLanguageFilter((_b = selection == null ? void 0 : selection.language) != null ? _b : null, "audio"),
5664
+ createLanguageFilter((_d = selection == null ? void 0 : selection.language) != null ? _d : null, "audio"),
5536
5665
  throwLanguagesUnsupported,
5537
5666
  t
5538
5667
  );
@@ -5547,32 +5676,11 @@ function createDefaultMediaTimelineTransformer(deps) {
5547
5676
  });
5548
5677
  }
5549
5678
 
5550
- // src/streaming/DescriptorRecord.ts
5551
- import {
5552
- array as array2,
5553
- object as object8,
5554
- record as record2,
5555
- string as string5
5556
- } from "@amazon/vinyl-validation";
5557
- import { first } from "@amazon/vinyl-util";
5558
- function getDescriptorValue(record4, uri, id) {
5559
- var _a, _b;
5560
- let arr = record4[uri];
5561
- if (!arr) return null;
5562
- if (id !== void 0) arr = arr.filter((descriptor) => descriptor.id === id);
5563
- return (_b = (_a = first(arr)) == null ? void 0 : _a.value) != null ? _b : null;
5564
- }
5565
- var descriptorValidator = /* @__PURE__ */ object8({
5566
- id: /* @__PURE__ */ string5().maybe().optional(),
5567
- value: /* @__PURE__ */ string5().maybe().optional()
5568
- });
5569
- var descriptorRecordValidator = /* @__PURE__ */ record2(/* @__PURE__ */ string5(), /* @__PURE__ */ array2(descriptorValidator).readonly().orUndefined());
5570
-
5571
5679
  // src/streaming/ManifestControllerImpl.ts
5572
5680
  import { data } from "@amazon/vinyl-observable";
5573
5681
  import {
5574
5682
  createAbortSlot as createAbortSlot2,
5575
- createDisposer as createDisposer12,
5683
+ createDisposer as createDisposer11,
5576
5684
  EventHostImpl as EventHostImpl11,
5577
5685
  logDebug as logDebug11
5578
5686
  } from "@amazon/vinyl-util";
@@ -5582,7 +5690,7 @@ var ManifestControllerImpl = class {
5582
5690
  __publicField(this, "_data");
5583
5691
  __publicField(this, "_error", null);
5584
5692
  __publicField(this, "abortSlot", /* @__PURE__ */ createAbortSlot2());
5585
- __publicField(this, "disposer", /* @__PURE__ */ createDisposer12());
5693
+ __publicField(this, "disposer", /* @__PURE__ */ createDisposer11());
5586
5694
  __publicField(this, "events", /* @__PURE__ */ new EventHostImpl11());
5587
5695
  __publicField(this, "manifestSpanArmed", true);
5588
5696
  __publicField(this, "__eventMapType", this.events.__eventMapType);
@@ -5674,84 +5782,6 @@ var ManifestControllerImpl = class {
5674
5782
  }
5675
5783
  };
5676
5784
 
5677
- // src/streaming/MediaQualityMetadata.ts
5678
- import {
5679
- createShortUid
5680
- } from "@amazon/vinyl-util";
5681
- import {
5682
- array as array3,
5683
- enumOf as enumOf3,
5684
- isOneOf as isOneOf3,
5685
- number as number5,
5686
- object as object9,
5687
- string as string6,
5688
- tuple
5689
- } from "@amazon/vinyl-validation";
5690
- var ALL_CONTENT_TYPES = [
5691
- "video",
5692
- "audio",
5693
- "text"
5694
- ];
5695
- var RESTRICTABLE_CONTENT_TYPES = [
5696
- "video",
5697
- "audio"
5698
- ];
5699
- var drmProtectionValidator = /* @__PURE__ */ descriptorValidator.extend({
5700
- keySystem: /* @__PURE__ */ enumOf3(DrmKeySystem),
5701
- pro: /* @__PURE__ */ string6().maybe().optional(),
5702
- pssh: /* @__PURE__ */ string6().maybe().optional()
5703
- });
5704
- var mediaFormatMetadataValidator = /* @__PURE__ */ object9({
5705
- contentProtections: /* @__PURE__ */ array3(drmProtectionValidator).readonly(),
5706
- contentType: /* @__PURE__ */ isOneOf3("audio", "video", "text").orNull(),
5707
- initDataType: /* @__PURE__ */ string6().orNull(),
5708
- encryptionScheme: /* @__PURE__ */ string6().orNull(),
5709
- mimeType: /* @__PURE__ */ string6().orNull()
5710
- });
5711
- function createEmptyMediaFormatMetadata() {
5712
- return {
5713
- contentType: null,
5714
- mimeType: null,
5715
- initDataType: null,
5716
- encryptionScheme: null,
5717
- contentProtections: []
5718
- };
5719
- }
5720
- function createEmptyMediaQualityMetadata() {
5721
- return __spreadProps(__spreadValues({}, createEmptyMediaFormatMetadata()), {
5722
- decoderId: createShortUid(),
5723
- qualityId: createShortUid(),
5724
- codecs: null,
5725
- bandwidth: null,
5726
- bandwidthTotal: null,
5727
- supplementalProperties: {},
5728
- audioSamplingRate: null,
5729
- frameRate: null,
5730
- height: null,
5731
- width: null,
5732
- lang: null,
5733
- characteristics: [],
5734
- groupId: createShortUid(),
5735
- switchingGroupIds: null
5736
- });
5737
- }
5738
- var mediaQualityMetadataValidator = /* @__PURE__ */ mediaFormatMetadataValidator.extend({
5739
- audioSamplingRate: /* @__PURE__ */ array3(/* @__PURE__ */ number5()).readonly().orNull(),
5740
- bandwidth: /* @__PURE__ */ number5().orNull(),
5741
- bandwidthTotal: /* @__PURE__ */ number5().orNull(),
5742
- codecs: /* @__PURE__ */ string6().orNull(),
5743
- decoderId: /* @__PURE__ */ string6(),
5744
- frameRate: /* @__PURE__ */ tuple(/* @__PURE__ */ number5(), /* @__PURE__ */ number5()).readonly().orNull(),
5745
- height: /* @__PURE__ */ number5().orNull(),
5746
- qualityId: /* @__PURE__ */ string6(),
5747
- supplementalProperties: descriptorRecordValidator,
5748
- width: /* @__PURE__ */ number5().orNull(),
5749
- lang: /* @__PURE__ */ string6().orNull(),
5750
- characteristics: /* @__PURE__ */ array3(/* @__PURE__ */ string6()).readonly(),
5751
- groupId: /* @__PURE__ */ string6(),
5752
- switchingGroupIds: /* @__PURE__ */ array3(/* @__PURE__ */ string6()).readonly().orNull()
5753
- });
5754
-
5755
5785
  // src/streaming/MediaTimeline.ts
5756
5786
  import { sortedInsertionIndex as sortedInsertionIndex2 } from "@amazon/vinyl-util";
5757
5787
  function getMediaPeriodAtTime(timeline, time) {
@@ -5767,9 +5797,9 @@ function getMediaPeriodAtTime(timeline, time) {
5767
5797
  import {
5768
5798
  Abort as Abort2,
5769
5799
  clone as clone2,
5770
- closeTo as closeTo6,
5771
- createDisposer as createDisposer13,
5772
- createLogPrefix as createLogPrefix9,
5800
+ closeTo as closeTo4,
5801
+ createDisposer as createDisposer12,
5802
+ createLogPrefix as createLogPrefix8,
5773
5803
  EventHostImpl as EventHostImpl12,
5774
5804
  getNetworkState,
5775
5805
  getOrSet,
@@ -5949,7 +5979,7 @@ var SegmentControllerImpl = class extends EventHostImpl12 {
5949
5979
  */
5950
5980
  __publicField(this, "cachedInitSegments", /* @__PURE__ */ new Map());
5951
5981
  __publicField(this, "cachedSegments", []);
5952
- __publicField(this, "disposer", /* @__PURE__ */ createDisposer13());
5982
+ __publicField(this, "disposer", /* @__PURE__ */ createDisposer12());
5953
5983
  __publicField(this, "options");
5954
5984
  __publicField(this, "prefetchingPriority", /* @__PURE__ */ clone2(defaultTrackPriority));
5955
5985
  /**
@@ -6020,7 +6050,7 @@ var SegmentControllerImpl = class extends EventHostImpl12 {
6020
6050
  }
6021
6051
  });
6022
6052
  __publicField(this, "_streamingQuality", null);
6023
- this.logPrefix = createLogPrefix9(`Segment_${contentType2}`);
6053
+ this.logPrefix = createLogPrefix8(`Segment_${contentType2}`);
6024
6054
  logDebug12(this, "constructed");
6025
6055
  const { add } = this.disposer;
6026
6056
  this.options = __spreadValues(__spreadValues({}, defaultSegmentControllerBaseOptions), options);
@@ -6290,7 +6320,7 @@ var SegmentControllerImpl = class extends EventHostImpl12 {
6290
6320
  );
6291
6321
  if (insertionIndex > 0) {
6292
6322
  const cachedSegment2 = this.cachedSegments[insertionIndex - 1];
6293
- if (closeTo6(newSlot.startTime, cachedSegment2.startTime)) {
6323
+ if (closeTo4(newSlot.startTime, cachedSegment2.startTime)) {
6294
6324
  return cachedSegment2;
6295
6325
  }
6296
6326
  }
@@ -6451,7 +6481,6 @@ var ALL_STREAMING_EVENTS = [
6451
6481
  "bufferingQualityChange",
6452
6482
  "playbackQualityChange",
6453
6483
  "bufferingEnded",
6454
- "hasDataChange",
6455
6484
  "error",
6456
6485
  "reset",
6457
6486
  "qualitiesChange",
@@ -6954,14 +6983,19 @@ function scoreTextTrack(track, prefs) {
6954
6983
  // src/text/SidecarTextTrackController.ts
6955
6984
  import {
6956
6985
  createAbortSlot as createAbortSlot4,
6957
- createDisposer as createDisposer14,
6986
+ createDisposer as createDisposer13,
6958
6987
  equalDeep,
6959
6988
  EventHostImpl as EventHostImpl13,
6960
6989
  logError as logError4
6961
6990
  } from "@amazon/vinyl-util";
6962
6991
 
6963
6992
  // src/text/SidecarTextTrackLoader.ts
6964
- import { requestWithRetry as requestWithRetry4, resolveUrl as resolveUrl4, sleep as sleep2 } from "@amazon/vinyl-util";
6993
+ import {
6994
+ readResponseBody as readResponseBody3,
6995
+ requestWithRetry as requestWithRetry4,
6996
+ resolveUrl as resolveUrl4,
6997
+ sleep as sleep2
6998
+ } from "@amazon/vinyl-util";
6965
6999
  import { parseMediaPlaylist } from "@amazon/vinyl-hls-parser";
6966
7000
  var DEFAULT_TEXT_LOOK_AHEAD = 10;
6967
7001
  var DEFAULT_TEXT_LOOK_BEHIND = 2;
@@ -6987,7 +7021,7 @@ async function loadWebVttCues(uri, options) {
6987
7021
  }
6988
7022
  const response = await requestWithRetry4(uri, init, { abort });
6989
7023
  const contentType2 = ((_c = response.headers.get("content-type")) != null ? _c : "").toLowerCase();
6990
- const body = await response.text();
7024
+ const body = await readResponseBody3(response, "text");
6991
7025
  if (contentType2.includes("mpegurl") || body.startsWith("#EXTM3U")) {
6992
7026
  return streamMediaPlaylistText({
6993
7027
  text: body,
@@ -7014,7 +7048,7 @@ async function streamMediaPlaylist(ctx) {
7014
7048
  const response = await requestWithRetry4(ctx.uri, ctx.init, {
7015
7049
  abort: ctx.abort
7016
7050
  });
7017
- const text = await response.text();
7051
+ const text = await readResponseBody3(response, "text");
7018
7052
  return streamMediaPlaylistText(__spreadProps(__spreadValues({}, ctx), {
7019
7053
  text,
7020
7054
  baseUrl: response.url || ctx.uri
@@ -7043,7 +7077,7 @@ async function streamMediaPlaylistText(ctx) {
7043
7077
  const res = await requestWithRetry4(segUri, ctx.init, {
7044
7078
  abort: ctx.abort
7045
7079
  });
7046
- const body = await res.text();
7080
+ const body = await readResponseBody3(res, "text");
7047
7081
  const doc = parseWebVtt(body);
7048
7082
  if (doc.cues.length > 0) ctx.onCues(doc.cues);
7049
7083
  if (ctx.onStyles && doc.styles.length > 0) ctx.onStyles(doc.styles);
@@ -7069,7 +7103,7 @@ function pickInWindow(pending, ranges, ctx) {
7069
7103
  }
7070
7104
 
7071
7105
  // src/text/VttCueStyle.ts
7072
- import { boolean as boolean4, isOneOf as isOneOf4, number as number6, object as object10 } from "@amazon/vinyl-validation";
7106
+ import { boolean as boolean4, isOneOf as isOneOf4, number as number7, object as object10 } from "@amazon/vinyl-validation";
7073
7107
  function isVttCue(cue) {
7074
7108
  return typeof VTTCue !== "undefined" && cue instanceof VTTCue;
7075
7109
  }
@@ -7086,16 +7120,16 @@ function applyVttCueStyle(cue, style) {
7086
7120
  }
7087
7121
  var vttCueStyleValidator = /* @__PURE__ */ object10({
7088
7122
  align: /* @__PURE__ */ isOneOf4("start", "center", "end", "left", "right").optional(),
7089
- line: /* @__PURE__ */ number6().or(/* @__PURE__ */ isOneOf4("auto")).optional(),
7123
+ line: /* @__PURE__ */ number7().or(/* @__PURE__ */ isOneOf4("auto")).optional(),
7090
7124
  lineAlign: /* @__PURE__ */ isOneOf4("start", "center", "end").optional(),
7091
- position: /* @__PURE__ */ number6().or(/* @__PURE__ */ isOneOf4("auto")).optional(),
7125
+ position: /* @__PURE__ */ number7().or(/* @__PURE__ */ isOneOf4("auto")).optional(),
7092
7126
  positionAlign: /* @__PURE__ */ isOneOf4(
7093
7127
  "line-left",
7094
7128
  "center",
7095
7129
  "line-right",
7096
7130
  "auto"
7097
7131
  ).optional(),
7098
- size: /* @__PURE__ */ number6().optional(),
7132
+ size: /* @__PURE__ */ number7().optional(),
7099
7133
  snapToLines: /* @__PURE__ */ boolean4().optional(),
7100
7134
  vertical: /* @__PURE__ */ isOneOf4("", "rl", "lr").optional()
7101
7135
  });
@@ -7130,7 +7164,7 @@ var SidecarTextTrackController = class extends EventHostImpl13 {
7130
7164
  // the provider (never created/removed here).
7131
7165
  __publicField(this, "_ref", null);
7132
7166
  __publicField(this, "loadAbort", /* @__PURE__ */ createAbortSlot4());
7133
- __publicField(this, "disposer", /* @__PURE__ */ createDisposer14());
7167
+ __publicField(this, "disposer", /* @__PURE__ */ createDisposer13());
7134
7168
  const { add } = this.disposer;
7135
7169
  add(deps.options.onData(() => this.refreshSelection()));
7136
7170
  add(
@@ -7319,11 +7353,11 @@ var ALL_TEXT_TRACK_EVENTS = [
7319
7353
 
7320
7354
  // src/track/AutoResetController.ts
7321
7355
  import {
7322
- createDisposer as createDisposer15,
7356
+ createDisposer as createDisposer14,
7323
7357
  EventHostImpl as EventHostImpl14,
7324
7358
  getNetworkState as getNetworkState2,
7325
7359
  logDebug as logDebug13,
7326
- onAny as onAny3,
7360
+ onAny as onAny2,
7327
7361
  RequestError
7328
7362
  } from "@amazon/vinyl-util";
7329
7363
  var defaultResetControllerOptions = {
@@ -7339,11 +7373,11 @@ var AutoResetControllerImpl = class extends EventHostImpl14 {
7339
7373
  __publicField(this, "_error", null);
7340
7374
  __publicField(this, "watchSub", null);
7341
7375
  __publicField(this, "currentRetry", 0);
7342
- __publicField(this, "disposer", /* @__PURE__ */ createDisposer15());
7376
+ __publicField(this, "disposer", /* @__PURE__ */ createDisposer14());
7343
7377
  logDebug13(this, "constructor");
7344
7378
  this.options = __spreadValues(__spreadValues({}, defaultResetControllerOptions), options);
7345
7379
  this.disposer.add(
7346
- onAny3(
7380
+ onAny2(
7347
7381
  deps.playbackController,
7348
7382
  ["play", "pause", "seeking", "playing"],
7349
7383
  (_event) => {
@@ -7377,7 +7411,7 @@ var AutoResetControllerImpl = class extends EventHostImpl14 {
7377
7411
  this.watchSub = null;
7378
7412
  if (value) {
7379
7413
  const networkState = getNetworkState2();
7380
- const { add, dispose: watchSub } = createDisposer15();
7414
+ const { add, dispose: watchSub } = createDisposer14();
7381
7415
  this.watchSub = watchSub;
7382
7416
  add(
7383
7417
  networkState.on("online", () => {
@@ -7428,6 +7462,7 @@ import {
7428
7462
  last as last2,
7429
7463
  networkMetricsController,
7430
7464
  normalizeHeadersInit as normalizeHeadersInit2,
7465
+ readResponseBody as readResponseBody4,
7431
7466
  requestWithRetry as requestWithRetry5
7432
7467
  } from "@amazon/vinyl-util";
7433
7468
  import { stringifyByteRange } from "@amazon/vinyl-mpd-parser";
@@ -7452,7 +7487,7 @@ function createSegmentDataProvider(deps, options) {
7452
7487
  abort
7453
7488
  });
7454
7489
  const responseEnd = Date.now();
7455
- const arrayBuffer = await response.arrayBuffer();
7490
+ const arrayBuffer = await readResponseBody4(response, "arrayBuffer");
7456
7491
  const contentEnd = Date.now();
7457
7492
  let responseStart = null;
7458
7493
  if ("getEntriesByName" in performance) {
@@ -7465,7 +7500,7 @@ function createSegmentDataProvider(deps, options) {
7465
7500
  }
7466
7501
  }
7467
7502
  }
7468
- if (options.reportDownlinkMetrics) {
7503
+ if (options.reportDownlinkMetrics && !(abort == null ? void 0 : abort.aborted())) {
7469
7504
  networkMetricsController.value.addDownlinkTransferEntry({
7470
7505
  bytes: arrayBuffer.byteLength,
7471
7506
  serviceId,
@@ -7487,13 +7522,13 @@ import {
7487
7522
  import {
7488
7523
  any as any2,
7489
7524
  isOneOf as isOneOf6,
7490
- number as number7,
7525
+ number as number8,
7491
7526
  object as object12,
7492
7527
  string as string8
7493
7528
  } from "@amazon/vinyl-validation";
7494
7529
  var trackConfigOptionsValidator = /* @__PURE__ */ object12({
7495
7530
  extra: /* @__PURE__ */ any2().optional(),
7496
- startTime: /* @__PURE__ */ number7().maybe().optional(),
7531
+ startTime: /* @__PURE__ */ number8().maybe().optional(),
7497
7532
  drm: /* @__PURE__ */ drmOptionsValidator.partial().optional()
7498
7533
  });
7499
7534
  var trackLoadOptionsValidator = /* @__PURE__ */ object12(
@@ -7523,7 +7558,7 @@ import { func as func2, isOneOf as isOneOf7 } from "@amazon/vinyl-validation";
7523
7558
  // src/track/TrackBase.ts
7524
7559
  import {
7525
7560
  createAbortSlot as createAbortSlot5,
7526
- createDisposer as createDisposer16,
7561
+ createDisposer as createDisposer15,
7527
7562
  emptyRanges as emptyRanges2,
7528
7563
  equalDeep as equalDeep2,
7529
7564
  EventHostImpl as EventHostImpl15,
@@ -7551,7 +7586,7 @@ var TrackBase = class extends EventHostImpl15 {
7551
7586
  });
7552
7587
  }
7553
7588
  });
7554
- __publicField(this, "disposer", /* @__PURE__ */ createDisposer16());
7589
+ __publicField(this, "disposer", /* @__PURE__ */ createDisposer15());
7555
7590
  __publicField(this, "drmSessionAbort", /* @__PURE__ */ createAbortSlot5());
7556
7591
  /**
7557
7592
  * Sets on handleError, cleared on 'reset'.
@@ -7781,7 +7816,7 @@ var FixedPlaybackQuality = class extends EventHostImpl16 {
7781
7816
 
7782
7817
  // src/track/source/SourceTrackBase.ts
7783
7818
  import {
7784
- createDisposer as createDisposer17,
7819
+ createDisposer as createDisposer16,
7785
7820
  logDebug as logDebug15,
7786
7821
  redispatchEvents as redispatchEvents2
7787
7822
  } from "@amazon/vinyl-util";
@@ -7840,7 +7875,7 @@ var SourceTrackBase = class extends TrackBase {
7840
7875
  return this.fixedPlaybackQuality.getPlaybackQuality(contentType2);
7841
7876
  }
7842
7877
  onActivated() {
7843
- const { add, dispose } = createDisposer17();
7878
+ const { add, dispose } = createDisposer16();
7844
7879
  this.activeSub = dispose;
7845
7880
  add(
7846
7881
  this.deps.playbackController.on("durationChange", (event) => {
@@ -7966,19 +8001,15 @@ import {
7966
8001
  first as first2,
7967
8002
  IntersectionRanges,
7968
8003
  logDebug as logDebug16,
7969
- noop as noop7,
7970
8004
  redispatchEvents as redispatchEvents3
7971
8005
  } from "@amazon/vinyl-util";
7972
8006
  import { createContainer as createContainer2 } from "@amazon/vinyl-di";
7973
- var SEEKING_STALL_TIME_CHECK = 0.1;
7974
- var PLAYHEAD_NUDGE = 0.05;
7975
8007
  var MseTrack = class extends TrackBase {
7976
8008
  constructor(uri, type, dependencyFactories) {
7977
8009
  const depsContainer = createContainer2(dependencyFactories);
7978
8010
  const deps = depsContainer.dependencies;
7979
8011
  super(uri, type, deps);
7980
8012
  __publicField(this, "streams", []);
7981
- __publicField(this, "stallNudgeTimer", null);
7982
8013
  __publicField(this, "disposeAbort", /* @__PURE__ */ new Abort3());
7983
8014
  __publicField(this, "lastPreloadOptions", null);
7984
8015
  __publicField(this, "allFetchedRanges", []);
@@ -8040,11 +8071,6 @@ var MseTrack = class extends TrackBase {
8040
8071
  if (previous !== void 0) this.reloadStreams();
8041
8072
  })
8042
8073
  );
8043
- add(
8044
- deps.allowedContentTypes.onData((_value, previous) => {
8045
- if (previous !== void 0) this.reloadStreams();
8046
- })
8047
- );
8048
8074
  add(
8049
8075
  deps.abr.onData((value, previous) => {
8050
8076
  if (previous === void 0) return;
@@ -8186,7 +8212,6 @@ var MseTrack = class extends TrackBase {
8186
8212
  this.dispatch("bufferingEnded", {});
8187
8213
  }
8188
8214
  });
8189
- stream.on("hasDataChange", () => this.checkStalledSeek());
8190
8215
  stream.on("fetchedRangesChange", () => {
8191
8216
  this._fetchedRanges.invalidate();
8192
8217
  });
@@ -8322,34 +8347,6 @@ var MseTrack = class extends TrackBase {
8322
8347
  get bufferingEnded() {
8323
8348
  return this.streams.every((stream) => stream.bufferingEnded);
8324
8349
  }
8325
- /**
8326
- * A seek only completes once every stream has data at the target, but on
8327
- * some platforms the element can stay stuck `seeking` even after that. Once
8328
- * all streams hold data, if we're still seeking a moment later, nudge the
8329
- * playhead to prod the element into completing the seek.
8330
- */
8331
- checkStalledSeek() {
8332
- const { playbackController } = this.deps;
8333
- if (this.stallNudgeTimer !== null || !playbackController.seeking) return;
8334
- if (!this.streams.length || !this.streams.every((s) => s.hasData)) {
8335
- return;
8336
- }
8337
- this.stallNudgeTimer = setTimeout(() => {
8338
- this.stallNudgeTimer = null;
8339
- if (this.disposed || !playbackController.seeking) return;
8340
- if (!this.streams.every((s) => s.hasData)) return;
8341
- const from = playbackController.currentTime;
8342
- const to = from + PLAYHEAD_NUDGE;
8343
- logDebug16(
8344
- this,
8345
- "nudging playhead to recover a stalled seek",
8346
- from,
8347
- "->",
8348
- to
8349
- );
8350
- playbackController.seekTo(to, 0).catch(noop7);
8351
- }, SEEKING_STALL_TIME_CHECK * 1e3);
8352
- }
8353
8350
  setContentTypes(contentTypes) {
8354
8351
  if (this.disposed) return;
8355
8352
  const previous = this.contentTypes;
@@ -8373,7 +8370,6 @@ var MseTrack = class extends TrackBase {
8373
8370
  }
8374
8371
  dispose() {
8375
8372
  logDebug16(this, "dispose");
8376
- if (this.stallNudgeTimer !== null) clearTimeout(this.stallNudgeTimer);
8377
8373
  this.clearStreams();
8378
8374
  super.dispose();
8379
8375
  }
@@ -8549,13 +8545,18 @@ function calculatePeriodTimeRange(period) {
8549
8545
  return [calculatePeriodStart(period), calculatePeriodEnd(period)];
8550
8546
  }
8551
8547
  function calculatePeriodStart(period) {
8552
- var _a;
8553
- return (_a = period.start) != null ? _a : 0;
8548
+ if (period.start != null) return period.start;
8549
+ const mpd = period.parent;
8550
+ const periodIndex = mpd.Period.indexOf(period);
8551
+ if (periodIndex <= 0) return 0;
8552
+ const previous = mpd.Period[periodIndex - 1];
8553
+ const previousStart = calculatePeriodStart(previous);
8554
+ return previous.duration != null ? previousStart + previous.duration : previousStart;
8554
8555
  }
8555
8556
  function calculatePeriodEnd(period) {
8556
8557
  var _a;
8557
- if (period.start != null && period.duration != null)
8558
- return period.start + period.duration;
8558
+ if (period.duration != null)
8559
+ return calculatePeriodStart(period) + period.duration;
8559
8560
  const mpd = period.parent;
8560
8561
  const periodIndex = mpd.Period.indexOf(period);
8561
8562
  if (periodIndex < mpd.Period.length - 1)
@@ -8611,6 +8612,8 @@ import {
8611
8612
  ErrorOrigin as ErrorOrigin23,
8612
8613
  getSidxSampleTimes,
8613
8614
  parseSidxBox,
8615
+ parseWebmCues,
8616
+ parseWebmInit,
8614
8617
  ValidationError as ValidationError5
8615
8618
  } from "@amazon/vinyl-util";
8616
8619
 
@@ -8722,9 +8725,13 @@ function createDashRepresentationSegmentProvider(deps, baseUrl, representation)
8722
8725
  segmentTemplate
8723
8726
  }));
8724
8727
  } else if (segmentBase) {
8725
- getSegmentReferences = () => createSegmentsFromSegmentBase(deps, __spreadProps(__spreadValues({}, options), {
8726
- segmentBase
8727
- }));
8728
+ getSegmentReferences = () => createSegmentsFromSegmentBase(
8729
+ deps,
8730
+ __spreadProps(__spreadValues({}, options), {
8731
+ segmentBase
8732
+ }),
8733
+ initData
8734
+ );
8728
8735
  }
8729
8736
  return {
8730
8737
  async getSegment(time, affordance = 0) {
@@ -8836,10 +8843,14 @@ function createSegmentsFromSegmentTemplate(deps, options) {
8836
8843
  }
8837
8844
  );
8838
8845
  }
8839
- async function createSegmentsFromSegmentBase(deps, options) {
8846
+ async function createSegmentsFromSegmentBase(deps, options, initData) {
8840
8847
  var _a;
8841
8848
  const { baseUrl, periodTimeRange, representation, segmentBase } = options;
8842
8849
  if (segmentBase.indexRange) {
8850
+ const { mimeType } = getRepresentationMimeInfo(representation);
8851
+ if (mimeType == null ? void 0 : mimeType.includes("webm")) {
8852
+ return createSegmentsFromWebmCues(deps, options, initData);
8853
+ }
8843
8854
  const indexRange = segmentBase.indexRange;
8844
8855
  const { url: indexUrl, serviceLocation: indexServiceLocation } = resolveDashUri(deps, { baseUrl, representation });
8845
8856
  const sidx = parseSidxBox(
@@ -8876,6 +8887,56 @@ async function createSegmentsFromSegmentBase(deps, options) {
8876
8887
  throw new ValidationError5("Manifest missing segments");
8877
8888
  }
8878
8889
  }
8890
+ async function createSegmentsFromWebmCues(deps, options, initData) {
8891
+ var _a, _b;
8892
+ const { baseUrl, periodTimeRange, representation, segmentBase } = options;
8893
+ const indexRange = segmentBase.indexRange;
8894
+ const { url, serviceLocation } = resolveDashUri(deps, {
8895
+ baseUrl,
8896
+ representation
8897
+ });
8898
+ const [{ segmentDataStart, timecodeScale }, cues] = await Promise.all([
8899
+ Promise.resolve(initData()).then(parseWebmInit),
8900
+ createSegmentDataProvider(deps, {
8901
+ url,
8902
+ mediaRange: indexRange,
8903
+ serviceId: serviceLocation,
8904
+ reportDownlinkMetrics: false
8905
+ })().then(parseWebmCues)
8906
+ ]);
8907
+ if (!cues.length) {
8908
+ throw new ValidationError5("WebM Cues contained no cue points");
8909
+ }
8910
+ const ticksPerSecond = Math.round(1e9 / timecodeScale);
8911
+ const manifestTimescale = (_a = segmentBase.timescale) != null ? _a : ticksPerSecond;
8912
+ const presentationTimeOffset = ((_b = segmentBase.presentationTimeOffset) != null ? _b : 0) * ticksPerSecond / manifestTimescale;
8913
+ const [, periodEnd] = periodTimeRange;
8914
+ if (periodEnd == null)
8915
+ throw new ValidationError5(
8916
+ "MPD.mediaPresentationDuration or Period.duration required",
8917
+ ErrorOrigin23.MEDIA
8918
+ );
8919
+ const sampleTimes = cues.map((cue) => cue.time);
8920
+ sampleTimes.push(periodEnd * ticksPerSecond);
8921
+ return createTimeline(
8922
+ {
8923
+ sampleTimes,
8924
+ periodTimeRange,
8925
+ presentationTimeOffset,
8926
+ timescale: ticksPerSecond
8927
+ },
8928
+ (i) => {
8929
+ const start = segmentDataStart + cues[i].clusterPosition;
8930
+ const end = i < cues.length - 1 ? segmentDataStart + cues[i + 1].clusterPosition - 1 : null;
8931
+ return createSegmentDataProvider(deps, {
8932
+ url,
8933
+ mediaRange: [start, end],
8934
+ serviceId: serviceLocation,
8935
+ reportDownlinkMetrics: true
8936
+ });
8937
+ }
8938
+ );
8939
+ }
8879
8940
  function calculateSegmentSampleTimes(options) {
8880
8941
  const { multipleSegmentBase, periodTimeRange } = options;
8881
8942
  const timescale = getTimescale(multipleSegmentBase);
@@ -9256,13 +9317,12 @@ function estimatePeakBandwidth(representation, contentType2) {
9256
9317
  0,
9257
9318
  sortedInsertionIndex5(own, representation.bandwidth, (a, b) => b - a) - 1
9258
9319
  );
9259
- const position = own.length <= 1 ? 0 : ownIndex / (own.length - 1);
9260
9320
  let total = representation.bandwidth;
9261
9321
  for (const [ct, bandwidths] of sortedByType) {
9262
9322
  if (ct === contentType2) continue;
9263
9323
  const peerIndex = Math.min(
9264
- Math.round(position * (bandwidths.length - 1)),
9265
- bandwidths.length - 1
9324
+ bandwidths.length - 1,
9325
+ Math.ceil((ownIndex + 1) / own.length * bandwidths.length) - 1
9266
9326
  );
9267
9327
  total += bandwidths[peerIndex];
9268
9328
  }
@@ -9337,11 +9397,11 @@ import {
9337
9397
  } from "@amazon/vinyl-di";
9338
9398
 
9339
9399
  // src/track/dash/urlDashManifestProvider.ts
9340
- import { noop as noop8 } from "@amazon/vinyl-util";
9400
+ import { noop as noop7 } from "@amazon/vinyl-util";
9341
9401
  import { clone as clone4, getLocation, resolveUrl as resolveUrl6 } from "@amazon/vinyl-util";
9342
- import { requestWithRetry as requestWithRetry6 } from "@amazon/vinyl-util";
9402
+ import { readResponseBody as readResponseBody5, requestWithRetry as requestWithRetry6 } from "@amazon/vinyl-util";
9343
9403
  import { parseDashManifest } from "@amazon/vinyl-mpd-parser";
9344
- function urlDashManifestProvider(input, init, requestInterceptor = noop8) {
9404
+ function urlDashManifestProvider(input, init, requestInterceptor = noop7) {
9345
9405
  return async (abort) => {
9346
9406
  var _a;
9347
9407
  const params = {
@@ -9352,7 +9412,7 @@ function urlDashManifestProvider(input, init, requestInterceptor = noop8) {
9352
9412
  const response = await requestWithRetry6(params.input, params.init, {
9353
9413
  abort
9354
9414
  });
9355
- const xml = await response.text();
9415
+ const xml = await readResponseBody5(response, "text");
9356
9416
  const manifest = parseDashManifest(xml);
9357
9417
  const baseInput = response.url || params.input;
9358
9418
  return {
@@ -9731,13 +9791,18 @@ import {
9731
9791
 
9732
9792
  // src/track/hls/createUrlHlsManifestProvider.ts
9733
9793
  import { parseMainPlaylist, parseMediaPlaylist as parseMediaPlaylist2 } from "@amazon/vinyl-hls-parser";
9734
- import { memoize as memoize11, requestWithRetry as requestWithRetry7, resolveUrl as resolveUrl9 } from "@amazon/vinyl-util";
9794
+ import {
9795
+ memoize as memoize11,
9796
+ readResponseBody as readResponseBody6,
9797
+ requestWithRetry as requestWithRetry7,
9798
+ resolveUrl as resolveUrl9
9799
+ } from "@amazon/vinyl-util";
9735
9800
  function createUrlHlsManifestProvider(url, requestInit) {
9736
9801
  return async (abort) => {
9737
9802
  const mainResponse = await requestWithRetry7(url, requestInit, {
9738
9803
  abort
9739
9804
  });
9740
- const mainText = await mainResponse.text();
9805
+ const mainText = await readResponseBody6(mainResponse, "text");
9741
9806
  const baseUrl = mainResponse.url || url;
9742
9807
  const mainPlaylist = parseMainPlaylist(
9743
9808
  mainText,
@@ -9764,7 +9829,7 @@ async function fetchMediaPlaylist(options) {
9764
9829
  const { uri, baseUrl, defines, requestInit, abort } = options;
9765
9830
  const variantUrl = resolveUrl9(uri, baseUrl);
9766
9831
  const response = await requestWithRetry7(variantUrl, requestInit, { abort });
9767
- const text = await response.text();
9832
+ const text = await readResponseBody6(response, "text");
9768
9833
  const queryParams = parseQueryParams(response.url || variantUrl);
9769
9834
  return parseMediaPlaylist2(text, defines, queryParams);
9770
9835
  }
@@ -9840,18 +9905,18 @@ function createHlsFactories(options) {
9840
9905
  // src/track/TrackController.ts
9841
9906
  import {
9842
9907
  countElements,
9843
- createDisposer as createDisposer18,
9908
+ createDisposer as createDisposer17,
9844
9909
  EventHostImpl as EventHostImpl17,
9845
9910
  first as first3,
9846
9911
  getOrSet as getOrSet3,
9847
9912
  IllegalStateError as IllegalStateError4,
9848
9913
  logDebug as logDebug17,
9849
9914
  logError as logError5,
9850
- logInfo as logInfo3,
9915
+ logInfo as logInfo2,
9851
9916
  logVerbose as logVerbose4,
9852
- logWarn as logWarn6,
9917
+ logWarn as logWarn5,
9853
9918
  LruCache,
9854
- noop as noop9,
9919
+ noop as noop8,
9855
9920
  resolveValueProvider as resolveValueProvider3
9856
9921
  } from "@amazon/vinyl-util";
9857
9922
  var ALL_TRACK_CONTROLLER_EVENTS = [
@@ -9891,7 +9956,7 @@ var TrackControllerImpl = class extends EventHostImpl17 {
9891
9956
  // Ad tracks keyed by parent content URI, kept out of the content cache.
9892
9957
  // Pegged to the parent: disposed when the parent is evicted (see onEvict).
9893
9958
  __publicField(this, "adTracksByParent", /* @__PURE__ */ new Map());
9894
- __publicField(this, "disposer", /* @__PURE__ */ createDisposer18());
9959
+ __publicField(this, "disposer", /* @__PURE__ */ createDisposer17());
9895
9960
  __publicField(this, "_options", defaultTrackControllerImplOptions);
9896
9961
  /**
9897
9962
  * The current track has ended naturally. On the next tick advance the queue or emit queue ended.
@@ -9901,11 +9966,12 @@ var TrackControllerImpl = class extends EventHostImpl17 {
9901
9966
  if (this.currentTrackIsAdTrack) return;
9902
9967
  const track = this._current;
9903
9968
  if (!track) {
9904
- logWarn6(this, "an ended event was received with no current track");
9969
+ logWarn5(this, "an ended event was received with no current track");
9905
9970
  return;
9906
9971
  }
9907
9972
  const interrupted = this.getQueueInterrupted();
9908
9973
  adController.enterPostroll().then((postroll) => {
9974
+ if (interrupted()) return;
9909
9975
  if (postroll) {
9910
9976
  logDebug17(this, "postroll entered");
9911
9977
  } else {
@@ -9916,12 +9982,13 @@ var TrackControllerImpl = class extends EventHostImpl17 {
9916
9982
  if (this.hasNext()) {
9917
9983
  this.next();
9918
9984
  } else {
9919
- logInfo3(this, "queueEnded");
9985
+ logInfo2(this, "queueEnded");
9920
9986
  this.dispatch("queueEnded", {});
9921
9987
  }
9922
9988
  });
9923
9989
  }
9924
9990
  }).catch((error) => {
9991
+ if (interrupted()) return;
9925
9992
  logError5(this, "enterPostroll failed", error);
9926
9993
  });
9927
9994
  });
@@ -9975,7 +10042,7 @@ var TrackControllerImpl = class extends EventHostImpl17 {
9975
10042
  config: {}
9976
10043
  }
9977
10044
  );
9978
- playbackController.play().catch(noop9);
10045
+ playbackController.play().catch(noop8);
9979
10046
  }
9980
10047
  }).catch((error) => {
9981
10048
  if (!interrupted()) adController.failAd(error);
@@ -10014,7 +10081,7 @@ var TrackControllerImpl = class extends EventHostImpl17 {
10014
10081
  return;
10015
10082
  }
10016
10083
  if (!noAdBegan) resumeContent(event.resumePosition);
10017
- logInfo3(this, "queueEnded after postroll");
10084
+ logInfo2(this, "queueEnded after postroll");
10018
10085
  this.dispatch("queueEnded", {});
10019
10086
  return;
10020
10087
  }
@@ -10025,7 +10092,7 @@ var TrackControllerImpl = class extends EventHostImpl17 {
10025
10092
  resumeContent(
10026
10093
  isPreroll ? (_a = adParentLoad.config) == null ? void 0 : _a.startTime : event.resumePosition
10027
10094
  );
10028
- playbackController.play().catch(noop9);
10095
+ playbackController.play().catch(noop8);
10029
10096
  })
10030
10097
  );
10031
10098
  }
@@ -10180,7 +10247,7 @@ var TrackControllerImpl = class extends EventHostImpl17 {
10180
10247
  var _a;
10181
10248
  const { adTrackLoadOptionsProvider } = this.deps;
10182
10249
  const loadOptions = await adTrackLoadOptionsProvider(ad);
10183
- if (parentTrack.disposed) return;
10250
+ if (parentTrack.disposed || this.disposed) return;
10184
10251
  logVerbose4(
10185
10252
  this,
10186
10253
  `preloading ad id=${ad.id} uri=${ad.uri} priority=${prefetchPriority}`
@@ -10296,7 +10363,7 @@ var TrackControllerImpl = class extends EventHostImpl17 {
10296
10363
  }
10297
10364
  );
10298
10365
  if (options == null ? void 0 : options.shouldPlay) {
10299
- playbackController.play().catch(noop9);
10366
+ playbackController.play().catch(noop8);
10300
10367
  }
10301
10368
  } else {
10302
10369
  this._queue = queue;
@@ -10335,7 +10402,7 @@ var TrackControllerImpl = class extends EventHostImpl17 {
10335
10402
  const previousTrack = this._currentTrack;
10336
10403
  const previousWasActive = (_a = previousTrack == null ? void 0 : previousTrack.active) != null ? _a : false;
10337
10404
  this._currentTrack = newTrack;
10338
- const interrupted = () => this._currentTrack !== newTrack;
10405
+ const interrupted = () => this.disposed || this._currentTrack !== newTrack;
10339
10406
  previousTrack == null ? void 0 : previousTrack.deactivate();
10340
10407
  if (previousTrack && previousWasActive) {
10341
10408
  this.dispatch("trackDeactivated", { track: previousTrack });
@@ -10363,6 +10430,7 @@ var TrackControllerImpl = class extends EventHostImpl17 {
10363
10430
  if (preroll) return;
10364
10431
  activate();
10365
10432
  }).catch((error) => {
10433
+ if (interrupted()) return;
10366
10434
  logError5(this, "enterPreroll failed", error);
10367
10435
  activate();
10368
10436
  });
@@ -10405,18 +10473,14 @@ var TrackControllerImpl = class extends EventHostImpl17 {
10405
10473
  }
10406
10474
  };
10407
10475
 
10408
- // src/vinyl/createVinylFactories.ts
10409
- import { mergeDeep, noop as noop10 } from "@amazon/vinyl-util";
10410
-
10411
- // src/vinyl/VinylPatchOptions.ts
10412
- import { lazy as lazy3 } from "@amazon/vinyl-util";
10413
- var defaultPatchOptions = /* @__PURE__ */ lazy3(() => {
10414
- return {
10415
- media: defaultMediaElementPatchOptions.value
10416
- };
10417
- });
10476
+ // src/util/media/mimeType.ts
10477
+ function mimeSubtype(mimeType) {
10478
+ var _a;
10479
+ return (_a = mimeType.split(";", 1)[0].trim().toLowerCase().split("/")[1]) != null ? _a : "";
10480
+ }
10418
10481
 
10419
10482
  // src/vinyl/createVinylFactories.ts
10483
+ import { noop as noop9 } from "@amazon/vinyl-util";
10420
10484
  import { validateFactories as validateFactories5 } from "@amazon/vinyl-di";
10421
10485
 
10422
10486
  // src/vinyl/VinylOptions.ts
@@ -10466,27 +10530,19 @@ function playerConfigFactory(defaults, validator) {
10466
10530
 
10467
10531
  // src/vinyl/createVinylFactories.ts
10468
10532
  function createVinylFactories(options) {
10469
- var _a;
10470
- const patches = mergeDeep([
10471
- defaultPatchOptions.value,
10472
- (_a = options.patches) != null ? _a : {}
10473
- ]);
10474
10533
  return validateFactories5({
10475
10534
  options: playerConfigFactory(
10476
10535
  defaultVinylOptions,
10477
10536
  vinylOptionsValidator
10478
10537
  ),
10479
- patchedMedia: () => {
10480
- return patchMediaElement(options.media, patches.media);
10481
- },
10482
- media: (deps) => deps.patchedMedia.patched,
10538
+ media: () => options.media,
10483
10539
  // One provider per media element (the player container creates each
10484
10540
  // dependency once), so text tracks are reused rather than accumulated.
10485
10541
  textTrackProvider: (deps) => createMediaTextTrackProvider({ media: deps.media }),
10486
10542
  // App-provided cue renderer (or null for native rendering).
10487
10543
  textTrackRenderer: () => {
10488
- var _a2;
10489
- return (_a2 = options.textTrackRenderer) != null ? _a2 : null;
10544
+ var _a;
10545
+ return (_a = options.textTrackRenderer) != null ? _a : null;
10490
10546
  },
10491
10547
  playbackController: (deps) => new PlaybackControllerImpl(deps, options.playbackController),
10492
10548
  playbackSource: (deps) => new PlaybackSourceImpl(deps),
@@ -10494,7 +10550,7 @@ function createVinylFactories(options) {
10494
10550
  options: deps.options.pick("loudnessNormalization")
10495
10551
  }),
10496
10552
  capabilities: (deps) => new CapabilitiesImpl(deps),
10497
- requestInterceptor: () => noop10,
10553
+ requestInterceptor: () => noop9,
10498
10554
  trackFactory: (deps) => createTrackFactory(createVinylTrackFactories(deps)),
10499
10555
  adTrackLoadOptionsProvider: () => defaultAdLoadOptionsResolver,
10500
10556
  trackController: (deps) => new TrackControllerImpl(deps, options.trackController),
@@ -10510,13 +10566,16 @@ function createVinylFactories(options) {
10510
10566
 
10511
10567
  // src/vinyl/VinylPlayer.ts
10512
10568
  import {
10513
- createDisposer as createDisposer19,
10569
+ createDisposer as createDisposer18,
10514
10570
  emptyRanges as emptyRanges3,
10515
10571
  equalDeep as equalDeep4,
10516
10572
  EventHostImpl as EventHostImpl18,
10573
+ getLogLevel as getLogLevel2,
10517
10574
  logDebug as logDebug18,
10518
- logInfo as logInfo4,
10519
- logWarn as logWarn7,
10575
+ logInfo as logInfo3,
10576
+ LogLevel as LogLevel3,
10577
+ logVerbose as logVerbose5,
10578
+ logWarn as logWarn6,
10520
10579
  redispatchEvents as redispatchEvents4
10521
10580
  } from "@amazon/vinyl-util";
10522
10581
  import {
@@ -10539,7 +10598,7 @@ var VinylPlayer = class extends EventHostImpl18 {
10539
10598
  */
10540
10599
  __publicField(this, "client");
10541
10600
  __publicField(this, "_error", null);
10542
- __publicField(this, "disposer", /* @__PURE__ */ createDisposer19());
10601
+ __publicField(this, "disposer", /* @__PURE__ */ createDisposer18());
10543
10602
  const add = this.disposer.add;
10544
10603
  this.deps = add(createContainer3(factories)).dependencies;
10545
10604
  this.client = {
@@ -10548,6 +10607,7 @@ var VinylPlayer = class extends EventHostImpl18 {
10548
10607
  playerRegistryRef.value.addPlayer(this);
10549
10608
  this.redispatchSubControllerEvents();
10550
10609
  this.redispatchCurrentTrackEvents();
10610
+ this.initializeLoadSpanLogging();
10551
10611
  this.initializeAutoResetHandling();
10552
10612
  }
10553
10613
  get [Symbol.toStringTag]() {
@@ -10565,6 +10625,26 @@ var VinylPlayer = class extends EventHostImpl18 {
10565
10625
  get autoResetController() {
10566
10626
  return this.deps.autoResetController;
10567
10627
  }
10628
+ /**
10629
+ * Logs each republished load span once at the verbose level, formatting its
10630
+ * bounds as ISO date strings and its duration in milliseconds.
10631
+ */
10632
+ initializeLoadSpanLogging() {
10633
+ this.disposer.add(
10634
+ this.on("loadSpan", (span) => {
10635
+ if (getLogLevel2() > LogLevel3.VERBOSE) return;
10636
+ logVerbose5(this, "loadSpan", {
10637
+ kind: span.kind,
10638
+ trackUri: span.trackUri,
10639
+ mimeType: span.mimeType,
10640
+ contentType: span.contentType,
10641
+ startTime: new Date(span.startTime).toISOString(),
10642
+ endTime: new Date(span.endTime).toISOString(),
10643
+ durationMs: (span.endTime - span.startTime).toFixed(2)
10644
+ });
10645
+ })
10646
+ );
10647
+ }
10568
10648
  redispatchSubControllerEvents() {
10569
10649
  const add = this.disposer.add;
10570
10650
  add(
@@ -10597,7 +10677,7 @@ var VinylPlayer = class extends EventHostImpl18 {
10597
10677
  add(
10598
10678
  this.on("codecUnsupported", (event) => {
10599
10679
  if (this.deps.adController.currentAdBreak) return;
10600
- logWarn7(
10680
+ logWarn6(
10601
10681
  this,
10602
10682
  "codec unsupported, reloading track:",
10603
10683
  event.mimeType
@@ -11123,7 +11203,7 @@ var VinylPlayer = class extends EventHostImpl18 {
11123
11203
  };
11124
11204
  function createVinylPlayer(options, factoryOverrides) {
11125
11205
  const player = new VinylPlayer(__spreadValues(__spreadValues({}, createVinylFactories(options)), factoryOverrides));
11126
- logInfo4(player, `VinylPlayer initialized`);
11206
+ logInfo3(player, `VinylPlayer initialized`);
11127
11207
  return player;
11128
11208
  }
11129
11209
  function notResetEvent(type) {
@@ -11175,10 +11255,7 @@ export {
11175
11255
  LICENSE_TIMEOUT,
11176
11256
  LIVE_DURATION,
11177
11257
  LoudnessNormalizationControllerImpl,
11178
- MAX_UNCHANGED_COUNT,
11179
11258
  MIN_APPEND_SIZE,
11180
- MIN_PLAYING_BEFORE_FAB,
11181
- MIN_STALLED_BEFORE_FAB,
11182
11259
  ManifestControllerImpl,
11183
11260
  MediaKeySessionErrorType,
11184
11261
  MediaSourceControllerImpl,
@@ -11188,7 +11265,6 @@ export {
11188
11265
  MsCommonMediaKeySystemAccess,
11189
11266
  MsCommonMediaKeys,
11190
11267
  MseTrack,
11191
- PLAYHEAD_NUDGE,
11192
11268
  PLAY_READY_KEY_SYSTEMS,
11193
11269
  POLL_BUFFER_THROTTLE,
11194
11270
  PREFETCH_POLL_THROTTLE,
@@ -11203,7 +11279,6 @@ export {
11203
11279
  READY_TO_APPEND_TIMEOUT,
11204
11280
  RESTRICTABLE_CONTENT_TYPES,
11205
11281
  ReportableMediaError,
11206
- SEEKING_STALL_TIME_CHECK,
11207
11282
  SEGMENT_START_AFFORDANCE,
11208
11283
  SegmentControllerImpl,
11209
11284
  SegmentDataSlot,
@@ -11214,6 +11289,7 @@ export {
11214
11289
  SourceObjectTrack,
11215
11290
  SourceTrack,
11216
11291
  SourceTrackBase,
11292
+ StallEndedReason,
11217
11293
  StandardCommonEme,
11218
11294
  StandardCommonMediaKeySession,
11219
11295
  StandardCommonMediaKeySystemAccess,
@@ -11221,7 +11297,6 @@ export {
11221
11297
  TIMEUPDATE_THROTTLE,
11222
11298
  TrackBase,
11223
11299
  TrackControllerImpl,
11224
- UNRELIABLE_EVENTS_POLL_INTERVAL,
11225
11300
  UnresolvableAdError,
11226
11301
  VinylGlobal,
11227
11302
  VinylPlayer,
@@ -11283,14 +11358,14 @@ export {
11283
11358
  createMediaQualityMetadataFromDashRepresentation,
11284
11359
  createMediaSource,
11285
11360
  createMediaTextTrackProvider,
11286
- createPreventStallsPatch,
11287
11361
  createSegmentControllerFactory,
11288
11362
  createSegmentDataProvider,
11289
11363
  createSourceObjectTrackFactory,
11290
11364
  createSourceTrackFactory,
11365
+ createStallDetector,
11366
+ createStallMonitor,
11291
11367
  createTrackFactory,
11292
11368
  createTrackLoadOptionsFromUrl,
11293
- createUnreliablePlaybackEventsPatch,
11294
11369
  createUrlHlsManifestProvider,
11295
11370
  createVinylFactories,
11296
11371
  createVinylPlayer,
@@ -11301,8 +11376,6 @@ export {
11301
11376
  defaultDrmKeySystemResolver,
11302
11377
  defaultLicenseProvider,
11303
11378
  defaultLoudnessNormalizationControllerImplOptions,
11304
- defaultMediaElementPatchOptions,
11305
- defaultPatchOptions,
11306
11379
  defaultPlaybackControllerImplOptions,
11307
11380
  defaultQualitySelectorImplOptions,
11308
11381
  defaultResetControllerOptions,
@@ -11372,6 +11445,7 @@ export {
11372
11445
  mediaFormatMetadataValidator,
11373
11446
  mediaKeySupportRef,
11374
11447
  mediaQualityMetadataValidator,
11448
+ mimeSubtype,
11375
11449
  msErrorCodeToStr,
11376
11450
  nextHasMetadata,
11377
11451
  nextMediaSourceEnded,
@@ -11382,7 +11456,6 @@ export {
11382
11456
  parseCencEncryptionScheme,
11383
11457
  parsePlayReadyKeyMessage,
11384
11458
  parseWebVtt,
11385
- patchMediaElement,
11386
11459
  pickFirstBaseUrlSelector,
11387
11460
  pickPreferredTextTrack,
11388
11461
  playbackStateLoggingHandler,
@@ -11392,8 +11465,6 @@ export {
11392
11465
  prefetchPriorityQueuesRef,
11393
11466
  qualitySelectorImplOptionsValidator,
11394
11467
  renderCueText,
11395
- requiresPreventStallsPatch,
11396
- requiresUnreliablePlaybackEventsPatch,
11397
11468
  resolveCodecOverride,
11398
11469
  resolveDashUri,
11399
11470
  resolvePreferredLanguages,
@@ -11404,7 +11475,6 @@ export {
11404
11475
  sortDashAdaptationSets,
11405
11476
  sortDashRepresentations,
11406
11477
  sourceTrackBaseOptionsValidator,
11407
- supportsAudioSamplingRate,
11408
11478
  supportsMsEme,
11409
11479
  supportsMse,
11410
11480
  supportsStandardEme,
@@ -11425,6 +11495,7 @@ export {
11425
11495
  vinylVersion,
11426
11496
  vttCueStyleValidator,
11427
11497
  waitedReasons,
11428
- webkitErrorCodeToStr
11498
+ webkitErrorCodeToStr,
11499
+ withinAudioSampleRateRange
11429
11500
  };
11430
11501
  //# sourceMappingURL=index.js.map