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 { S as Scte35Marker, a as StormcloudVideoPlayerConfig, A as AdController } from '../types-cTqIKw_D.cjs';
1
+ import { a as Scte35Marker, S as StormcloudVideoPlayerConfig, A as AdController } from '../types-iDjS8f_7.cjs';
2
2
  import { AdTimingService } from './AdTimingService.cjs';
3
3
  import { AdConfigManager } from './AdConfigManager.cjs';
4
4
  import { Scte35CueManager } from './Scte35CueManager.cjs';
@@ -1,4 +1,4 @@
1
- import { b as AdBreak, a as StormcloudVideoPlayerConfig, A as AdController } from '../types-cTqIKw_D.cjs';
1
+ import { b as AdBreak, S as StormcloudVideoPlayerConfig, A as AdController } from '../types-iDjS8f_7.cjs';
2
2
  import { PalNonceManager } from '../sdk/pal.cjs';
3
3
  import { VastConsentSignals } from '../utils/vastMacros.cjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { a as StormcloudVideoPlayerConfig, S as Scte35Marker, A as AdController } from '../types-cTqIKw_D.cjs';
1
+ import { S as StormcloudVideoPlayerConfig, a as Scte35Marker, A as AdController } from '../types-iDjS8f_7.cjs';
2
2
 
3
3
  interface AdTimingCallbacks {
4
4
  onAdStopTimerFired(): void;
@@ -1,5 +1,5 @@
1
1
  import Hls from 'hls.js';
2
- import { a as StormcloudVideoPlayerConfig, S as Scte35Marker } from '../types-cTqIKw_D.cjs';
2
+ import { S as StormcloudVideoPlayerConfig, a as Scte35Marker } from '../types-iDjS8f_7.cjs';
3
3
  import { Scte35CueContext } from './playerTypes.cjs';
4
4
  import { Scte35CueManager } from './Scte35CueManager.cjs';
5
5
  import { AdTimingService } from './AdTimingService.cjs';
@@ -1,4 +1,4 @@
1
- import { A as AdController } from '../types-cTqIKw_D.cjs';
1
+ import { A as AdController } from '../types-iDjS8f_7.cjs';
2
2
 
3
3
  declare function getAdAudioVolume(adPlayer: AdController): number;
4
4
  declare function toggleMute(video: HTMLVideoElement, adPlayer: AdController, debug: boolean): void;
@@ -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
  import { Scte35CueSource, Scte35CueReadiness, Scte35CueContext } from './playerTypes.cjs';
3
3
 
4
4
  interface Scte35CueManagerCallbacks {
@@ -1,4 +1,4 @@
1
- import { S as Scte35Marker, I as Id3TagInfo } from '../types-cTqIKw_D.cjs';
1
+ import { a as Scte35Marker, I as Id3TagInfo } from '../types-iDjS8f_7.cjs';
2
2
 
3
3
  declare function parseCueOutDuration(value: string): number | undefined;
4
4
  declare function parseCueOutCont(value: string): {
@@ -374,9 +374,11 @@ function createHlsAdPlayer(contentVideo, options) {
374
374
  var pendingTimeouts = [];
375
375
  var STALL_TIMEOUT_MS = 4e3;
376
376
  var STALL_CHECK_INTERVAL_MS = 1e3;
377
+ var BLACKFRAME_MIN_PLAYBACK_S = 1.5;
377
378
  var stallWatchdogId;
378
379
  var lastAdProgressTime = 0;
379
380
  var lastAdProgressPosition = 0;
381
+ var sawDecodedVideoFrame = false;
380
382
  var trackingFired = {
381
383
  impression: false,
382
384
  start: false,
@@ -557,6 +559,11 @@ function createHlsAdPlayer(contentVideo, options) {
557
559
  console.warn("[HlsAdPlayer] MediaFile ".concat(index, ' skipped (audio-only, type="').concat(type, '") — audio ads are not played to avoid a black screen'));
558
560
  return;
559
561
  }
562
+ var hasExplicitDimensions = mf.getAttribute("width") != null && mf.getAttribute("height") != null;
563
+ if (!isHlsMediaFile(mediaFile) && hasExplicitDimensions && (mediaFile.width <= 1 || mediaFile.height <= 1)) {
564
+ 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'));
565
+ return;
566
+ }
560
567
  if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
561
568
  mediaFiles.push(mediaFile);
562
569
  if (verbose) {
@@ -1024,6 +1031,14 @@ function createHlsAdPlayer(contentVideo, options) {
1024
1031
  fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
1025
1032
  }
1026
1033
  };
1034
+ var onLoadedMetadata = function onLoadedMetadata() {
1035
+ if (!adPlaying || !adVideoElement) return;
1036
+ var videoWidth = adVideoElement.videoWidth, videoHeight = adVideoElement.videoHeight;
1037
+ if (videoWidth <= 1 || videoHeight <= 1) {
1038
+ console.warn("[HlsAdPlayer] Ad creative has no usable video dimensions (".concat(videoWidth, "x").concat(videoHeight, ") - skipping this creative"));
1039
+ handleVideoDecodeFailure();
1040
+ }
1041
+ };
1027
1042
  var onPlaying = function onPlaying() {
1028
1043
  startStallWatchdog();
1029
1044
  if (!currentAd || trackingFired.start) return;
@@ -1075,6 +1090,10 @@ function createHlsAdPlayer(contentVideo, options) {
1075
1090
  type: "timeupdate",
1076
1091
  handler: onTimeUpdate
1077
1092
  },
1093
+ {
1094
+ type: "loadedmetadata",
1095
+ handler: onLoadedMetadata
1096
+ },
1078
1097
  {
1079
1098
  type: "playing",
1080
1099
  handler: onPlaying
@@ -1264,13 +1283,51 @@ function createHlsAdPlayer(contentVideo, options) {
1264
1283
  }
1265
1284
  handleAdError();
1266
1285
  }
1286
+ function getDecodedVideoFrameCount(video) {
1287
+ try {
1288
+ if (typeof video.getVideoPlaybackQuality === "function") {
1289
+ var quality = video.getVideoPlaybackQuality();
1290
+ if (quality && typeof quality.totalVideoFrames === "number") {
1291
+ return quality.totalVideoFrames;
1292
+ }
1293
+ }
1294
+ var legacyCount = video.webkitDecodedFrameCount;
1295
+ if (typeof legacyCount === "number") {
1296
+ return legacyCount;
1297
+ }
1298
+ } catch (error) {
1299
+ console.warn("[HlsAdPlayer] Unable to read decoded video frame count:", error);
1300
+ }
1301
+ return void 0;
1302
+ }
1303
+ function handleVideoDecodeFailure() {
1304
+ console.warn("[HlsAdPlayer] Ad audio is advancing but no video frames decoded (black screen) - skipping this creative");
1305
+ clearStallWatchdog();
1306
+ if (currentAd) {
1307
+ fireTrackingPixels(currentAd.trackingUrls.error);
1308
+ }
1309
+ if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1310
+ return;
1311
+ }
1312
+ handleAdError();
1313
+ }
1267
1314
  function startStallWatchdog() {
1268
1315
  clearStallWatchdog();
1269
1316
  noteAdProgress();
1317
+ sawDecodedVideoFrame = false;
1270
1318
  stallWatchdogId = window.setInterval(function() {
1271
1319
  if (!adPlaying || !adVideoElement) {
1272
1320
  return;
1273
1321
  }
1322
+ if (!sawDecodedVideoFrame && !adVideoElement.paused) {
1323
+ var decodedFrames = getDecodedVideoFrameCount(adVideoElement);
1324
+ if (decodedFrames !== void 0 && decodedFrames > 0) {
1325
+ sawDecodedVideoFrame = true;
1326
+ } else if (decodedFrames === 0 && adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S) {
1327
+ handleVideoDecodeFailure();
1328
+ return;
1329
+ }
1330
+ }
1274
1331
  if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
1275
1332
  noteAdProgress();
1276
1333
  return;