@amazon/vinyl 1.2.0 → 1.2.2
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.
- package/dist/index.cjs +24 -6
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +33 -13
- package/dist/index.js.map +3 -3
- package/dist/test/integ.es5.js +62 -62
- package/dist/test/integ.js +119 -6
- package/dist/test/integ.js.map +2 -2
- package/dist/types/current/ad/AdBreakInfo.d.ts +160 -0
- package/dist/types/current/ad/AdBreakInfo.d.ts.map +1 -0
- package/dist/types/current/ad/AdBreakInfo.js +5 -0
- package/dist/types/current/ad/AdController.d.ts +229 -0
- package/dist/types/current/ad/AdController.d.ts.map +1 -0
- package/dist/types/current/ad/AdController.js +19 -0
- package/dist/types/current/ad/AdControllerImpl.d.ts +162 -0
- package/dist/types/current/ad/AdControllerImpl.d.ts.map +1 -0
- package/dist/types/current/ad/AdControllerImpl.js +741 -0
- package/dist/types/current/ad/AdError.d.ts +6 -0
- package/dist/types/current/ad/AdError.d.ts.map +1 -0
- package/dist/types/current/ad/AdError.js +14 -0
- package/dist/types/current/ad/AdsProvider.d.ts +28 -0
- package/dist/types/current/ad/AdsProvider.d.ts.map +1 -0
- package/dist/types/current/ad/AdsProvider.js +5 -0
- package/dist/types/current/ad/defaultAdLoadOptionsResolver.d.ts +12 -0
- package/dist/types/current/ad/defaultAdLoadOptionsResolver.d.ts.map +1 -0
- package/dist/types/current/ad/defaultAdLoadOptionsResolver.js +26 -0
- package/dist/types/current/ad/discoverHlsInterstitials.d.ts +22 -0
- package/dist/types/current/ad/discoverHlsInterstitials.d.ts.map +1 -0
- package/dist/types/current/ad/discoverHlsInterstitials.js +248 -0
- package/dist/types/current/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/current/drm/DrmControllerImpl.d.ts.map +1 -1
- package/dist/types/current/drm/DrmControllerImpl.js +23 -1
- package/dist/types/current/playback/PlaybackControllerImpl.d.ts +1 -1
- package/dist/types/current/playback/createStallDetector.d.ts +43 -0
- package/dist/types/current/playback/createStallDetector.d.ts.map +1 -0
- package/dist/types/current/playback/createStallDetector.js +101 -0
- package/dist/types/current/playback/createStallMonitor.d.ts +45 -0
- package/dist/types/current/playback/createStallMonitor.d.ts.map +1 -0
- package/dist/types/current/playback/createStallMonitor.js +99 -0
- package/dist/types/current/streaming/AudioOptions.d.ts +66 -0
- package/dist/types/current/streaming/AudioOptions.d.ts.map +1 -0
- package/dist/types/current/streaming/AudioOptions.js +19 -0
- package/dist/types/current/streaming/LoadMetric.d.ts +72 -0
- package/dist/types/current/streaming/LoadMetric.d.ts.map +1 -0
- package/dist/types/current/streaming/LoadMetric.js +5 -0
- package/dist/types/current/streaming/ManifestControllerImpl.d.ts +43 -0
- package/dist/types/current/streaming/ManifestControllerImpl.d.ts.map +1 -0
- package/dist/types/current/streaming/ManifestControllerImpl.js +104 -0
- package/dist/types/current/streaming/buffering/codecDenylist.d.ts +23 -0
- package/dist/types/current/streaming/buffering/codecDenylist.d.ts.map +1 -0
- package/dist/types/current/streaming/buffering/codecDenylist.js +62 -0
- package/dist/types/current/streaming/createAllowedContentTypesValue.d.ts +30 -0
- package/dist/types/current/streaming/createAllowedContentTypesValue.d.ts.map +1 -0
- package/dist/types/current/streaming/createAllowedContentTypesValue.js +43 -0
- package/dist/types/current/streaming/createTimelineContentTypesValue.d.ts +21 -0
- package/dist/types/current/streaming/createTimelineContentTypesValue.d.ts.map +1 -0
- package/dist/types/current/streaming/createTimelineContentTypesValue.js +25 -0
- package/dist/types/current/streaming/mediaTimelineAccessibilityFilter.d.ts +35 -0
- package/dist/types/current/streaming/mediaTimelineAccessibilityFilter.d.ts.map +1 -0
- package/dist/types/current/streaming/mediaTimelineAccessibilityFilter.js +75 -0
- package/dist/types/current/text/HtmlTextTrackRenderer.d.ts +60 -0
- package/dist/types/current/text/HtmlTextTrackRenderer.d.ts.map +1 -0
- package/dist/types/current/text/HtmlTextTrackRenderer.js +231 -0
- package/dist/types/current/text/SidecarTextTrackController.d.ts +103 -0
- package/dist/types/current/text/SidecarTextTrackController.d.ts.map +1 -0
- package/dist/types/current/text/SidecarTextTrackController.js +250 -0
- package/dist/types/current/text/SidecarTextTrackLoader.d.ts +65 -0
- package/dist/types/current/text/SidecarTextTrackLoader.d.ts.map +1 -0
- package/dist/types/current/text/SidecarTextTrackLoader.js +150 -0
- package/dist/types/current/text/TextTrack.d.ts +179 -0
- package/dist/types/current/text/TextTrack.d.ts.map +1 -0
- package/dist/types/current/text/TextTrack.js +29 -0
- package/dist/types/current/text/TextTrackRenderer.d.ts +24 -0
- package/dist/types/current/text/TextTrackRenderer.d.ts.map +1 -0
- package/dist/types/current/text/TextTrackRenderer.js +5 -0
- package/dist/types/current/text/VttCueStyle.d.ts +41 -0
- package/dist/types/current/text/VttCueStyle.d.ts.map +1 -0
- package/dist/types/current/text/VttCueStyle.js +45 -0
- package/dist/types/current/text/discoverDashTextTracks.d.ts +24 -0
- package/dist/types/current/text/discoverDashTextTracks.d.ts.map +1 -0
- package/dist/types/current/text/discoverDashTextTracks.js +110 -0
- package/dist/types/current/text/discoverHlsTextTracks.d.ts +19 -0
- package/dist/types/current/text/discoverHlsTextTracks.d.ts.map +1 -0
- package/dist/types/current/text/discoverHlsTextTracks.js +49 -0
- package/dist/types/current/text/mediaTextTrackProvider.d.ts +34 -0
- package/dist/types/current/text/mediaTextTrackProvider.d.ts.map +1 -0
- package/dist/types/current/text/mediaTextTrackProvider.js +42 -0
- package/dist/types/current/text/parseWebVtt.d.ts +60 -0
- package/dist/types/current/text/parseWebVtt.d.ts.map +1 -0
- package/dist/types/current/text/parseWebVtt.js +249 -0
- package/dist/types/current/text/pickPreferredTextTrack.d.ts +15 -0
- package/dist/types/current/text/pickPreferredTextTrack.d.ts.map +1 -0
- package/dist/types/current/text/pickPreferredTextTrack.js +71 -0
- package/dist/types/current/track/SeekRange.d.ts +9 -0
- package/dist/types/current/track/SeekRange.d.ts.map +1 -0
- package/dist/types/current/track/SeekRange.js +5 -0
- package/dist/types/current/track/hls/HlsManifestData.d.ts +19 -0
- package/dist/types/current/track/hls/HlsManifestData.d.ts.map +1 -0
- package/dist/types/current/track/hls/HlsManifestData.js +5 -0
- package/dist/types/current/track/hls/createHlsManifestProvider.d.ts +6 -0
- package/dist/types/current/track/hls/createHlsManifestProvider.d.ts.map +1 -0
- package/dist/types/current/track/hls/createHlsManifestProvider.js +9 -0
- package/dist/types/current/track/inferLoadOptionsFromUri.d.ts +15 -0
- package/dist/types/current/track/inferLoadOptionsFromUri.d.ts.map +1 -0
- package/dist/types/current/track/inferLoadOptionsFromUri.js +55 -0
- package/dist/types/current/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/current/track/mse/MseTrack.d.ts.map +1 -1
- package/dist/types/current/track/mse/MseTrack.js +4 -5
- package/dist/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/types/current/util/media/codecOverrides.d.ts +33 -0
- package/dist/types/current/util/media/codecOverrides.d.ts.map +1 -0
- package/dist/types/current/util/media/codecOverrides.js +37 -0
- package/dist/types/current/util/media/codecSupport.d.ts +6 -0
- package/dist/types/current/util/media/codecSupport.d.ts.map +1 -0
- package/dist/types/current/util/media/codecSupport.js +17 -0
- package/dist/types/current/util/media/mimeType.d.ts +8 -0
- package/dist/types/current/util/media/mimeType.d.ts.map +1 -0
- package/dist/types/current/util/media/mimeType.js +13 -0
- package/dist/types/ts3.7/ad/AdBreakInfo.d.ts +160 -0
- package/dist/types/ts3.7/ad/AdController.d.ts +243 -0
- package/dist/types/ts3.7/ad/AdControllerImpl.d.ts +162 -0
- package/dist/types/ts3.7/ad/AdError.d.ts +6 -0
- package/dist/types/ts3.7/ad/AdsProvider.d.ts +28 -0
- package/dist/types/ts3.7/ad/defaultAdLoadOptionsResolver.d.ts +12 -0
- package/dist/types/ts3.7/ad/discoverHlsInterstitials.d.ts +22 -0
- package/dist/types/ts3.7/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts3.7/playback/PlaybackControllerImpl.d.ts +1 -1
- package/dist/types/ts3.7/playback/createStallDetector.d.ts +43 -0
- package/dist/types/ts3.7/playback/createStallMonitor.d.ts +45 -0
- package/dist/types/ts3.7/streaming/AudioOptions.d.ts +66 -0
- package/dist/types/ts3.7/streaming/LoadMetric.d.ts +72 -0
- package/dist/types/ts3.7/streaming/ManifestControllerImpl.d.ts +40 -0
- package/dist/types/ts3.7/streaming/buffering/codecDenylist.d.ts +23 -0
- package/dist/types/ts3.7/streaming/createAllowedContentTypesValue.d.ts +30 -0
- package/dist/types/ts3.7/streaming/createTimelineContentTypesValue.d.ts +21 -0
- package/dist/types/ts3.7/streaming/mediaTimelineAccessibilityFilter.d.ts +35 -0
- package/dist/types/ts3.7/text/HtmlTextTrackRenderer.d.ts +60 -0
- package/dist/types/ts3.7/text/SidecarTextTrackController.d.ts +103 -0
- package/dist/types/ts3.7/text/SidecarTextTrackLoader.d.ts +65 -0
- package/dist/types/ts3.7/text/TextTrack.d.ts +183 -0
- package/dist/types/ts3.7/text/TextTrackRenderer.d.ts +24 -0
- package/dist/types/ts3.7/text/VttCueStyle.d.ts +41 -0
- package/dist/types/ts3.7/text/discoverDashTextTracks.d.ts +24 -0
- package/dist/types/ts3.7/text/discoverHlsTextTracks.d.ts +19 -0
- package/dist/types/ts3.7/text/mediaTextTrackProvider.d.ts +34 -0
- package/dist/types/ts3.7/text/parseWebVtt.d.ts +60 -0
- package/dist/types/ts3.7/text/pickPreferredTextTrack.d.ts +15 -0
- package/dist/types/ts3.7/track/SeekRange.d.ts +9 -0
- package/dist/types/ts3.7/track/hls/HlsManifestData.d.ts +19 -0
- package/dist/types/ts3.7/track/hls/createHlsManifestProvider.d.ts +6 -0
- package/dist/types/ts3.7/track/inferLoadOptionsFromUri.d.ts +15 -0
- package/dist/types/ts3.7/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/ts3.7/util/media/codecOverrides.d.ts +33 -0
- package/dist/types/ts3.7/util/media/codecSupport.d.ts +6 -0
- package/dist/types/ts3.7/util/media/mimeType.d.ts +8 -0
- package/dist/types/ts4.1/ad/AdBreakInfo.d.ts +160 -0
- package/dist/types/ts4.1/ad/AdController.d.ts +243 -0
- package/dist/types/ts4.1/ad/AdControllerImpl.d.ts +162 -0
- package/dist/types/ts4.1/ad/AdError.d.ts +6 -0
- package/dist/types/ts4.1/ad/AdsProvider.d.ts +28 -0
- package/dist/types/ts4.1/ad/defaultAdLoadOptionsResolver.d.ts +12 -0
- package/dist/types/ts4.1/ad/discoverHlsInterstitials.d.ts +22 -0
- package/dist/types/ts4.1/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts4.1/playback/PlaybackControllerImpl.d.ts +1 -1
- package/dist/types/ts4.1/playback/createStallDetector.d.ts +43 -0
- package/dist/types/ts4.1/playback/createStallMonitor.d.ts +45 -0
- package/dist/types/ts4.1/streaming/AudioOptions.d.ts +66 -0
- package/dist/types/ts4.1/streaming/LoadMetric.d.ts +72 -0
- package/dist/types/ts4.1/streaming/ManifestControllerImpl.d.ts +40 -0
- package/dist/types/ts4.1/streaming/buffering/codecDenylist.d.ts +23 -0
- package/dist/types/ts4.1/streaming/createAllowedContentTypesValue.d.ts +30 -0
- package/dist/types/ts4.1/streaming/createTimelineContentTypesValue.d.ts +21 -0
- package/dist/types/ts4.1/streaming/mediaTimelineAccessibilityFilter.d.ts +35 -0
- package/dist/types/ts4.1/text/HtmlTextTrackRenderer.d.ts +60 -0
- package/dist/types/ts4.1/text/SidecarTextTrackController.d.ts +104 -0
- package/dist/types/ts4.1/text/SidecarTextTrackLoader.d.ts +65 -0
- package/dist/types/ts4.1/text/TextTrack.d.ts +183 -0
- package/dist/types/ts4.1/text/TextTrackRenderer.d.ts +24 -0
- package/dist/types/ts4.1/text/VttCueStyle.d.ts +41 -0
- package/dist/types/ts4.1/text/discoverDashTextTracks.d.ts +24 -0
- package/dist/types/ts4.1/text/discoverHlsTextTracks.d.ts +19 -0
- package/dist/types/ts4.1/text/mediaTextTrackProvider.d.ts +34 -0
- package/dist/types/ts4.1/text/parseWebVtt.d.ts +60 -0
- package/dist/types/ts4.1/text/pickPreferredTextTrack.d.ts +15 -0
- package/dist/types/ts4.1/track/SeekRange.d.ts +9 -0
- package/dist/types/ts4.1/track/hls/HlsManifestData.d.ts +19 -0
- package/dist/types/ts4.1/track/hls/createHlsManifestProvider.d.ts +6 -0
- package/dist/types/ts4.1/track/inferLoadOptionsFromUri.d.ts +15 -0
- package/dist/types/ts4.1/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/ts4.1/util/media/codecOverrides.d.ts +33 -0
- package/dist/types/ts4.1/util/media/codecSupport.d.ts +6 -0
- package/dist/types/ts4.1/util/media/mimeType.d.ts +8 -0
- package/dist/types/ts4.7/ad/AdBreakInfo.d.ts +160 -0
- package/dist/types/ts4.7/ad/AdController.d.ts +243 -0
- package/dist/types/ts4.7/ad/AdControllerImpl.d.ts +162 -0
- package/dist/types/ts4.7/ad/AdError.d.ts +6 -0
- package/dist/types/ts4.7/ad/AdsProvider.d.ts +28 -0
- package/dist/types/ts4.7/ad/defaultAdLoadOptionsResolver.d.ts +12 -0
- package/dist/types/ts4.7/ad/discoverHlsInterstitials.d.ts +22 -0
- package/dist/types/ts4.7/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts4.7/playback/PlaybackControllerImpl.d.ts +1 -1
- package/dist/types/ts4.7/playback/createStallDetector.d.ts +43 -0
- package/dist/types/ts4.7/playback/createStallMonitor.d.ts +45 -0
- package/dist/types/ts4.7/streaming/AudioOptions.d.ts +66 -0
- package/dist/types/ts4.7/streaming/LoadMetric.d.ts +72 -0
- package/dist/types/ts4.7/streaming/ManifestControllerImpl.d.ts +43 -0
- package/dist/types/ts4.7/streaming/buffering/codecDenylist.d.ts +23 -0
- package/dist/types/ts4.7/streaming/createAllowedContentTypesValue.d.ts +30 -0
- package/dist/types/ts4.7/streaming/createTimelineContentTypesValue.d.ts +21 -0
- package/dist/types/ts4.7/streaming/mediaTimelineAccessibilityFilter.d.ts +35 -0
- package/dist/types/ts4.7/text/HtmlTextTrackRenderer.d.ts +60 -0
- package/dist/types/ts4.7/text/SidecarTextTrackController.d.ts +103 -0
- package/dist/types/ts4.7/text/SidecarTextTrackLoader.d.ts +65 -0
- package/dist/types/ts4.7/text/TextTrack.d.ts +183 -0
- package/dist/types/ts4.7/text/TextTrackRenderer.d.ts +24 -0
- package/dist/types/ts4.7/text/VttCueStyle.d.ts +41 -0
- package/dist/types/ts4.7/text/discoverDashTextTracks.d.ts +24 -0
- package/dist/types/ts4.7/text/discoverHlsTextTracks.d.ts +19 -0
- package/dist/types/ts4.7/text/mediaTextTrackProvider.d.ts +34 -0
- package/dist/types/ts4.7/text/parseWebVtt.d.ts +60 -0
- package/dist/types/ts4.7/text/pickPreferredTextTrack.d.ts +15 -0
- package/dist/types/ts4.7/track/SeekRange.d.ts +9 -0
- package/dist/types/ts4.7/track/hls/HlsManifestData.d.ts +19 -0
- package/dist/types/ts4.7/track/hls/createHlsManifestProvider.d.ts +6 -0
- package/dist/types/ts4.7/track/inferLoadOptionsFromUri.d.ts +15 -0
- package/dist/types/ts4.7/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/ts4.7/util/media/codecOverrides.d.ts +33 -0
- package/dist/types/ts4.7/util/media/codecSupport.d.ts +6 -0
- package/dist/types/ts4.7/util/media/mimeType.d.ts +8 -0
- package/dist/unit/types/current/ad/AdController.test.d.ts +2 -0
- package/dist/unit/types/current/ad/AdController.test.d.ts.map +1 -0
- package/dist/unit/types/current/ad/AdController.test.js +10 -0
- package/dist/unit/types/current/ad/AdControllerImpl.test.d.ts +2 -0
- package/dist/unit/types/current/ad/AdControllerImpl.test.d.ts.map +1 -0
- package/dist/unit/types/current/ad/AdControllerImpl.test.js +1654 -0
- package/dist/unit/types/current/ad/defaultAdLoadOptionsResolver.test.d.ts +2 -0
- package/dist/unit/types/current/ad/defaultAdLoadOptionsResolver.test.d.ts.map +1 -0
- package/dist/unit/types/current/ad/defaultAdLoadOptionsResolver.test.js +56 -0
- package/dist/unit/types/current/ad/discoverHlsInterstitials.test.d.ts +2 -0
- package/dist/unit/types/current/ad/discoverHlsInterstitials.test.d.ts.map +1 -0
- package/dist/unit/types/current/ad/discoverHlsInterstitials.test.js +757 -0
- package/dist/unit/types/current/drm/DrmControllerImpl.test.js +96 -2
- package/dist/unit/types/current/playback/createStallDetector.test.d.ts +2 -0
- package/dist/unit/types/current/playback/createStallDetector.test.d.ts.map +1 -0
- package/dist/unit/types/current/playback/createStallDetector.test.js +163 -0
- package/dist/unit/types/current/playback/createStallMonitor.test.d.ts +2 -0
- package/dist/unit/types/current/playback/createStallMonitor.test.d.ts.map +1 -0
- package/dist/unit/types/current/playback/createStallMonitor.test.js +163 -0
- package/dist/unit/types/current/streaming/ManifestControllerImpl.test.d.ts +2 -0
- package/dist/unit/types/current/streaming/ManifestControllerImpl.test.d.ts.map +1 -0
- package/dist/unit/types/current/streaming/ManifestControllerImpl.test.js +197 -0
- package/dist/unit/types/current/streaming/MseTrack.test.js +15 -0
- package/dist/unit/types/current/streaming/buffering/codecDenylist.test.d.ts +2 -0
- package/dist/unit/types/current/streaming/buffering/codecDenylist.test.d.ts.map +1 -0
- package/dist/unit/types/current/streaming/buffering/codecDenylist.test.js +56 -0
- package/dist/unit/types/current/streaming/createAllowedContentTypesValue.test.d.ts +2 -0
- package/dist/unit/types/current/streaming/createAllowedContentTypesValue.test.d.ts.map +1 -0
- package/dist/unit/types/current/streaming/createAllowedContentTypesValue.test.js +77 -0
- package/dist/unit/types/current/streaming/createTimelineContentTypesValue.test.d.ts +2 -0
- package/dist/unit/types/current/streaming/createTimelineContentTypesValue.test.d.ts.map +1 -0
- package/dist/unit/types/current/streaming/createTimelineContentTypesValue.test.js +57 -0
- package/dist/unit/types/current/streaming/mediaTimelineAccessibilityFilter.test.d.ts +2 -0
- package/dist/unit/types/current/streaming/mediaTimelineAccessibilityFilter.test.d.ts.map +1 -0
- package/dist/unit/types/current/streaming/mediaTimelineAccessibilityFilter.test.js +99 -0
- package/dist/unit/types/current/text/HtmlTextTrackRenderer.test.d.ts +2 -0
- package/dist/unit/types/current/text/HtmlTextTrackRenderer.test.d.ts.map +1 -0
- package/dist/unit/types/current/text/HtmlTextTrackRenderer.test.js +231 -0
- package/dist/unit/types/current/text/SidecarTextTrackController.test.d.ts +2 -0
- package/dist/unit/types/current/text/SidecarTextTrackController.test.d.ts.map +1 -0
- package/dist/unit/types/current/text/SidecarTextTrackController.test.js +686 -0
- package/dist/unit/types/current/text/SidecarTextTrackLoader.test.d.ts +2 -0
- package/dist/unit/types/current/text/SidecarTextTrackLoader.test.d.ts.map +1 -0
- package/dist/unit/types/current/text/SidecarTextTrackLoader.test.js +365 -0
- package/dist/unit/types/current/text/TextTrack.test.d.ts +2 -0
- package/dist/unit/types/current/text/TextTrack.test.d.ts.map +1 -0
- package/dist/unit/types/current/text/TextTrack.test.js +12 -0
- package/dist/unit/types/current/text/VttCueStyle.test.d.ts +2 -0
- package/dist/unit/types/current/text/VttCueStyle.test.d.ts.map +1 -0
- package/dist/unit/types/current/text/VttCueStyle.test.js +76 -0
- package/dist/unit/types/current/text/discoverDashTextTracks.test.d.ts +2 -0
- package/dist/unit/types/current/text/discoverDashTextTracks.test.d.ts.map +1 -0
- package/dist/unit/types/current/text/discoverDashTextTracks.test.js +216 -0
- package/dist/unit/types/current/text/discoverHlsTextTracks.test.d.ts +2 -0
- package/dist/unit/types/current/text/discoverHlsTextTracks.test.d.ts.map +1 -0
- package/dist/unit/types/current/text/discoverHlsTextTracks.test.js +177 -0
- package/dist/unit/types/current/text/mediaTextTrackProvider.test.d.ts +2 -0
- package/dist/unit/types/current/text/mediaTextTrackProvider.test.d.ts.map +1 -0
- package/dist/unit/types/current/text/mediaTextTrackProvider.test.js +86 -0
- package/dist/unit/types/current/text/parseWebVtt.test.d.ts +2 -0
- package/dist/unit/types/current/text/parseWebVtt.test.d.ts.map +1 -0
- package/dist/unit/types/current/text/parseWebVtt.test.js +419 -0
- package/dist/unit/types/current/text/pickPreferredTextTrack.test.d.ts +2 -0
- package/dist/unit/types/current/text/pickPreferredTextTrack.test.d.ts.map +1 -0
- package/dist/unit/types/current/text/pickPreferredTextTrack.test.js +78 -0
- package/dist/unit/types/current/track/inferLoadOptionsFromUri.test.d.ts +2 -0
- package/dist/unit/types/current/track/inferLoadOptionsFromUri.test.d.ts.map +1 -0
- package/dist/unit/types/current/track/inferLoadOptionsFromUri.test.js +165 -0
- package/dist/unit/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/unit/types/current/util/media/codecOverrides.test.d.ts +2 -0
- package/dist/unit/types/current/util/media/codecOverrides.test.d.ts.map +1 -0
- package/dist/unit/types/current/util/media/codecOverrides.test.js +42 -0
- package/dist/unit/types/current/util/media/codecSupport.test.d.ts +2 -0
- package/dist/unit/types/current/util/media/codecSupport.test.d.ts.map +1 -0
- package/dist/unit/types/current/util/media/codecSupport.test.js +26 -0
- package/dist/unit/types/current/util/media/mimeType.test.d.ts +2 -0
- package/dist/unit/types/current/util/media/mimeType.test.d.ts.map +1 -0
- package/dist/unit/types/current/util/media/mimeType.test.js +22 -0
- package/dist/unit/types/current/vinyl/VinylPlayerAdBreaks.test.d.ts +2 -0
- package/dist/unit/types/current/vinyl/VinylPlayerAdBreaks.test.d.ts.map +1 -0
- package/dist/unit/types/current/vinyl/VinylPlayerAdBreaks.test.js +142 -0
- package/dist/unit/types/current/vinyl/VinylPlayerTextTracks.test.d.ts +2 -0
- package/dist/unit/types/current/vinyl/VinylPlayerTextTracks.test.d.ts.map +1 -0
- package/dist/unit/types/current/vinyl/VinylPlayerTextTracks.test.js +188 -0
- package/dist/vinylTestUtil/types/current/mock/ad/MockAdController.d.ts +15 -0
- package/dist/vinylTestUtil/types/current/mock/ad/MockAdController.d.ts.map +1 -0
- package/dist/vinylTestUtil/types/current/mock/ad/MockAdController.js +26 -0
- package/dist/vinylTestUtil/types/current/mock/dash/mockDashManifest.d.ts +84 -84
- package/dist/vinylTestUtil/types/current/mock/text/MockTextTrackController.d.ts +10 -0
- package/dist/vinylTestUtil/types/current/mock/text/MockTextTrackController.d.ts.map +1 -0
- package/dist/vinylTestUtil/types/current/mock/text/MockTextTrackController.js +14 -0
- package/dist/vinylTestUtil/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/vinylTestUtil/types/ts3.7/mock/ad/MockAdController.d.ts +15 -0
- package/dist/vinylTestUtil/types/ts3.7/mock/dash/mockDashManifest.d.ts +84 -84
- package/dist/vinylTestUtil/types/ts3.7/mock/text/MockTextTrackController.d.ts +10 -0
- package/dist/vinylTestUtil/types/ts4.1/mock/ad/MockAdController.d.ts +15 -0
- package/dist/vinylTestUtil/types/ts4.1/mock/dash/mockDashManifest.d.ts +84 -84
- package/dist/vinylTestUtil/types/ts4.1/mock/text/MockTextTrackController.d.ts +10 -0
- package/dist/vinylTestUtil/types/ts4.7/mock/ad/MockAdController.d.ts +15 -0
- package/dist/vinylTestUtil/types/ts4.7/mock/dash/mockDashManifest.d.ts +84 -84
- package/dist/vinylTestUtil/types/ts4.7/mock/text/MockTextTrackController.d.ts +10 -0
- package/package.json +10 -11
|
@@ -0,0 +1,757 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { discoverHlsInterstitials } from '@amazon/vinyl';
|
|
6
|
+
import { resolveValueProvider } from '@amazon/vinyl-util';
|
|
7
|
+
describe('discoverHlsInterstitials', () => {
|
|
8
|
+
const BASE = 'https://cdn.example.com/media/index.m3u8';
|
|
9
|
+
const INTERSTITIAL = 'com.apple.hls.interstitial';
|
|
10
|
+
function makePlaylist(overrides = {}) {
|
|
11
|
+
return {
|
|
12
|
+
version: 7,
|
|
13
|
+
targetDuration: 6,
|
|
14
|
+
mediaSequence: 0,
|
|
15
|
+
playlistType: 'VOD',
|
|
16
|
+
ended: true,
|
|
17
|
+
segments: [],
|
|
18
|
+
dateRanges: [],
|
|
19
|
+
...overrides,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function makeRange(overrides = {}) {
|
|
23
|
+
return {
|
|
24
|
+
id: 'ad1',
|
|
25
|
+
classId: INTERSTITIAL,
|
|
26
|
+
startDate: '2024-01-01T00:00:00.000Z',
|
|
27
|
+
clientAttributes: {},
|
|
28
|
+
...overrides,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A minimal `fetch` Response stand-in that satisfies `requestWithRetry`
|
|
33
|
+
* (which reads `ok`/`status`/`headers` and rejects on non-ok responses).
|
|
34
|
+
*/
|
|
35
|
+
function okJsonResponse(body) {
|
|
36
|
+
return {
|
|
37
|
+
ok: true,
|
|
38
|
+
status: 200,
|
|
39
|
+
headers: { get: () => null },
|
|
40
|
+
json: () => Promise.resolve(body),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
it('returns empty when there are no date ranges', async () => {
|
|
44
|
+
expect(await discoverHlsInterstitials(makePlaylist(), BASE)).toEqual([]);
|
|
45
|
+
});
|
|
46
|
+
it('ignores non-interstitial date ranges', async () => {
|
|
47
|
+
const playlist = makePlaylist({
|
|
48
|
+
dateRanges: [makeRange({ classId: 'com.example.other' })],
|
|
49
|
+
});
|
|
50
|
+
expect(await discoverHlsInterstitials(playlist, BASE)).toEqual([]);
|
|
51
|
+
});
|
|
52
|
+
it('anchors a pre-roll to time 0 when no program-date-time exists', async () => {
|
|
53
|
+
const playlist = makePlaylist({
|
|
54
|
+
dateRanges: [makeRange({ duration: 15 })],
|
|
55
|
+
});
|
|
56
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
57
|
+
expect(breaks.length).toBe(1);
|
|
58
|
+
expect(breaks[0].startTime).toBe(0);
|
|
59
|
+
expect(breaks[0].duration).toBe(15);
|
|
60
|
+
expect(breaks[0].placement).toBe('preroll');
|
|
61
|
+
});
|
|
62
|
+
it('correlates START-DATE against EXT-X-PROGRAM-DATE-TIME for a mid-roll', async () => {
|
|
63
|
+
const playlist = makePlaylist({
|
|
64
|
+
segments: [
|
|
65
|
+
{
|
|
66
|
+
uri: 'seg0.ts',
|
|
67
|
+
duration: 10,
|
|
68
|
+
sequenceNumber: 0,
|
|
69
|
+
discontinuity: false,
|
|
70
|
+
programDateTime: '2024-01-01T00:00:00.000Z',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
uri: 'seg1.ts',
|
|
74
|
+
duration: 10,
|
|
75
|
+
sequenceNumber: 1,
|
|
76
|
+
discontinuity: false,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
dateRanges: [
|
|
80
|
+
makeRange({
|
|
81
|
+
startDate: '2024-01-01T00:00:12.000Z',
|
|
82
|
+
duration: 6,
|
|
83
|
+
}),
|
|
84
|
+
],
|
|
85
|
+
});
|
|
86
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE, 20);
|
|
87
|
+
expect(breaks[0].startTime).toBe(12);
|
|
88
|
+
expect(breaks[0].placement).toBe('midroll');
|
|
89
|
+
});
|
|
90
|
+
it('uses a later segment program-date-time as the anchor', async () => {
|
|
91
|
+
const playlist = makePlaylist({
|
|
92
|
+
segments: [
|
|
93
|
+
{
|
|
94
|
+
uri: 'seg0.ts',
|
|
95
|
+
duration: 10,
|
|
96
|
+
sequenceNumber: 0,
|
|
97
|
+
discontinuity: false,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
uri: 'seg1.ts',
|
|
101
|
+
duration: 10,
|
|
102
|
+
sequenceNumber: 1,
|
|
103
|
+
discontinuity: false,
|
|
104
|
+
// Anchor: media time 10 == this wall clock.
|
|
105
|
+
programDateTime: '2024-01-01T00:00:10.000Z',
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
dateRanges: [
|
|
109
|
+
makeRange({
|
|
110
|
+
startDate: '2024-01-01T00:00:15.000Z',
|
|
111
|
+
duration: 5,
|
|
112
|
+
}),
|
|
113
|
+
],
|
|
114
|
+
});
|
|
115
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE, 20);
|
|
116
|
+
// 10 (anchor media time) + (15 - 10) = 15
|
|
117
|
+
expect(breaks[0].startTime).toBe(15);
|
|
118
|
+
});
|
|
119
|
+
it('resolves duration from END-DATE when DURATION is absent', async () => {
|
|
120
|
+
const playlist = makePlaylist({
|
|
121
|
+
dateRanges: [
|
|
122
|
+
makeRange({
|
|
123
|
+
startDate: '2024-01-01T00:00:00.000Z',
|
|
124
|
+
endDate: '2024-01-01T00:00:08.000Z',
|
|
125
|
+
}),
|
|
126
|
+
],
|
|
127
|
+
});
|
|
128
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
129
|
+
expect(breaks[0].duration).toBe(8);
|
|
130
|
+
});
|
|
131
|
+
it('falls back to PLANNED-DURATION when neither DURATION nor END-DATE exist', async () => {
|
|
132
|
+
const playlist = makePlaylist({
|
|
133
|
+
dateRanges: [makeRange({ plannedDuration: 12 })],
|
|
134
|
+
});
|
|
135
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
136
|
+
expect(breaks[0].duration).toBe(12);
|
|
137
|
+
});
|
|
138
|
+
it('reports null duration when unresolvable', async () => {
|
|
139
|
+
const playlist = makePlaylist({ dateRanges: [makeRange()] });
|
|
140
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
141
|
+
expect(breaks[0].duration).toBeNull();
|
|
142
|
+
});
|
|
143
|
+
it('resolves X-ASSET-URI to an absolute ad URI', async () => {
|
|
144
|
+
const playlist = makePlaylist({
|
|
145
|
+
dateRanges: [
|
|
146
|
+
makeRange({
|
|
147
|
+
duration: 10,
|
|
148
|
+
clientAttributes: { 'X-ASSET-URI': '../ads/ad.m3u8' },
|
|
149
|
+
}),
|
|
150
|
+
],
|
|
151
|
+
});
|
|
152
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
153
|
+
const ads = await resolveValueProvider(breaks[0].ads);
|
|
154
|
+
expect(ads.length).toBe(1);
|
|
155
|
+
expect(ads[0].uri).toBe('https://cdn.example.com/ads/ad.m3u8');
|
|
156
|
+
expect(ads[0].startTime).toBe(0);
|
|
157
|
+
expect(ads[0].duration).toBe(10);
|
|
158
|
+
});
|
|
159
|
+
it('yields no ads for a break with neither X-ASSET-URI nor X-ASSET-LIST', async () => {
|
|
160
|
+
const playlist = makePlaylist({
|
|
161
|
+
dateRanges: [makeRange({ duration: 10 })],
|
|
162
|
+
});
|
|
163
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
164
|
+
expect(await resolveValueProvider(breaks[0].ads)).toEqual([]);
|
|
165
|
+
});
|
|
166
|
+
it('parses X-RESTRICT into typed restrict field', async () => {
|
|
167
|
+
const playlist = makePlaylist({
|
|
168
|
+
dateRanges: [
|
|
169
|
+
makeRange({
|
|
170
|
+
duration: 10,
|
|
171
|
+
clientAttributes: { 'X-RESTRICT': 'SKIP,JUMP' },
|
|
172
|
+
}),
|
|
173
|
+
],
|
|
174
|
+
});
|
|
175
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
176
|
+
expect(breaks[0].restrict).toEqual({ skip: true, jump: true });
|
|
177
|
+
});
|
|
178
|
+
it('resolves X-ASSET-LIST ads by fetching the list JSON', async () => {
|
|
179
|
+
const origFetch = globalThis.fetch;
|
|
180
|
+
const fetchSpy = jasmine.createSpy('fetch').and.resolveTo(okJsonResponse({
|
|
181
|
+
ASSETS: [
|
|
182
|
+
{ URI: 'mid1.m3u8', DURATION: 10 },
|
|
183
|
+
{ URI: 'https://cdn.example.com/mid2.m3u8' },
|
|
184
|
+
],
|
|
185
|
+
}));
|
|
186
|
+
globalThis.fetch = fetchSpy;
|
|
187
|
+
try {
|
|
188
|
+
const playlist = makePlaylist({
|
|
189
|
+
dateRanges: [
|
|
190
|
+
makeRange({
|
|
191
|
+
duration: 10,
|
|
192
|
+
clientAttributes: {
|
|
193
|
+
'X-ASSET-LIST': 'https://example.com/ads.json',
|
|
194
|
+
},
|
|
195
|
+
}),
|
|
196
|
+
],
|
|
197
|
+
});
|
|
198
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
199
|
+
const ads = await resolveValueProvider(breaks[0].ads);
|
|
200
|
+
expect(fetchSpy.calls.argsFor(0)[0]).toBe('https://example.com/ads.json');
|
|
201
|
+
expect(ads.length).toBe(2);
|
|
202
|
+
// Relative to the asset list, not to the media playlist.
|
|
203
|
+
expect(ads[0].uri).toBe('https://example.com/mid1.m3u8');
|
|
204
|
+
expect(ads[0].duration).toBe(10);
|
|
205
|
+
expect(ads[1].uri).toBe('https://cdn.example.com/mid2.m3u8');
|
|
206
|
+
expect(ads[1].duration).toBeNull();
|
|
207
|
+
}
|
|
208
|
+
finally {
|
|
209
|
+
globalThis.fetch = origFetch;
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
it('caches the X-ASSET-LIST fetch across calls', async () => {
|
|
213
|
+
const origFetch = globalThis.fetch;
|
|
214
|
+
const fetchSpy = jasmine
|
|
215
|
+
.createSpy('fetch')
|
|
216
|
+
.and.resolveTo(okJsonResponse({ ASSETS: [{ URI: 'x.m3u8' }] }));
|
|
217
|
+
globalThis.fetch = fetchSpy;
|
|
218
|
+
try {
|
|
219
|
+
const playlist = makePlaylist({
|
|
220
|
+
dateRanges: [
|
|
221
|
+
makeRange({
|
|
222
|
+
duration: 10,
|
|
223
|
+
clientAttributes: {
|
|
224
|
+
'X-ASSET-LIST': 'https://example.com/ads.json',
|
|
225
|
+
},
|
|
226
|
+
}),
|
|
227
|
+
],
|
|
228
|
+
});
|
|
229
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
230
|
+
const resolver = breaks[0].ads;
|
|
231
|
+
await resolveValueProvider(resolver);
|
|
232
|
+
await resolveValueProvider(resolver);
|
|
233
|
+
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
|
234
|
+
}
|
|
235
|
+
finally {
|
|
236
|
+
globalThis.fetch = origFetch;
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
/** Runs `body` with a stubbed global fetch returning `json`. */
|
|
240
|
+
async function withFetch(json, body) {
|
|
241
|
+
const origFetch = globalThis.fetch;
|
|
242
|
+
const fetchSpy = jasmine
|
|
243
|
+
.createSpy('fetch')
|
|
244
|
+
.and.resolveTo(okJsonResponse(json));
|
|
245
|
+
globalThis.fetch = fetchSpy;
|
|
246
|
+
try {
|
|
247
|
+
await body(fetchSpy);
|
|
248
|
+
}
|
|
249
|
+
finally {
|
|
250
|
+
globalThis.fetch = origFetch;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Distinct URLs per case so requestWithRetry's per-URL caching does not make
|
|
254
|
+
// one case's asset list bleed into the next within a single spec.
|
|
255
|
+
function assetListRange(url = 'https://example.com/ads.json') {
|
|
256
|
+
return makePlaylist({
|
|
257
|
+
dateRanges: [
|
|
258
|
+
makeRange({
|
|
259
|
+
duration: 10,
|
|
260
|
+
clientAttributes: { 'X-ASSET-LIST': url },
|
|
261
|
+
}),
|
|
262
|
+
],
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
it('parses the X-ASSET-LIST SKIP-CONTROL into a skip window', async () => {
|
|
266
|
+
await withFetch({
|
|
267
|
+
ASSETS: [{ URI: 'a.m3u8', DURATION: 10 }],
|
|
268
|
+
'SKIP-CONTROL': { OFFSET: 6, DURATION: 5 },
|
|
269
|
+
}, async () => {
|
|
270
|
+
const breaks = await discoverHlsInterstitials(assetListRange(), BASE);
|
|
271
|
+
expect(await resolveValueProvider(breaks[0].skipControl)).toEqual({ offset: 6, duration: 5 });
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
it('treats a SKIP-CONTROL without DURATION as open-ended', async () => {
|
|
275
|
+
await withFetch({
|
|
276
|
+
ASSETS: [{ URI: 'a.m3u8' }],
|
|
277
|
+
'SKIP-CONTROL': { OFFSET: 4 },
|
|
278
|
+
}, async () => {
|
|
279
|
+
const breaks = await discoverHlsInterstitials(assetListRange(), BASE);
|
|
280
|
+
expect(await resolveValueProvider(breaks[0].skipControl)).toEqual({ offset: 4, duration: null });
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
it('reports no skip window when SKIP-CONTROL is absent', async () => {
|
|
284
|
+
await withFetch({ ASSETS: [{ URI: 'a.m3u8' }] }, async () => {
|
|
285
|
+
const breaks = await discoverHlsInterstitials(assetListRange('https://example.com/absent.json'), BASE);
|
|
286
|
+
expect(await resolveValueProvider(breaks[0].skipControl)).toBeNull();
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
it('rejects a SKIP-CONTROL with a missing offset', async () => {
|
|
290
|
+
await withFetch({ ASSETS: [{ URI: 'a.m3u8' }], 'SKIP-CONTROL': { DURATION: 5 } }, async () => {
|
|
291
|
+
const breaks = await discoverHlsInterstitials(assetListRange('https://example.com/missing.json'), BASE);
|
|
292
|
+
expect(await resolveValueProvider(breaks[0].skipControl)).toBeNull();
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
it('rejects a SKIP-CONTROL with a negative offset', async () => {
|
|
296
|
+
await withFetch({ ASSETS: [{ URI: 'a.m3u8' }], 'SKIP-CONTROL': { OFFSET: -2 } }, async () => {
|
|
297
|
+
const breaks = await discoverHlsInterstitials(assetListRange('https://example.com/negative.json'), BASE);
|
|
298
|
+
expect(await resolveValueProvider(breaks[0].skipControl)).toBeNull();
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
it('reports no skip window for an inline X-ASSET-URI', async () => {
|
|
302
|
+
const playlist = makePlaylist({
|
|
303
|
+
dateRanges: [
|
|
304
|
+
makeRange({
|
|
305
|
+
duration: 10,
|
|
306
|
+
clientAttributes: { 'X-ASSET-URI': 'ad.m3u8' },
|
|
307
|
+
}),
|
|
308
|
+
],
|
|
309
|
+
});
|
|
310
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
311
|
+
expect(await resolveValueProvider(breaks[0].skipControl)).toBeNull();
|
|
312
|
+
});
|
|
313
|
+
it('shares one asset-list fetch between the ads and skip window', async () => {
|
|
314
|
+
await withFetch({
|
|
315
|
+
ASSETS: [{ URI: 'a.m3u8' }],
|
|
316
|
+
'SKIP-CONTROL': { OFFSET: 1 },
|
|
317
|
+
}, async (fetchSpy) => {
|
|
318
|
+
const breaks = await discoverHlsInterstitials(assetListRange(), BASE);
|
|
319
|
+
await resolveValueProvider(breaks[0].ads);
|
|
320
|
+
await resolveValueProvider(breaks[0].skipControl);
|
|
321
|
+
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
it('memoizes the X-ASSET-LIST resolution, including failures, within a discovery', async () => {
|
|
325
|
+
// The per-break ads resolver is memoized, so a failed asset-list fetch
|
|
326
|
+
// is cached for the lifetime of the discovered break (a fresh discovery
|
|
327
|
+
// re-fetches). This documents the shipped behavior.
|
|
328
|
+
const origFetch = globalThis.fetch;
|
|
329
|
+
const fetchSpy = jasmine
|
|
330
|
+
.createSpy('fetch')
|
|
331
|
+
.and.rejectWith(new Error('network'));
|
|
332
|
+
globalThis.fetch = fetchSpy;
|
|
333
|
+
try {
|
|
334
|
+
const playlist = makePlaylist({
|
|
335
|
+
dateRanges: [
|
|
336
|
+
makeRange({
|
|
337
|
+
duration: 10,
|
|
338
|
+
clientAttributes: {
|
|
339
|
+
'X-ASSET-LIST': 'https://example.com/ads.json',
|
|
340
|
+
},
|
|
341
|
+
}),
|
|
342
|
+
],
|
|
343
|
+
});
|
|
344
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
345
|
+
const resolver = breaks[0].ads;
|
|
346
|
+
await expectAsync(resolveValueProvider(resolver)).toBeRejected();
|
|
347
|
+
// The rejected resolution is memoized: a second call reuses the
|
|
348
|
+
// cached (rejected) result and does not fetch again.
|
|
349
|
+
const callsAfterFirst = fetchSpy.calls.count();
|
|
350
|
+
await expectAsync(resolveValueProvider(resolver)).toBeRejected();
|
|
351
|
+
expect(fetchSpy.calls.count()).toBe(callsAfterFirst);
|
|
352
|
+
}
|
|
353
|
+
finally {
|
|
354
|
+
globalThis.fetch = origFetch;
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
it('yields empty ads when X-ASSET-LIST JSON has no ASSETS', async () => {
|
|
358
|
+
const origFetch = globalThis.fetch;
|
|
359
|
+
globalThis.fetch = jasmine
|
|
360
|
+
.createSpy('fetch')
|
|
361
|
+
.and.resolveTo(okJsonResponse({}));
|
|
362
|
+
try {
|
|
363
|
+
const playlist = makePlaylist({
|
|
364
|
+
dateRanges: [
|
|
365
|
+
makeRange({
|
|
366
|
+
duration: 10,
|
|
367
|
+
clientAttributes: {
|
|
368
|
+
'X-ASSET-LIST': 'https://example.com/ads.json',
|
|
369
|
+
},
|
|
370
|
+
}),
|
|
371
|
+
],
|
|
372
|
+
});
|
|
373
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
374
|
+
expect(await resolveValueProvider(breaks[0].ads)).toEqual([]);
|
|
375
|
+
}
|
|
376
|
+
finally {
|
|
377
|
+
globalThis.fetch = origFetch;
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
it('classifies a break at the end of content as a post-roll', async () => {
|
|
381
|
+
const playlist = makePlaylist({
|
|
382
|
+
segments: [
|
|
383
|
+
{
|
|
384
|
+
uri: 'seg0.ts',
|
|
385
|
+
duration: 30,
|
|
386
|
+
sequenceNumber: 0,
|
|
387
|
+
discontinuity: false,
|
|
388
|
+
programDateTime: '2024-01-01T00:00:00.000Z',
|
|
389
|
+
},
|
|
390
|
+
],
|
|
391
|
+
dateRanges: [
|
|
392
|
+
makeRange({
|
|
393
|
+
startDate: '2024-01-01T00:00:30.000Z',
|
|
394
|
+
duration: 10,
|
|
395
|
+
}),
|
|
396
|
+
],
|
|
397
|
+
});
|
|
398
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE, 30);
|
|
399
|
+
expect(breaks[0].placement).toBe('postroll');
|
|
400
|
+
});
|
|
401
|
+
it('skips an interstitial with no START-DATE (e.g. END-ON-NEXT)', async () => {
|
|
402
|
+
const playlist = makePlaylist({
|
|
403
|
+
dateRanges: [
|
|
404
|
+
makeRange({ startDate: '', endOnNext: true, duration: 5 }),
|
|
405
|
+
],
|
|
406
|
+
});
|
|
407
|
+
expect(await discoverHlsInterstitials(playlist, BASE)).toEqual([]);
|
|
408
|
+
});
|
|
409
|
+
it('skips an interstitial with an unparseable START-DATE', async () => {
|
|
410
|
+
const playlist = makePlaylist({
|
|
411
|
+
dateRanges: [makeRange({ startDate: 'not-a-date', duration: 5 })],
|
|
412
|
+
});
|
|
413
|
+
expect(await discoverHlsInterstitials(playlist, BASE)).toEqual([]);
|
|
414
|
+
});
|
|
415
|
+
it('clamps a slightly-negative correlated start time to 0', async () => {
|
|
416
|
+
const playlist = makePlaylist({
|
|
417
|
+
segments: [
|
|
418
|
+
{
|
|
419
|
+
uri: 'seg0.ts',
|
|
420
|
+
duration: 30,
|
|
421
|
+
sequenceNumber: 0,
|
|
422
|
+
discontinuity: false,
|
|
423
|
+
programDateTime: '2024-01-01T00:00:00.000Z',
|
|
424
|
+
},
|
|
425
|
+
],
|
|
426
|
+
dateRanges: [
|
|
427
|
+
makeRange({
|
|
428
|
+
// 200ms before the anchor — within the clamp epsilon.
|
|
429
|
+
startDate: '2023-12-31T23:59:59.800Z',
|
|
430
|
+
duration: 5,
|
|
431
|
+
}),
|
|
432
|
+
],
|
|
433
|
+
});
|
|
434
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE, 30);
|
|
435
|
+
expect(breaks[0].startTime).toBe(0);
|
|
436
|
+
expect(breaks[0].placement).toBe('preroll');
|
|
437
|
+
});
|
|
438
|
+
it('ignores a program-date-time that cannot be parsed', async () => {
|
|
439
|
+
const playlist = makePlaylist({
|
|
440
|
+
segments: [
|
|
441
|
+
{
|
|
442
|
+
uri: 'seg0.ts',
|
|
443
|
+
duration: 30,
|
|
444
|
+
sequenceNumber: 0,
|
|
445
|
+
discontinuity: false,
|
|
446
|
+
programDateTime: 'bogus',
|
|
447
|
+
},
|
|
448
|
+
],
|
|
449
|
+
dateRanges: [
|
|
450
|
+
makeRange({
|
|
451
|
+
startDate: '2024-01-01T00:00:10.000Z',
|
|
452
|
+
duration: 5,
|
|
453
|
+
}),
|
|
454
|
+
],
|
|
455
|
+
});
|
|
456
|
+
// No usable anchor → treated as a best-effort pre-roll at time 0.
|
|
457
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE, 30);
|
|
458
|
+
expect(breaks[0].startTime).toBe(0);
|
|
459
|
+
});
|
|
460
|
+
it('ignores an END-DATE that precedes START-DATE', async () => {
|
|
461
|
+
const playlist = makePlaylist({
|
|
462
|
+
dateRanges: [
|
|
463
|
+
makeRange({
|
|
464
|
+
startDate: '2024-01-01T00:00:10.000Z',
|
|
465
|
+
endDate: '2024-01-01T00:00:05.000Z',
|
|
466
|
+
}),
|
|
467
|
+
],
|
|
468
|
+
});
|
|
469
|
+
// Invalid span → duration falls through to null.
|
|
470
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
471
|
+
expect(breaks[0].duration).toBeNull();
|
|
472
|
+
});
|
|
473
|
+
it('classifies a null-duration break near content end as a post-roll', async () => {
|
|
474
|
+
const playlist = makePlaylist({
|
|
475
|
+
segments: [
|
|
476
|
+
{
|
|
477
|
+
uri: 'seg0.ts',
|
|
478
|
+
duration: 30,
|
|
479
|
+
sequenceNumber: 0,
|
|
480
|
+
discontinuity: false,
|
|
481
|
+
programDateTime: '2024-01-01T00:00:00.000Z',
|
|
482
|
+
},
|
|
483
|
+
],
|
|
484
|
+
dateRanges: [makeRange({ startDate: '2024-01-01T00:00:30.000Z' })],
|
|
485
|
+
});
|
|
486
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE, 30);
|
|
487
|
+
expect(breaks[0].duration).toBeNull();
|
|
488
|
+
expect(breaks[0].placement).toBe('postroll');
|
|
489
|
+
});
|
|
490
|
+
it('sorts breaks by start time', async () => {
|
|
491
|
+
const playlist = makePlaylist({
|
|
492
|
+
segments: [
|
|
493
|
+
{
|
|
494
|
+
uri: 'seg0.ts',
|
|
495
|
+
duration: 60,
|
|
496
|
+
sequenceNumber: 0,
|
|
497
|
+
discontinuity: false,
|
|
498
|
+
programDateTime: '2024-01-01T00:00:00.000Z',
|
|
499
|
+
},
|
|
500
|
+
],
|
|
501
|
+
dateRanges: [
|
|
502
|
+
makeRange({
|
|
503
|
+
id: 'late',
|
|
504
|
+
startDate: '2024-01-01T00:00:40.000Z',
|
|
505
|
+
duration: 5,
|
|
506
|
+
}),
|
|
507
|
+
makeRange({
|
|
508
|
+
id: 'early',
|
|
509
|
+
startDate: '2024-01-01T00:00:10.000Z',
|
|
510
|
+
duration: 5,
|
|
511
|
+
}),
|
|
512
|
+
],
|
|
513
|
+
});
|
|
514
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE, 60);
|
|
515
|
+
expect(breaks.map((b) => b.id)).toEqual(['early', 'late']);
|
|
516
|
+
});
|
|
517
|
+
it('uses CUE=PRE to classify preroll and set startTime to 0', async () => {
|
|
518
|
+
const playlist = makePlaylist({
|
|
519
|
+
segments: [
|
|
520
|
+
{
|
|
521
|
+
duration: 6,
|
|
522
|
+
uri: 's0.ts',
|
|
523
|
+
programDateTime: '2024-01-01T00:00:00.000Z',
|
|
524
|
+
sequenceNumber: 0,
|
|
525
|
+
discontinuity: false,
|
|
526
|
+
},
|
|
527
|
+
],
|
|
528
|
+
dateRanges: [
|
|
529
|
+
makeRange({
|
|
530
|
+
id: 'pre',
|
|
531
|
+
startDate: '2024-01-01T00:00:10.000Z',
|
|
532
|
+
duration: 6,
|
|
533
|
+
clientAttributes: { 'X-ASSET-URI': 'ad.m3u8', CUE: 'PRE' },
|
|
534
|
+
}),
|
|
535
|
+
],
|
|
536
|
+
});
|
|
537
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE, 60);
|
|
538
|
+
expect(breaks[0].placement).toBe('preroll');
|
|
539
|
+
expect(breaks[0].startTime).toBe(0);
|
|
540
|
+
});
|
|
541
|
+
it('uses CUE=POST to classify postroll', async () => {
|
|
542
|
+
const playlist = makePlaylist({
|
|
543
|
+
segments: [
|
|
544
|
+
{
|
|
545
|
+
duration: 6,
|
|
546
|
+
uri: 's0.ts',
|
|
547
|
+
programDateTime: '2024-01-01T00:00:00.000Z',
|
|
548
|
+
sequenceNumber: 0,
|
|
549
|
+
discontinuity: false,
|
|
550
|
+
},
|
|
551
|
+
],
|
|
552
|
+
dateRanges: [
|
|
553
|
+
makeRange({
|
|
554
|
+
id: 'post',
|
|
555
|
+
startDate: '2024-01-01T00:00:30.000Z',
|
|
556
|
+
duration: 10,
|
|
557
|
+
clientAttributes: { 'X-ASSET-URI': 'ad.m3u8', CUE: 'POST' },
|
|
558
|
+
}),
|
|
559
|
+
],
|
|
560
|
+
});
|
|
561
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE, 60);
|
|
562
|
+
expect(breaks[0].placement).toBe('postroll');
|
|
563
|
+
});
|
|
564
|
+
it('uses X-PLAYOUT-LIMIT to cap duration', async () => {
|
|
565
|
+
const playlist = makePlaylist({
|
|
566
|
+
segments: [
|
|
567
|
+
{
|
|
568
|
+
duration: 6,
|
|
569
|
+
uri: 's0.ts',
|
|
570
|
+
programDateTime: '2024-01-01T00:00:00.000Z',
|
|
571
|
+
sequenceNumber: 0,
|
|
572
|
+
discontinuity: false,
|
|
573
|
+
},
|
|
574
|
+
],
|
|
575
|
+
dateRanges: [
|
|
576
|
+
makeRange({
|
|
577
|
+
id: 'limited',
|
|
578
|
+
startDate: '2024-01-01T00:00:10.000Z',
|
|
579
|
+
duration: 600,
|
|
580
|
+
clientAttributes: {
|
|
581
|
+
'X-ASSET-URI': 'ad.m3u8',
|
|
582
|
+
'X-PLAYOUT-LIMIT': '10.0',
|
|
583
|
+
},
|
|
584
|
+
}),
|
|
585
|
+
],
|
|
586
|
+
});
|
|
587
|
+
const breaks = await discoverHlsInterstitials(playlist, BASE);
|
|
588
|
+
expect(breaks[0].duration).toBe(10);
|
|
589
|
+
});
|
|
590
|
+
// ─── CUE token list / X-RESUME-OFFSET / X-PLAYOUT-LIMIT field ─────────
|
|
591
|
+
const ANCHOR_SEG = {
|
|
592
|
+
uri: 's0.ts',
|
|
593
|
+
duration: 60,
|
|
594
|
+
sequenceNumber: 0,
|
|
595
|
+
discontinuity: false,
|
|
596
|
+
programDateTime: '2024-01-01T00:00:00.000Z',
|
|
597
|
+
};
|
|
598
|
+
/** A playlist anchored at t=0 carrying a single interstitial range. */
|
|
599
|
+
function anchored(range) {
|
|
600
|
+
return makePlaylist({
|
|
601
|
+
segments: [ANCHOR_SEG],
|
|
602
|
+
dateRanges: [makeRange(range)],
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
function attrs(cue, extra = {}) {
|
|
606
|
+
return {
|
|
607
|
+
'X-ASSET-URI': 'ad.m3u8',
|
|
608
|
+
...(cue == null ? {} : { CUE: cue }),
|
|
609
|
+
...extra,
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
it('tokenizes a CUE list, honoring PRE and ONCE together', async () => {
|
|
613
|
+
const breaks = await discoverHlsInterstitials(anchored({
|
|
614
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
615
|
+
duration: 6,
|
|
616
|
+
clientAttributes: attrs('PRE,ONCE'),
|
|
617
|
+
}), BASE, 60);
|
|
618
|
+
expect(breaks[0].placement).toBe('preroll');
|
|
619
|
+
expect(breaks[0].startTime).toBe(0);
|
|
620
|
+
expect(breaks[0].once).toBeTrue();
|
|
621
|
+
});
|
|
622
|
+
it('marks a bare CUE=ONCE break once, leaving placement to the heuristic', async () => {
|
|
623
|
+
const breaks = await discoverHlsInterstitials(anchored({
|
|
624
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
625
|
+
duration: 6,
|
|
626
|
+
clientAttributes: attrs('ONCE'),
|
|
627
|
+
}), BASE, 60);
|
|
628
|
+
expect(breaks[0].placement).toBe('midroll');
|
|
629
|
+
expect(breaks[0].once).toBeTrue();
|
|
630
|
+
});
|
|
631
|
+
it('honors POST together with ONCE', async () => {
|
|
632
|
+
const breaks = await discoverHlsInterstitials(anchored({
|
|
633
|
+
startDate: '2024-01-01T00:00:30.000Z',
|
|
634
|
+
duration: 6,
|
|
635
|
+
clientAttributes: attrs('POST,ONCE'),
|
|
636
|
+
}), BASE, 60);
|
|
637
|
+
expect(breaks[0].placement).toBe('postroll');
|
|
638
|
+
expect(breaks[0].once).toBeTrue();
|
|
639
|
+
});
|
|
640
|
+
it('ignores unknown CUE tokens', async () => {
|
|
641
|
+
const breaks = await discoverHlsInterstitials(anchored({
|
|
642
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
643
|
+
duration: 6,
|
|
644
|
+
clientAttributes: attrs('PRE,FOO'),
|
|
645
|
+
}), BASE, 60);
|
|
646
|
+
expect(breaks[0].placement).toBe('preroll');
|
|
647
|
+
expect(breaks[0].once).toBeFalse();
|
|
648
|
+
});
|
|
649
|
+
it('lets PRE win when CUE illegally lists both PRE and POST', async () => {
|
|
650
|
+
const breaks = await discoverHlsInterstitials(anchored({
|
|
651
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
652
|
+
duration: 6,
|
|
653
|
+
clientAttributes: attrs('PRE,POST'),
|
|
654
|
+
}), BASE, 60);
|
|
655
|
+
expect(breaks[0].placement).toBe('preroll');
|
|
656
|
+
});
|
|
657
|
+
it('tokenizes CUE case- and whitespace-insensitively', async () => {
|
|
658
|
+
const breaks = await discoverHlsInterstitials(anchored({
|
|
659
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
660
|
+
duration: 6,
|
|
661
|
+
clientAttributes: attrs(' once , pre '),
|
|
662
|
+
}), BASE, 60);
|
|
663
|
+
expect(breaks[0].once).toBeTrue();
|
|
664
|
+
expect(breaks[0].placement).toBe('preroll');
|
|
665
|
+
});
|
|
666
|
+
it('defaults once to false when there is no CUE', async () => {
|
|
667
|
+
const breaks = await discoverHlsInterstitials(anchored({
|
|
668
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
669
|
+
duration: 6,
|
|
670
|
+
clientAttributes: attrs(),
|
|
671
|
+
}), BASE, 60);
|
|
672
|
+
expect(breaks[0].once).toBeFalse();
|
|
673
|
+
});
|
|
674
|
+
it('parses X-RESUME-OFFSET, distinguishing a present 0 from absent', async () => {
|
|
675
|
+
const zero = await discoverHlsInterstitials(anchored({
|
|
676
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
677
|
+
duration: 6,
|
|
678
|
+
clientAttributes: attrs(undefined, { 'X-RESUME-OFFSET': '0' }),
|
|
679
|
+
}), BASE, 60);
|
|
680
|
+
expect(zero[0].resumeOffset).toBe(0);
|
|
681
|
+
const absent = await discoverHlsInterstitials(anchored({
|
|
682
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
683
|
+
duration: 6,
|
|
684
|
+
clientAttributes: attrs(),
|
|
685
|
+
}), BASE, 60);
|
|
686
|
+
expect(absent[0].resumeOffset).toBeNull();
|
|
687
|
+
});
|
|
688
|
+
it('parses a signed / fractional X-RESUME-OFFSET and rejects garbage', async () => {
|
|
689
|
+
const neg = await discoverHlsInterstitials(anchored({
|
|
690
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
691
|
+
duration: 6,
|
|
692
|
+
clientAttributes: attrs(undefined, { 'X-RESUME-OFFSET': '-5' }),
|
|
693
|
+
}), BASE, 60);
|
|
694
|
+
expect(neg[0].resumeOffset).toBe(-5);
|
|
695
|
+
const frac = await discoverHlsInterstitials(anchored({
|
|
696
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
697
|
+
duration: 6,
|
|
698
|
+
clientAttributes: attrs(undefined, {
|
|
699
|
+
'X-RESUME-OFFSET': '15.0',
|
|
700
|
+
}),
|
|
701
|
+
}), BASE, 60);
|
|
702
|
+
expect(frac[0].resumeOffset).toBe(15);
|
|
703
|
+
const garbage = await discoverHlsInterstitials(anchored({
|
|
704
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
705
|
+
duration: 6,
|
|
706
|
+
clientAttributes: attrs(undefined, {
|
|
707
|
+
'X-RESUME-OFFSET': 'nope',
|
|
708
|
+
}),
|
|
709
|
+
}), BASE, 60);
|
|
710
|
+
expect(garbage[0].resumeOffset).toBeNull();
|
|
711
|
+
});
|
|
712
|
+
it('parses X-RESOLUTION-TIME-OFFSET, or null when absent/invalid', async () => {
|
|
713
|
+
const present = await discoverHlsInterstitials(anchored({
|
|
714
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
715
|
+
duration: 6,
|
|
716
|
+
clientAttributes: attrs(undefined, {
|
|
717
|
+
'X-RESOLUTION-TIME-OFFSET': '8.5',
|
|
718
|
+
}),
|
|
719
|
+
}), BASE, 60);
|
|
720
|
+
expect(present[0].resolutionTimeOffset).toBe(8.5);
|
|
721
|
+
const absent = await discoverHlsInterstitials(anchored({
|
|
722
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
723
|
+
duration: 6,
|
|
724
|
+
clientAttributes: attrs(),
|
|
725
|
+
}), BASE, 60);
|
|
726
|
+
expect(absent[0].resolutionTimeOffset).toBeNull();
|
|
727
|
+
// A negative or non-numeric offset is rejected (falls back to null).
|
|
728
|
+
for (const bad of ['-3', 'nope']) {
|
|
729
|
+
const invalid = await discoverHlsInterstitials(anchored({
|
|
730
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
731
|
+
duration: 6,
|
|
732
|
+
clientAttributes: attrs(undefined, {
|
|
733
|
+
'X-RESOLUTION-TIME-OFFSET': bad,
|
|
734
|
+
}),
|
|
735
|
+
}), BASE, 60);
|
|
736
|
+
expect(invalid[0].resolutionTimeOffset).toBeNull();
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
it('carries X-PLAYOUT-LIMIT as its own field, even without a DURATION', async () => {
|
|
740
|
+
const breaks = await discoverHlsInterstitials(anchored({
|
|
741
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
742
|
+
clientAttributes: attrs(undefined, { 'X-PLAYOUT-LIMIT': '8' }),
|
|
743
|
+
}), BASE, 60);
|
|
744
|
+
expect(breaks[0].playoutLimit).toBe(8);
|
|
745
|
+
// No DURATION/END-DATE/PLANNED-DURATION → duration unresolved, but the
|
|
746
|
+
// pod-total cap survives (previously it was dropped).
|
|
747
|
+
expect(breaks[0].duration).toBeNull();
|
|
748
|
+
});
|
|
749
|
+
it('reports a null playoutLimit when X-PLAYOUT-LIMIT is absent', async () => {
|
|
750
|
+
const breaks = await discoverHlsInterstitials(anchored({
|
|
751
|
+
startDate: '2024-01-01T00:00:20.000Z',
|
|
752
|
+
duration: 6,
|
|
753
|
+
clientAttributes: attrs(),
|
|
754
|
+
}), BASE, 60);
|
|
755
|
+
expect(breaks[0].playoutLimit).toBeNull();
|
|
756
|
+
});
|
|
757
|
+
});
|