stormcloud-video-player 0.8.48 → 0.8.50
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 +2 -2
- package/lib/index.cjs +107 -5
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +107 -5
- package/lib/index.js.map +1 -1
- package/lib/player/AdTimingService.cjs +5 -5
- package/lib/player/AdTimingService.cjs.map +1 -1
- package/lib/player/AdTimingService.d.cts +6 -1
- package/lib/player/StormcloudVideoPlayer.cjs +107 -5
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.cjs +107 -5
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +107 -5
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +95 -0
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/types-iDjS8f_7.d.cts +133 -0
- package/lib/ui/StormcloudVideoPlayer.cjs +107 -5
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +1 -1
package/lib/players/index.cjs
CHANGED
|
@@ -447,6 +447,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
447
447
|
var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
|
|
448
448
|
var AD_CONTAINER_PROP = "__stormcloudAdContainer";
|
|
449
449
|
var AD_VIDEO_PROP = "__stormcloudAdVideo";
|
|
450
|
+
var FRAME_COUNTER_RELIABLE_PROP = "__stormcloudFrameCounterReliable";
|
|
450
451
|
var adVideoElement = (_contentVideo_AD_VIDEO_PROP = contentVideo[AD_VIDEO_PROP]) !== null && _contentVideo_AD_VIDEO_PROP !== void 0 ? _contentVideo_AD_VIDEO_PROP : void 0;
|
|
451
452
|
var adHls;
|
|
452
453
|
var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
|
|
@@ -461,9 +462,12 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
461
462
|
var pendingTimeouts = [];
|
|
462
463
|
var STALL_TIMEOUT_MS = 4e3;
|
|
463
464
|
var STALL_CHECK_INTERVAL_MS = 1e3;
|
|
465
|
+
var BLACKFRAME_MIN_PLAYBACK_S = 1.5;
|
|
464
466
|
var stallWatchdogId;
|
|
465
467
|
var lastAdProgressTime = 0;
|
|
466
468
|
var lastAdProgressPosition = 0;
|
|
469
|
+
var sawDecodedVideoFrame = false;
|
|
470
|
+
var videoFrameCallbackHandle;
|
|
467
471
|
var trackingFired = {
|
|
468
472
|
impression: false,
|
|
469
473
|
start: false,
|
|
@@ -644,6 +648,11 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
644
648
|
console.warn("[HlsAdPlayer] MediaFile ".concat(index, ' skipped (audio-only, type="').concat(type, '") — audio ads are not played to avoid a black screen'));
|
|
645
649
|
return;
|
|
646
650
|
}
|
|
651
|
+
var hasExplicitDimensions = mf.getAttribute("width") != null && mf.getAttribute("height") != null;
|
|
652
|
+
if (!isHlsMediaFile(mediaFile) && hasExplicitDimensions && (mediaFile.width <= 1 || mediaFile.height <= 1)) {
|
|
653
|
+
console.warn("[HlsAdPlayer] MediaFile ".concat(index, " skipped (degenerate dimensions ").concat(mediaFile.width, "x").concat(mediaFile.height, ', type="').concat(type, '") — likely an audio-only placeholder rendition'));
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
647
656
|
if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
|
|
648
657
|
mediaFiles.push(mediaFile);
|
|
649
658
|
if (verbose) {
|
|
@@ -1111,6 +1120,14 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1111
1120
|
fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
|
|
1112
1121
|
}
|
|
1113
1122
|
};
|
|
1123
|
+
var onLoadedMetadata = function onLoadedMetadata() {
|
|
1124
|
+
if (!adPlaying || !adVideoElement) return;
|
|
1125
|
+
var videoWidth = adVideoElement.videoWidth, videoHeight = adVideoElement.videoHeight;
|
|
1126
|
+
if (videoWidth <= 1 || videoHeight <= 1) {
|
|
1127
|
+
console.warn("[HlsAdPlayer] Ad creative has no usable video dimensions (".concat(videoWidth, "x").concat(videoHeight, ") - skipping this creative"));
|
|
1128
|
+
handleVideoDecodeFailure();
|
|
1129
|
+
}
|
|
1130
|
+
};
|
|
1114
1131
|
var onPlaying = function onPlaying() {
|
|
1115
1132
|
startStallWatchdog();
|
|
1116
1133
|
if (!currentAd || trackingFired.start) return;
|
|
@@ -1162,6 +1179,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1162
1179
|
type: "timeupdate",
|
|
1163
1180
|
handler: onTimeUpdate
|
|
1164
1181
|
},
|
|
1182
|
+
{
|
|
1183
|
+
type: "loadedmetadata",
|
|
1184
|
+
handler: onLoadedMetadata
|
|
1185
|
+
},
|
|
1165
1186
|
{
|
|
1166
1187
|
type: "playing",
|
|
1167
1188
|
handler: onPlaying
|
|
@@ -1333,6 +1354,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1333
1354
|
clearInterval(stallWatchdogId);
|
|
1334
1355
|
stallWatchdogId = void 0;
|
|
1335
1356
|
}
|
|
1357
|
+
cancelVideoFrameProbe();
|
|
1336
1358
|
}
|
|
1337
1359
|
function noteAdProgress() {
|
|
1338
1360
|
lastAdProgressTime = Date.now();
|
|
@@ -1351,13 +1373,86 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1351
1373
|
}
|
|
1352
1374
|
handleAdError();
|
|
1353
1375
|
}
|
|
1376
|
+
function getDecodedVideoFrameCount(video) {
|
|
1377
|
+
try {
|
|
1378
|
+
if (typeof video.getVideoPlaybackQuality === "function") {
|
|
1379
|
+
var quality = video.getVideoPlaybackQuality();
|
|
1380
|
+
if (quality && typeof quality.totalVideoFrames === "number") {
|
|
1381
|
+
return quality.totalVideoFrames;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
var legacyCount = video.webkitDecodedFrameCount;
|
|
1385
|
+
if (typeof legacyCount === "number") {
|
|
1386
|
+
return legacyCount;
|
|
1387
|
+
}
|
|
1388
|
+
} catch (error) {
|
|
1389
|
+
console.warn("[HlsAdPlayer] Unable to read decoded video frame count:", error);
|
|
1390
|
+
}
|
|
1391
|
+
return void 0;
|
|
1392
|
+
}
|
|
1393
|
+
function isFrameCounterReliable() {
|
|
1394
|
+
return contentVideo[FRAME_COUNTER_RELIABLE_PROP] === true;
|
|
1395
|
+
}
|
|
1396
|
+
function markFrameCounterReliable() {
|
|
1397
|
+
contentVideo[FRAME_COUNTER_RELIABLE_PROP] = true;
|
|
1398
|
+
}
|
|
1399
|
+
function cancelVideoFrameProbe() {
|
|
1400
|
+
if (videoFrameCallbackHandle != null && adVideoElement && typeof adVideoElement.cancelVideoFrameCallback === "function") {
|
|
1401
|
+
try {
|
|
1402
|
+
adVideoElement.cancelVideoFrameCallback(videoFrameCallbackHandle);
|
|
1403
|
+
} catch (error) {
|
|
1404
|
+
console.warn("[HlsAdPlayer] Error cancelling video frame callback:", error);
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
videoFrameCallbackHandle = void 0;
|
|
1408
|
+
}
|
|
1409
|
+
function startVideoFrameProbe() {
|
|
1410
|
+
cancelVideoFrameProbe();
|
|
1411
|
+
if (!adVideoElement) return;
|
|
1412
|
+
var rvfc = adVideoElement.requestVideoFrameCallback;
|
|
1413
|
+
if (typeof rvfc !== "function") return;
|
|
1414
|
+
var onPresentedFrame = function onPresentedFrame() {
|
|
1415
|
+
videoFrameCallbackHandle = void 0;
|
|
1416
|
+
if (!adPlaying) return;
|
|
1417
|
+
sawDecodedVideoFrame = true;
|
|
1418
|
+
};
|
|
1419
|
+
try {
|
|
1420
|
+
videoFrameCallbackHandle = rvfc.call(adVideoElement, onPresentedFrame);
|
|
1421
|
+
} catch (error) {
|
|
1422
|
+
console.warn("[HlsAdPlayer] Error requesting video frame callback:", error);
|
|
1423
|
+
videoFrameCallbackHandle = void 0;
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
function handleVideoDecodeFailure() {
|
|
1427
|
+
console.warn("[HlsAdPlayer] Ad audio is advancing but no video frames decoded (black screen) - skipping this creative");
|
|
1428
|
+
clearStallWatchdog();
|
|
1429
|
+
if (currentAd) {
|
|
1430
|
+
fireTrackingPixels(currentAd.trackingUrls.error);
|
|
1431
|
+
}
|
|
1432
|
+
if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
|
|
1433
|
+
return;
|
|
1434
|
+
}
|
|
1435
|
+
handleAdError();
|
|
1436
|
+
}
|
|
1354
1437
|
function startStallWatchdog() {
|
|
1355
1438
|
clearStallWatchdog();
|
|
1356
1439
|
noteAdProgress();
|
|
1440
|
+
sawDecodedVideoFrame = false;
|
|
1441
|
+
startVideoFrameProbe();
|
|
1357
1442
|
stallWatchdogId = window.setInterval(function() {
|
|
1358
1443
|
if (!adPlaying || !adVideoElement) {
|
|
1359
1444
|
return;
|
|
1360
1445
|
}
|
|
1446
|
+
if (!sawDecodedVideoFrame && !adVideoElement.paused) {
|
|
1447
|
+
var decodedFrames = getDecodedVideoFrameCount(adVideoElement);
|
|
1448
|
+
if (decodedFrames !== void 0 && decodedFrames > 0) {
|
|
1449
|
+
sawDecodedVideoFrame = true;
|
|
1450
|
+
markFrameCounterReliable();
|
|
1451
|
+
} else if (decodedFrames === 0 && adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S && isFrameCounterReliable()) {
|
|
1452
|
+
handleVideoDecodeFailure();
|
|
1453
|
+
return;
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1361
1456
|
if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
|
|
1362
1457
|
noteAdProgress();
|
|
1363
1458
|
return;
|
|
@@ -6198,17 +6293,17 @@ var AdTimingService = /*#__PURE__*/ function() {
|
|
|
6198
6293
|
{
|
|
6199
6294
|
key: "logAdState",
|
|
6200
6295
|
value: function logAdState(event) {
|
|
6201
|
-
var extra = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {}
|
|
6202
|
-
var _ref;
|
|
6296
|
+
var extra = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
6203
6297
|
if (!this.debug) {
|
|
6204
6298
|
return;
|
|
6205
6299
|
}
|
|
6300
|
+
var _this_callbacks_getAdState = this.callbacks.getAdState(), inAdBreak = _this_callbacks_getAdState.inAdBreak, showAds = _this_callbacks_getAdState.showAds, adPlaying = _this_callbacks_getAdState.adPlaying;
|
|
6206
6301
|
console.log("[StormcloudVideoPlayer][AdState]", _object_spread({
|
|
6207
6302
|
event: event,
|
|
6208
6303
|
timestamp: /* @__PURE__ */ new Date().toISOString(),
|
|
6209
|
-
showAds: showAds
|
|
6210
|
-
adPlaying:
|
|
6211
|
-
inAdBreak: inAdBreak
|
|
6304
|
+
showAds: showAds,
|
|
6305
|
+
adPlaying: adPlaying,
|
|
6306
|
+
inAdBreak: inAdBreak,
|
|
6212
6307
|
activeAdRequestToken: this.activeAdRequestToken
|
|
6213
6308
|
}, extra));
|
|
6214
6309
|
}
|
|
@@ -8558,6 +8653,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
8558
8653
|
},
|
|
8559
8654
|
onFailsafeTimeout: function onFailsafeTimeout() {
|
|
8560
8655
|
return _this.adBreak.handleAdFailure();
|
|
8656
|
+
},
|
|
8657
|
+
getAdState: function getAdState() {
|
|
8658
|
+
return {
|
|
8659
|
+
inAdBreak: _this.adBreak.inAdBreak,
|
|
8660
|
+
showAds: _this.adBreak.showAds,
|
|
8661
|
+
adPlaying: _this.adPlayer.isAdPlaying()
|
|
8662
|
+
};
|
|
8561
8663
|
}
|
|
8562
8664
|
});
|
|
8563
8665
|
this.placeholder = new PlaceholderLayer(this.video, !!this.config.debugAdTiming);
|