stormcloud-video-player 0.8.34 → 0.8.35
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/stormcloud-vp.min.js +1 -1
- package/lib/index.cjs +105 -16
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +2 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +105 -16
- package/lib/index.js.map +1 -1
- package/lib/player/AdBreakOrchestrator.cjs +36 -16
- package/lib/player/AdBreakOrchestrator.cjs.map +1 -1
- package/lib/player/AdBreakOrchestrator.d.cts +3 -7
- package/lib/player/AdConfigManager.d.cts +1 -1
- package/lib/player/AdTimingService.d.cts +1 -1
- package/lib/player/HlsEngine.d.cts +1 -1
- package/lib/player/PlayerControls.d.cts +1 -1
- package/lib/player/Scte35CueManager.d.cts +1 -1
- package/lib/player/Scte35Parser.d.cts +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +105 -16
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +1 -1
- package/lib/player/playerTypes.d.cts +1 -1
- package/lib/players/HlsPlayer.cjs +105 -16
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +105 -16
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +62 -0
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.d.cts +1 -1
- package/lib/{types-CSHvCbhZ.d.cts → types-cTqIKw_D.d.cts} +1 -0
- package/lib/ui/StormcloudVideoPlayer.cjs +105 -16
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
- package/lib/utils/browserCompat.cjs +1 -0
- package/lib/utils/browserCompat.cjs.map +1 -1
- package/lib/utils/browserCompat.d.cts +1 -0
- package/lib/utils/tracking.d.cts +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as Scte35Marker, a as StormcloudVideoPlayerConfig, A as AdController } from '../types-
|
|
1
|
+
import { S as Scte35Marker, a as StormcloudVideoPlayerConfig, A as AdController } from '../types-cTqIKw_D.cjs';
|
|
2
2
|
import { AdTimingService } from './AdTimingService.cjs';
|
|
3
3
|
import { AdConfigManager } from './AdConfigManager.cjs';
|
|
4
4
|
import { Scte35CueManager } from './Scte35CueManager.cjs';
|
|
@@ -14,6 +14,7 @@ interface AdBreakOrchestratorHost {
|
|
|
14
14
|
setAdPlayer(player: AdController): void;
|
|
15
15
|
createAdPlayer(continueLiveStreamDuringAds: boolean): AdController;
|
|
16
16
|
shouldContinueLiveStreamDuringAds(): boolean;
|
|
17
|
+
isLiveStream(): boolean;
|
|
17
18
|
getLiveSyncPosition(): number | undefined;
|
|
18
19
|
generatePodVastUrl(baseUrl: string, breakDurationMs?: number): string;
|
|
19
20
|
}
|
|
@@ -43,12 +44,6 @@ declare class AdBreakOrchestrator {
|
|
|
43
44
|
constructor(host: AdBreakOrchestratorHost, timing: AdTimingService, adConfig: AdConfigManager, cueManager: Scte35CueManager, placeholder: PlaceholderLayer);
|
|
44
45
|
private get debug();
|
|
45
46
|
private get analyticsContext();
|
|
46
|
-
/**
|
|
47
|
-
* Produces the next pod ad-request URL for the current break. Every request
|
|
48
|
-
* (initial and continuous-fetch top-up) carries pod macros (pmad/pmnd/pmxd,
|
|
49
|
-
* no ppos); pmxd tracks the remaining break time so top-up pods only ask for
|
|
50
|
-
* what still fits.
|
|
51
|
-
*/
|
|
52
47
|
private nextAdRequestUrl;
|
|
53
48
|
attachImaEventListeners(): void;
|
|
54
49
|
recreateAdController(): void;
|
|
@@ -63,6 +58,7 @@ declare class AdBreakOrchestrator {
|
|
|
63
58
|
playSingleAd(vastTagUrl: string): Promise<void>;
|
|
64
59
|
private showPlaceholderAndWaitForAds;
|
|
65
60
|
handleAdPodComplete(): void;
|
|
61
|
+
private resumeContentPlayback;
|
|
66
62
|
handleAdFailure(): void;
|
|
67
63
|
}
|
|
68
64
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as AdBreak, a as StormcloudVideoPlayerConfig, A as AdController } from '../types-
|
|
1
|
+
import { b as AdBreak, a as StormcloudVideoPlayerConfig, A as AdController } from '../types-cTqIKw_D.cjs';
|
|
2
2
|
import { PalNonceManager } from '../sdk/pal.cjs';
|
|
3
3
|
import { VastConsentSignals } from '../utils/vastMacros.cjs';
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as StormcloudVideoPlayerConfig, S as Scte35Marker, A as AdController } from '../types-
|
|
1
|
+
import { a as StormcloudVideoPlayerConfig, S as Scte35Marker, A as AdController } from '../types-cTqIKw_D.cjs';
|
|
2
2
|
|
|
3
3
|
interface AdTimingCallbacks {
|
|
4
4
|
onAdStopTimerFired(): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Hls from 'hls.js';
|
|
2
|
-
import { a as StormcloudVideoPlayerConfig, S as Scte35Marker } from '../types-
|
|
2
|
+
import { a as StormcloudVideoPlayerConfig, S as Scte35Marker } from '../types-cTqIKw_D.cjs';
|
|
3
3
|
import { Scte35CueContext } from './playerTypes.cjs';
|
|
4
4
|
import { Scte35CueManager } from './Scte35CueManager.cjs';
|
|
5
5
|
import { AdTimingService } from './AdTimingService.cjs';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as AdController } from '../types-
|
|
1
|
+
import { A as AdController } from '../types-cTqIKw_D.cjs';
|
|
2
2
|
|
|
3
3
|
declare function getAdAudioVolume(adPlayer: AdController): number;
|
|
4
4
|
declare function toggleMute(video: HTMLVideoElement, adPlayer: AdController, debug: boolean): void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as Scte35Marker, I as Id3TagInfo } from '../types-
|
|
1
|
+
import { S as Scte35Marker, I as Id3TagInfo } from '../types-cTqIKw_D.cjs';
|
|
2
2
|
|
|
3
3
|
declare function parseCueOutDuration(value: string): number | undefined;
|
|
4
4
|
declare function parseCueOutCont(value: string): {
|
|
@@ -368,6 +368,11 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
368
368
|
var preloadingAds = /* @__PURE__ */ new Map();
|
|
369
369
|
var destroyed = false;
|
|
370
370
|
var pendingTimeouts = [];
|
|
371
|
+
var STALL_TIMEOUT_MS = 4e3;
|
|
372
|
+
var STALL_CHECK_INTERVAL_MS = 1e3;
|
|
373
|
+
var stallWatchdogId;
|
|
374
|
+
var lastAdProgressTime = 0;
|
|
375
|
+
var lastAdProgressPosition = 0;
|
|
371
376
|
var trackingFired = {
|
|
372
377
|
impression: false,
|
|
373
378
|
start: false,
|
|
@@ -1000,6 +1005,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1000
1005
|
if (!adVideoElement || !currentAd) return;
|
|
1001
1006
|
adVideoElement.addEventListener("timeupdate", function() {
|
|
1002
1007
|
if (!currentAd || !adVideoElement) return;
|
|
1008
|
+
noteAdProgress();
|
|
1003
1009
|
var progress = adVideoElement.currentTime / currentAd.duration;
|
|
1004
1010
|
if (progress >= 0.25 && !trackingFired.firstQuartile) {
|
|
1005
1011
|
trackingFired.firstQuartile = true;
|
|
@@ -1015,6 +1021,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1015
1021
|
}
|
|
1016
1022
|
});
|
|
1017
1023
|
adVideoElement.addEventListener("playing", function() {
|
|
1024
|
+
startStallWatchdog();
|
|
1018
1025
|
if (!currentAd || trackingFired.start) return;
|
|
1019
1026
|
trackingFired.start = true;
|
|
1020
1027
|
fireTrackingPixels(currentAd.trackingUrls.start);
|
|
@@ -1155,8 +1162,52 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1155
1162
|
return false;
|
|
1156
1163
|
}
|
|
1157
1164
|
}
|
|
1165
|
+
function clearStallWatchdog() {
|
|
1166
|
+
if (stallWatchdogId != null) {
|
|
1167
|
+
clearInterval(stallWatchdogId);
|
|
1168
|
+
stallWatchdogId = void 0;
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
function noteAdProgress() {
|
|
1172
|
+
lastAdProgressTime = Date.now();
|
|
1173
|
+
if (adVideoElement) {
|
|
1174
|
+
lastAdProgressPosition = adVideoElement.currentTime;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
function handleAdStall() {
|
|
1178
|
+
console.warn("[HlsAdPlayer] Ad playback stalled (no progress) - recovering to avoid a blank frame");
|
|
1179
|
+
clearStallWatchdog();
|
|
1180
|
+
if (currentAd) {
|
|
1181
|
+
fireTrackingPixels(currentAd.trackingUrls.error);
|
|
1182
|
+
}
|
|
1183
|
+
if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
|
|
1184
|
+
return;
|
|
1185
|
+
}
|
|
1186
|
+
handleAdError();
|
|
1187
|
+
}
|
|
1188
|
+
function startStallWatchdog() {
|
|
1189
|
+
clearStallWatchdog();
|
|
1190
|
+
noteAdProgress();
|
|
1191
|
+
stallWatchdogId = window.setInterval(function() {
|
|
1192
|
+
if (!adPlaying || !adVideoElement) {
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
|
|
1196
|
+
noteAdProgress();
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
if (adVideoElement.paused) {
|
|
1200
|
+
noteAdProgress();
|
|
1201
|
+
return;
|
|
1202
|
+
}
|
|
1203
|
+
if (Date.now() - lastAdProgressTime >= STALL_TIMEOUT_MS) {
|
|
1204
|
+
handleAdStall();
|
|
1205
|
+
}
|
|
1206
|
+
}, STALL_CHECK_INTERVAL_MS);
|
|
1207
|
+
}
|
|
1158
1208
|
function handleAdComplete() {
|
|
1159
1209
|
console.log("[HlsAdPlayer] Handling ad completion");
|
|
1210
|
+
clearStallWatchdog();
|
|
1160
1211
|
adPlaying = false;
|
|
1161
1212
|
setAdPlayingFlag(false);
|
|
1162
1213
|
contentVideo.muted = true;
|
|
@@ -1164,6 +1215,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1164
1215
|
adContainerEl.style.display = "none";
|
|
1165
1216
|
adContainerEl.style.pointerEvents = "none";
|
|
1166
1217
|
}
|
|
1218
|
+
if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1219
|
+
contentVideo.style.visibility = "visible";
|
|
1220
|
+
contentVideo.style.opacity = "1";
|
|
1221
|
+
}
|
|
1167
1222
|
if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
|
|
1168
1223
|
if (contentVideo.paused) {
|
|
1169
1224
|
console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback");
|
|
@@ -1176,6 +1231,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1176
1231
|
}
|
|
1177
1232
|
function handleAdError() {
|
|
1178
1233
|
console.log("[HlsAdPlayer] Handling ad error");
|
|
1234
|
+
clearStallWatchdog();
|
|
1179
1235
|
adPlaying = false;
|
|
1180
1236
|
setAdPlayingFlag(false);
|
|
1181
1237
|
contentVideo.muted = true;
|
|
@@ -1183,6 +1239,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1183
1239
|
adContainerEl.style.display = "none";
|
|
1184
1240
|
adContainerEl.style.pointerEvents = "none";
|
|
1185
1241
|
}
|
|
1242
|
+
if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1243
|
+
contentVideo.style.visibility = "visible";
|
|
1244
|
+
contentVideo.style.opacity = "1";
|
|
1245
|
+
}
|
|
1186
1246
|
emit("ad_error");
|
|
1187
1247
|
}
|
|
1188
1248
|
return {
|
|
@@ -1380,6 +1440,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1380
1440
|
var previousMutedState;
|
|
1381
1441
|
return _ts_generator(this, function(_state) {
|
|
1382
1442
|
console.log("[HlsAdPlayer] Stopping ad");
|
|
1443
|
+
clearStallWatchdog();
|
|
1383
1444
|
adPlaying = false;
|
|
1384
1445
|
setAdPlayingFlag(false);
|
|
1385
1446
|
previousMutedState = contentVideo.muted;
|
|
@@ -1418,6 +1479,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1418
1479
|
destroy: function destroy() {
|
|
1419
1480
|
console.log("[HlsAdPlayer] Destroying");
|
|
1420
1481
|
destroyed = true;
|
|
1482
|
+
clearStallWatchdog();
|
|
1421
1483
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
1422
1484
|
try {
|
|
1423
1485
|
for(var _iterator = pendingTimeouts[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
@@ -3809,6 +3871,7 @@ function getBrowserConfigOverrides() {
|
|
|
3809
3871
|
var overrides = {};
|
|
3810
3872
|
if (browser.isSmartTV) {
|
|
3811
3873
|
overrides.allowNativeHls = true;
|
|
3874
|
+
overrides.pauseContentDuringAds = true;
|
|
3812
3875
|
}
|
|
3813
3876
|
return overrides;
|
|
3814
3877
|
}
|
|
@@ -6691,12 +6754,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
|
|
|
6691
6754
|
// ───────────────────────────────────────────────────────────────
|
|
6692
6755
|
// IMA event listeners
|
|
6693
6756
|
// ───────────────────────────────────────────────────────────────
|
|
6694
|
-
|
|
6695
|
-
* Produces the next pod ad-request URL for the current break. Every request
|
|
6696
|
-
* (initial and continuous-fetch top-up) carries pod macros (pmad/pmnd/pmxd,
|
|
6697
|
-
* no ppos); pmxd tracks the remaining break time so top-up pods only ask for
|
|
6698
|
-
* what still fits.
|
|
6699
|
-
*/ key: "nextAdRequestUrl",
|
|
6757
|
+
key: "nextAdRequestUrl",
|
|
6700
6758
|
value: function nextAdRequestUrl(baseVastUrl) {
|
|
6701
6759
|
var remaining = Math.min(this.timing.getWallClockRemainingAdMs(), this.timing.getDurationBudgetRemainingMs());
|
|
6702
6760
|
var breakDurationMs = remaining > 0 ? remaining : void 0;
|
|
@@ -7825,7 +7883,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
|
|
|
7825
7883
|
if (Math.abs(this.host.video.volume - restoredVolume) > 0.01) {
|
|
7826
7884
|
this.host.video.volume = restoredVolume;
|
|
7827
7885
|
}
|
|
7828
|
-
|
|
7886
|
+
this.host.video.style.visibility = "visible";
|
|
7887
|
+
this.host.video.style.opacity = "1";
|
|
7888
|
+
if (this.host.isLiveStream()) {
|
|
7829
7889
|
var liveSyncPos = this.host.getLiveSyncPosition();
|
|
7830
7890
|
if (liveSyncPos != null && liveSyncPos > this.host.video.currentTime) {
|
|
7831
7891
|
if (this.debug) {
|
|
@@ -7833,16 +7893,39 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
|
|
|
7833
7893
|
}
|
|
7834
7894
|
this.host.video.currentTime = liveSyncPos;
|
|
7835
7895
|
}
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7896
|
+
}
|
|
7897
|
+
this.resumeContentPlayback();
|
|
7898
|
+
}
|
|
7899
|
+
},
|
|
7900
|
+
{
|
|
7901
|
+
key: "resumeContentPlayback",
|
|
7902
|
+
value: function resumeContentPlayback() {
|
|
7903
|
+
var _this = this;
|
|
7904
|
+
var attempt = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 0;
|
|
7905
|
+
var maxAttempts = 3;
|
|
7906
|
+
if (!this.host.video.paused) {
|
|
7907
|
+
if (this.debug && attempt === 0) {
|
|
7908
|
+
console.log("[StormcloudVideoPlayer] Content video already playing after ads");
|
|
7842
7909
|
}
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
7910
|
+
return;
|
|
7911
|
+
}
|
|
7912
|
+
if (this.debug) {
|
|
7913
|
+
console.log("[StormcloudVideoPlayer] Resuming content playback after ads (attempt ".concat(attempt + 1, "/").concat(maxAttempts, ")"));
|
|
7914
|
+
}
|
|
7915
|
+
var playResult = this.host.video.play();
|
|
7916
|
+
if (playResult && typeof playResult.catch === "function") {
|
|
7917
|
+
playResult.catch(function(error) {
|
|
7918
|
+
if (attempt + 1 >= maxAttempts) {
|
|
7919
|
+
if (_this.debug) {
|
|
7920
|
+
console.warn("[StormcloudVideoPlayer] Failed to resume content playback after ads:", error);
|
|
7921
|
+
}
|
|
7922
|
+
return;
|
|
7923
|
+
}
|
|
7924
|
+
var backoffMs = 250 * (attempt + 1);
|
|
7925
|
+
window.setTimeout(function() {
|
|
7926
|
+
_this.resumeContentPlayback(attempt + 1);
|
|
7927
|
+
}, backoffMs);
|
|
7928
|
+
});
|
|
7846
7929
|
}
|
|
7847
7930
|
}
|
|
7848
7931
|
},
|
|
@@ -7956,6 +8039,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
7956
8039
|
shouldContinueLiveStreamDuringAds: function shouldContinueLiveStreamDuringAds() {
|
|
7957
8040
|
return _this.shouldContinueLiveStreamDuringAds();
|
|
7958
8041
|
},
|
|
8042
|
+
isLiveStream: function isLiveStream() {
|
|
8043
|
+
return _this.hlsEngine.isLiveStream;
|
|
8044
|
+
},
|
|
7959
8045
|
getLiveSyncPosition: function getLiveSyncPosition() {
|
|
7960
8046
|
return _this.hlsEngine.getLiveSyncPosition();
|
|
7961
8047
|
},
|
|
@@ -8178,6 +8264,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
8178
8264
|
{
|
|
8179
8265
|
key: "shouldContinueLiveStreamDuringAds",
|
|
8180
8266
|
value: function shouldContinueLiveStreamDuringAds() {
|
|
8267
|
+
if (this.config.pauseContentDuringAds) {
|
|
8268
|
+
return false;
|
|
8269
|
+
}
|
|
8181
8270
|
if (this.hlsEngine.isLiveStream) {
|
|
8182
8271
|
return true;
|
|
8183
8272
|
}
|