stormcloud-video-player 0.8.33 → 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 +143 -19
- 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 +143 -19
- 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.cjs +36 -1
- package/lib/player/AdConfigManager.cjs.map +1 -1
- 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 +143 -19
- 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 +143 -19
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +143 -19
- 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/sdk/pal.cjs +38 -2
- package/lib/sdk/pal.cjs.map +1 -1
- package/lib/{types-CSHvCbhZ.d.cts → types-cTqIKw_D.d.cts} +1 -0
- package/lib/ui/StormcloudVideoPlayer.cjs +143 -19
- 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/devUrl.cjs +102 -0
- package/lib/utils/devUrl.cjs.map +1 -0
- package/lib/utils/devUrl.d.cts +4 -0
- package/lib/utils/tracking.d.cts +1 -1
- package/package.json +1 -1
package/lib/index.cjs
CHANGED
|
@@ -606,6 +606,11 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
606
606
|
var preloadingAds = /* @__PURE__ */ new Map();
|
|
607
607
|
var destroyed = false;
|
|
608
608
|
var pendingTimeouts = [];
|
|
609
|
+
var STALL_TIMEOUT_MS = 4e3;
|
|
610
|
+
var STALL_CHECK_INTERVAL_MS = 1e3;
|
|
611
|
+
var stallWatchdogId;
|
|
612
|
+
var lastAdProgressTime = 0;
|
|
613
|
+
var lastAdProgressPosition = 0;
|
|
609
614
|
var trackingFired = {
|
|
610
615
|
impression: false,
|
|
611
616
|
start: false,
|
|
@@ -1238,6 +1243,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1238
1243
|
if (!adVideoElement || !currentAd) return;
|
|
1239
1244
|
adVideoElement.addEventListener("timeupdate", function() {
|
|
1240
1245
|
if (!currentAd || !adVideoElement) return;
|
|
1246
|
+
noteAdProgress();
|
|
1241
1247
|
var progress = adVideoElement.currentTime / currentAd.duration;
|
|
1242
1248
|
if (progress >= 0.25 && !trackingFired.firstQuartile) {
|
|
1243
1249
|
trackingFired.firstQuartile = true;
|
|
@@ -1253,6 +1259,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1253
1259
|
}
|
|
1254
1260
|
});
|
|
1255
1261
|
adVideoElement.addEventListener("playing", function() {
|
|
1262
|
+
startStallWatchdog();
|
|
1256
1263
|
if (!currentAd || trackingFired.start) return;
|
|
1257
1264
|
trackingFired.start = true;
|
|
1258
1265
|
fireTrackingPixels(currentAd.trackingUrls.start);
|
|
@@ -1393,8 +1400,52 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1393
1400
|
return false;
|
|
1394
1401
|
}
|
|
1395
1402
|
}
|
|
1403
|
+
function clearStallWatchdog() {
|
|
1404
|
+
if (stallWatchdogId != null) {
|
|
1405
|
+
clearInterval(stallWatchdogId);
|
|
1406
|
+
stallWatchdogId = void 0;
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
function noteAdProgress() {
|
|
1410
|
+
lastAdProgressTime = Date.now();
|
|
1411
|
+
if (adVideoElement) {
|
|
1412
|
+
lastAdProgressPosition = adVideoElement.currentTime;
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
function handleAdStall() {
|
|
1416
|
+
console.warn("[HlsAdPlayer] Ad playback stalled (no progress) - recovering to avoid a blank frame");
|
|
1417
|
+
clearStallWatchdog();
|
|
1418
|
+
if (currentAd) {
|
|
1419
|
+
fireTrackingPixels(currentAd.trackingUrls.error);
|
|
1420
|
+
}
|
|
1421
|
+
if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
handleAdError();
|
|
1425
|
+
}
|
|
1426
|
+
function startStallWatchdog() {
|
|
1427
|
+
clearStallWatchdog();
|
|
1428
|
+
noteAdProgress();
|
|
1429
|
+
stallWatchdogId = window.setInterval(function() {
|
|
1430
|
+
if (!adPlaying || !adVideoElement) {
|
|
1431
|
+
return;
|
|
1432
|
+
}
|
|
1433
|
+
if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
|
|
1434
|
+
noteAdProgress();
|
|
1435
|
+
return;
|
|
1436
|
+
}
|
|
1437
|
+
if (adVideoElement.paused) {
|
|
1438
|
+
noteAdProgress();
|
|
1439
|
+
return;
|
|
1440
|
+
}
|
|
1441
|
+
if (Date.now() - lastAdProgressTime >= STALL_TIMEOUT_MS) {
|
|
1442
|
+
handleAdStall();
|
|
1443
|
+
}
|
|
1444
|
+
}, STALL_CHECK_INTERVAL_MS);
|
|
1445
|
+
}
|
|
1396
1446
|
function handleAdComplete() {
|
|
1397
1447
|
console.log("[HlsAdPlayer] Handling ad completion");
|
|
1448
|
+
clearStallWatchdog();
|
|
1398
1449
|
adPlaying = false;
|
|
1399
1450
|
setAdPlayingFlag(false);
|
|
1400
1451
|
contentVideo.muted = true;
|
|
@@ -1402,6 +1453,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1402
1453
|
adContainerEl.style.display = "none";
|
|
1403
1454
|
adContainerEl.style.pointerEvents = "none";
|
|
1404
1455
|
}
|
|
1456
|
+
if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1457
|
+
contentVideo.style.visibility = "visible";
|
|
1458
|
+
contentVideo.style.opacity = "1";
|
|
1459
|
+
}
|
|
1405
1460
|
if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
|
|
1406
1461
|
if (contentVideo.paused) {
|
|
1407
1462
|
console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback");
|
|
@@ -1414,6 +1469,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1414
1469
|
}
|
|
1415
1470
|
function handleAdError() {
|
|
1416
1471
|
console.log("[HlsAdPlayer] Handling ad error");
|
|
1472
|
+
clearStallWatchdog();
|
|
1417
1473
|
adPlaying = false;
|
|
1418
1474
|
setAdPlayingFlag(false);
|
|
1419
1475
|
contentVideo.muted = true;
|
|
@@ -1421,6 +1477,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1421
1477
|
adContainerEl.style.display = "none";
|
|
1422
1478
|
adContainerEl.style.pointerEvents = "none";
|
|
1423
1479
|
}
|
|
1480
|
+
if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1481
|
+
contentVideo.style.visibility = "visible";
|
|
1482
|
+
contentVideo.style.opacity = "1";
|
|
1483
|
+
}
|
|
1424
1484
|
emit("ad_error");
|
|
1425
1485
|
}
|
|
1426
1486
|
return {
|
|
@@ -1618,6 +1678,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1618
1678
|
var previousMutedState;
|
|
1619
1679
|
return _ts_generator(this, function(_state) {
|
|
1620
1680
|
console.log("[HlsAdPlayer] Stopping ad");
|
|
1681
|
+
clearStallWatchdog();
|
|
1621
1682
|
adPlaying = false;
|
|
1622
1683
|
setAdPlayingFlag(false);
|
|
1623
1684
|
previousMutedState = contentVideo.muted;
|
|
@@ -1656,6 +1717,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1656
1717
|
destroy: function destroy() {
|
|
1657
1718
|
console.log("[HlsAdPlayer] Destroying");
|
|
1658
1719
|
destroyed = true;
|
|
1720
|
+
clearStallWatchdog();
|
|
1659
1721
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
1660
1722
|
try {
|
|
1661
1723
|
for(var _iterator = pendingTimeouts[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
@@ -1800,6 +1862,41 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1800
1862
|
}
|
|
1801
1863
|
};
|
|
1802
1864
|
}
|
|
1865
|
+
// src/utils/devUrl.ts
|
|
1866
|
+
var PRIVATE_HOST_PATTERNS = [
|
|
1867
|
+
/^localhost$/i,
|
|
1868
|
+
/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,
|
|
1869
|
+
/^0\.0\.0\.0$/,
|
|
1870
|
+
/^::1$/,
|
|
1871
|
+
/^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,
|
|
1872
|
+
/^192\.168\.\d{1,3}\.\d{1,3}$/,
|
|
1873
|
+
/^172\.(1[6-9]|2\d|3[0-1])\.\d{1,3}\.\d{1,3}$/
|
|
1874
|
+
];
|
|
1875
|
+
function isLocalDevHost(hostname) {
|
|
1876
|
+
var host = hostname.replace(/^\[/, "").replace(/\]$/, "").toLowerCase();
|
|
1877
|
+
if (!host) return false;
|
|
1878
|
+
if (host.endsWith(".local") || host.endsWith(".localhost")) return true;
|
|
1879
|
+
return PRIVATE_HOST_PATTERNS.some(function(pattern) {
|
|
1880
|
+
return pattern.test(host);
|
|
1881
|
+
});
|
|
1882
|
+
}
|
|
1883
|
+
function toDevSafeUrl(rawUrl) {
|
|
1884
|
+
if (!rawUrl) return rawUrl !== null && rawUrl !== void 0 ? rawUrl : "";
|
|
1885
|
+
var url;
|
|
1886
|
+
try {
|
|
1887
|
+
url = new URL(rawUrl);
|
|
1888
|
+
} catch (unused) {
|
|
1889
|
+
return rawUrl;
|
|
1890
|
+
}
|
|
1891
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
1892
|
+
return rawUrl;
|
|
1893
|
+
}
|
|
1894
|
+
if (!isLocalDevHost(url.hostname)) {
|
|
1895
|
+
return rawUrl;
|
|
1896
|
+
}
|
|
1897
|
+
var cleanPath = url.pathname.replace(/\/{2,}/g, "/") || "/index.html";
|
|
1898
|
+
return "file://".concat(cleanPath);
|
|
1899
|
+
}
|
|
1803
1900
|
// src/sdk/pal.ts
|
|
1804
1901
|
var PAL_SDK_URL = "https://imasdk.googleapis.com/pal/sdkloader/pal.js";
|
|
1805
1902
|
var _nonceLoader;
|
|
@@ -1886,12 +1983,12 @@ function createPalNonceManager() {
|
|
|
1886
1983
|
request.adWillPlayMuted = (_options_adWillPlayMuted = options.adWillPlayMuted) !== null && _options_adWillPlayMuted !== void 0 ? _options_adWillPlayMuted : false;
|
|
1887
1984
|
request.playerVolume = (_options_playerVolume = options.playerVolume) !== null && _options_playerVolume !== void 0 ? _options_playerVolume : request.adWillPlayMuted ? 0 : 1;
|
|
1888
1985
|
request.continuousPlayback = (_options_continuousPlayback = options.continuousPlayback) !== null && _options_continuousPlayback !== void 0 ? _options_continuousPlayback : true;
|
|
1889
|
-
request.descriptionUrl = options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : "");
|
|
1986
|
+
request.descriptionUrl = toDevSafeUrl(options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : ""));
|
|
1890
1987
|
request.iconsSupported = true;
|
|
1891
1988
|
request.playerType = "StormcloudVideoPlayer";
|
|
1892
1989
|
request.playerVersion = "1.0";
|
|
1893
1990
|
request.supportedApiFrameworks = "2,7,9";
|
|
1894
|
-
request.url = options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : "");
|
|
1991
|
+
request.url = toDevSafeUrl(options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : ""));
|
|
1895
1992
|
request.videoWidth = options.videoWidth || 640;
|
|
1896
1993
|
request.videoHeight = options.videoHeight || 480;
|
|
1897
1994
|
if (options.ppid) request.ppid = options.ppid;
|
|
@@ -4036,6 +4133,7 @@ function getBrowserConfigOverrides() {
|
|
|
4036
4133
|
var overrides = {};
|
|
4037
4134
|
if (browser.isSmartTV) {
|
|
4038
4135
|
overrides.allowNativeHls = true;
|
|
4136
|
+
overrides.pauseContentDuringAds = true;
|
|
4039
4137
|
}
|
|
4040
4138
|
return overrides;
|
|
4041
4139
|
}
|
|
@@ -5557,7 +5655,7 @@ var AdConfigManager = /*#__PURE__*/ function() {
|
|
|
5557
5655
|
podMaxDurationMs: podParams.maxDurationMs,
|
|
5558
5656
|
isCtv: envSignals.isCtv,
|
|
5559
5657
|
contentUrl: envSignals.contentUrl,
|
|
5560
|
-
pageUrl: !envSignals.isCtv && typeof window !== "undefined" ? window.location.href : void 0,
|
|
5658
|
+
pageUrl: !envSignals.isCtv && typeof window !== "undefined" ? toDevSafeUrl(window.location.href) : void 0,
|
|
5561
5659
|
adWillPlayMuted: adWillPlayMuted,
|
|
5562
5660
|
adWillAutoPlay: !!this.config.autoplay,
|
|
5563
5661
|
appId: envSignals.appId,
|
|
@@ -6941,12 +7039,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
|
|
|
6941
7039
|
// ───────────────────────────────────────────────────────────────
|
|
6942
7040
|
// IMA event listeners
|
|
6943
7041
|
// ───────────────────────────────────────────────────────────────
|
|
6944
|
-
|
|
6945
|
-
* Produces the next pod ad-request URL for the current break. Every request
|
|
6946
|
-
* (initial and continuous-fetch top-up) carries pod macros (pmad/pmnd/pmxd,
|
|
6947
|
-
* no ppos); pmxd tracks the remaining break time so top-up pods only ask for
|
|
6948
|
-
* what still fits.
|
|
6949
|
-
*/ key: "nextAdRequestUrl",
|
|
7042
|
+
key: "nextAdRequestUrl",
|
|
6950
7043
|
value: function nextAdRequestUrl(baseVastUrl) {
|
|
6951
7044
|
var remaining = Math.min(this.timing.getWallClockRemainingAdMs(), this.timing.getDurationBudgetRemainingMs());
|
|
6952
7045
|
var breakDurationMs = remaining > 0 ? remaining : void 0;
|
|
@@ -8075,7 +8168,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
|
|
|
8075
8168
|
if (Math.abs(this.host.video.volume - restoredVolume) > 0.01) {
|
|
8076
8169
|
this.host.video.volume = restoredVolume;
|
|
8077
8170
|
}
|
|
8078
|
-
|
|
8171
|
+
this.host.video.style.visibility = "visible";
|
|
8172
|
+
this.host.video.style.opacity = "1";
|
|
8173
|
+
if (this.host.isLiveStream()) {
|
|
8079
8174
|
var liveSyncPos = this.host.getLiveSyncPosition();
|
|
8080
8175
|
if (liveSyncPos != null && liveSyncPos > this.host.video.currentTime) {
|
|
8081
8176
|
if (this.debug) {
|
|
@@ -8083,16 +8178,39 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
|
|
|
8083
8178
|
}
|
|
8084
8179
|
this.host.video.currentTime = liveSyncPos;
|
|
8085
8180
|
}
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8181
|
+
}
|
|
8182
|
+
this.resumeContentPlayback();
|
|
8183
|
+
}
|
|
8184
|
+
},
|
|
8185
|
+
{
|
|
8186
|
+
key: "resumeContentPlayback",
|
|
8187
|
+
value: function resumeContentPlayback() {
|
|
8188
|
+
var _this = this;
|
|
8189
|
+
var attempt = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 0;
|
|
8190
|
+
var maxAttempts = 3;
|
|
8191
|
+
if (!this.host.video.paused) {
|
|
8192
|
+
if (this.debug && attempt === 0) {
|
|
8193
|
+
console.log("[StormcloudVideoPlayer] Content video already playing after ads");
|
|
8092
8194
|
}
|
|
8093
|
-
|
|
8094
|
-
|
|
8095
|
-
|
|
8195
|
+
return;
|
|
8196
|
+
}
|
|
8197
|
+
if (this.debug) {
|
|
8198
|
+
console.log("[StormcloudVideoPlayer] Resuming content playback after ads (attempt ".concat(attempt + 1, "/").concat(maxAttempts, ")"));
|
|
8199
|
+
}
|
|
8200
|
+
var playResult = this.host.video.play();
|
|
8201
|
+
if (playResult && typeof playResult.catch === "function") {
|
|
8202
|
+
playResult.catch(function(error) {
|
|
8203
|
+
if (attempt + 1 >= maxAttempts) {
|
|
8204
|
+
if (_this.debug) {
|
|
8205
|
+
console.warn("[StormcloudVideoPlayer] Failed to resume content playback after ads:", error);
|
|
8206
|
+
}
|
|
8207
|
+
return;
|
|
8208
|
+
}
|
|
8209
|
+
var backoffMs = 250 * (attempt + 1);
|
|
8210
|
+
window.setTimeout(function() {
|
|
8211
|
+
_this.resumeContentPlayback(attempt + 1);
|
|
8212
|
+
}, backoffMs);
|
|
8213
|
+
});
|
|
8096
8214
|
}
|
|
8097
8215
|
}
|
|
8098
8216
|
},
|
|
@@ -8206,6 +8324,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
8206
8324
|
shouldContinueLiveStreamDuringAds: function shouldContinueLiveStreamDuringAds() {
|
|
8207
8325
|
return _this.shouldContinueLiveStreamDuringAds();
|
|
8208
8326
|
},
|
|
8327
|
+
isLiveStream: function isLiveStream() {
|
|
8328
|
+
return _this.hlsEngine.isLiveStream;
|
|
8329
|
+
},
|
|
8209
8330
|
getLiveSyncPosition: function getLiveSyncPosition() {
|
|
8210
8331
|
return _this.hlsEngine.getLiveSyncPosition();
|
|
8211
8332
|
},
|
|
@@ -8428,6 +8549,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
8428
8549
|
{
|
|
8429
8550
|
key: "shouldContinueLiveStreamDuringAds",
|
|
8430
8551
|
value: function shouldContinueLiveStreamDuringAds() {
|
|
8552
|
+
if (this.config.pauseContentDuringAds) {
|
|
8553
|
+
return false;
|
|
8554
|
+
}
|
|
8431
8555
|
if (this.hlsEngine.isLiveStream) {
|
|
8432
8556
|
return true;
|
|
8433
8557
|
}
|