@amazon/vinyl 3.2.1 → 3.2.3-next.20261001143710
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/README.md +2 -2
- package/dist/index.cjs +98 -43
- package/dist/index.cjs.map +3 -3
- package/dist/index.js +126 -68
- package/dist/index.js.map +3 -3
- package/dist/test/benchmark.es5.js +7 -6
- package/dist/test/benchmark.js +35 -30
- package/dist/test/benchmark.js.map +3 -3
- package/dist/test/integ.es5.js +329 -312
- package/dist/test/integ.js +519 -187
- package/dist/test/integ.js.map +4 -4
- package/dist/types/current/ad/AdControllerImpl.d.ts.map +1 -1
- package/dist/types/current/ad/AdControllerImpl.js +15 -1
- package/dist/types/current/ad/discoverHlsInterstitials.js +13 -1
- 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 +11 -1
- package/dist/types/current/drm/commonEme/MsCommonEme.d.ts.map +1 -1
- package/dist/types/current/drm/commonEme/MsCommonEme.js +2 -2
- package/dist/types/current/drm/commonEme/StandardCommonEme.d.ts.map +1 -1
- package/dist/types/current/drm/commonEme/StandardCommonEme.js +3 -2
- package/dist/types/current/drm/commonEme/WebKitCommonEme.d.ts.map +1 -1
- package/dist/types/current/drm/commonEme/WebKitCommonEme.js +2 -2
- package/dist/types/current/drm/dom/MSMediaKeys.d.ts +1 -1
- package/dist/types/current/drm/dom/MSMediaKeys.d.ts.map +1 -1
- package/dist/types/current/drm/dom/WebKitMediaKeys.d.ts +1 -1
- package/dist/types/current/drm/dom/WebKitMediaKeys.d.ts.map +1 -1
- package/dist/types/current/drm/util/extractContentId.js +2 -2
- package/dist/types/current/playback/PlaybackControllerImpl.d.ts +9 -3
- package/dist/types/current/playback/PlaybackControllerImpl.d.ts.map +1 -1
- package/dist/types/current/playback/PlaybackControllerImpl.js +38 -33
- package/dist/types/current/streaming/MediaQualityMetadata.d.ts +3 -1
- package/dist/types/current/streaming/MediaQualityMetadata.d.ts.map +1 -1
- package/dist/types/current/streaming/SegmentControllerImpl.d.ts +1 -1
- package/dist/types/current/streaming/buffering/BufferingController.d.ts +1 -1
- package/dist/types/current/streaming/buffering/BufferingController.d.ts.map +1 -1
- package/dist/types/current/streaming/buffering/BufferingController.js +14 -5
- package/dist/types/current/streaming/buffering/MediaSourceController.d.ts.map +1 -1
- package/dist/types/current/streaming/buffering/MediaSourceController.js +4 -0
- package/dist/types/current/text/discoverDashTextTracks.d.ts +2 -2
- package/dist/types/current/text/discoverDashTextTracks.js +4 -3
- package/dist/types/current/text/parseWebVtt.d.ts.map +1 -1
- package/dist/types/current/text/parseWebVtt.js +3 -2
- package/dist/types/current/track/TrackController.d.ts.map +1 -1
- package/dist/types/current/track/TrackController.js +7 -0
- package/dist/types/current/track/hls/HlsManifestData.d.ts +14 -1
- package/dist/types/current/track/hls/HlsManifestData.d.ts.map +1 -1
- package/dist/types/current/track/hls/buildHlsMediaTimeline.d.ts.map +1 -1
- package/dist/types/current/track/hls/buildHlsMediaTimeline.js +10 -2
- package/dist/types/current/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
- package/dist/types/current/track/hls/createUrlHlsManifestProvider.d.ts.map +1 -1
- package/dist/types/current/track/hls/createUrlHlsManifestProvider.js +8 -3
- 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 +5 -6
- package/dist/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/types/ts3.7/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts3.7/playback/PlaybackControllerImpl.d.ts +9 -3
- package/dist/types/ts3.7/streaming/MediaQualityMetadata.d.ts +3 -1
- package/dist/types/ts3.7/streaming/SegmentControllerImpl.d.ts +1 -1
- package/dist/types/ts3.7/streaming/buffering/BufferingController.d.ts +1 -1
- package/dist/types/ts3.7/text/discoverDashTextTracks.d.ts +2 -2
- package/dist/types/ts3.7/track/hls/HlsManifestData.d.ts +14 -1
- package/dist/types/ts3.7/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
- package/dist/types/ts3.7/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/ts4.1/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts4.1/playback/PlaybackControllerImpl.d.ts +9 -3
- package/dist/types/ts4.1/streaming/MediaQualityMetadata.d.ts +3 -1
- package/dist/types/ts4.1/streaming/SegmentControllerImpl.d.ts +1 -1
- package/dist/types/ts4.1/streaming/buffering/BufferingController.d.ts +1 -1
- package/dist/types/ts4.1/text/discoverDashTextTracks.d.ts +2 -2
- package/dist/types/ts4.1/track/hls/HlsManifestData.d.ts +14 -1
- package/dist/types/ts4.1/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
- package/dist/types/ts4.1/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/ts4.7/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts4.7/playback/PlaybackControllerImpl.d.ts +9 -3
- package/dist/types/ts4.7/streaming/MediaQualityMetadata.d.ts +3 -1
- package/dist/types/ts4.7/streaming/SegmentControllerImpl.d.ts +1 -1
- package/dist/types/ts4.7/streaming/buffering/BufferingController.d.ts +1 -1
- package/dist/types/ts4.7/text/discoverDashTextTracks.d.ts +2 -2
- package/dist/types/ts4.7/track/hls/HlsManifestData.d.ts +14 -1
- package/dist/types/ts4.7/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
- package/dist/types/ts4.7/track/mse/MseTrack.d.ts +0 -1
- package/dist/unit/types/current/ad/AdControllerImpl.test.js +66 -0
- package/dist/unit/types/current/ad/discoverHlsInterstitials.test.js +29 -2
- package/dist/unit/types/current/drm/DrmControllerImpl.test.js +19 -1
- package/dist/unit/types/current/drm/commonEme/StandardCommonEme.test.js +12 -4
- package/dist/unit/types/current/drm/util/extractContentId.test.js +7 -0
- package/dist/unit/types/current/index.d.ts +1 -0
- package/dist/unit/types/current/index.d.ts.map +1 -1
- package/dist/unit/types/current/index.js +1 -0
- package/dist/unit/types/current/playback/PlaybackControllerImpl.test.js +15 -0
- package/dist/unit/types/current/streaming/MediaQualityMetadata.test.js +8 -0
- package/dist/unit/types/current/streaming/MseTrack.test.js +15 -0
- package/dist/unit/types/current/streaming/buffering/BufferingController.test.js +26 -0
- package/dist/unit/types/current/streaming/buffering/MediaSourceController.test.js +29 -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/discoverDashTextTracks.test.js +17 -0
- package/dist/unit/types/current/text/parseWebVtt.test.js +26 -0
- package/dist/unit/types/current/track/TrackController.test.js +15 -60
- package/dist/unit/types/current/track/hls/buildHlsMediaTimeline.test.js +22 -0
- package/dist/unit/types/current/track/hls/createUrlHlsManifestProvider.test.js +23 -0
- package/dist/unit/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/vinylTestUtil/types/current/tsconfig.tsbuildinfo +1 -1
- package/docs/CUSTOMIZATION_GUIDE.md +310 -0
- package/package.json +10 -10
- package/docs/DASH_MANIFEST_TRANSFORM_GUIDE.md +0 -236
|
@@ -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';
|
|
@@ -496,6 +496,21 @@ describe('PlaybackController', () => {
|
|
|
496
496
|
await clock.tick(controller.options.seekTimeout);
|
|
497
497
|
await seekExpectation;
|
|
498
498
|
});
|
|
499
|
+
it('resolves a superseded seek at once when its seeking event never fires', async () => {
|
|
500
|
+
// A source swap can leave the original seek's `seeking`
|
|
501
|
+
// event unfired (the default mock never emits it). A newer
|
|
502
|
+
// seek supersedes it; the stale one must resolve immediately
|
|
503
|
+
// rather than hang for the full seekTimeout.
|
|
504
|
+
setSeekable([[0, 100]]);
|
|
505
|
+
const first = controller.seekTo(50);
|
|
506
|
+
const second = controller.seekTo(60);
|
|
507
|
+
// No clock tick: the newer seek's abort resolves `first` now.
|
|
508
|
+
// (A full-timeout hang would require clock.tick(seekTimeout).)
|
|
509
|
+
await expectAsync(first).toBeResolved();
|
|
510
|
+
// `second`'s own `seeking` never fires either; park its
|
|
511
|
+
// rejection (settled on dispose) so it isn't unhandled.
|
|
512
|
+
second.catch(() => undefined);
|
|
513
|
+
});
|
|
499
514
|
it('times out pending seeks after seekTimeout', async () => {
|
|
500
515
|
const pendingSeekExpectation = expectAsync(controller.seekTo(60)).toBeRejectedWithError('seek timed out on seeking event after 30s');
|
|
501
516
|
setSeekable([[0, 100]]);
|
|
@@ -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
|
+
});
|
|
@@ -224,6 +224,21 @@ describe('MseTrack', () => {
|
|
|
224
224
|
abort: any(Abort),
|
|
225
225
|
});
|
|
226
226
|
});
|
|
227
|
+
it('aborts the drm session abort so key sessions close', async () => {
|
|
228
|
+
// Regression: MSE key sessions must be tied to the per-activation
|
|
229
|
+
// drmSessionAbort (fired by closeDrmSessions on deactivate), not a
|
|
230
|
+
// separate abort that never fires — otherwise sessions leak.
|
|
231
|
+
track = createTrack();
|
|
232
|
+
await awaitContentTypes();
|
|
233
|
+
getAudioStream().streamingQuality =
|
|
234
|
+
createEmptyMediaQualityMetadata();
|
|
235
|
+
track.activate({});
|
|
236
|
+
const { abort } = deps.drmController.initializeForPlayback.calls.mostRecent()
|
|
237
|
+
.args[1];
|
|
238
|
+
expect(abort.aborted()).toBeFalse();
|
|
239
|
+
track.deactivate();
|
|
240
|
+
expect(abort.aborted()).toBeTrue();
|
|
241
|
+
});
|
|
227
242
|
});
|
|
228
243
|
describe('error', () => {
|
|
229
244
|
it('returns the first emitted error', async () => {
|
|
@@ -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 @@
|
|
|
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
|
+
});
|
|
@@ -42,6 +42,19 @@ describe('discoverDashTextTracks', () => {
|
|
|
42
42
|
expect(result.length).toBe(1);
|
|
43
43
|
expect(result[0].language).toBe('es');
|
|
44
44
|
});
|
|
45
|
+
it('discovers a text AdaptationSet by its Representation mimeType', () => {
|
|
46
|
+
// DASH allows @mimeType on the Representation instead of the set.
|
|
47
|
+
const m = manifest(`
|
|
48
|
+
<AdaptationSet lang="fr">
|
|
49
|
+
<Representation id="fr-sub" mimeType="text/vtt" bandwidth="100">
|
|
50
|
+
<BaseURL>fr.vtt</BaseURL>
|
|
51
|
+
</Representation>
|
|
52
|
+
</AdaptationSet>`);
|
|
53
|
+
const result = discoverDashTextTracks(m, baseUrl);
|
|
54
|
+
expect(result.length).toBe(1);
|
|
55
|
+
expect(result[0].language).toBe('fr');
|
|
56
|
+
expect(result[0].uri).toBe('https://example.com/dash/fr.vtt');
|
|
57
|
+
});
|
|
45
58
|
it('classifies kind=captions when role=caption is set', () => {
|
|
46
59
|
const m = manifest(`
|
|
47
60
|
<AdaptationSet contentType="text" lang="en" mimeType="text/vtt">
|
|
@@ -96,6 +109,10 @@ describe('discoverDashTextTracks', () => {
|
|
|
96
109
|
</AdaptationSet>`);
|
|
97
110
|
expect(discoverDashTextTracks(m, baseUrl)).toEqual([]);
|
|
98
111
|
});
|
|
112
|
+
it('skips a non-text AdaptationSet with no Representation', () => {
|
|
113
|
+
const m = manifest(`<AdaptationSet contentType="audio"/>`);
|
|
114
|
+
expect(discoverDashTextTracks(m, baseUrl)).toEqual([]);
|
|
115
|
+
});
|
|
99
116
|
it('skips text AdaptationSets carrying segmented codecs (stpp/wvtt)', () => {
|
|
100
117
|
const m = manifest(`
|
|
101
118
|
<AdaptationSet contentType="text" mimeType="application/mp4" codecs="stpp">
|
|
@@ -382,6 +382,32 @@ hi`;
|
|
|
382
382
|
expect(cues.length).toBe(1);
|
|
383
383
|
expect(cues[0].text).toBe('hi');
|
|
384
384
|
});
|
|
385
|
+
it('parses a cue that follows the signature with no blank line', () => {
|
|
386
|
+
// The header block ends at a timing line as well as at a blank line
|
|
387
|
+
// (WebVTT file parsing breaks out of the header loop on `-->`), so a
|
|
388
|
+
// document omitting the blank line still yields its cues.
|
|
389
|
+
const text = `WEBVTT
|
|
390
|
+
00:00:01.000 --> 00:00:02.000
|
|
391
|
+
hi
|
|
392
|
+
|
|
393
|
+
00:00:03.000 --> 00:00:04.000
|
|
394
|
+
there`;
|
|
395
|
+
const cues = parseWebVtt(text).cues;
|
|
396
|
+
expect(cues.length).toBe(2);
|
|
397
|
+
expect(cues[0].startTime).toBe(1);
|
|
398
|
+
expect(cues[0].text).toBe('hi');
|
|
399
|
+
expect(cues[1].text).toBe('there');
|
|
400
|
+
});
|
|
401
|
+
it('keeps header lines as header when a cue follows with no blank line', () => {
|
|
402
|
+
const text = `WEBVTT
|
|
403
|
+
Kind: captions
|
|
404
|
+
00:00:01.000 --> 00:00:02.000
|
|
405
|
+
hi`;
|
|
406
|
+
const cues = parseWebVtt(text).cues;
|
|
407
|
+
expect(cues.length).toBe(1);
|
|
408
|
+
expect(cues[0].id).toBeNull();
|
|
409
|
+
expect(cues[0].text).toBe('hi');
|
|
410
|
+
});
|
|
385
411
|
it('handles trailing identifier without timing line', () => {
|
|
386
412
|
// Identifier with no following timing line - cue is dropped, parser
|
|
387
413
|
// breaks out cleanly without throwing.
|
|
@@ -597,49 +597,6 @@ describe('TrackControllerImpl', () => {
|
|
|
597
597
|
expect(track.clearPrefetch).toHaveBeenCalledTimes(1);
|
|
598
598
|
}
|
|
599
599
|
});
|
|
600
|
-
it('also clears prefetch on preloaded ad tracks', async () => {
|
|
601
|
-
pending('REVIEW: the refactor no longer proactively preloads ad tracks ' +
|
|
602
|
-
'discovered on the current track (ad tracks are created on ' +
|
|
603
|
-
'adEntered only). Decide: intended removal (delete this spec) ' +
|
|
604
|
-
'or regression (restore discovery-time ad preloading).');
|
|
605
|
-
const [main] = createLoadOptionsList(1);
|
|
606
|
-
trackController.load(main);
|
|
607
|
-
const track = trackController.activeTrack;
|
|
608
|
-
const ads = {
|
|
609
|
-
trackUri: main.uri,
|
|
610
|
-
adBreaks: [
|
|
611
|
-
{
|
|
612
|
-
id: 'b1',
|
|
613
|
-
startTime: 5,
|
|
614
|
-
duration: 10,
|
|
615
|
-
placement: 'midroll',
|
|
616
|
-
restrict: {},
|
|
617
|
-
once: false,
|
|
618
|
-
resumeOffset: null,
|
|
619
|
-
playoutLimit: null,
|
|
620
|
-
resolutionTimeOffset: null,
|
|
621
|
-
skipControl: () => null,
|
|
622
|
-
ads: () => Promise.resolve([
|
|
623
|
-
{
|
|
624
|
-
id: 'a1',
|
|
625
|
-
startTime: 5,
|
|
626
|
-
duration: 10,
|
|
627
|
-
uri: 'https://ads/a.m3u8',
|
|
628
|
-
},
|
|
629
|
-
]),
|
|
630
|
-
},
|
|
631
|
-
],
|
|
632
|
-
};
|
|
633
|
-
track.ads = ads;
|
|
634
|
-
track.dispatch('adsChange', { previous: null, current: ads });
|
|
635
|
-
// Ad resolution runs on microtasks.
|
|
636
|
-
await Promise.resolve();
|
|
637
|
-
await Promise.resolve();
|
|
638
|
-
await Promise.resolve();
|
|
639
|
-
const adTrack = trackController.getCachedTrack('https://ads/a.m3u8');
|
|
640
|
-
trackController.clearPrefetch();
|
|
641
|
-
expect(adTrack.clearPrefetch).toHaveBeenCalled();
|
|
642
|
-
});
|
|
643
600
|
});
|
|
644
601
|
describe('clearQueue', () => {
|
|
645
602
|
it('clears the queue without unloading the current track', async () => {
|
|
@@ -1124,6 +1081,21 @@ describe('TrackControllerImpl', () => {
|
|
|
1124
1081
|
expect(adTrack).withContext('midroll ad track warmed').toBeDefined();
|
|
1125
1082
|
expect(adTrack.preload).toHaveBeenCalled();
|
|
1126
1083
|
});
|
|
1084
|
+
it('clears prefetch on a preloaded ad track', async () => {
|
|
1085
|
+
const [main] = createLoadOptionsList(1);
|
|
1086
|
+
factoryGivingBreak(main.uri, []); // records created tracks; no preroll
|
|
1087
|
+
trackController.load(main);
|
|
1088
|
+
await flushAds();
|
|
1089
|
+
deps.adController.dispatch('adPreload', {
|
|
1090
|
+
adBreak: midrollBreak('https://ads/mid.m3u8'),
|
|
1091
|
+
});
|
|
1092
|
+
await flushAds();
|
|
1093
|
+
const adTrack = created.get('https://ads/mid.m3u8');
|
|
1094
|
+
// Ad tracks are not in the content cache, so this only holds if
|
|
1095
|
+
// clearPrefetch reaches the per-parent ad track store too.
|
|
1096
|
+
trackController.clearPrefetch();
|
|
1097
|
+
expect(adTrack.clearPrefetch).toHaveBeenCalledTimes(1);
|
|
1098
|
+
});
|
|
1127
1099
|
it('ignores adPreload when there is no parent track', () => {
|
|
1128
1100
|
expect(() => deps.adController.dispatch('adPreload', {
|
|
1129
1101
|
adBreak: midrollBreak('https://ads/mid.m3u8'),
|
|
@@ -1307,23 +1279,6 @@ describe('TrackControllerImpl', () => {
|
|
|
1307
1279
|
const track = trackController.activeTrack;
|
|
1308
1280
|
expect(track.activate).toHaveBeenCalledWith(objectContaining({ startTime: 3 }));
|
|
1309
1281
|
});
|
|
1310
|
-
it('skips the deferred resume if interrupted before the frame', async () => {
|
|
1311
|
-
pending('REVIEW: content resume on adBreakCompleted is now synchronous ' +
|
|
1312
|
-
'(no deferred/interruptible frame), so this interruption ' +
|
|
1313
|
-
'guard no longer applies. Decide: intended or restore deferral.');
|
|
1314
|
-
const [main] = createLoadOptionsList(1);
|
|
1315
|
-
trackController.load(main);
|
|
1316
|
-
const changeSpy = createEventSpy(trackController, 'trackActivated');
|
|
1317
|
-
deps.adController.dispatch('adBreakCompleted', {
|
|
1318
|
-
adBreak: adBreak('midroll'),
|
|
1319
|
-
resumePosition: 5,
|
|
1320
|
-
});
|
|
1321
|
-
// Interrupt: a new ad becomes current before the deferred resume runs.
|
|
1322
|
-
deps.adController.currentAd = { ...ad, id: 'other' };
|
|
1323
|
-
await clock.tick();
|
|
1324
|
-
// The deferred setQueue was skipped; no track change occurred.
|
|
1325
|
-
expect(changeSpy).not.toHaveBeenCalled();
|
|
1326
|
-
});
|
|
1327
1282
|
it('advances to the next track after a postroll ad when one exists', async () => {
|
|
1328
1283
|
const list = createLoadOptionsList(2);
|
|
1329
1284
|
trackController.load(...list);
|
|
@@ -542,6 +542,28 @@ describe('buildHlsMediaTimeline', () => {
|
|
|
542
542
|
expect(initCall[1]?.headers).toEqual(jasmine.objectContaining({ Range: 'bytes=0-499' }));
|
|
543
543
|
fetchSpy.and.callThrough();
|
|
544
544
|
});
|
|
545
|
+
it('resolves segment and map URIs against the media playlist baseUrl', async () => {
|
|
546
|
+
const variant = createVariant('v1.m3u8', 128000);
|
|
547
|
+
const playlist = {
|
|
548
|
+
...createMediaPlaylist([10]),
|
|
549
|
+
// The media playlist was redirected away from the main playlist's
|
|
550
|
+
// directory.
|
|
551
|
+
baseUrl: 'https://redirect.example.net/hls/v1.m3u8',
|
|
552
|
+
};
|
|
553
|
+
const manifestData = createManifestData([variant], playlist);
|
|
554
|
+
const fetchSpy = spyOn(globalThis, 'fetch').and.callFake(() => Promise.resolve(new Response(new ArrayBuffer(100))));
|
|
555
|
+
const timeline = buildHlsMediaTimeline(deps, manifestData);
|
|
556
|
+
const quality = timeline.periods[0].qualities[0];
|
|
557
|
+
const segment = await quality.getSegment(5);
|
|
558
|
+
await segment.initData();
|
|
559
|
+
await segment.data();
|
|
560
|
+
const urls = fetchSpy.calls.allArgs().map(([input]) => String(input));
|
|
561
|
+
expect(urls).toEqual([
|
|
562
|
+
'https://redirect.example.net/hls/init.mp4',
|
|
563
|
+
'https://redirect.example.net/hls/seg0.m4s',
|
|
564
|
+
]);
|
|
565
|
+
fetchSpy.and.callThrough();
|
|
566
|
+
});
|
|
545
567
|
it('getDuration throws when no variants', async () => {
|
|
546
568
|
const manifestData = createManifestData([], createMediaPlaylist([]));
|
|
547
569
|
const timeline = buildHlsMediaTimeline(deps, manifestData);
|
|
@@ -113,6 +113,29 @@ describe('fetchMediaPlaylist', () => {
|
|
|
113
113
|
expect(playlist.segments.length).toBe(1);
|
|
114
114
|
expect(String(mockRequester.request.calls.argsFor(0)[0])).toBe('https://example.com/path/audio.m3u8');
|
|
115
115
|
});
|
|
116
|
+
it('sets the baseUrl from the response URL', async () => {
|
|
117
|
+
mockRequester.request.and.callFake(() => {
|
|
118
|
+
const resp = new Response(mediaM3u8);
|
|
119
|
+
Object.defineProperty(resp, 'url', {
|
|
120
|
+
value: 'https://redirected.com/hls/audio.m3u8',
|
|
121
|
+
});
|
|
122
|
+
return Promise.resolve(resp);
|
|
123
|
+
});
|
|
124
|
+
const playlist = await fetchMediaPlaylist({
|
|
125
|
+
uri: 'audio.m3u8',
|
|
126
|
+
baseUrl: 'https://example.com/path/main.m3u8',
|
|
127
|
+
defines: undefined,
|
|
128
|
+
});
|
|
129
|
+
expect(playlist.baseUrl).toBe('https://redirected.com/hls/audio.m3u8');
|
|
130
|
+
});
|
|
131
|
+
it('falls back to the requested URL when the response has no URL', async () => {
|
|
132
|
+
const playlist = await fetchMediaPlaylist({
|
|
133
|
+
uri: 'audio.m3u8',
|
|
134
|
+
baseUrl: 'https://example.com/path/main.m3u8',
|
|
135
|
+
defines: undefined,
|
|
136
|
+
});
|
|
137
|
+
expect(playlist.baseUrl).toBe('https://example.com/path/audio.m3u8');
|
|
138
|
+
});
|
|
116
139
|
it('resolves EXT-X-DEFINE:QUERYPARAM from the playlist URL query string', async () => {
|
|
117
140
|
mockRequester.request.and.callFake(() => Promise.resolve(new Response([
|
|
118
141
|
'#EXTM3U',
|