stormcloud-video-player 0.8.48 → 0.8.49

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.
@@ -1,4 +1,4 @@
1
- import { a as StormcloudVideoPlayerConfig } from '../types-cTqIKw_D.cjs';
1
+ import { S as StormcloudVideoPlayerConfig } from '../types-iDjS8f_7.cjs';
2
2
 
3
3
  declare class StormcloudVideoPlayer {
4
4
  private readonly video;
@@ -1,4 +1,4 @@
1
- import { S as Scte35Marker } from '../types-cTqIKw_D.cjs';
1
+ import { a as Scte35Marker } from '../types-iDjS8f_7.cjs';
2
2
 
3
3
  type Scte35CueSource = "manifest" | "id3" | "ts";
4
4
  type Scte35CueReadiness = "early" | "playback";
@@ -425,9 +425,11 @@ function createHlsAdPlayer(contentVideo, options) {
425
425
  var pendingTimeouts = [];
426
426
  var STALL_TIMEOUT_MS = 4e3;
427
427
  var STALL_CHECK_INTERVAL_MS = 1e3;
428
+ var BLACKFRAME_MIN_PLAYBACK_S = 1.5;
428
429
  var stallWatchdogId;
429
430
  var lastAdProgressTime = 0;
430
431
  var lastAdProgressPosition = 0;
432
+ var sawDecodedVideoFrame = false;
431
433
  var trackingFired = {
432
434
  impression: false,
433
435
  start: false,
@@ -608,6 +610,11 @@ function createHlsAdPlayer(contentVideo, options) {
608
610
  console.warn("[HlsAdPlayer] MediaFile ".concat(index, ' skipped (audio-only, type="').concat(type, '") — audio ads are not played to avoid a black screen'));
609
611
  return;
610
612
  }
613
+ var hasExplicitDimensions = mf.getAttribute("width") != null && mf.getAttribute("height") != null;
614
+ if (!isHlsMediaFile(mediaFile) && hasExplicitDimensions && (mediaFile.width <= 1 || mediaFile.height <= 1)) {
615
+ 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'));
616
+ return;
617
+ }
611
618
  if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
612
619
  mediaFiles.push(mediaFile);
613
620
  if (verbose) {
@@ -1075,6 +1082,14 @@ function createHlsAdPlayer(contentVideo, options) {
1075
1082
  fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
1076
1083
  }
1077
1084
  };
1085
+ var onLoadedMetadata = function onLoadedMetadata() {
1086
+ if (!adPlaying || !adVideoElement) return;
1087
+ var videoWidth = adVideoElement.videoWidth, videoHeight = adVideoElement.videoHeight;
1088
+ if (videoWidth <= 1 || videoHeight <= 1) {
1089
+ console.warn("[HlsAdPlayer] Ad creative has no usable video dimensions (".concat(videoWidth, "x").concat(videoHeight, ") - skipping this creative"));
1090
+ handleVideoDecodeFailure();
1091
+ }
1092
+ };
1078
1093
  var onPlaying = function onPlaying() {
1079
1094
  startStallWatchdog();
1080
1095
  if (!currentAd || trackingFired.start) return;
@@ -1126,6 +1141,10 @@ function createHlsAdPlayer(contentVideo, options) {
1126
1141
  type: "timeupdate",
1127
1142
  handler: onTimeUpdate
1128
1143
  },
1144
+ {
1145
+ type: "loadedmetadata",
1146
+ handler: onLoadedMetadata
1147
+ },
1129
1148
  {
1130
1149
  type: "playing",
1131
1150
  handler: onPlaying
@@ -1315,13 +1334,51 @@ function createHlsAdPlayer(contentVideo, options) {
1315
1334
  }
1316
1335
  handleAdError();
1317
1336
  }
1337
+ function getDecodedVideoFrameCount(video) {
1338
+ try {
1339
+ if (typeof video.getVideoPlaybackQuality === "function") {
1340
+ var quality = video.getVideoPlaybackQuality();
1341
+ if (quality && typeof quality.totalVideoFrames === "number") {
1342
+ return quality.totalVideoFrames;
1343
+ }
1344
+ }
1345
+ var legacyCount = video.webkitDecodedFrameCount;
1346
+ if (typeof legacyCount === "number") {
1347
+ return legacyCount;
1348
+ }
1349
+ } catch (error) {
1350
+ console.warn("[HlsAdPlayer] Unable to read decoded video frame count:", error);
1351
+ }
1352
+ return void 0;
1353
+ }
1354
+ function handleVideoDecodeFailure() {
1355
+ console.warn("[HlsAdPlayer] Ad audio is advancing but no video frames decoded (black screen) - skipping this creative");
1356
+ clearStallWatchdog();
1357
+ if (currentAd) {
1358
+ fireTrackingPixels(currentAd.trackingUrls.error);
1359
+ }
1360
+ if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1361
+ return;
1362
+ }
1363
+ handleAdError();
1364
+ }
1318
1365
  function startStallWatchdog() {
1319
1366
  clearStallWatchdog();
1320
1367
  noteAdProgress();
1368
+ sawDecodedVideoFrame = false;
1321
1369
  stallWatchdogId = window.setInterval(function() {
1322
1370
  if (!adPlaying || !adVideoElement) {
1323
1371
  return;
1324
1372
  }
1373
+ if (!sawDecodedVideoFrame && !adVideoElement.paused) {
1374
+ var decodedFrames = getDecodedVideoFrameCount(adVideoElement);
1375
+ if (decodedFrames !== void 0 && decodedFrames > 0) {
1376
+ sawDecodedVideoFrame = true;
1377
+ } else if (decodedFrames === 0 && adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S) {
1378
+ handleVideoDecodeFailure();
1379
+ return;
1380
+ }
1381
+ }
1325
1382
  if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
1326
1383
  noteAdProgress();
1327
1384
  return;