@amazon/vinyl 3.2.2 → 3.2.3-next.20261001224604

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 (92) hide show
  1. package/README.md +2 -2
  2. package/dist/index.cjs +62 -21
  3. package/dist/index.cjs.map +3 -3
  4. package/dist/index.js +65 -22
  5. package/dist/index.js.map +3 -3
  6. package/dist/test/benchmark.es5.js +7 -6
  7. package/dist/test/benchmark.js +35 -30
  8. package/dist/test/benchmark.js.map +3 -3
  9. package/dist/test/integ.es5.js +184 -171
  10. package/dist/test/integ.js +450 -165
  11. package/dist/test/integ.js.map +4 -4
  12. package/dist/types/current/ad/AdControllerImpl.d.ts.map +1 -1
  13. package/dist/types/current/ad/AdControllerImpl.js +15 -1
  14. package/dist/types/current/ad/discoverHlsInterstitials.js +13 -1
  15. package/dist/types/current/drm/commonEme/MsCommonEme.d.ts.map +1 -1
  16. package/dist/types/current/drm/commonEme/MsCommonEme.js +2 -2
  17. package/dist/types/current/drm/commonEme/StandardCommonEme.d.ts.map +1 -1
  18. package/dist/types/current/drm/commonEme/StandardCommonEme.js +3 -2
  19. package/dist/types/current/drm/commonEme/WebKitCommonEme.d.ts.map +1 -1
  20. package/dist/types/current/drm/commonEme/WebKitCommonEme.js +2 -2
  21. package/dist/types/current/drm/dom/MSMediaKeys.d.ts +1 -1
  22. package/dist/types/current/drm/dom/MSMediaKeys.d.ts.map +1 -1
  23. package/dist/types/current/drm/dom/WebKitMediaKeys.d.ts +1 -1
  24. package/dist/types/current/drm/dom/WebKitMediaKeys.d.ts.map +1 -1
  25. package/dist/types/current/drm/util/extractContentId.js +2 -2
  26. package/dist/types/current/playback/PlaybackControllerImpl.d.ts +1 -1
  27. package/dist/types/current/streaming/MediaQualityMetadata.d.ts +3 -1
  28. package/dist/types/current/streaming/MediaQualityMetadata.d.ts.map +1 -1
  29. package/dist/types/current/streaming/SegmentControllerImpl.d.ts +1 -1
  30. package/dist/types/current/streaming/buffering/BufferingController.d.ts +1 -1
  31. package/dist/types/current/streaming/buffering/BufferingController.d.ts.map +1 -1
  32. package/dist/types/current/streaming/buffering/BufferingController.js +14 -5
  33. package/dist/types/current/streaming/buffering/MediaSourceController.d.ts.map +1 -1
  34. package/dist/types/current/streaming/buffering/MediaSourceController.js +4 -0
  35. package/dist/types/current/text/discoverDashTextTracks.d.ts +2 -2
  36. package/dist/types/current/text/discoverDashTextTracks.js +4 -3
  37. package/dist/types/current/text/parseWebVtt.d.ts.map +1 -1
  38. package/dist/types/current/text/parseWebVtt.js +3 -2
  39. package/dist/types/current/track/TrackController.d.ts.map +1 -1
  40. package/dist/types/current/track/TrackController.js +7 -0
  41. package/dist/types/current/track/hls/HlsManifestData.d.ts +14 -1
  42. package/dist/types/current/track/hls/HlsManifestData.d.ts.map +1 -1
  43. package/dist/types/current/track/hls/buildHlsMediaTimeline.d.ts.map +1 -1
  44. package/dist/types/current/track/hls/buildHlsMediaTimeline.js +10 -2
  45. package/dist/types/current/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
  46. package/dist/types/current/track/hls/createUrlHlsManifestProvider.d.ts.map +1 -1
  47. package/dist/types/current/track/hls/createUrlHlsManifestProvider.js +8 -3
  48. package/dist/types/current/tsconfig.tsbuildinfo +1 -1
  49. package/dist/types/ts3.7/playback/PlaybackControllerImpl.d.ts +1 -1
  50. package/dist/types/ts3.7/streaming/MediaQualityMetadata.d.ts +3 -1
  51. package/dist/types/ts3.7/streaming/SegmentControllerImpl.d.ts +1 -1
  52. package/dist/types/ts3.7/streaming/buffering/BufferingController.d.ts +1 -1
  53. package/dist/types/ts3.7/text/discoverDashTextTracks.d.ts +2 -2
  54. package/dist/types/ts3.7/track/hls/HlsManifestData.d.ts +14 -1
  55. package/dist/types/ts3.7/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
  56. package/dist/types/ts4.1/playback/PlaybackControllerImpl.d.ts +1 -1
  57. package/dist/types/ts4.1/streaming/MediaQualityMetadata.d.ts +3 -1
  58. package/dist/types/ts4.1/streaming/SegmentControllerImpl.d.ts +1 -1
  59. package/dist/types/ts4.1/streaming/buffering/BufferingController.d.ts +1 -1
  60. package/dist/types/ts4.1/text/discoverDashTextTracks.d.ts +2 -2
  61. package/dist/types/ts4.1/track/hls/HlsManifestData.d.ts +14 -1
  62. package/dist/types/ts4.1/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
  63. package/dist/types/ts4.7/playback/PlaybackControllerImpl.d.ts +1 -1
  64. package/dist/types/ts4.7/streaming/MediaQualityMetadata.d.ts +3 -1
  65. package/dist/types/ts4.7/streaming/SegmentControllerImpl.d.ts +1 -1
  66. package/dist/types/ts4.7/streaming/buffering/BufferingController.d.ts +1 -1
  67. package/dist/types/ts4.7/text/discoverDashTextTracks.d.ts +2 -2
  68. package/dist/types/ts4.7/track/hls/HlsManifestData.d.ts +14 -1
  69. package/dist/types/ts4.7/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
  70. package/dist/unit/types/current/ad/AdControllerImpl.test.js +66 -0
  71. package/dist/unit/types/current/ad/discoverHlsInterstitials.test.js +29 -2
  72. package/dist/unit/types/current/drm/commonEme/StandardCommonEme.test.js +12 -4
  73. package/dist/unit/types/current/drm/util/extractContentId.test.js +7 -0
  74. package/dist/unit/types/current/index.d.ts +1 -0
  75. package/dist/unit/types/current/index.d.ts.map +1 -1
  76. package/dist/unit/types/current/index.js +1 -0
  77. package/dist/unit/types/current/streaming/MediaQualityMetadata.test.js +8 -0
  78. package/dist/unit/types/current/streaming/buffering/BufferingController.test.js +26 -0
  79. package/dist/unit/types/current/streaming/buffering/MediaSourceController.test.js +29 -0
  80. package/dist/unit/types/current/text/TextTrack.test.d.ts +2 -0
  81. package/dist/unit/types/current/text/TextTrack.test.d.ts.map +1 -0
  82. package/dist/unit/types/current/text/TextTrack.test.js +12 -0
  83. package/dist/unit/types/current/text/discoverDashTextTracks.test.js +17 -0
  84. package/dist/unit/types/current/text/parseWebVtt.test.js +26 -0
  85. package/dist/unit/types/current/track/TrackController.test.js +15 -60
  86. package/dist/unit/types/current/track/hls/buildHlsMediaTimeline.test.js +22 -0
  87. package/dist/unit/types/current/track/hls/createUrlHlsManifestProvider.test.js +23 -0
  88. package/dist/unit/types/current/tsconfig.tsbuildinfo +1 -1
  89. package/dist/vinylTestUtil/types/current/tsconfig.tsbuildinfo +1 -1
  90. package/docs/CUSTOMIZATION_GUIDE.md +310 -0
  91. package/package.json +10 -10
  92. package/docs/DASH_MANIFEST_TRANSFORM_GUIDE.md +0 -236
@@ -15,7 +15,7 @@ export interface PlaybackControllerImplOptions {
15
15
  * The minimum number of seconds before the end of the next seekable range allowed for a seek
16
16
  * operation. Some browsers will never complete a seek operation if the seek is too close to
17
17
  * this end range.
18
- * Default: getMinSeekableBufferDefault() which is between 0.5 and 5, browser dependent.
18
+ * Default: getMinSeekableBufferDefault(), which is 2 on Chromium and 5 elsewhere.
19
19
  */
20
20
  readonly minSeekableBuffer: number;
21
21
  /**
@@ -148,7 +148,9 @@ export interface MediaQualityMetadata extends MediaFormatMetadata {
148
148
  * An array restricts switching to only the listed group IDs.
149
149
  * Default behavior:
150
150
  * - DASH: restricted to own group unless adaptation-set-switching property is present.
151
- * - HLS: restricted to variants with the same base codec and language.
151
+ * - HLS: unconstrained (null). Every variant is one group, and renditions are
152
+ * selected by the media timeline's language and accessibility filters
153
+ * rather than by a switching group.
152
154
  */
153
155
  readonly switchingGroupIds: readonly string[] | null;
154
156
  }
@@ -18,7 +18,7 @@ export interface SegmentControllerImplDeps {
18
18
  export interface SegmentControllerImplOptions {
19
19
  /**
20
20
  * The amount of time ahead of the playhead to prefetch when the track is active.
21
- * Default: 240
21
+ * Default: 180
22
22
  */
23
23
  readonly prefetchActive: number;
24
24
  /**
@@ -119,7 +119,7 @@ export interface BufferingControllerImplOptions {
119
119
  readonly minBuffer: number;
120
120
  /**
121
121
  * The maximum number of bytes to append at a time per content type.
122
- * Default: { audio: 1MiB, video: 15MiB }
122
+ * Default: { audio: 10MiB, video: 150MiB }
123
123
  */
124
124
  readonly maxAppendSize: Partial<Record<ContentType, number>>;
125
125
  }
@@ -5,8 +5,8 @@ import { TextTrackInfo } from './TextTrack';
5
5
  *
6
6
  * Considers an `<AdaptationSet>` to carry text when one of:
7
7
  * - `contentType="text"`
8
- * - `mimeType` starts with `text/` (e.g. `text/vtt`)
9
- * - `mimeType` is `application/mp4` *and* the codec/role indicates text
8
+ * - its `mimeType`, or that of one of its `<Representation>`s, starts with
9
+ * `text/` (e.g. `text/vtt`)
10
10
  *
11
11
  * Within a text adaptation set, each `<Representation>` becomes one
12
12
  * {@link TextTrackInfo}. The `BaseURL` chain (MPD → Period → AdaptationSet →
@@ -14,6 +14,19 @@ export interface HlsManifestData {
14
14
  /**
15
15
  * Lazily fetches and caches a media playlist by variant URI.
16
16
  */
17
- readonly getMediaPlaylist: (uri: string) => Promise<HlsMediaPlaylist>;
17
+ readonly getMediaPlaylist: (uri: string) => Promise<HlsMediaPlaylistData>;
18
+ }
19
+ /**
20
+ * A media playlist with the URL its relative URIs resolve against.
21
+ */
22
+ export interface HlsMediaPlaylistData extends HlsMediaPlaylist {
23
+ /**
24
+ * The media playlist's URL after redirects, against which its segment, map,
25
+ * and date range URIs resolve. Guaranteed to be absolute when set.
26
+ *
27
+ * When absent, the variant URI resolved against
28
+ * {@link HlsManifestData.baseUrl} is used instead.
29
+ */
30
+ readonly baseUrl?: string;
18
31
  }
19
32
  //# sourceMappingURL=HlsManifestData.d.ts.map
@@ -1,5 +1,6 @@
1
- import { HlsMainPlaylist, HlsMediaPlaylist } from '@amazon/vinyl-hls-parser';
1
+ import { HlsMainPlaylist } from '@amazon/vinyl-hls-parser';
2
2
  import { Maybe, ReadonlyAbort, RequestInitOptions } from '@amazon/vinyl-util';
3
+ import { HlsMediaPlaylistData } from './HlsManifestData';
3
4
  import { HlsManifestProvider } from './createHlsManifestProvider';
4
5
  export declare function createUrlHlsManifestProvider(url: string, requestInit?: RequestInitOptions): HlsManifestProvider;
5
6
  export interface FetchMediaPlaylistOptions {
@@ -17,5 +18,5 @@ export interface FetchMediaPlaylistOptions {
17
18
  /**
18
19
  * Fetches and parses an HLS media playlist from a variant URI.
19
20
  */
20
- export declare function fetchMediaPlaylist(options: FetchMediaPlaylistOptions): Promise<HlsMediaPlaylist>;
21
+ export declare function fetchMediaPlaylist(options: FetchMediaPlaylistOptions): Promise<HlsMediaPlaylistData>;
21
22
  //# sourceMappingURL=createUrlHlsManifestProvider.d.ts.map
@@ -17,7 +17,7 @@ export interface PlaybackControllerImplOptions {
17
17
  * The minimum number of seconds before the end of the next seekable range allowed for a seek
18
18
  * operation. Some browsers will never complete a seek operation if the seek is too close to
19
19
  * this end range.
20
- * Default: getMinSeekableBufferDefault() which is between 0.5 and 5, browser dependent.
20
+ * Default: getMinSeekableBufferDefault(), which is 2 on Chromium and 5 elsewhere.
21
21
  */
22
22
  readonly minSeekableBuffer: number;
23
23
  /**
@@ -148,7 +148,9 @@ export interface MediaQualityMetadata extends MediaFormatMetadata {
148
148
  * An array restricts switching to only the listed group IDs.
149
149
  * Default behavior:
150
150
  * - DASH: restricted to own group unless adaptation-set-switching property is present.
151
- * - HLS: restricted to variants with the same base codec and language.
151
+ * - HLS: unconstrained (null). Every variant is one group, and renditions are
152
+ * selected by the media timeline's language and accessibility filters
153
+ * rather than by a switching group.
152
154
  */
153
155
  readonly switchingGroupIds: readonly string[] | null;
154
156
  }
@@ -19,7 +19,7 @@ export interface SegmentControllerImplDeps {
19
19
  export interface SegmentControllerImplOptions {
20
20
  /**
21
21
  * The amount of time ahead of the playhead to prefetch when the track is active.
22
- * Default: 240
22
+ * Default: 180
23
23
  */
24
24
  readonly prefetchActive: number;
25
25
  /**
@@ -120,7 +120,7 @@ export interface BufferingControllerImplOptions {
120
120
  readonly minBuffer: number;
121
121
  /**
122
122
  * The maximum number of bytes to append at a time per content type.
123
- * Default: { audio: 1MiB, video: 15MiB }
123
+ * Default: { audio: 10MiB, video: 150MiB }
124
124
  */
125
125
  readonly maxAppendSize: Partial<Record<ContentType, number>>;
126
126
  }
@@ -5,8 +5,8 @@ import type { TextTrackInfo } from './TextTrack';
5
5
  *
6
6
  * Considers an `<AdaptationSet>` to carry text when one of:
7
7
  * - `contentType="text"`
8
- * - `mimeType` starts with `text/` (e.g. `text/vtt`)
9
- * - `mimeType` is `application/mp4` *and* the codec/role indicates text
8
+ * - its `mimeType`, or that of one of its `<Representation>`s, starts with
9
+ * `text/` (e.g. `text/vtt`)
10
10
  *
11
11
  * Within a text adaptation set, each `<Representation>` becomes one
12
12
  * {@link TextTrackInfo}. The `BaseURL` chain (MPD → Period → AdaptationSet →
@@ -14,6 +14,19 @@ export interface HlsManifestData {
14
14
  /**
15
15
  * Lazily fetches and caches a media playlist by variant URI.
16
16
  */
17
- readonly getMediaPlaylist: (uri: string) => Promise<HlsMediaPlaylist>;
17
+ readonly getMediaPlaylist: (uri: string) => Promise<HlsMediaPlaylistData>;
18
+ }
19
+ /**
20
+ * A media playlist with the URL its relative URIs resolve against.
21
+ */
22
+ export interface HlsMediaPlaylistData extends HlsMediaPlaylist {
23
+ /**
24
+ * The media playlist's URL after redirects, against which its segment, map,
25
+ * and date range URIs resolve. Guaranteed to be absolute when set.
26
+ *
27
+ * When absent, the variant URI resolved against
28
+ * {@link HlsManifestData.baseUrl} is used instead.
29
+ */
30
+ readonly baseUrl?: string;
18
31
  }
19
32
  //# sourceMappingURL=HlsManifestData.d.ts.map
@@ -1,5 +1,6 @@
1
- import type { HlsMainPlaylist, HlsMediaPlaylist } from '@amazon/vinyl-hls-parser';
1
+ import type { HlsMainPlaylist } from '@amazon/vinyl-hls-parser';
2
2
  import type { Maybe, ReadonlyAbort, RequestInitOptions } from '@amazon/vinyl-util';
3
+ import type { HlsMediaPlaylistData } from './HlsManifestData';
3
4
  import type { HlsManifestProvider } from './createHlsManifestProvider';
4
5
  export declare function createUrlHlsManifestProvider(url: string, requestInit?: RequestInitOptions): HlsManifestProvider;
5
6
  export interface FetchMediaPlaylistOptions {
@@ -17,5 +18,5 @@ export interface FetchMediaPlaylistOptions {
17
18
  /**
18
19
  * Fetches and parses an HLS media playlist from a variant URI.
19
20
  */
20
- export declare function fetchMediaPlaylist(options: FetchMediaPlaylistOptions): Promise<HlsMediaPlaylist>;
21
+ export declare function fetchMediaPlaylist(options: FetchMediaPlaylistOptions): Promise<HlsMediaPlaylistData>;
21
22
  //# sourceMappingURL=createUrlHlsManifestProvider.d.ts.map
@@ -15,7 +15,7 @@ export interface PlaybackControllerImplOptions {
15
15
  * The minimum number of seconds before the end of the next seekable range allowed for a seek
16
16
  * operation. Some browsers will never complete a seek operation if the seek is too close to
17
17
  * this end range.
18
- * Default: getMinSeekableBufferDefault() which is between 0.5 and 5, browser dependent.
18
+ * Default: getMinSeekableBufferDefault(), which is 2 on Chromium and 5 elsewhere.
19
19
  */
20
20
  readonly minSeekableBuffer: number;
21
21
  /**
@@ -148,7 +148,9 @@ export interface MediaQualityMetadata extends MediaFormatMetadata {
148
148
  * An array restricts switching to only the listed group IDs.
149
149
  * Default behavior:
150
150
  * - DASH: restricted to own group unless adaptation-set-switching property is present.
151
- * - HLS: restricted to variants with the same base codec and language.
151
+ * - HLS: unconstrained (null). Every variant is one group, and renditions are
152
+ * selected by the media timeline's language and accessibility filters
153
+ * rather than by a switching group.
152
154
  */
153
155
  readonly switchingGroupIds: readonly string[] | null;
154
156
  }
@@ -18,7 +18,7 @@ export interface SegmentControllerImplDeps {
18
18
  export interface SegmentControllerImplOptions {
19
19
  /**
20
20
  * The amount of time ahead of the playhead to prefetch when the track is active.
21
- * Default: 240
21
+ * Default: 180
22
22
  */
23
23
  readonly prefetchActive: number;
24
24
  /**
@@ -119,7 +119,7 @@ export interface BufferingControllerImplOptions {
119
119
  readonly minBuffer: number;
120
120
  /**
121
121
  * The maximum number of bytes to append at a time per content type.
122
- * Default: { audio: 1MiB, video: 15MiB }
122
+ * Default: { audio: 10MiB, video: 150MiB }
123
123
  */
124
124
  readonly maxAppendSize: Partial<Record<ContentType, number>>;
125
125
  }
@@ -5,8 +5,8 @@ import type { TextTrackInfo } from './TextTrack';
5
5
  *
6
6
  * Considers an `<AdaptationSet>` to carry text when one of:
7
7
  * - `contentType="text"`
8
- * - `mimeType` starts with `text/` (e.g. `text/vtt`)
9
- * - `mimeType` is `application/mp4` *and* the codec/role indicates text
8
+ * - its `mimeType`, or that of one of its `<Representation>`s, starts with
9
+ * `text/` (e.g. `text/vtt`)
10
10
  *
11
11
  * Within a text adaptation set, each `<Representation>` becomes one
12
12
  * {@link TextTrackInfo}. The `BaseURL` chain (MPD → Period → AdaptationSet →
@@ -14,6 +14,19 @@ export interface HlsManifestData {
14
14
  /**
15
15
  * Lazily fetches and caches a media playlist by variant URI.
16
16
  */
17
- readonly getMediaPlaylist: (uri: string) => Promise<HlsMediaPlaylist>;
17
+ readonly getMediaPlaylist: (uri: string) => Promise<HlsMediaPlaylistData>;
18
+ }
19
+ /**
20
+ * A media playlist with the URL its relative URIs resolve against.
21
+ */
22
+ export interface HlsMediaPlaylistData extends HlsMediaPlaylist {
23
+ /**
24
+ * The media playlist's URL after redirects, against which its segment, map,
25
+ * and date range URIs resolve. Guaranteed to be absolute when set.
26
+ *
27
+ * When absent, the variant URI resolved against
28
+ * {@link HlsManifestData.baseUrl} is used instead.
29
+ */
30
+ readonly baseUrl?: string;
18
31
  }
19
32
  //# sourceMappingURL=HlsManifestData.d.ts.map
@@ -1,5 +1,6 @@
1
- import type { HlsMainPlaylist, HlsMediaPlaylist } from '@amazon/vinyl-hls-parser';
1
+ import type { HlsMainPlaylist } from '@amazon/vinyl-hls-parser';
2
2
  import type { Maybe, ReadonlyAbort, RequestInitOptions } from '@amazon/vinyl-util';
3
+ import type { HlsMediaPlaylistData } from './HlsManifestData';
3
4
  import type { HlsManifestProvider } from './createHlsManifestProvider';
4
5
  export declare function createUrlHlsManifestProvider(url: string, requestInit?: RequestInitOptions): HlsManifestProvider;
5
6
  export interface FetchMediaPlaylistOptions {
@@ -17,5 +18,5 @@ export interface FetchMediaPlaylistOptions {
17
18
  /**
18
19
  * Fetches and parses an HLS media playlist from a variant URI.
19
20
  */
20
- export declare function fetchMediaPlaylist(options: FetchMediaPlaylistOptions): Promise<HlsMediaPlaylist>;
21
+ export declare function fetchMediaPlaylist(options: FetchMediaPlaylistOptions): Promise<HlsMediaPlaylistData>;
21
22
  //# sourceMappingURL=createUrlHlsManifestProvider.d.ts.map
@@ -526,6 +526,44 @@ describe('AdControllerImpl', () => {
526
526
  await flush();
527
527
  expect(c.currentAdBreak).toBeNull();
528
528
  });
529
+ it('still enters a pending break when skipped while its ads resolve', async () => {
530
+ const c = createController();
531
+ let resolveAds = () => undefined;
532
+ const entered = [];
533
+ await setContent(c, trackAds(makeBreak({
534
+ id: 'b1',
535
+ startTime: 0,
536
+ duration: 30,
537
+ ads: () => new Promise((resolve) => {
538
+ resolveAds = resolve;
539
+ }),
540
+ }), makeBreak({
541
+ id: 'b2',
542
+ startTime: 1,
543
+ duration: 30,
544
+ ads: [
545
+ {
546
+ id: 'a2',
547
+ startTime: 1,
548
+ duration: 10,
549
+ uri: 'ad2.m3u8',
550
+ },
551
+ ],
552
+ })));
553
+ c.on('adBreakEntered', (e) => entered.push(e.adBreak.id));
554
+ // Both breaks contain the playhead, so both become pending and the
555
+ // first is entered while its ad list is still in flight.
556
+ updateTime(2);
557
+ await flush();
558
+ expect(entered).toEqual(['b1']);
559
+ c.skipAdBreak();
560
+ resolveAds([]);
561
+ await flush();
562
+ // Nothing else drains the pending list, and a non-empty list blocks
563
+ // further midroll ingress, so b2 must be entered here.
564
+ expect(entered).toEqual(['b1', 'b2']);
565
+ expect(c.currentAdBreak?.id).toBe('b2');
566
+ });
529
567
  });
530
568
  describe('a break with no ads', () => {
531
569
  it('completes immediately with a resume position and plays no ad', async () => {
@@ -753,6 +791,34 @@ describe('AdControllerImpl', () => {
753
791
  await flush();
754
792
  expect(thirds).toEqual(['a1']);
755
793
  });
794
+ it('dispatches each quartile at most once per ad', async () => {
795
+ const c = createController();
796
+ const events = [];
797
+ c.on('adFirstQuartile', () => events.push('first'));
798
+ c.on('adMidpoint', () => events.push('mid'));
799
+ c.on('adThirdQuartile', () => events.push('third'));
800
+ await setContent(c, trackAds(makeBreak({ startTime: 0, duration: 10 })));
801
+ updateTime(0);
802
+ await flush();
803
+ playbackController.dispatch('playing', {});
804
+ playbackController.duration = 10;
805
+ playbackController.playbackRate = 1;
806
+ // Every subsequent timeUpdate is still past each threshold, so an
807
+ // unlatched check would report the quartile again.
808
+ for (const [percent, time] of [
809
+ [0.3, 3],
810
+ [0.4, 4],
811
+ [0.6, 6],
812
+ [0.7, 7],
813
+ [0.8, 8],
814
+ [0.9, 9],
815
+ ]) {
816
+ playbackController.currentTimePercent = percent;
817
+ updateTime(time);
818
+ await flush();
819
+ }
820
+ expect(events).toEqual(['first', 'mid', 'third']);
821
+ });
756
822
  it('does not emit quartiles or throw when the ad duration is zero', async () => {
757
823
  // Regression: a zero reported duration must not divide-by-zero into
758
824
  // NaN progress and must not emit bogus quartile events.
@@ -32,8 +32,9 @@ describe('discoverHlsInterstitials', () => {
32
32
  * A minimal `fetch` Response stand-in that satisfies `requestWithRetry`
33
33
  * (which reads `ok`/`status`/`headers` and rejects on non-ok responses).
34
34
  */
35
- function okJsonResponse(body) {
35
+ function okJsonResponse(body, url = '') {
36
36
  return {
37
+ url,
37
38
  ok: true,
38
39
  status: 200,
39
40
  headers: { get: () => null },
@@ -199,7 +200,8 @@ describe('discoverHlsInterstitials', () => {
199
200
  const ads = await resolveValueProvider(breaks[0].ads);
200
201
  expect(fetchSpy.calls.argsFor(0)[0]).toBe('https://example.com/ads.json');
201
202
  expect(ads.length).toBe(2);
202
- expect(ads[0].uri).toBe('https://cdn.example.com/media/mid1.m3u8');
203
+ // Relative to the asset list, not to the media playlist.
204
+ expect(ads[0].uri).toBe('https://example.com/mid1.m3u8');
203
205
  expect(ads[0].duration).toBe(10);
204
206
  expect(ads[1].uri).toBe('https://cdn.example.com/mid2.m3u8');
205
207
  expect(ads[1].duration).toBeNull();
@@ -208,6 +210,31 @@ describe('discoverHlsInterstitials', () => {
208
210
  globalThis.fetch = origFetch;
209
211
  }
210
212
  });
213
+ it('resolves relative asset URIs against the redirected asset list URL', async () => {
214
+ const origFetch = globalThis.fetch;
215
+ const fetchSpy = jasmine
216
+ .createSpy('fetch')
217
+ .and.resolveTo(okJsonResponse({ ASSETS: [{ URI: 'mid1.m3u8' }] }, 'https://ads.example.net/v2/ads.json'));
218
+ globalThis.fetch = fetchSpy;
219
+ try {
220
+ const playlist = makePlaylist({
221
+ dateRanges: [
222
+ makeRange({
223
+ duration: 10,
224
+ clientAttributes: {
225
+ 'X-ASSET-LIST': 'https://example.com/redirected.json',
226
+ },
227
+ }),
228
+ ],
229
+ });
230
+ const breaks = await discoverHlsInterstitials(playlist, BASE);
231
+ const ads = await resolveValueProvider(breaks[0].ads);
232
+ expect(ads[0].uri).toBe('https://ads.example.net/v2/mid1.m3u8');
233
+ }
234
+ finally {
235
+ globalThis.fetch = origFetch;
236
+ }
237
+ });
211
238
  it('caches the X-ASSET-LIST fetch across calls', async () => {
212
239
  const origFetch = globalThis.fetch;
213
240
  const fetchSpy = jasmine
@@ -3,8 +3,8 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import { DrmKeySystem, StandardCommonEme, StandardCommonMediaKeys, StandardCommonMediaKeySession, StandardCommonMediaKeySystemAccess, } from '@amazon/vinyl';
6
- import { Deferred, DisposedError, never, } from '@amazon/vinyl-util';
7
- import { expectTypeEquals, flushPromises, implementEventFakes, mockEvent, MockHTMLAudioElement, MockMediaKeyMessageEvent, MockMediaKeys, MockMediaKeySession, MockMediaKeySystemAccess, } from '@amazon/vinyl-util/browserTestUtil';
6
+ import { bufferToArrayBuffer, Deferred, DisposedError, never, } from '@amazon/vinyl-util';
7
+ import { expectIterableEquals, expectTypeEquals, flushPromises, implementEventFakes, mockEvent, MockHTMLAudioElement, MockMediaKeyMessageEvent, MockMediaKeys, MockMediaKeySession, MockMediaKeySystemAccess, } from '@amazon/vinyl-util/browserTestUtil';
8
8
  import { createEventSpy, setMockNavigator } from '@amazon/vinyl-util/testUtil';
9
9
  var any = jasmine.any;
10
10
  describe('StandardCommonEme', () => {
@@ -163,14 +163,22 @@ describe('StandardCommonEme', () => {
163
163
  });
164
164
  });
165
165
  describe('when created', () => {
166
- it('calls session.generateRequest() with the initData buffer', () => {
167
- expect(mediaKeySession.generateRequest).toHaveBeenCalledOnceWith('cenc', initData.buffer);
166
+ it('calls session.generateRequest() with the initData', () => {
167
+ expect(mediaKeySession.generateRequest).toHaveBeenCalledOnceWith('cenc', initData);
168
168
  mediaKeySession.generateRequest.calls.reset();
169
169
  const arrayBuffer = new ArrayBuffer(0);
170
170
  standardCommonMediaKeySession =
171
171
  new StandardCommonMediaKeySession(mediaKeySession, mimeType, 'cenc', arrayBuffer);
172
172
  expect(mediaKeySession.generateRequest).toHaveBeenCalledOnceWith('cenc', arrayBuffer);
173
173
  });
174
+ it('passes only the bytes an offset initData view spans', () => {
175
+ mediaKeySession.generateRequest.calls.reset();
176
+ const view = new Uint8Array([1, 2, 3, 4, 5]).subarray(1, 4);
177
+ standardCommonMediaKeySession =
178
+ new StandardCommonMediaKeySession(mediaKeySession, mimeType, 'cenc', view);
179
+ const [, passed] = mediaKeySession.generateRequest.calls.mostRecent().args;
180
+ expectIterableEquals(new Uint8Array(bufferToArrayBuffer(passed)), [2, 3, 4]);
181
+ });
174
182
  describe('when session.generateRequest rejects', () => {
175
183
  it('emits an error event', async () => {
176
184
  mediaKeySession.generateRequest.and.rejectWith(new Error('expected'));
@@ -14,6 +14,13 @@ describe('extractContentId', () => {
14
14
  expect(extractContentId(createContentIdByteArray('skd://example0'))).toBe('example0');
15
15
  });
16
16
  });
17
+ describe('with an offset view', () => {
18
+ it('reads only the bytes the view spans', () => {
19
+ const padded = createContentIdByteArray('\0\0skd://example0\0\0');
20
+ const view = padded.subarray(4, padded.byteLength - 4);
21
+ expect(extractContentId(view)).toBe('example0');
22
+ });
23
+ });
17
24
  describe('without match', () => {
18
25
  it('throws ValidationError', () => {
19
26
  expect(() => {
@@ -67,6 +67,7 @@ import './text/parseWebVtt.test';
67
67
  import './text/pickPreferredTextTrack.test';
68
68
  import './text/SidecarTextTrackController.test';
69
69
  import './text/SidecarTextTrackLoader.test';
70
+ import './text/TextTrack.test';
70
71
  import './text/VttCueStyle.test';
71
72
  import './track/AutoResetController.test';
72
73
  import './track/createSegmentDataProvider.test';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../test/unit/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../test/unit/index.ts"],"names":[],"mappings":"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"}
@@ -67,6 +67,7 @@ import './text/parseWebVtt.test';
67
67
  import './text/pickPreferredTextTrack.test';
68
68
  import './text/SidecarTextTrackController.test';
69
69
  import './text/SidecarTextTrackLoader.test';
70
+ import './text/TextTrack.test';
70
71
  import './text/VttCueStyle.test';
71
72
  import './track/AutoResetController.test';
72
73
  import './track/createSegmentDataProvider.test';
@@ -3,6 +3,7 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import { DrmKeySystem, drmProtectionValidator } from '@amazon/vinyl';
6
+ import { expectTypeStrictlyEquals } from '@amazon/vinyl-util/browserTestUtil';
6
7
  describe('drmProtectionValidator', () => {
7
8
  it('validates a complete DrmProtection', () => {
8
9
  expect(drmProtectionValidator.isValid({
@@ -37,3 +38,10 @@ describe('drmProtectionValidator', () => {
37
38
  expect(drmProtectionValidator.isValid({ keySystem: 123 })).toBeFalse();
38
39
  });
39
40
  });
41
+ describe('ALL_CONTENT_TYPES', () => {
42
+ it('provides a comprehensive list of all content types', () => {
43
+ // The player emits quality-change events per entry; a missing type
44
+ // silently emits none, and `satisfies` alone does not catch it.
45
+ expectTypeStrictlyEquals(true);
46
+ });
47
+ });
@@ -286,6 +286,32 @@ describe('BufferingControllerImpl', () => {
286
286
  expect(sourceBufferController.append).toHaveBeenCalledTimes(1);
287
287
  });
288
288
  });
289
+ describe('when the append budget grows while a segment is partly appended', () => {
290
+ it('appends only the bytes remaining in the segment', async () => {
291
+ // A budget wide enough to hold a whole segment, so draining the
292
+ // buffer can lift it back above the segment size mid-append.
293
+ bufferingController.dispose();
294
+ bufferingController = createBufferingController({
295
+ maxAppendSize: { audio: 500 },
296
+ minBuffer: 6,
297
+ });
298
+ bufferingController.activate();
299
+ setSegmentList([200, 400]);
300
+ await open(); // segment 0 appends whole, buffering 0-10s
301
+ await setTime(5); // segment 1 partly appends: 300 of 400 bytes
302
+ expect(getMostRecentAppendData().byteLength).toBe(300);
303
+ sourceBufferController.append.calls.reset();
304
+ // The playhead drains the buffer, widening the budget past the
305
+ // segment's full size.
306
+ await setTime(15.5);
307
+ const appended = sourceBufferController.append.calls
308
+ .allArgs()
309
+ .map(([data]) => data.byteLength);
310
+ // Only the 100 unappended bytes; re-appending all 400 would
311
+ // duplicate the 300 already buffered.
312
+ expect(appended[0]).toBe(100);
313
+ });
314
+ });
289
315
  describe('when contentType is undefined', () => {
290
316
  it('uses DEFAULT_MAX_APPEND_SIZE for max byte length', async () => {
291
317
  setSegmentList([DEFAULT_MAX_APPEND_SIZE * 2], 0, 'unknown');
@@ -89,6 +89,35 @@ describe('MediaSourceControllerImpl', () => {
89
89
  URL.revokeObjectURL.and.throwError(new Error('revoke failed'));
90
90
  expect(() => controller.deactivate()).not.toThrow();
91
91
  });
92
+ it('does not report a re-activated media source as ready to append', async () => {
93
+ // A track is deactivated and reactivated whenever an ad plays over
94
+ // it, and each activation builds its own media source, whose
95
+ // duration has not been set yet.
96
+ open();
97
+ await flushPromises();
98
+ const firstRef = controller.createSourceBuffer('audio', 'audio/mp4');
99
+ expect(controller.readyToAppend)
100
+ .withContext('ready on the first media source')
101
+ .toBeTrue();
102
+ firstRef.dispose(); // the buffering controller drops its buffers
103
+ controller.deactivate();
104
+ const secondSource = new MockMediaSource();
105
+ implementEventFakes(secondSource);
106
+ secondSource.addSourceBuffer.and.callFake(() => new MockSourceBuffer());
107
+ mediaSourceFactory.and.returnValue(secondSource);
108
+ controller.activate();
109
+ await flushPromises();
110
+ controller.createSourceBuffer('audio', 'audio/mp4');
111
+ expect(controller.readyToAppend)
112
+ .withContext('duration not yet set on the new media source')
113
+ .toBeFalse();
114
+ secondSource.readyState = 'open';
115
+ secondSource.dispatchEvent(mockEvent('sourceopen'));
116
+ await flushPromises();
117
+ expect(controller.readyToAppend)
118
+ .withContext('ready once the new duration is set')
119
+ .toBeTrue();
120
+ });
92
121
  });
93
122
  describe('duration', () => {
94
123
  it('sets media source duration after sourceopen', async () => {
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=TextTrack.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextTrack.test.d.ts","sourceRoot":"","sources":["../../../../../test/unit/text/TextTrack.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ /*
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { expectTypeStrictlyEquals } from '@amazon/vinyl-util/browserTestUtil';
6
+ describe('ALL_TEXT_TRACK_EVENTS', () => {
7
+ it('provides a comprehensive list of all text track events', () => {
8
+ // The player redispatches exactly these; an omission silently stops an
9
+ // event reaching consumers, and `satisfies` alone does not catch it.
10
+ expectTypeStrictlyEquals(true);
11
+ });
12
+ });