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.
@@ -223,9 +223,11 @@ function createHlsAdPlayer(contentVideo, options) {
223
223
  var pendingTimeouts = [];
224
224
  var STALL_TIMEOUT_MS = 4e3;
225
225
  var STALL_CHECK_INTERVAL_MS = 1e3;
226
+ var BLACKFRAME_MIN_PLAYBACK_S = 1.5;
226
227
  var stallWatchdogId;
227
228
  var lastAdProgressTime = 0;
228
229
  var lastAdProgressPosition = 0;
230
+ var sawDecodedVideoFrame = false;
229
231
  var trackingFired = {
230
232
  impression: false,
231
233
  start: false,
@@ -406,6 +408,11 @@ function createHlsAdPlayer(contentVideo, options) {
406
408
  console.warn("[HlsAdPlayer] MediaFile ".concat(index, ' skipped (audio-only, type="').concat(type, '") — audio ads are not played to avoid a black screen'));
407
409
  return;
408
410
  }
411
+ var hasExplicitDimensions = mf.getAttribute("width") != null && mf.getAttribute("height") != null;
412
+ if (!isHlsMediaFile(mediaFile) && hasExplicitDimensions && (mediaFile.width <= 1 || mediaFile.height <= 1)) {
413
+ 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'));
414
+ return;
415
+ }
409
416
  if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
410
417
  mediaFiles.push(mediaFile);
411
418
  if (verbose) {
@@ -873,6 +880,14 @@ function createHlsAdPlayer(contentVideo, options) {
873
880
  fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
874
881
  }
875
882
  };
883
+ var onLoadedMetadata = function onLoadedMetadata() {
884
+ if (!adPlaying || !adVideoElement) return;
885
+ var videoWidth = adVideoElement.videoWidth, videoHeight = adVideoElement.videoHeight;
886
+ if (videoWidth <= 1 || videoHeight <= 1) {
887
+ console.warn("[HlsAdPlayer] Ad creative has no usable video dimensions (".concat(videoWidth, "x").concat(videoHeight, ") - skipping this creative"));
888
+ handleVideoDecodeFailure();
889
+ }
890
+ };
876
891
  var onPlaying = function onPlaying() {
877
892
  startStallWatchdog();
878
893
  if (!currentAd || trackingFired.start) return;
@@ -924,6 +939,10 @@ function createHlsAdPlayer(contentVideo, options) {
924
939
  type: "timeupdate",
925
940
  handler: onTimeUpdate
926
941
  },
942
+ {
943
+ type: "loadedmetadata",
944
+ handler: onLoadedMetadata
945
+ },
927
946
  {
928
947
  type: "playing",
929
948
  handler: onPlaying
@@ -1113,13 +1132,51 @@ function createHlsAdPlayer(contentVideo, options) {
1113
1132
  }
1114
1133
  handleAdError();
1115
1134
  }
1135
+ function getDecodedVideoFrameCount(video) {
1136
+ try {
1137
+ if (typeof video.getVideoPlaybackQuality === "function") {
1138
+ var quality = video.getVideoPlaybackQuality();
1139
+ if (quality && typeof quality.totalVideoFrames === "number") {
1140
+ return quality.totalVideoFrames;
1141
+ }
1142
+ }
1143
+ var legacyCount = video.webkitDecodedFrameCount;
1144
+ if (typeof legacyCount === "number") {
1145
+ return legacyCount;
1146
+ }
1147
+ } catch (error) {
1148
+ console.warn("[HlsAdPlayer] Unable to read decoded video frame count:", error);
1149
+ }
1150
+ return void 0;
1151
+ }
1152
+ function handleVideoDecodeFailure() {
1153
+ console.warn("[HlsAdPlayer] Ad audio is advancing but no video frames decoded (black screen) - skipping this creative");
1154
+ clearStallWatchdog();
1155
+ if (currentAd) {
1156
+ fireTrackingPixels(currentAd.trackingUrls.error);
1157
+ }
1158
+ if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1159
+ return;
1160
+ }
1161
+ handleAdError();
1162
+ }
1116
1163
  function startStallWatchdog() {
1117
1164
  clearStallWatchdog();
1118
1165
  noteAdProgress();
1166
+ sawDecodedVideoFrame = false;
1119
1167
  stallWatchdogId = window.setInterval(function() {
1120
1168
  if (!adPlaying || !adVideoElement) {
1121
1169
  return;
1122
1170
  }
1171
+ if (!sawDecodedVideoFrame && !adVideoElement.paused) {
1172
+ var decodedFrames = getDecodedVideoFrameCount(adVideoElement);
1173
+ if (decodedFrames !== void 0 && decodedFrames > 0) {
1174
+ sawDecodedVideoFrame = true;
1175
+ } else if (decodedFrames === 0 && adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S) {
1176
+ handleVideoDecodeFailure();
1177
+ return;
1178
+ }
1179
+ }
1123
1180
  if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
1124
1181
  noteAdProgress();
1125
1182
  return;