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
package/lib/index.d.cts
CHANGED
|
@@ -21,6 +21,7 @@ interface StormcloudVideoPlayerConfig {
|
|
|
21
21
|
allowNativeHls?: boolean;
|
|
22
22
|
lowLatencyMode?: boolean;
|
|
23
23
|
isLiveStream?: boolean;
|
|
24
|
+
pauseContentDuringAds?: boolean;
|
|
24
25
|
driftToleranceMs?: number;
|
|
25
26
|
immediateManifestAds?: boolean;
|
|
26
27
|
debugAdTiming?: boolean;
|
|
@@ -4002,6 +4003,7 @@ interface BrowserInfo {
|
|
|
4002
4003
|
declare function detectBrowser(): BrowserInfo;
|
|
4003
4004
|
declare function getBrowserConfigOverrides(): {
|
|
4004
4005
|
allowNativeHls?: boolean;
|
|
4006
|
+
pauseContentDuringAds?: boolean;
|
|
4005
4007
|
};
|
|
4006
4008
|
declare function supportsModernJS(): boolean;
|
|
4007
4009
|
declare function logBrowserInfo(debug?: boolean): void;
|
package/lib/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ interface StormcloudVideoPlayerConfig {
|
|
|
21
21
|
allowNativeHls?: boolean;
|
|
22
22
|
lowLatencyMode?: boolean;
|
|
23
23
|
isLiveStream?: boolean;
|
|
24
|
+
pauseContentDuringAds?: boolean;
|
|
24
25
|
driftToleranceMs?: number;
|
|
25
26
|
immediateManifestAds?: boolean;
|
|
26
27
|
debugAdTiming?: boolean;
|
|
@@ -4002,6 +4003,7 @@ interface BrowserInfo {
|
|
|
4002
4003
|
declare function detectBrowser(): BrowserInfo;
|
|
4003
4004
|
declare function getBrowserConfigOverrides(): {
|
|
4004
4005
|
allowNativeHls?: boolean;
|
|
4006
|
+
pauseContentDuringAds?: boolean;
|
|
4005
4007
|
};
|
|
4006
4008
|
declare function supportsModernJS(): boolean;
|
|
4007
4009
|
declare function logBrowserInfo(debug?: boolean): void;
|
package/lib/index.js
CHANGED
|
@@ -389,6 +389,11 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
389
389
|
var preloadingAds = /* @__PURE__ */ new Map();
|
|
390
390
|
var destroyed = false;
|
|
391
391
|
var pendingTimeouts = [];
|
|
392
|
+
var STALL_TIMEOUT_MS = 4e3;
|
|
393
|
+
var STALL_CHECK_INTERVAL_MS = 1e3;
|
|
394
|
+
var stallWatchdogId;
|
|
395
|
+
var lastAdProgressTime = 0;
|
|
396
|
+
var lastAdProgressPosition = 0;
|
|
392
397
|
var trackingFired = {
|
|
393
398
|
impression: false,
|
|
394
399
|
start: false,
|
|
@@ -1021,6 +1026,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1021
1026
|
if (!adVideoElement || !currentAd) return;
|
|
1022
1027
|
adVideoElement.addEventListener("timeupdate", function() {
|
|
1023
1028
|
if (!currentAd || !adVideoElement) return;
|
|
1029
|
+
noteAdProgress();
|
|
1024
1030
|
var progress = adVideoElement.currentTime / currentAd.duration;
|
|
1025
1031
|
if (progress >= 0.25 && !trackingFired.firstQuartile) {
|
|
1026
1032
|
trackingFired.firstQuartile = true;
|
|
@@ -1036,6 +1042,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1036
1042
|
}
|
|
1037
1043
|
});
|
|
1038
1044
|
adVideoElement.addEventListener("playing", function() {
|
|
1045
|
+
startStallWatchdog();
|
|
1039
1046
|
if (!currentAd || trackingFired.start) return;
|
|
1040
1047
|
trackingFired.start = true;
|
|
1041
1048
|
fireTrackingPixels(currentAd.trackingUrls.start);
|
|
@@ -1176,8 +1183,52 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1176
1183
|
return false;
|
|
1177
1184
|
}
|
|
1178
1185
|
}
|
|
1186
|
+
function clearStallWatchdog() {
|
|
1187
|
+
if (stallWatchdogId != null) {
|
|
1188
|
+
clearInterval(stallWatchdogId);
|
|
1189
|
+
stallWatchdogId = void 0;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
function noteAdProgress() {
|
|
1193
|
+
lastAdProgressTime = Date.now();
|
|
1194
|
+
if (adVideoElement) {
|
|
1195
|
+
lastAdProgressPosition = adVideoElement.currentTime;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
function handleAdStall() {
|
|
1199
|
+
console.warn("[HlsAdPlayer] Ad playback stalled (no progress) - recovering to avoid a blank frame");
|
|
1200
|
+
clearStallWatchdog();
|
|
1201
|
+
if (currentAd) {
|
|
1202
|
+
fireTrackingPixels(currentAd.trackingUrls.error);
|
|
1203
|
+
}
|
|
1204
|
+
if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
|
|
1205
|
+
return;
|
|
1206
|
+
}
|
|
1207
|
+
handleAdError();
|
|
1208
|
+
}
|
|
1209
|
+
function startStallWatchdog() {
|
|
1210
|
+
clearStallWatchdog();
|
|
1211
|
+
noteAdProgress();
|
|
1212
|
+
stallWatchdogId = window.setInterval(function() {
|
|
1213
|
+
if (!adPlaying || !adVideoElement) {
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
|
|
1217
|
+
noteAdProgress();
|
|
1218
|
+
return;
|
|
1219
|
+
}
|
|
1220
|
+
if (adVideoElement.paused) {
|
|
1221
|
+
noteAdProgress();
|
|
1222
|
+
return;
|
|
1223
|
+
}
|
|
1224
|
+
if (Date.now() - lastAdProgressTime >= STALL_TIMEOUT_MS) {
|
|
1225
|
+
handleAdStall();
|
|
1226
|
+
}
|
|
1227
|
+
}, STALL_CHECK_INTERVAL_MS);
|
|
1228
|
+
}
|
|
1179
1229
|
function handleAdComplete() {
|
|
1180
1230
|
console.log("[HlsAdPlayer] Handling ad completion");
|
|
1231
|
+
clearStallWatchdog();
|
|
1181
1232
|
adPlaying = false;
|
|
1182
1233
|
setAdPlayingFlag(false);
|
|
1183
1234
|
contentVideo.muted = true;
|
|
@@ -1185,6 +1236,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1185
1236
|
adContainerEl.style.display = "none";
|
|
1186
1237
|
adContainerEl.style.pointerEvents = "none";
|
|
1187
1238
|
}
|
|
1239
|
+
if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1240
|
+
contentVideo.style.visibility = "visible";
|
|
1241
|
+
contentVideo.style.opacity = "1";
|
|
1242
|
+
}
|
|
1188
1243
|
if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
|
|
1189
1244
|
if (contentVideo.paused) {
|
|
1190
1245
|
console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback");
|
|
@@ -1197,6 +1252,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1197
1252
|
}
|
|
1198
1253
|
function handleAdError() {
|
|
1199
1254
|
console.log("[HlsAdPlayer] Handling ad error");
|
|
1255
|
+
clearStallWatchdog();
|
|
1200
1256
|
adPlaying = false;
|
|
1201
1257
|
setAdPlayingFlag(false);
|
|
1202
1258
|
contentVideo.muted = true;
|
|
@@ -1204,6 +1260,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1204
1260
|
adContainerEl.style.display = "none";
|
|
1205
1261
|
adContainerEl.style.pointerEvents = "none";
|
|
1206
1262
|
}
|
|
1263
|
+
if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1264
|
+
contentVideo.style.visibility = "visible";
|
|
1265
|
+
contentVideo.style.opacity = "1";
|
|
1266
|
+
}
|
|
1207
1267
|
emit("ad_error");
|
|
1208
1268
|
}
|
|
1209
1269
|
return {
|
|
@@ -1401,6 +1461,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1401
1461
|
var previousMutedState;
|
|
1402
1462
|
return _ts_generator(this, function(_state) {
|
|
1403
1463
|
console.log("[HlsAdPlayer] Stopping ad");
|
|
1464
|
+
clearStallWatchdog();
|
|
1404
1465
|
adPlaying = false;
|
|
1405
1466
|
setAdPlayingFlag(false);
|
|
1406
1467
|
previousMutedState = contentVideo.muted;
|
|
@@ -1439,6 +1500,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1439
1500
|
destroy: function destroy() {
|
|
1440
1501
|
console.log("[HlsAdPlayer] Destroying");
|
|
1441
1502
|
destroyed = true;
|
|
1503
|
+
clearStallWatchdog();
|
|
1442
1504
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
1443
1505
|
try {
|
|
1444
1506
|
for(var _iterator = pendingTimeouts[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
@@ -3856,6 +3918,7 @@ function getBrowserConfigOverrides() {
|
|
|
3856
3918
|
var overrides = {};
|
|
3857
3919
|
if (browser.isSmartTV) {
|
|
3858
3920
|
overrides.allowNativeHls = true;
|
|
3921
|
+
overrides.pauseContentDuringAds = true;
|
|
3859
3922
|
}
|
|
3860
3923
|
return overrides;
|
|
3861
3924
|
}
|
|
@@ -6768,12 +6831,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
|
|
|
6768
6831
|
// ───────────────────────────────────────────────────────────────
|
|
6769
6832
|
// IMA event listeners
|
|
6770
6833
|
// ───────────────────────────────────────────────────────────────
|
|
6771
|
-
|
|
6772
|
-
* Produces the next pod ad-request URL for the current break. Every request
|
|
6773
|
-
* (initial and continuous-fetch top-up) carries pod macros (pmad/pmnd/pmxd,
|
|
6774
|
-
* no ppos); pmxd tracks the remaining break time so top-up pods only ask for
|
|
6775
|
-
* what still fits.
|
|
6776
|
-
*/ key: "nextAdRequestUrl",
|
|
6834
|
+
key: "nextAdRequestUrl",
|
|
6777
6835
|
value: function nextAdRequestUrl(baseVastUrl) {
|
|
6778
6836
|
var remaining = Math.min(this.timing.getWallClockRemainingAdMs(), this.timing.getDurationBudgetRemainingMs());
|
|
6779
6837
|
var breakDurationMs = remaining > 0 ? remaining : void 0;
|
|
@@ -7902,7 +7960,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
|
|
|
7902
7960
|
if (Math.abs(this.host.video.volume - restoredVolume) > 0.01) {
|
|
7903
7961
|
this.host.video.volume = restoredVolume;
|
|
7904
7962
|
}
|
|
7905
|
-
|
|
7963
|
+
this.host.video.style.visibility = "visible";
|
|
7964
|
+
this.host.video.style.opacity = "1";
|
|
7965
|
+
if (this.host.isLiveStream()) {
|
|
7906
7966
|
var liveSyncPos = this.host.getLiveSyncPosition();
|
|
7907
7967
|
if (liveSyncPos != null && liveSyncPos > this.host.video.currentTime) {
|
|
7908
7968
|
if (this.debug) {
|
|
@@ -7910,16 +7970,39 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
|
|
|
7910
7970
|
}
|
|
7911
7971
|
this.host.video.currentTime = liveSyncPos;
|
|
7912
7972
|
}
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
7973
|
+
}
|
|
7974
|
+
this.resumeContentPlayback();
|
|
7975
|
+
}
|
|
7976
|
+
},
|
|
7977
|
+
{
|
|
7978
|
+
key: "resumeContentPlayback",
|
|
7979
|
+
value: function resumeContentPlayback() {
|
|
7980
|
+
var _this = this;
|
|
7981
|
+
var attempt = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 0;
|
|
7982
|
+
var maxAttempts = 3;
|
|
7983
|
+
if (!this.host.video.paused) {
|
|
7984
|
+
if (this.debug && attempt === 0) {
|
|
7985
|
+
console.log("[StormcloudVideoPlayer] Content video already playing after ads");
|
|
7919
7986
|
}
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7987
|
+
return;
|
|
7988
|
+
}
|
|
7989
|
+
if (this.debug) {
|
|
7990
|
+
console.log("[StormcloudVideoPlayer] Resuming content playback after ads (attempt ".concat(attempt + 1, "/").concat(maxAttempts, ")"));
|
|
7991
|
+
}
|
|
7992
|
+
var playResult = this.host.video.play();
|
|
7993
|
+
if (playResult && typeof playResult.catch === "function") {
|
|
7994
|
+
playResult.catch(function(error) {
|
|
7995
|
+
if (attempt + 1 >= maxAttempts) {
|
|
7996
|
+
if (_this.debug) {
|
|
7997
|
+
console.warn("[StormcloudVideoPlayer] Failed to resume content playback after ads:", error);
|
|
7998
|
+
}
|
|
7999
|
+
return;
|
|
8000
|
+
}
|
|
8001
|
+
var backoffMs = 250 * (attempt + 1);
|
|
8002
|
+
window.setTimeout(function() {
|
|
8003
|
+
_this.resumeContentPlayback(attempt + 1);
|
|
8004
|
+
}, backoffMs);
|
|
8005
|
+
});
|
|
7923
8006
|
}
|
|
7924
8007
|
}
|
|
7925
8008
|
},
|
|
@@ -8034,6 +8117,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
8034
8117
|
shouldContinueLiveStreamDuringAds: function shouldContinueLiveStreamDuringAds() {
|
|
8035
8118
|
return _this.shouldContinueLiveStreamDuringAds();
|
|
8036
8119
|
},
|
|
8120
|
+
isLiveStream: function isLiveStream() {
|
|
8121
|
+
return _this.hlsEngine.isLiveStream;
|
|
8122
|
+
},
|
|
8037
8123
|
getLiveSyncPosition: function getLiveSyncPosition() {
|
|
8038
8124
|
return _this.hlsEngine.getLiveSyncPosition();
|
|
8039
8125
|
},
|
|
@@ -8256,6 +8342,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
8256
8342
|
{
|
|
8257
8343
|
key: "shouldContinueLiveStreamDuringAds",
|
|
8258
8344
|
value: function shouldContinueLiveStreamDuringAds() {
|
|
8345
|
+
if (this.config.pauseContentDuringAds) {
|
|
8346
|
+
return false;
|
|
8347
|
+
}
|
|
8259
8348
|
if (this.hlsEngine.isLiveStream) {
|
|
8260
8349
|
return true;
|
|
8261
8350
|
}
|