@amazon/vinyl 3.2.0 → 3.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 +65 -45
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +90 -69
- package/dist/index.js.map +3 -3
- package/dist/test/integ.es5.js +303 -287
- package/dist/test/integ.js +328 -71
- package/dist/test/integ.js.map +2 -2
- package/dist/types/current/ad/AdControllerImpl.d.ts +18 -2
- package/dist/types/current/ad/AdControllerImpl.d.ts.map +1 -1
- package/dist/types/current/ad/AdControllerImpl.js +42 -20
- 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/playback/PlaybackControllerImpl.d.ts +8 -2
- package/dist/types/current/playback/PlaybackControllerImpl.d.ts.map +1 -1
- package/dist/types/current/playback/PlaybackControllerImpl.js +38 -33
- package/dist/types/current/playback/createStallMonitor.d.ts.map +1 -1
- package/dist/types/current/playback/createStallMonitor.js +19 -14
- 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/ad/AdControllerImpl.d.ts +18 -2
- package/dist/types/ts3.7/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts3.7/playback/PlaybackControllerImpl.d.ts +8 -2
- package/dist/types/ts3.7/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/ts4.1/ad/AdControllerImpl.d.ts +18 -2
- package/dist/types/ts4.1/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts4.1/playback/PlaybackControllerImpl.d.ts +8 -2
- package/dist/types/ts4.1/track/mse/MseTrack.d.ts +0 -1
- package/dist/types/ts4.7/ad/AdControllerImpl.d.ts +18 -2
- package/dist/types/ts4.7/drm/DrmControllerImpl.d.ts +6 -0
- package/dist/types/ts4.7/playback/PlaybackControllerImpl.d.ts +8 -2
- package/dist/types/ts4.7/track/mse/MseTrack.d.ts +0 -1
- package/dist/unit/types/current/ad/AdControllerImpl.test.js +110 -4
- package/dist/unit/types/current/drm/DrmControllerImpl.test.js +19 -1
- package/dist/unit/types/current/playback/PlaybackControllerImpl.test.js +15 -0
- package/dist/unit/types/current/playback/createStallMonitor.test.js +38 -0
- package/dist/unit/types/current/streaming/MseTrack.test.js +15 -0
- package/dist/unit/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/vinylTestUtil/index.js +10 -1
- package/dist/vinylTestUtil/index.js.map +2 -2
- package/dist/vinylTestUtil/types/current/assets/vinylTestAssets.d.ts +5 -0
- package/dist/vinylTestUtil/types/current/assets/vinylTestAssets.d.ts.map +1 -1
- package/dist/vinylTestUtil/types/current/assets/vinylTestAssets.js +9 -0
- package/dist/vinylTestUtil/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/vinylTestUtil/types/ts3.7/assets/vinylTestAssets.d.ts +5 -0
- package/dist/vinylTestUtil/types/ts4.1/assets/vinylTestAssets.d.ts +5 -0
- package/dist/vinylTestUtil/types/ts4.7/assets/vinylTestAssets.d.ts +5 -0
- package/package.json +10 -10
package/dist/test/integ.js
CHANGED
|
@@ -9953,6 +9953,7 @@ ${this.lastInitStack}` : "";
|
|
|
9953
9953
|
|
|
9954
9954
|
// src/ad/AdControllerImpl.ts
|
|
9955
9955
|
var AD_START_TOLERANCE = 0.05;
|
|
9956
|
+
var PLAYOUT_LIMIT_TOLERANCE = 1;
|
|
9956
9957
|
var defaultAdControllerImplOptions = {
|
|
9957
9958
|
adLoadTimeout: 15,
|
|
9958
9959
|
preloadAheadTime: 10
|
|
@@ -10443,23 +10444,29 @@ ${this.lastInitStack}` : "";
|
|
|
10443
10444
|
});
|
|
10444
10445
|
}
|
|
10445
10446
|
/**
|
|
10446
|
-
*
|
|
10447
|
-
*
|
|
10447
|
+
* Enforces the break-level playout limit (X-PLAYOUT-LIMIT): a budget shared
|
|
10448
|
+
* across all of the break's ads. When cumulative playout reaches it, the
|
|
10449
|
+
* whole break ends, dropping any ads that have not started.
|
|
10450
|
+
*
|
|
10451
|
+
* This is deliberately NOT a per-ad cap. Each ad asset is its own source and
|
|
10452
|
+
* ends on its media `ended` (see the 'ended' handler), which is what advances
|
|
10453
|
+
* a multi-ad break. Ending an ad at its declared per-ad DURATION instead would
|
|
10454
|
+
* truncate the real asset whenever a packager under-declares it — e.g. rounds
|
|
10455
|
+
* a 6.732s asset down to a whole-second 6 — cutting off the fractional tail.
|
|
10448
10456
|
*/
|
|
10449
10457
|
enforcePlayoutLimits(adState) {
|
|
10458
|
+
if (!adState.started) return;
|
|
10459
|
+
const { parentBreak } = adState;
|
|
10460
|
+
const limit = parentBreak.adBreak.playoutLimit;
|
|
10461
|
+
if (limit == null) return;
|
|
10450
10462
|
const pC = this.deps.playbackController;
|
|
10451
|
-
const
|
|
10452
|
-
if (
|
|
10453
|
-
|
|
10454
|
-
|
|
10455
|
-
const limit = adBreak.playoutLimit;
|
|
10456
|
-
if (limit != null && parentBreak.playoutElapsed + elapsed >= limit) {
|
|
10457
|
-
parentBreak.clear();
|
|
10458
|
-
this.endAd(adState);
|
|
10459
|
-
} else if (ad.duration != null && elapsed >= ad.duration) {
|
|
10460
|
-
this.endAd(adState);
|
|
10461
|
-
}
|
|
10463
|
+
const elapsed = Math.max(0, pC.currentTime - adState.timeStart);
|
|
10464
|
+
if (parentBreak.playoutElapsed + elapsed < limit) return;
|
|
10465
|
+
if (isFinite(pC.duration) && pC.duration > 0 && pC.duration - pC.currentTime <= PLAYOUT_LIMIT_TOLERANCE) {
|
|
10466
|
+
return;
|
|
10462
10467
|
}
|
|
10468
|
+
parentBreak.clear();
|
|
10469
|
+
this.endAd(adState);
|
|
10463
10470
|
}
|
|
10464
10471
|
setPendingBreaks(newPending) {
|
|
10465
10472
|
this.pendingAdBreaks = newPending.filter(
|
|
@@ -14000,6 +14007,7 @@ ${this.lastInitStack}` : "";
|
|
|
14000
14007
|
// src/drm/DrmControllerImpl.ts
|
|
14001
14008
|
var LICENSE_TIMEOUT = 90;
|
|
14002
14009
|
var LICENSE_TIMEOUT_MESSAGE = "License provider timed out after {time}s";
|
|
14010
|
+
var EXCESSIVE_SESSION_COUNT = 20;
|
|
14003
14011
|
var DrmControllerImpl = class extends EventHostImpl {
|
|
14004
14012
|
constructor(deps, options) {
|
|
14005
14013
|
super();
|
|
@@ -14216,6 +14224,13 @@ ${this.lastInitStack}` : "";
|
|
|
14216
14224
|
trackUri
|
|
14217
14225
|
});
|
|
14218
14226
|
this.sessions.push(newSession);
|
|
14227
|
+
logVerbose(this, `total sessions: ${this.sessions.length}`);
|
|
14228
|
+
if (this.sessions.length === EXCESSIVE_SESSION_COUNT + 1) {
|
|
14229
|
+
logWarn(
|
|
14230
|
+
this,
|
|
14231
|
+
`${this.sessions.length} open key sessions exceeds ${EXCESSIVE_SESSION_COUNT}; sessions may be leaking (not closing on track deactivation)`
|
|
14232
|
+
);
|
|
14233
|
+
}
|
|
14219
14234
|
this.dispatch("sessionCreate", {
|
|
14220
14235
|
initDataType: newSession.initDataType,
|
|
14221
14236
|
mimeType: newSession.mimeType
|
|
@@ -15214,7 +15229,7 @@ ${this.lastInitStack}` : "";
|
|
|
15214
15229
|
// src/global/environment.ts
|
|
15215
15230
|
var vinylVersion = parseVersion(
|
|
15216
15231
|
/* istanbul ignore next */
|
|
15217
|
-
"3.2.
|
|
15232
|
+
"3.2.2"
|
|
15218
15233
|
);
|
|
15219
15234
|
|
|
15220
15235
|
// src/global/globalRef.ts
|
|
@@ -15371,6 +15386,7 @@ ${this.lastInitStack}` : "";
|
|
|
15371
15386
|
];
|
|
15372
15387
|
|
|
15373
15388
|
// src/playback/createStallMonitor.ts
|
|
15389
|
+
var PROGRESS_EPSILON = 1e-6;
|
|
15374
15390
|
function createStallMonitor(controller, callbacks, options = {}) {
|
|
15375
15391
|
var _a3, _b;
|
|
15376
15392
|
const stallThresholdMs = ((_a3 = options.stallThreshold) != null ? _a3 : 1) * 1e3;
|
|
@@ -15379,6 +15395,7 @@ ${this.lastInitStack}` : "";
|
|
|
15379
15395
|
let lastProgressAt = Date.now();
|
|
15380
15396
|
let inStall = false;
|
|
15381
15397
|
let pollId = null;
|
|
15398
|
+
const { add, dispose } = createDisposer();
|
|
15382
15399
|
const endStall = (reason) => {
|
|
15383
15400
|
if (!inStall) return;
|
|
15384
15401
|
inStall = false;
|
|
@@ -15395,6 +15412,7 @@ ${this.lastInitStack}` : "";
|
|
|
15395
15412
|
clearInterval(pollId);
|
|
15396
15413
|
pollId = null;
|
|
15397
15414
|
};
|
|
15415
|
+
add(stopPoll);
|
|
15398
15416
|
const startPoll = () => {
|
|
15399
15417
|
if (pollId != null) return;
|
|
15400
15418
|
pollId = setInterval(() => {
|
|
@@ -15410,17 +15428,18 @@ ${this.lastInitStack}` : "";
|
|
|
15410
15428
|
observedPlaying = false;
|
|
15411
15429
|
stopPoll();
|
|
15412
15430
|
};
|
|
15413
|
-
const { add, dispose } = createDisposer();
|
|
15414
15431
|
add(
|
|
15415
15432
|
controller.on("playing", () => {
|
|
15416
15433
|
if (inStall) endStall("playing" /* PLAYING */);
|
|
15417
|
-
|
|
15434
|
+
lastProgressAt = Date.now();
|
|
15418
15435
|
observedPlaying = true;
|
|
15419
15436
|
startPoll();
|
|
15420
15437
|
})
|
|
15421
15438
|
);
|
|
15422
15439
|
add(
|
|
15423
|
-
controller.on("timeUpdate", () => {
|
|
15440
|
+
controller.on("timeUpdate", ({ previous, current }) => {
|
|
15441
|
+
if (previous != null && current - previous <= PROGRESS_EPSILON)
|
|
15442
|
+
return;
|
|
15424
15443
|
if (inStall) endStall("playing" /* PLAYING */);
|
|
15425
15444
|
lastProgressAt = Date.now();
|
|
15426
15445
|
})
|
|
@@ -15428,13 +15447,7 @@ ${this.lastInitStack}` : "";
|
|
|
15428
15447
|
add(controller.on("pause", () => suspend("pause" /* PAUSE */)));
|
|
15429
15448
|
add(controller.on("seeking", () => suspend("seeking" /* SEEKING */)));
|
|
15430
15449
|
add(controller.on("emptied", () => suspend("emptied" /* EMPTIED */)));
|
|
15431
|
-
|
|
15432
|
-
return () => {
|
|
15433
|
-
if (stopped) return;
|
|
15434
|
-
stopped = true;
|
|
15435
|
-
stopPoll();
|
|
15436
|
-
dispose();
|
|
15437
|
-
};
|
|
15450
|
+
return dispose;
|
|
15438
15451
|
}
|
|
15439
15452
|
|
|
15440
15453
|
// src/playback/error/InvalidSeekError.ts
|
|
@@ -15710,15 +15723,13 @@ ${this.lastInitStack}` : "";
|
|
|
15710
15723
|
__publicField(this, "_playing", false);
|
|
15711
15724
|
__publicField(this, "_seeking", false);
|
|
15712
15725
|
__publicField(this, "_waiting", false);
|
|
15713
|
-
|
|
15714
|
-
__publicField(this, "_seekId", 0);
|
|
15726
|
+
__publicField(this, "seekAbortSlot", createAbortSlot());
|
|
15715
15727
|
// Stops the stall detector started after the last seek, if any.
|
|
15716
15728
|
__publicField(this, "stopStallDetection", null);
|
|
15717
15729
|
// default user volume (0.0 to 1.0 scale)
|
|
15718
15730
|
__publicField(this, "userVolume", 1);
|
|
15719
15731
|
__publicField(this, "_pendingPlay", null);
|
|
15720
15732
|
__publicField(this, "playAbort", null);
|
|
15721
|
-
__publicField(this, "disposeAbort", new Abort());
|
|
15722
15733
|
__publicField(this, "options");
|
|
15723
15734
|
this.options = __spreadValues(__spreadProps(__spreadValues({}, defaultPlaybackControllerImplOptions), {
|
|
15724
15735
|
minSeekableBuffer: getMinSeekableBufferDefault()
|
|
@@ -15729,8 +15740,7 @@ ${this.lastInitStack}` : "";
|
|
|
15729
15740
|
const { add } = this.disposer;
|
|
15730
15741
|
add(() => {
|
|
15731
15742
|
var _a3;
|
|
15732
|
-
this.
|
|
15733
|
-
this.disposeAbort.dispose();
|
|
15743
|
+
this.seekAbortSlot.abort();
|
|
15734
15744
|
(_a3 = this.stopStallDetection) == null ? void 0 : _a3.call(this);
|
|
15735
15745
|
});
|
|
15736
15746
|
this.domEvents = add(
|
|
@@ -16143,14 +16153,10 @@ ${this.lastInitStack}` : "";
|
|
|
16143
16153
|
async seekTo(time, tolerance = 0.5) {
|
|
16144
16154
|
var _a3;
|
|
16145
16155
|
logDebug(this, `seekTo: ${time}`);
|
|
16146
|
-
const seekId = ++this._seekId;
|
|
16147
16156
|
(_a3 = this.stopStallDetection) == null ? void 0 : _a3.call(this);
|
|
16148
16157
|
this.stopStallDetection = null;
|
|
16149
|
-
|
|
16150
|
-
|
|
16151
|
-
logDebug(this, `seekTo: ${time} superseded by a newer seek`);
|
|
16152
|
-
return true;
|
|
16153
|
-
};
|
|
16158
|
+
this.seekAbortSlot.abort();
|
|
16159
|
+
const seekAbort = this.seekAbortSlot.value;
|
|
16154
16160
|
const nextEvent = (type, options) => {
|
|
16155
16161
|
var _a4;
|
|
16156
16162
|
return nextEventAsPromise(this, type, {
|
|
@@ -16158,12 +16164,25 @@ ${this.lastInitStack}` : "";
|
|
|
16158
16164
|
timeoutMessage: `seek timed out on ${type} event after {time}s`,
|
|
16159
16165
|
timeoutOrigin: ErrorOrigin.INTERNAL,
|
|
16160
16166
|
timeoutLevel: "warn" /* WARN */,
|
|
16161
|
-
abort:
|
|
16167
|
+
abort: seekAbort
|
|
16162
16168
|
});
|
|
16163
16169
|
};
|
|
16170
|
+
try {
|
|
16171
|
+
await this.doSeek(time, tolerance, seekAbort, nextEvent);
|
|
16172
|
+
} catch (error) {
|
|
16173
|
+
if (seekAbort.aborted() && !this.disposed) return;
|
|
16174
|
+
throw error;
|
|
16175
|
+
}
|
|
16176
|
+
}
|
|
16177
|
+
/**
|
|
16178
|
+
* The body of a single {@link seekTo} attempt. Extracted so {@link seekTo}
|
|
16179
|
+
* can wrap it with per-seek abort/supersession handling. `seekAbort` is
|
|
16180
|
+
* aborted when a newer seek supersedes this one (or on dispose).
|
|
16181
|
+
* @private
|
|
16182
|
+
*/
|
|
16183
|
+
async doSeek(time, tolerance, seekAbort, nextEvent) {
|
|
16164
16184
|
if (!this.hasMetadata) {
|
|
16165
16185
|
await nextEvent("loadedMetadata");
|
|
16166
|
-
if (superseded()) return;
|
|
16167
16186
|
}
|
|
16168
16187
|
const seekable = this.seekable;
|
|
16169
16188
|
const range = seekable.getRangeAt(
|
|
@@ -16194,7 +16213,7 @@ ${this.lastInitStack}` : "";
|
|
|
16194
16213
|
);
|
|
16195
16214
|
} else {
|
|
16196
16215
|
const nullIfStuck = (error) => {
|
|
16197
|
-
if (this.
|
|
16216
|
+
if (this.disposed) throw error;
|
|
16198
16217
|
return null;
|
|
16199
16218
|
};
|
|
16200
16219
|
const seekOnce = async (reSeeking) => {
|
|
@@ -16208,7 +16227,7 @@ ${this.lastInitStack}` : "";
|
|
|
16208
16227
|
}).catch(nullIfStuck);
|
|
16209
16228
|
};
|
|
16210
16229
|
let seekedEvent = await seekOnce(false);
|
|
16211
|
-
for (let attempt = 0; !
|
|
16230
|
+
for (let attempt = 0; !seekAbort.aborted() && attempt < SEEK_RETRY_LIMIT && (seekedEvent === null || seekedEvent.reason === "seeked" && !closeTo(clampedTime, this.currentTime, tolerance)); attempt++) {
|
|
16212
16231
|
if (seekedEvent === null) void this.media.play().catch(noop);
|
|
16213
16232
|
logDebug(this, `seekTo: re-seeking to ${clampedTime}`);
|
|
16214
16233
|
seekedEvent = await seekOnce(true);
|
|
@@ -16216,7 +16235,7 @@ ${this.lastInitStack}` : "";
|
|
|
16216
16235
|
if ((seekedEvent == null ? void 0 : seekedEvent.reason) === "emptied") {
|
|
16217
16236
|
throw new AbortError();
|
|
16218
16237
|
}
|
|
16219
|
-
if (!this.paused) this.startStallDetection();
|
|
16238
|
+
if (!this.paused && !seekAbort.aborted()) this.startStallDetection();
|
|
16220
16239
|
}
|
|
16221
16240
|
}
|
|
16222
16241
|
/**
|
|
@@ -20556,7 +20575,6 @@ ${this.lastInitStack}` : "";
|
|
|
20556
20575
|
const deps = depsContainer.dependencies;
|
|
20557
20576
|
super(uri, type, deps);
|
|
20558
20577
|
__publicField(this, "streams", []);
|
|
20559
|
-
__publicField(this, "disposeAbort", new Abort());
|
|
20560
20578
|
__publicField(this, "lastPreloadOptions", null);
|
|
20561
20579
|
__publicField(this, "allFetchedRanges", []);
|
|
20562
20580
|
__publicField(this, "_fetchedRanges", new IntersectionRanges(
|
|
@@ -20581,7 +20599,7 @@ ${this.lastInitStack}` : "";
|
|
|
20581
20599
|
if (this.active) {
|
|
20582
20600
|
this.deps.drmController.initializeForPlayback(event.current, {
|
|
20583
20601
|
trackUri: this.uri,
|
|
20584
|
-
abort: this.
|
|
20602
|
+
abort: this.drmSessionAbort.value
|
|
20585
20603
|
});
|
|
20586
20604
|
}
|
|
20587
20605
|
});
|
|
@@ -20589,7 +20607,7 @@ ${this.lastInitStack}` : "";
|
|
|
20589
20607
|
if (event.current == null) return;
|
|
20590
20608
|
this.deps.drmController.setBufferingDrmInfo(event.current, {
|
|
20591
20609
|
trackUri: this.uri,
|
|
20592
|
-
abort: this.
|
|
20610
|
+
abort: this.drmSessionAbort.value
|
|
20593
20611
|
});
|
|
20594
20612
|
});
|
|
20595
20613
|
add(
|
|
@@ -20827,7 +20845,7 @@ ${this.lastInitStack}` : "";
|
|
|
20827
20845
|
this.streams.forEach((stream) => {
|
|
20828
20846
|
this.deps.drmController.initializeForPlayback(
|
|
20829
20847
|
stream.streamingQuality,
|
|
20830
|
-
{ trackUri: this.uri, abort: this.
|
|
20848
|
+
{ trackUri: this.uri, abort: this.drmSessionAbort.value }
|
|
20831
20849
|
);
|
|
20832
20850
|
});
|
|
20833
20851
|
this.deps.playbackSource.src = this.deps.mediaSourceController.activate();
|
|
@@ -20853,7 +20871,7 @@ ${this.lastInitStack}` : "";
|
|
|
20853
20871
|
this.callOnStreams("deactivate");
|
|
20854
20872
|
this.deps.drmController.setBufferingDrmInfo(null, {
|
|
20855
20873
|
trackUri: this.uri,
|
|
20856
|
-
abort: this.
|
|
20874
|
+
abort: this.drmSessionAbort.value
|
|
20857
20875
|
});
|
|
20858
20876
|
(_b = this.deps.textTrackController) == null ? void 0 : _b.deactivate();
|
|
20859
20877
|
this.deps.playbackSource.src = null;
|
|
@@ -24951,7 +24969,8 @@ ${this.lastInitStack}` : "";
|
|
|
24951
24969
|
var vinylTestAssets = {
|
|
24952
24970
|
prog: {
|
|
24953
24971
|
libmp3lame_60s_2ch_16bit_44100Hz_48kbps: `https://assets.dev.vinyl.music.amazon.dev/prog/libmp3lame_60s_2ch_16bit_44100Hz_48kbps.mp3`,
|
|
24954
|
-
libmp3lame_1800s_2ch_16bit_44100Hz_48kbps: `https://assets.dev.vinyl.music.amazon.dev/prog/libmp3lame_1800s_2ch_16bit_44100Hz_48kbps.mp3
|
|
24972
|
+
libmp3lame_1800s_2ch_16bit_44100Hz_48kbps: `https://assets.dev.vinyl.music.amazon.dev/prog/libmp3lame_1800s_2ch_16bit_44100Hz_48kbps.mp3`,
|
|
24973
|
+
libmp3lame_1s_2ch_16bit_44100Hz_48kbps: `https://assets.dev.vinyl.music.amazon.dev/prog/libmp3lame_1s_2ch_16bit_44100Hz_48kbps.mp3`
|
|
24955
24974
|
},
|
|
24956
24975
|
dash: {
|
|
24957
24976
|
live_static_aac_opus_flac_60s_segmentTemplate: `https://assets.dev.vinyl.music.amazon.dev/dash/live_static_aac_opus_flac_60s_segmentTemplate/manifest.mpd`,
|
|
@@ -24966,6 +24985,10 @@ ${this.lastInitStack}` : "";
|
|
|
24966
24985
|
live_static_aac_opus_flac_60s_segmentBase_widevine_cl10: `https://assets.dev.vinyl.music.amazon.dev/dash/live_static_aac_opus_flac_60s_segmentBase_widevine_cl10/manifest.mpd`,
|
|
24967
24986
|
live_static_aac_opus_flac_60s_segmentBase_widevine: `https://assets.dev.vinyl.music.amazon.dev/dash/live_static_aac_opus_flac_60s_segmentBase_widevine/manifest.mpd`,
|
|
24968
24987
|
live_static_aac_1800s_segmentBase_widevine_cl30: `https://assets.dev.vinyl.music.amazon.dev/dash/live_static_aac_1800s_segmentBase_widevine_cl30/manifest.mpd`,
|
|
24988
|
+
// Edge-case tracks: ultra-short 1s assets (audio-only + video), no
|
|
24989
|
+
// captions or translations.
|
|
24990
|
+
edge_static_aac_1s_segmentTemplate: `https://assets.dev.vinyl.music.amazon.dev/dash/edge_static_aac_1s_segmentTemplate/manifest.mpd`,
|
|
24991
|
+
edge_static_video_1s_segmentTemplate: `https://assets.dev.vinyl.music.amazon.dev/dash/edge_static_video_1s_segmentTemplate/manifest.mpd`,
|
|
24969
24992
|
// Ad-break assets (see DMTestAssetBuilder src/adBreaks): a ~3-min
|
|
24970
24993
|
// labeled ABR ladder with five-language narration, full + forced
|
|
24971
24994
|
// captions. Base content only — DASH ad-break scenarios are not
|
|
@@ -24985,6 +25008,10 @@ ${this.lastInitStack}` : "";
|
|
|
24985
25008
|
live_static_video_60s_4s_mpegts: `https://assets.dev.vinyl.music.amazon.dev/hls/live_static_video_60s_4s_mpegts/main.m3u8`,
|
|
24986
25009
|
live_static_video_audio_60s_2s_mpegts: `https://assets.dev.vinyl.music.amazon.dev/hls/live_static_video_audio_60s_2s_mpegts/main.m3u8`,
|
|
24987
25010
|
live_static_video_audio_60s_4s_mpegts: `https://assets.dev.vinyl.music.amazon.dev/hls/live_static_video_audio_60s_4s_mpegts/main.m3u8`,
|
|
25011
|
+
// Edge-case tracks: ultra-short 1s assets (audio-only + video), no
|
|
25012
|
+
// captions or translations.
|
|
25013
|
+
edge_static_aac_1s: `https://assets.dev.vinyl.music.amazon.dev/hls/edge_static_aac_1s/main.m3u8`,
|
|
25014
|
+
edge_static_video_1s: `https://assets.dev.vinyl.music.amazon.dev/hls/edge_static_video_1s/main.m3u8`,
|
|
24988
25015
|
// Ad-break assets: base content + HLS Interstitial scenario variants.
|
|
24989
25016
|
// `*_av` = video+audio, `*_audio` = audio-only; each `__<scenario>`
|
|
24990
25017
|
// injects a different ad-break configuration. See DMTestAssetBuilder
|
|
@@ -27745,7 +27772,6 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
27745
27772
|
makeBreak({
|
|
27746
27773
|
startTime: 10,
|
|
27747
27774
|
duration: 20,
|
|
27748
|
-
// Null per-ad duration so the per-ad cap does not end it.
|
|
27749
27775
|
ads: [
|
|
27750
27776
|
{
|
|
27751
27777
|
id: "a1",
|
|
@@ -27849,8 +27875,8 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
27849
27875
|
});
|
|
27850
27876
|
});
|
|
27851
27877
|
describe("ad duration and playout limits", () => {
|
|
27852
|
-
it("advances to the next ad
|
|
27853
|
-
var _a3, _b;
|
|
27878
|
+
it("advances to the next ad on the ad media ended, not its declared duration", async () => {
|
|
27879
|
+
var _a3, _b, _c;
|
|
27854
27880
|
const c = createController();
|
|
27855
27881
|
await setContent(
|
|
27856
27882
|
c,
|
|
@@ -27863,6 +27889,7 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
27863
27889
|
id: "a1",
|
|
27864
27890
|
startTime: 0,
|
|
27865
27891
|
duration: 5,
|
|
27892
|
+
// declared, server-rounded
|
|
27866
27893
|
uri: "ad1.m3u8"
|
|
27867
27894
|
},
|
|
27868
27895
|
{
|
|
@@ -27881,7 +27908,51 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
27881
27908
|
playbackController.dispatch("playing", {});
|
|
27882
27909
|
updateTime(6);
|
|
27883
27910
|
await flush();
|
|
27884
|
-
expect((_b = c.currentAd) == null ? void 0 : _b.id).toBe("
|
|
27911
|
+
expect((_b = c.currentAd) == null ? void 0 : _b.id).toBe("a1");
|
|
27912
|
+
playbackController.dispatch("ended", {
|
|
27913
|
+
previous: false,
|
|
27914
|
+
current: true
|
|
27915
|
+
});
|
|
27916
|
+
await flush();
|
|
27917
|
+
expect((_c = c.currentAd) == null ? void 0 : _c.id).toBe("a2");
|
|
27918
|
+
});
|
|
27919
|
+
it("does not cut the final/only ad at its declared duration; it ends on media ended", async () => {
|
|
27920
|
+
var _a3, _b;
|
|
27921
|
+
const c = createController();
|
|
27922
|
+
const ended = [];
|
|
27923
|
+
c.on("adEnded", (e) => ended.push(e.ad.id));
|
|
27924
|
+
await setContent(
|
|
27925
|
+
c,
|
|
27926
|
+
trackAds(
|
|
27927
|
+
makeBreak({
|
|
27928
|
+
startTime: 0,
|
|
27929
|
+
duration: 30,
|
|
27930
|
+
ads: [
|
|
27931
|
+
{
|
|
27932
|
+
id: "a1",
|
|
27933
|
+
startTime: 0,
|
|
27934
|
+
duration: 6,
|
|
27935
|
+
// declared, server-rounded
|
|
27936
|
+
uri: "ad1.m3u8"
|
|
27937
|
+
}
|
|
27938
|
+
]
|
|
27939
|
+
})
|
|
27940
|
+
)
|
|
27941
|
+
);
|
|
27942
|
+
updateTime(0);
|
|
27943
|
+
await flush();
|
|
27944
|
+
expect((_a3 = c.currentAd) == null ? void 0 : _a3.id).toBe("a1");
|
|
27945
|
+
playbackController.dispatch("playing", {});
|
|
27946
|
+
updateTime(6.5);
|
|
27947
|
+
await flush();
|
|
27948
|
+
expect((_b = c.currentAd) == null ? void 0 : _b.id).toBe("a1");
|
|
27949
|
+
expect(ended).toEqual([]);
|
|
27950
|
+
playbackController.dispatch("ended", {
|
|
27951
|
+
previous: false,
|
|
27952
|
+
current: true
|
|
27953
|
+
});
|
|
27954
|
+
expect(ended).toEqual(["a1"]);
|
|
27955
|
+
expect(c.currentAdBreak).toBeNull();
|
|
27885
27956
|
});
|
|
27886
27957
|
it("ends the whole break when the playout limit is reached, dropping remaining ads", async () => {
|
|
27887
27958
|
var _a3;
|
|
@@ -27922,6 +27993,70 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
27922
27993
|
expect(c.currentAdBreak).toBeNull();
|
|
27923
27994
|
expect(resumes.at(-1)).toBe(0);
|
|
27924
27995
|
});
|
|
27996
|
+
it("does not cut at the playout limit when the ad is within tolerance of its media end", async () => {
|
|
27997
|
+
var _a3;
|
|
27998
|
+
const c = createController();
|
|
27999
|
+
await setContent(
|
|
28000
|
+
c,
|
|
28001
|
+
trackAds(
|
|
28002
|
+
makeBreak({
|
|
28003
|
+
startTime: 0,
|
|
28004
|
+
duration: null,
|
|
28005
|
+
playoutLimit: 8,
|
|
28006
|
+
ads: [
|
|
28007
|
+
{
|
|
28008
|
+
id: "a1",
|
|
28009
|
+
startTime: 0,
|
|
28010
|
+
duration: 20,
|
|
28011
|
+
uri: "ad1.m3u8"
|
|
28012
|
+
}
|
|
28013
|
+
]
|
|
28014
|
+
})
|
|
28015
|
+
)
|
|
28016
|
+
);
|
|
28017
|
+
updateTime(0);
|
|
28018
|
+
await flush();
|
|
28019
|
+
playbackController.dispatch("playing", {});
|
|
28020
|
+
playbackController.duration = 8.5;
|
|
28021
|
+
updateTime(8);
|
|
28022
|
+
await flush();
|
|
28023
|
+
expect(c.currentAdBreak).not.toBeNull();
|
|
28024
|
+
expect((_a3 = c.currentAd) == null ? void 0 : _a3.id).toBe("a1");
|
|
28025
|
+
playbackController.dispatch("ended", {
|
|
28026
|
+
previous: false,
|
|
28027
|
+
current: true
|
|
28028
|
+
});
|
|
28029
|
+
await flush();
|
|
28030
|
+
expect(c.currentAdBreak).toBeNull();
|
|
28031
|
+
});
|
|
28032
|
+
it("cuts at the playout limit when the ad has more than the tolerance of media left", async () => {
|
|
28033
|
+
const c = createController();
|
|
28034
|
+
await setContent(
|
|
28035
|
+
c,
|
|
28036
|
+
trackAds(
|
|
28037
|
+
makeBreak({
|
|
28038
|
+
startTime: 0,
|
|
28039
|
+
duration: null,
|
|
28040
|
+
playoutLimit: 8,
|
|
28041
|
+
ads: [
|
|
28042
|
+
{
|
|
28043
|
+
id: "a1",
|
|
28044
|
+
startTime: 0,
|
|
28045
|
+
duration: 20,
|
|
28046
|
+
uri: "ad1.m3u8"
|
|
28047
|
+
}
|
|
28048
|
+
]
|
|
28049
|
+
})
|
|
28050
|
+
)
|
|
28051
|
+
);
|
|
28052
|
+
updateTime(0);
|
|
28053
|
+
await flush();
|
|
28054
|
+
playbackController.dispatch("playing", {});
|
|
28055
|
+
playbackController.duration = 20;
|
|
28056
|
+
updateTime(8);
|
|
28057
|
+
await flush();
|
|
28058
|
+
expect(c.currentAdBreak).toBeNull();
|
|
28059
|
+
});
|
|
27925
28060
|
});
|
|
27926
28061
|
describe("CUE=ONCE and replay", () => {
|
|
27927
28062
|
it("replays a non-ONCE break after the playhead seeks back before it", async () => {
|
|
@@ -32017,6 +32152,23 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
32017
32152
|
expect(drmController.isEmeSupported()).toBeFalse();
|
|
32018
32153
|
});
|
|
32019
32154
|
});
|
|
32155
|
+
describe("excessive sessions", () => {
|
|
32156
|
+
it("warns once when the open session count exceeds the threshold", async () => {
|
|
32157
|
+
drmController.setBufferingDrmInfo(drmInfo);
|
|
32158
|
+
for (let i = 0; i < EXCESSIVE_SESSION_COUNT; i++) {
|
|
32159
|
+
await emitEncrypted(new Uint8Array([i]));
|
|
32160
|
+
}
|
|
32161
|
+
expect(drmController.activeSessions).toBe(EXCESSIVE_SESSION_COUNT);
|
|
32162
|
+
expect(logger.value.warn).not.toHaveBeenCalled();
|
|
32163
|
+
await emitEncrypted(new Uint8Array([EXCESSIVE_SESSION_COUNT]));
|
|
32164
|
+
expect(drmController.activeSessions).toBe(
|
|
32165
|
+
EXCESSIVE_SESSION_COUNT + 1
|
|
32166
|
+
);
|
|
32167
|
+
expect(logger.value.warn).toHaveBeenCalledTimes(1);
|
|
32168
|
+
await emitEncrypted(new Uint8Array([EXCESSIVE_SESSION_COUNT + 1]));
|
|
32169
|
+
expect(logger.value.warn).toHaveBeenCalledTimes(1);
|
|
32170
|
+
});
|
|
32171
|
+
});
|
|
32020
32172
|
describe("closeSessions", () => {
|
|
32021
32173
|
it("clears active sessions", async () => {
|
|
32022
32174
|
const sessionCloseSpy = createEventSpy(
|
|
@@ -33203,10 +33355,38 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
33203
33355
|
expect(onStallEntered).toHaveBeenCalledTimes(2);
|
|
33204
33356
|
expect(onStallEnded).toHaveBeenCalledTimes(2);
|
|
33205
33357
|
});
|
|
33358
|
+
it("does not end and re-detect a stall on a non-advancing timeUpdate", async () => {
|
|
33359
|
+
monitor();
|
|
33360
|
+
host.dispatch("playing", {});
|
|
33361
|
+
host.dispatch("timeUpdate", { previous: 4, current: 5 });
|
|
33362
|
+
await poll2(4);
|
|
33363
|
+
expect(onStallEntered).toHaveBeenCalledTimes(1);
|
|
33364
|
+
host.dispatch("timeUpdate", { previous: 5, current: 5 });
|
|
33365
|
+
host.dispatch("timeUpdate", { previous: 5, current: 4.99 });
|
|
33366
|
+
host.dispatch("timeUpdate", { previous: 5, current: 5 + 1e-9 });
|
|
33367
|
+
await poll2(4);
|
|
33368
|
+
expect(onStallEnded).not.toHaveBeenCalled();
|
|
33369
|
+
expect(onStallEntered).toHaveBeenCalledTimes(1);
|
|
33370
|
+
host.dispatch("timeUpdate", { previous: 5, current: 6 });
|
|
33371
|
+
expect(onStallEnded).toHaveBeenCalledTimes(1);
|
|
33372
|
+
expect(onStallEntered).toHaveBeenCalledTimes(1);
|
|
33373
|
+
});
|
|
33374
|
+
it("does not re-detect a stall immediately after resuming via a playing event", async () => {
|
|
33375
|
+
monitor();
|
|
33376
|
+
host.dispatch("playing", {});
|
|
33377
|
+
host.dispatch("timeUpdate", { previous: 0, current: 1 });
|
|
33378
|
+
await poll2(4);
|
|
33379
|
+
expect(onStallEntered).toHaveBeenCalledTimes(1);
|
|
33380
|
+
host.dispatch("playing", {});
|
|
33381
|
+
expect(onStallEnded).toHaveBeenCalledTimes(1);
|
|
33382
|
+
await poll2(3);
|
|
33383
|
+
expect(onStallEntered).toHaveBeenCalledTimes(1);
|
|
33384
|
+
});
|
|
33206
33385
|
it("stops reporting after disposal", async () => {
|
|
33207
33386
|
monitor();
|
|
33208
33387
|
host.dispatch("playing", {});
|
|
33209
33388
|
stop();
|
|
33389
|
+
stop = void 0;
|
|
33210
33390
|
await poll2(8);
|
|
33211
33391
|
expect(onStallEntered).not.toHaveBeenCalled();
|
|
33212
33392
|
});
|
|
@@ -33957,6 +34137,13 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
33957
34137
|
await clock.tick(controller.options.seekTimeout);
|
|
33958
34138
|
await seekExpectation;
|
|
33959
34139
|
});
|
|
34140
|
+
it("resolves a superseded seek at once when its seeking event never fires", async () => {
|
|
34141
|
+
setSeekable([[0, 100]]);
|
|
34142
|
+
const first2 = controller.seekTo(50);
|
|
34143
|
+
const second = controller.seekTo(60);
|
|
34144
|
+
await expectAsync(first2).toBeResolved();
|
|
34145
|
+
second.catch(() => void 0);
|
|
34146
|
+
});
|
|
33960
34147
|
it("times out pending seeks after seekTimeout", async () => {
|
|
33961
34148
|
const pendingSeekExpectation = expectAsync(
|
|
33962
34149
|
controller.seekTo(60)
|
|
@@ -39067,6 +39254,16 @@ ${(_a3 = this.failedResult.failedExpectations[0]) == null ? void 0 : _a3.message
|
|
|
39067
39254
|
abort: any14(Abort)
|
|
39068
39255
|
});
|
|
39069
39256
|
});
|
|
39257
|
+
it("aborts the drm session abort so key sessions close", async () => {
|
|
39258
|
+
track2 = createTrack();
|
|
39259
|
+
await awaitContentTypes();
|
|
39260
|
+
getAudioStream().streamingQuality = createEmptyMediaQualityMetadata();
|
|
39261
|
+
track2.activate({});
|
|
39262
|
+
const { abort } = deps.drmController.initializeForPlayback.calls.mostRecent().args[1];
|
|
39263
|
+
expect(abort.aborted()).toBeFalse();
|
|
39264
|
+
track2.deactivate();
|
|
39265
|
+
expect(abort.aborted()).toBeTrue();
|
|
39266
|
+
});
|
|
39070
39267
|
});
|
|
39071
39268
|
describe("error", () => {
|
|
39072
39269
|
it("returns the first emitted error", async () => {
|
|
@@ -55011,27 +55208,31 @@ x`);
|
|
|
55011
55208
|
if (!supportsMse()) pending("MSE not supported");
|
|
55012
55209
|
});
|
|
55013
55210
|
const suite = createVinylSuite();
|
|
55211
|
+
async function arrangeStall() {
|
|
55212
|
+
const player = suite.player;
|
|
55213
|
+
const stallEnteredSpy = createEventSpy(player, "stallEntered");
|
|
55214
|
+
const stallEndedSpy = createEventSpy(player, "stallEnded");
|
|
55215
|
+
const mediaSource = new ControlledMediaSource();
|
|
55216
|
+
player.load({
|
|
55217
|
+
type: "src",
|
|
55218
|
+
uri: URL.createObjectURL(await mediaSource.getMediaSource())
|
|
55219
|
+
});
|
|
55220
|
+
void player.play();
|
|
55221
|
+
await mediaSource.appendNext();
|
|
55222
|
+
await mediaSource.appendNext();
|
|
55223
|
+
await onPlaying(player);
|
|
55224
|
+
expect(stallEnteredSpy).not.toHaveBeenCalled();
|
|
55225
|
+
const entered = stallEnteredSpy.next(
|
|
55226
|
+
30,
|
|
55227
|
+
"stallEntered after hitting end of buffer timed out after {timeout}s"
|
|
55228
|
+
);
|
|
55229
|
+
await player.seekTo(5);
|
|
55230
|
+
await entered;
|
|
55231
|
+
return { player, mediaSource, stallEnteredSpy, stallEndedSpy };
|
|
55232
|
+
}
|
|
55014
55233
|
describe("when the play head freezes mid-playback", () => {
|
|
55015
55234
|
it("emits stallEntered then stallEnded when playback resumes", async () => {
|
|
55016
|
-
const player =
|
|
55017
|
-
const stallEnteredSpy = createEventSpy(player, "stallEntered");
|
|
55018
|
-
const stallEndedSpy = createEventSpy(player, "stallEnded");
|
|
55019
|
-
const mediaSource = new ControlledMediaSource();
|
|
55020
|
-
player.load({
|
|
55021
|
-
type: "src",
|
|
55022
|
-
uri: URL.createObjectURL(await mediaSource.getMediaSource())
|
|
55023
|
-
});
|
|
55024
|
-
void player.play();
|
|
55025
|
-
await mediaSource.appendNext();
|
|
55026
|
-
await mediaSource.appendNext();
|
|
55027
|
-
await onPlaying(player);
|
|
55028
|
-
expect(stallEnteredSpy).not.toHaveBeenCalled();
|
|
55029
|
-
const nextEntered = stallEnteredSpy.next(
|
|
55030
|
-
30,
|
|
55031
|
-
"stallEntered after hitting end of buffer timed out after {timeout}s"
|
|
55032
|
-
);
|
|
55033
|
-
await player.seekTo(5);
|
|
55034
|
-
await nextEntered;
|
|
55235
|
+
const { player, mediaSource, stallEnteredSpy, stallEndedSpy } = await arrangeStall();
|
|
55035
55236
|
const nextEnded = stallEndedSpy.next(
|
|
55036
55237
|
10,
|
|
55037
55238
|
"stallEnded after data buffered timed out after {timeout}s"
|
|
@@ -55040,7 +55241,62 @@ x`);
|
|
|
55040
55241
|
const ended = await nextEnded;
|
|
55041
55242
|
expect(ended.reason).toBe("playing");
|
|
55042
55243
|
expect(stallEnteredSpy).toHaveBeenCalledTimes(1);
|
|
55244
|
+
expect(stallEndedSpy).toHaveBeenCalledTimes(1);
|
|
55043
55245
|
expect(ended.duration).toBeGreaterThan(0.5);
|
|
55246
|
+
for (let i = 0; i < 5; i++) await onTimeUpdate(player);
|
|
55247
|
+
expect(stallEnteredSpy).toHaveBeenCalledTimes(1);
|
|
55248
|
+
expect(stallEndedSpy).toHaveBeenCalledTimes(1);
|
|
55249
|
+
});
|
|
55250
|
+
it('ends the stall with reason "seeking" when the user seeks away mid-stall', async () => {
|
|
55251
|
+
const { player, stallEnteredSpy, stallEndedSpy } = await arrangeStall();
|
|
55252
|
+
const nextEnded = stallEndedSpy.next(
|
|
55253
|
+
10,
|
|
55254
|
+
"stallEnded after seeking away timed out after {timeout}s"
|
|
55255
|
+
);
|
|
55256
|
+
await player.seekTo(1);
|
|
55257
|
+
const ended = await nextEnded;
|
|
55258
|
+
expect(ended.reason).toBe("seeking");
|
|
55259
|
+
expect(stallEnteredSpy).toHaveBeenCalledTimes(1);
|
|
55260
|
+
expect(stallEndedSpy).toHaveBeenCalledTimes(1);
|
|
55261
|
+
});
|
|
55262
|
+
it('ends the stall with reason "emptied" when the track is unloaded mid-stall', async () => {
|
|
55263
|
+
const { player, stallEnteredSpy, stallEndedSpy } = await arrangeStall();
|
|
55264
|
+
const nextEnded = stallEndedSpy.next(
|
|
55265
|
+
10,
|
|
55266
|
+
"stallEnded after unload timed out after {timeout}s"
|
|
55267
|
+
);
|
|
55268
|
+
player.unload();
|
|
55269
|
+
const ended = await nextEnded;
|
|
55270
|
+
expect(ended.reason).toBe("emptied");
|
|
55271
|
+
expect(stallEnteredSpy).toHaveBeenCalledTimes(1);
|
|
55272
|
+
expect(stallEndedSpy).toHaveBeenCalledTimes(1);
|
|
55273
|
+
});
|
|
55274
|
+
it("reports each distinct freeze exactly once", async () => {
|
|
55275
|
+
const { player, mediaSource, stallEnteredSpy, stallEndedSpy } = await arrangeStall();
|
|
55276
|
+
const firstEnded = stallEndedSpy.next(
|
|
55277
|
+
10,
|
|
55278
|
+
"stallEnded for freeze 1 timed out after {timeout}s"
|
|
55279
|
+
);
|
|
55280
|
+
await mediaSource.appendNext();
|
|
55281
|
+
expect((await firstEnded).reason).toBe("playing");
|
|
55282
|
+
expect(stallEnteredSpy).toHaveBeenCalledTimes(1);
|
|
55283
|
+
expect(stallEndedSpy).toHaveBeenCalledTimes(1);
|
|
55284
|
+
const secondEntered = stallEnteredSpy.next(
|
|
55285
|
+
30,
|
|
55286
|
+
"stallEntered for freeze 2 timed out after {timeout}s"
|
|
55287
|
+
);
|
|
55288
|
+
await player.seekTo(15);
|
|
55289
|
+
await secondEntered;
|
|
55290
|
+
expect(stallEnteredSpy).toHaveBeenCalledTimes(2);
|
|
55291
|
+
const secondEnded = stallEndedSpy.next(
|
|
55292
|
+
10,
|
|
55293
|
+
"stallEnded for freeze 2 timed out after {timeout}s"
|
|
55294
|
+
);
|
|
55295
|
+
await mediaSource.appendNext();
|
|
55296
|
+
expect((await secondEnded).reason).toBe("playing");
|
|
55297
|
+
for (let i = 0; i < 5; i++) await onTimeUpdate(player);
|
|
55298
|
+
expect(stallEnteredSpy).toHaveBeenCalledTimes(2);
|
|
55299
|
+
expect(stallEndedSpy).toHaveBeenCalledTimes(2);
|
|
55044
55300
|
});
|
|
55045
55301
|
});
|
|
55046
55302
|
});
|
|
@@ -55769,6 +56025,7 @@ x`);
|
|
|
55769
56025
|
var ANCHOR_MS = Date.parse(ANCHOR_ISO);
|
|
55770
56026
|
var CONTENT_ASSET = vinylTestAssets.hls.live_static_video_audio_60s_4s;
|
|
55771
56027
|
var AD_ASSET = vinylTestAssets.hls.live_static_video_audio_60s_2s;
|
|
56028
|
+
var SHORT_AD_ASSET = vinylTestAssets.hls.edge_static_video_1s;
|
|
55772
56029
|
function injectingManifestProvider(mainUrl, interstitials) {
|
|
55773
56030
|
return async () => {
|
|
55774
56031
|
const mainText = await (await fetch(mainUrl)).text();
|
|
@@ -56403,8 +56660,8 @@ x`);
|
|
|
56403
56660
|
id: "postroll-1",
|
|
56404
56661
|
startTime: 0,
|
|
56405
56662
|
duration: 4,
|
|
56406
|
-
//
|
|
56407
|
-
assetList: [{ uri:
|
|
56663
|
+
// A 1s ad so the break ends quickly on its own `ended`.
|
|
56664
|
+
assetList: [{ uri: SHORT_AD_ASSET, duration: 1 }],
|
|
56408
56665
|
cue: "POST"
|
|
56409
56666
|
}
|
|
56410
56667
|
])
|