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
|
@@ -411,6 +411,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
411
411
|
var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
|
|
412
412
|
var AD_CONTAINER_PROP = "__stormcloudAdContainer";
|
|
413
413
|
var AD_VIDEO_PROP = "__stormcloudAdVideo";
|
|
414
|
+
var FRAME_COUNTER_RELIABLE_PROP = "__stormcloudFrameCounterReliable";
|
|
414
415
|
var adVideoElement = (_contentVideo_AD_VIDEO_PROP = contentVideo[AD_VIDEO_PROP]) !== null && _contentVideo_AD_VIDEO_PROP !== void 0 ? _contentVideo_AD_VIDEO_PROP : void 0;
|
|
415
416
|
var adHls;
|
|
416
417
|
var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
|
|
@@ -425,9 +426,12 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
425
426
|
var pendingTimeouts = [];
|
|
426
427
|
var STALL_TIMEOUT_MS = 4e3;
|
|
427
428
|
var STALL_CHECK_INTERVAL_MS = 1e3;
|
|
429
|
+
var BLACKFRAME_MIN_PLAYBACK_S = 1.5;
|
|
428
430
|
var stallWatchdogId;
|
|
429
431
|
var lastAdProgressTime = 0;
|
|
430
432
|
var lastAdProgressPosition = 0;
|
|
433
|
+
var sawDecodedVideoFrame = false;
|
|
434
|
+
var videoFrameCallbackHandle;
|
|
431
435
|
var trackingFired = {
|
|
432
436
|
impression: false,
|
|
433
437
|
start: false,
|
|
@@ -608,6 +612,11 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
608
612
|
console.warn("[HlsAdPlayer] MediaFile ".concat(index, ' skipped (audio-only, type="').concat(type, '") — audio ads are not played to avoid a black screen'));
|
|
609
613
|
return;
|
|
610
614
|
}
|
|
615
|
+
var hasExplicitDimensions = mf.getAttribute("width") != null && mf.getAttribute("height") != null;
|
|
616
|
+
if (!isHlsMediaFile(mediaFile) && hasExplicitDimensions && (mediaFile.width <= 1 || mediaFile.height <= 1)) {
|
|
617
|
+
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'));
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
611
620
|
if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
|
|
612
621
|
mediaFiles.push(mediaFile);
|
|
613
622
|
if (verbose) {
|
|
@@ -1075,6 +1084,14 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1075
1084
|
fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
|
|
1076
1085
|
}
|
|
1077
1086
|
};
|
|
1087
|
+
var onLoadedMetadata = function onLoadedMetadata() {
|
|
1088
|
+
if (!adPlaying || !adVideoElement) return;
|
|
1089
|
+
var videoWidth = adVideoElement.videoWidth, videoHeight = adVideoElement.videoHeight;
|
|
1090
|
+
if (videoWidth <= 1 || videoHeight <= 1) {
|
|
1091
|
+
console.warn("[HlsAdPlayer] Ad creative has no usable video dimensions (".concat(videoWidth, "x").concat(videoHeight, ") - skipping this creative"));
|
|
1092
|
+
handleVideoDecodeFailure();
|
|
1093
|
+
}
|
|
1094
|
+
};
|
|
1078
1095
|
var onPlaying = function onPlaying() {
|
|
1079
1096
|
startStallWatchdog();
|
|
1080
1097
|
if (!currentAd || trackingFired.start) return;
|
|
@@ -1126,6 +1143,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1126
1143
|
type: "timeupdate",
|
|
1127
1144
|
handler: onTimeUpdate
|
|
1128
1145
|
},
|
|
1146
|
+
{
|
|
1147
|
+
type: "loadedmetadata",
|
|
1148
|
+
handler: onLoadedMetadata
|
|
1149
|
+
},
|
|
1129
1150
|
{
|
|
1130
1151
|
type: "playing",
|
|
1131
1152
|
handler: onPlaying
|
|
@@ -1297,6 +1318,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1297
1318
|
clearInterval(stallWatchdogId);
|
|
1298
1319
|
stallWatchdogId = void 0;
|
|
1299
1320
|
}
|
|
1321
|
+
cancelVideoFrameProbe();
|
|
1300
1322
|
}
|
|
1301
1323
|
function noteAdProgress() {
|
|
1302
1324
|
lastAdProgressTime = Date.now();
|
|
@@ -1315,13 +1337,86 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1315
1337
|
}
|
|
1316
1338
|
handleAdError();
|
|
1317
1339
|
}
|
|
1340
|
+
function getDecodedVideoFrameCount(video) {
|
|
1341
|
+
try {
|
|
1342
|
+
if (typeof video.getVideoPlaybackQuality === "function") {
|
|
1343
|
+
var quality = video.getVideoPlaybackQuality();
|
|
1344
|
+
if (quality && typeof quality.totalVideoFrames === "number") {
|
|
1345
|
+
return quality.totalVideoFrames;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
var legacyCount = video.webkitDecodedFrameCount;
|
|
1349
|
+
if (typeof legacyCount === "number") {
|
|
1350
|
+
return legacyCount;
|
|
1351
|
+
}
|
|
1352
|
+
} catch (error) {
|
|
1353
|
+
console.warn("[HlsAdPlayer] Unable to read decoded video frame count:", error);
|
|
1354
|
+
}
|
|
1355
|
+
return void 0;
|
|
1356
|
+
}
|
|
1357
|
+
function isFrameCounterReliable() {
|
|
1358
|
+
return contentVideo[FRAME_COUNTER_RELIABLE_PROP] === true;
|
|
1359
|
+
}
|
|
1360
|
+
function markFrameCounterReliable() {
|
|
1361
|
+
contentVideo[FRAME_COUNTER_RELIABLE_PROP] = true;
|
|
1362
|
+
}
|
|
1363
|
+
function cancelVideoFrameProbe() {
|
|
1364
|
+
if (videoFrameCallbackHandle != null && adVideoElement && typeof adVideoElement.cancelVideoFrameCallback === "function") {
|
|
1365
|
+
try {
|
|
1366
|
+
adVideoElement.cancelVideoFrameCallback(videoFrameCallbackHandle);
|
|
1367
|
+
} catch (error) {
|
|
1368
|
+
console.warn("[HlsAdPlayer] Error cancelling video frame callback:", error);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
videoFrameCallbackHandle = void 0;
|
|
1372
|
+
}
|
|
1373
|
+
function startVideoFrameProbe() {
|
|
1374
|
+
cancelVideoFrameProbe();
|
|
1375
|
+
if (!adVideoElement) return;
|
|
1376
|
+
var rvfc = adVideoElement.requestVideoFrameCallback;
|
|
1377
|
+
if (typeof rvfc !== "function") return;
|
|
1378
|
+
var onPresentedFrame = function onPresentedFrame() {
|
|
1379
|
+
videoFrameCallbackHandle = void 0;
|
|
1380
|
+
if (!adPlaying) return;
|
|
1381
|
+
sawDecodedVideoFrame = true;
|
|
1382
|
+
};
|
|
1383
|
+
try {
|
|
1384
|
+
videoFrameCallbackHandle = rvfc.call(adVideoElement, onPresentedFrame);
|
|
1385
|
+
} catch (error) {
|
|
1386
|
+
console.warn("[HlsAdPlayer] Error requesting video frame callback:", error);
|
|
1387
|
+
videoFrameCallbackHandle = void 0;
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
function handleVideoDecodeFailure() {
|
|
1391
|
+
console.warn("[HlsAdPlayer] Ad audio is advancing but no video frames decoded (black screen) - skipping this creative");
|
|
1392
|
+
clearStallWatchdog();
|
|
1393
|
+
if (currentAd) {
|
|
1394
|
+
fireTrackingPixels(currentAd.trackingUrls.error);
|
|
1395
|
+
}
|
|
1396
|
+
if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
|
|
1397
|
+
return;
|
|
1398
|
+
}
|
|
1399
|
+
handleAdError();
|
|
1400
|
+
}
|
|
1318
1401
|
function startStallWatchdog() {
|
|
1319
1402
|
clearStallWatchdog();
|
|
1320
1403
|
noteAdProgress();
|
|
1404
|
+
sawDecodedVideoFrame = false;
|
|
1405
|
+
startVideoFrameProbe();
|
|
1321
1406
|
stallWatchdogId = window.setInterval(function() {
|
|
1322
1407
|
if (!adPlaying || !adVideoElement) {
|
|
1323
1408
|
return;
|
|
1324
1409
|
}
|
|
1410
|
+
if (!sawDecodedVideoFrame && !adVideoElement.paused) {
|
|
1411
|
+
var decodedFrames = getDecodedVideoFrameCount(adVideoElement);
|
|
1412
|
+
if (decodedFrames !== void 0 && decodedFrames > 0) {
|
|
1413
|
+
sawDecodedVideoFrame = true;
|
|
1414
|
+
markFrameCounterReliable();
|
|
1415
|
+
} else if (decodedFrames === 0 && adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S && isFrameCounterReliable()) {
|
|
1416
|
+
handleVideoDecodeFailure();
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1325
1420
|
if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
|
|
1326
1421
|
noteAdProgress();
|
|
1327
1422
|
return;
|
|
@@ -6162,17 +6257,17 @@ var AdTimingService = /*#__PURE__*/ function() {
|
|
|
6162
6257
|
{
|
|
6163
6258
|
key: "logAdState",
|
|
6164
6259
|
value: function logAdState(event) {
|
|
6165
|
-
var extra = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {}
|
|
6166
|
-
var _ref;
|
|
6260
|
+
var extra = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
6167
6261
|
if (!this.debug) {
|
|
6168
6262
|
return;
|
|
6169
6263
|
}
|
|
6264
|
+
var _this_callbacks_getAdState = this.callbacks.getAdState(), inAdBreak = _this_callbacks_getAdState.inAdBreak, showAds = _this_callbacks_getAdState.showAds, adPlaying = _this_callbacks_getAdState.adPlaying;
|
|
6170
6265
|
console.log("[StormcloudVideoPlayer][AdState]", _object_spread({
|
|
6171
6266
|
event: event,
|
|
6172
6267
|
timestamp: /* @__PURE__ */ new Date().toISOString(),
|
|
6173
|
-
showAds: showAds
|
|
6174
|
-
adPlaying:
|
|
6175
|
-
inAdBreak: inAdBreak
|
|
6268
|
+
showAds: showAds,
|
|
6269
|
+
adPlaying: adPlaying,
|
|
6270
|
+
inAdBreak: inAdBreak,
|
|
6176
6271
|
activeAdRequestToken: this.activeAdRequestToken
|
|
6177
6272
|
}, extra));
|
|
6178
6273
|
}
|
|
@@ -8522,6 +8617,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
8522
8617
|
},
|
|
8523
8618
|
onFailsafeTimeout: function onFailsafeTimeout() {
|
|
8524
8619
|
return _this.adBreak.handleAdFailure();
|
|
8620
|
+
},
|
|
8621
|
+
getAdState: function getAdState() {
|
|
8622
|
+
return {
|
|
8623
|
+
inAdBreak: _this.adBreak.inAdBreak,
|
|
8624
|
+
showAds: _this.adBreak.showAds,
|
|
8625
|
+
adPlaying: _this.adPlayer.isAdPlaying()
|
|
8626
|
+
};
|
|
8525
8627
|
}
|
|
8526
8628
|
});
|
|
8527
8629
|
this.placeholder = new PlaceholderLayer(this.video, !!this.config.debugAdTiming);
|