stormcloud-video-player 0.3.52 → 0.3.54

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.
@@ -177,9 +177,17 @@ function _ts_generator(thisArg, body) {
177
177
  },
178
178
  trys: [],
179
179
  ops: []
180
- }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
181
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
182
- return this;
180
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
181
+ return d(g, "next", {
182
+ value: verb(0)
183
+ }), d(g, "throw", {
184
+ value: verb(1)
185
+ }), d(g, "return", {
186
+ value: verb(2)
187
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
188
+ value: function() {
189
+ return this;
190
+ }
183
191
  }), g;
184
192
  function verb(n) {
185
193
  return function(v) {
@@ -279,20 +287,20 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
279
287
  var __getOwnPropNames = Object.getOwnPropertyNames;
280
288
  var __getProtoOf = Object.getPrototypeOf;
281
289
  var __hasOwnProp = Object.prototype.hasOwnProperty;
282
- var __export = function(target, all) {
290
+ var __export = function __export(target, all) {
283
291
  for(var name in all)__defProp(target, name, {
284
292
  get: all[name],
285
293
  enumerable: true
286
294
  });
287
295
  };
288
- var __copyProps = function(to, from, except, desc) {
296
+ var __copyProps = function __copyProps(to, from, except, desc) {
289
297
  if (from && (typeof from === "undefined" ? "undefined" : _type_of(from)) === "object" || typeof from === "function") {
290
298
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
291
299
  try {
292
300
  var _loop = function() {
293
301
  var key = _step.value;
294
302
  if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
295
- get: function() {
303
+ get: function get() {
296
304
  return from[key];
297
305
  },
298
306
  enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
@@ -316,7 +324,7 @@ var __copyProps = function(to, from, except, desc) {
316
324
  }
317
325
  return to;
318
326
  };
319
- var __toESM = function(mod, isNodeMode, target) {
327
+ var __toESM = function __toESM(mod, isNodeMode, target) {
320
328
  return target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(// If the importer is in node compatibility mode or this is not an ESM
321
329
  // file that has been converted to a CommonJS file using a Babel-
322
330
  // compatible transform (i.e. "__esModule" has not been set), then set
@@ -326,7 +334,7 @@ var __toESM = function(mod, isNodeMode, target) {
326
334
  enumerable: true
327
335
  }) : target, mod);
328
336
  };
329
- var __toCommonJS = function(mod) {
337
+ var __toCommonJS = function __toCommonJS(mod) {
330
338
  return __copyProps(__defProp({}, "__esModule", {
331
339
  value: true
332
340
  }), mod);
@@ -334,7 +342,7 @@ var __toCommonJS = function(mod) {
334
342
  // src/player/StormcloudVideoPlayer.ts
335
343
  var StormcloudVideoPlayer_exports = {};
336
344
  __export(StormcloudVideoPlayer_exports, {
337
- StormcloudVideoPlayer: function() {
345
+ StormcloudVideoPlayer: function StormcloudVideoPlayer1() {
338
346
  return StormcloudVideoPlayer;
339
347
  }
340
348
  });
@@ -667,7 +675,7 @@ function createImaController(video, options) {
667
675
  var fn = _step.value;
668
676
  try {
669
677
  fn(payload);
670
- } catch (e) {}
678
+ } catch (unused) {}
671
679
  }
672
680
  } catch (err) {
673
681
  _didIteratorError = true;
@@ -705,7 +713,7 @@ function createImaController(video, options) {
705
713
  console.error("StormcloudVideoPlayer: The host page is inside a sandboxed iframe without 'allow-scripts'. Google IMA cannot run ads within sandboxed frames. Remove the sandbox attribute or include 'allow-scripts allow-same-origin'.");
706
714
  }
707
715
  }
708
- } catch (e) {}
716
+ } catch (unused) {}
709
717
  if (typeof window !== "undefined" && ((_window_google = window.google) === null || _window_google === void 0 ? void 0 : _window_google.ima)) return Promise.resolve();
710
718
  var existing = document.querySelector('script[data-ima="true"]');
711
719
  if (existing) {
@@ -747,9 +755,6 @@ function createImaController(video, options) {
747
755
  var adDisplayContainer;
748
756
  var adContainerEl;
749
757
  var lastAdTagUrl;
750
- var retryAttempts = 0;
751
- var maxRetries = 2;
752
- var backoffBaseMs = 500;
753
758
  var adsLoadedPromise;
754
759
  var adsLoadedResolve;
755
760
  var adsLoadedReject;
@@ -953,7 +958,7 @@ function createImaController(video, options) {
953
958
  if (adsManager) {
954
959
  try {
955
960
  adsManager.destroy();
956
- } catch (e) {}
961
+ } catch (unused) {}
957
962
  adsManager = void 0;
958
963
  }
959
964
  if (adVideoElement) {
@@ -964,7 +969,7 @@ function createImaController(video, options) {
964
969
  if (adsLoader) {
965
970
  try {
966
971
  adsLoader.destroy();
967
- } catch (e) {}
972
+ } catch (unused) {}
968
973
  adsLoader = void 0;
969
974
  }
970
975
  }
@@ -982,7 +987,7 @@ function createImaController(video, options) {
982
987
  try {
983
988
  var _adDisplayContainer_initialize;
984
989
  (_adDisplayContainer_initialize = adDisplayContainer.initialize) === null || _adDisplayContainer_initialize === void 0 ? void 0 : _adDisplayContainer_initialize.call(adDisplayContainer);
985
- } catch (e) {}
990
+ } catch (unused) {}
986
991
  }
987
992
  }).catch(function() {});
988
993
  },
@@ -1046,7 +1051,6 @@ function createImaController(video, options) {
1046
1051
  _state.sent();
1047
1052
  google = window.google;
1048
1053
  lastAdTagUrl = vastTagUrl;
1049
- retryAttempts = 0;
1050
1054
  if (!adDisplayContainer) {
1051
1055
  container = document.createElement("div");
1052
1056
  container.style.position = "absolute";
@@ -1130,32 +1134,23 @@ function createImaController(video, options) {
1130
1134
  }
1131
1135
  }, 300);
1132
1136
  }
1133
- hideContentVideo();
1137
+ showContentVideo();
1134
1138
  if (adsLoadedReject) {
1135
1139
  adsLoadedReject(new Error("Ad playback error"));
1136
1140
  adsLoadedReject = void 0;
1137
1141
  adsLoadedResolve = void 0;
1138
1142
  }
1139
- if (lastAdTagUrl && retryAttempts < maxRetries && !isNoFill) {
1140
- var delay = backoffBaseMs * Math.pow(2, retryAttempts++);
1141
- window.setTimeout(function() {
1142
- try {
1143
- makeAdsRequest(google, lastAdTagUrl);
1144
- } catch (e) {}
1145
- }, delay);
1146
- } else {
1147
- emit("ad_error", {
1148
- code: errorCode,
1149
- vastErrorCode: vastErrorCode,
1150
- message: errorMessage,
1151
- cause: innerError,
1152
- isNoFill: isNoFill
1153
- });
1154
- if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
1155
- if (video.paused) {
1156
- var _video_play;
1157
- (_video_play = video.play()) === null || _video_play === void 0 ? void 0 : _video_play.catch(function() {});
1158
- }
1143
+ emit("ad_error", {
1144
+ code: errorCode,
1145
+ vastErrorCode: vastErrorCode,
1146
+ message: errorMessage,
1147
+ cause: innerError,
1148
+ isNoFill: isNoFill
1149
+ });
1150
+ if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
1151
+ if (video.paused) {
1152
+ var _video_play;
1153
+ (_video_play = video.play()) === null || _video_play === void 0 ? void 0 : _video_play.catch(function() {});
1159
1154
  }
1160
1155
  }
1161
1156
  });
@@ -1173,7 +1168,7 @@ function createImaController(video, options) {
1173
1168
  if (adsManager) {
1174
1169
  try {
1175
1170
  adsManager.setVolume(adVolume);
1176
- } catch (e) {}
1171
+ } catch (unused) {}
1177
1172
  }
1178
1173
  emit("content_pause");
1179
1174
  });
@@ -1187,7 +1182,7 @@ function createImaController(video, options) {
1187
1182
  if (adsManager) {
1188
1183
  try {
1189
1184
  adsManager.setVolume(originalMutedState ? 0 : adVolume);
1190
- } catch (e) {}
1185
+ } catch (unused) {}
1191
1186
  }
1192
1187
  }
1193
1188
  if (adContainerEl) {
@@ -1201,7 +1196,7 @@ function createImaController(video, options) {
1201
1196
  adsManager.addEventListener(AdEvent.CONTENT_RESUME_REQUESTED, function() {
1202
1197
  adPlaying = false;
1203
1198
  setAdPlayingFlag(false);
1204
- hideContentVideo();
1199
+ showContentVideo();
1205
1200
  emit("content_resume");
1206
1201
  });
1207
1202
  adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, function() {
@@ -1217,7 +1212,7 @@ function createImaController(video, options) {
1217
1212
  }
1218
1213
  }, 300);
1219
1214
  }
1220
- hideContentVideo();
1215
+ showContentVideo();
1221
1216
  emit("all_ads_completed");
1222
1217
  });
1223
1218
  if (adsLoadedResolve) {
@@ -1239,7 +1234,7 @@ function createImaController(video, options) {
1239
1234
  }
1240
1235
  }, 300);
1241
1236
  }
1242
- hideContentVideo();
1237
+ showContentVideo();
1243
1238
  if (adsLoadedReject) {
1244
1239
  adsLoadedReject(new Error("Failed to setup ads manager"));
1245
1240
  adsLoadedReject = void 0;
@@ -1282,7 +1277,7 @@ function createImaController(video, options) {
1282
1277
  }
1283
1278
  }, 300);
1284
1279
  }
1285
- hideContentVideo();
1280
+ showContentVideo();
1286
1281
  if (adsLoadedReject) {
1287
1282
  adsLoadedReject(new Error(isNoFill ? "No ads available" : "Ads loader error"));
1288
1283
  adsLoadedReject = void 0;
@@ -1348,7 +1343,7 @@ function createImaController(video, options) {
1348
1343
  }
1349
1344
  try {
1350
1345
  adsManager.setVolume(originalMutedState ? 0 : adVolume);
1351
- } catch (e) {}
1346
+ } catch (unused) {}
1352
1347
  adsManager.start();
1353
1348
  return [
1354
1349
  2,
@@ -1430,7 +1425,7 @@ function createImaController(video, options) {
1430
1425
  try {
1431
1426
  ;
1432
1427
  adsManager === null || adsManager === void 0 ? void 0 : (_adsManager_stop = adsManager.stop) === null || _adsManager_stop === void 0 ? void 0 : _adsManager_stop.call(adsManager);
1433
- } catch (e) {}
1428
+ } catch (unused) {}
1434
1429
  destroyAdsManager();
1435
1430
  return [
1436
1431
  2
@@ -1461,7 +1456,7 @@ function createImaController(video, options) {
1461
1456
  try {
1462
1457
  var _adsLoader_destroy;
1463
1458
  adsLoader === null || adsLoader === void 0 ? void 0 : (_adsLoader_destroy = adsLoader.destroy) === null || _adsLoader_destroy === void 0 ? void 0 : _adsLoader_destroy.call(adsLoader);
1464
- } catch (e) {}
1459
+ } catch (unused) {}
1465
1460
  adDisplayContainer = void 0;
1466
1461
  adsLoader = void 0;
1467
1462
  contentVideoHidden = false;
@@ -1510,7 +1505,7 @@ function createImaController(video, options) {
1510
1505
  if (adsManager && adPlaying) {
1511
1506
  try {
1512
1507
  adsManager.setVolume(clampedVolume);
1513
- } catch (e) {}
1508
+ } catch (unused) {}
1514
1509
  }
1515
1510
  },
1516
1511
  getAdVolume: function getAdVolume() {
@@ -3003,22 +2998,29 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3003
2998
  this.maxPlaceholderDurationMs = 5e3;
3004
2999
  this.isShowingPlaceholder = false;
3005
3000
  this.totalAdRequestsInBreak = 0;
3006
- this.maxTotalAdRequestsPerBreak = 20;
3001
+ this.maxTotalAdRequestsPerBreak = 10;
3007
3002
  this.pendingAdBreak = null;
3008
3003
  this.consecutiveFailures = 0;
3009
3004
  this.maxConsecutiveFailures = 5;
3010
3005
  this.lastAdRequestTime = 0;
3011
- this.minAdRequestIntervalMs = 2500;
3006
+ this.minAdRequestIntervalMs = 3e3;
3012
3007
  this.backoffBaseMs = 1e3;
3013
3008
  this.maxBackoffMs = 15e3;
3009
+ this.globalConsecutiveNoFills = 0;
3010
+ this.globalNoFillThreshold = 3;
3011
+ this.globalNoFillCooldownUntil = 0;
3012
+ this.globalNoFillBackoffBaseMs = 5e3;
3013
+ this.globalNoFillBackoffMaxMs = 6e4;
3014
+ this.globalLastGamRequestTime = 0;
3015
+ this.globalMinGamIntervalMs = 3e3;
3014
3016
  this.preloadPool = [];
3015
- this.maxPreloadPoolSize = 3;
3017
+ this.maxPreloadPoolSize = 2;
3016
3018
  this.preloadPoolActive = false;
3017
3019
  this.preloadPoolLoopRunning = false;
3018
3020
  this.continuousFetchLoopRunning = false;
3019
3021
  initializePolyfills();
3020
3022
  var browserOverrides = getBrowserConfigOverrides();
3021
- this.config = _object_spread({}, config, browserOverrides);
3023
+ this.config = _object_spread({}, browserOverrides, config);
3022
3024
  this.video = config.videoElement;
3023
3025
  logBrowserInfo(config.debugAdTiming);
3024
3026
  this.ima = this.createAdPlayer(false);
@@ -3155,7 +3157,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3155
3157
  });
3156
3158
  this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, function(_, data) {
3157
3159
  return _async_to_generator(function() {
3158
- var _this_hls_levels, _this_hls, _this_hls_levels_some, adBehavior, _this_config_minSegmentsBeforePlay, minSegments, _this_video_play;
3160
+ var _this_config_minSegmentsBeforePlay, _ref, _this_hls_levels, _this_hls, adBehavior, minSegments, _this_video_play;
3159
3161
  return _ts_generator(this, function(_state) {
3160
3162
  switch(_state.label){
3161
3163
  case 0:
@@ -3164,10 +3166,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3164
3166
  } else {
3165
3167
  ;
3166
3168
  ;
3167
- this.isLiveStream = (_this_hls_levels_some = (_this_hls = this.hls) === null || _this_hls === void 0 ? void 0 : (_this_hls_levels = _this_hls.levels) === null || _this_hls_levels === void 0 ? void 0 : _this_hls_levels.some(function(level) {
3169
+ this.isLiveStream = (_ref = (_this_hls = this.hls) === null || _this_hls === void 0 ? void 0 : (_this_hls_levels = _this_hls.levels) === null || _this_hls_levels === void 0 ? void 0 : _this_hls_levels.some(function(level) {
3168
3170
  var _level_details, _level_details1;
3169
3171
  return (level === null || level === void 0 ? void 0 : (_level_details = level.details) === null || _level_details === void 0 ? void 0 : _level_details.live) === true || (level === null || level === void 0 ? void 0 : (_level_details1 = level.details) === null || _level_details1 === void 0 ? void 0 : _level_details1.type) === "LIVE";
3170
- })) !== null && _this_hls_levels_some !== void 0 ? _this_hls_levels_some : false;
3172
+ })) !== null && _ref !== void 0 ? _ref : false;
3171
3173
  }
3172
3174
  if (this.config.debugAdTiming) {
3173
3175
  adBehavior = this.shouldContinueLiveStreamDuringAds() ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
@@ -3231,9 +3233,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3231
3233
  var tag = "";
3232
3234
  var value = "";
3233
3235
  if (Array.isArray(entry)) {
3234
- var _entry_;
3236
+ var _entry_, _entry_1;
3235
3237
  tag = String((_entry_ = entry[0]) !== null && _entry_ !== void 0 ? _entry_ : "");
3236
- var _entry_1;
3237
3238
  value = String((_entry_1 = entry[1]) !== null && _entry_1 !== void 0 ? _entry_1 : "");
3238
3239
  } else if (typeof entry === "string") {
3239
3240
  var idx = entry.indexOf(":");
@@ -3356,9 +3357,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3356
3357
  var tag = "";
3357
3358
  var value = "";
3358
3359
  if (Array.isArray(entry)) {
3359
- var _entry_;
3360
+ var _entry_, _entry_1;
3360
3361
  tag = String((_entry_ = entry[0]) !== null && _entry_ !== void 0 ? _entry_ : "");
3361
- var _entry_1;
3362
3362
  value = String((_entry_1 = entry[1]) !== null && _entry_1 !== void 0 ? _entry_1 : "");
3363
3363
  } else if (typeof entry === "string") {
3364
3364
  var idx = entry.indexOf(":");
@@ -3408,10 +3408,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3408
3408
  }
3409
3409
  });
3410
3410
  } else if (tag.includes("EXT-X-DATERANGE")) {
3411
+ var _attrs_CLASS;
3411
3412
  var attrs = _this.parseAttributeList(value);
3412
3413
  var hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
3413
3414
  var hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
3414
- var _attrs_CLASS;
3415
3415
  var klass = String((_attrs_CLASS = attrs["CLASS"]) !== null && _attrs_CLASS !== void 0 ? _attrs_CLASS : "");
3416
3416
  var duration = _this.toNumber(attrs["DURATION"]);
3417
3417
  if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
@@ -3525,6 +3525,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3525
3525
  _this.clearAdRequestWatchdog();
3526
3526
  _this.activeAdRequestToken = null;
3527
3527
  _this.showAds = true;
3528
+ _this.resetGamNoFillCounter();
3528
3529
  if (_this.inAdBreak && _this.expectedAdBreakDurationMs != null) {
3529
3530
  if (_this.adStopTimerId == null) {
3530
3531
  _this.currentAdBreakStartWallClockMs = Date.now();
@@ -3813,11 +3814,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3813
3814
  }
3814
3815
  var daterangeMatch = text.match(/EXT-X-DATERANGE:([^\r\n]*)/i);
3815
3816
  if (daterangeMatch) {
3816
- var _daterangeMatch_;
3817
+ var _daterangeMatch_, _attrs_CLASS;
3817
3818
  var attrs = this.parseAttributeList((_daterangeMatch_ = daterangeMatch[1]) !== null && _daterangeMatch_ !== void 0 ? _daterangeMatch_ : "");
3818
3819
  var hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
3819
3820
  var hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
3820
- var _attrs_CLASS;
3821
3821
  var klass = String((_attrs_CLASS = attrs["CLASS"]) !== null && _attrs_CLASS !== void 0 ? _attrs_CLASS : "");
3822
3822
  var duration = this.toNumber(attrs["DURATION"]);
3823
3823
  if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
@@ -3893,7 +3893,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3893
3893
  var out = "";
3894
3894
  for(var i = 0; i < value.length; i++)out += String.fromCharCode(value[i]);
3895
3895
  return out;
3896
- } catch (e) {
3896
+ } catch (unused) {
3897
3897
  return void 0;
3898
3898
  }
3899
3899
  }
@@ -3912,6 +3912,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3912
3912
  });
3913
3913
  }
3914
3914
  if (marker.type === "start") {
3915
+ var _this_config_immediateManifestAds;
3915
3916
  var _this_pendingAdBreak;
3916
3917
  if (!this.video.muted) {
3917
3918
  this.video.muted = true;
@@ -3936,7 +3937,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3936
3937
  this.expectedAdBreakDurationMs = durationMs;
3937
3938
  this.currentAdBreakStartWallClockMs = Date.now();
3938
3939
  var isManifestMarker = this.isManifestBasedMarker(marker);
3939
- var _this_config_immediateManifestAds;
3940
3940
  var forceImmediate = (_this_config_immediateManifestAds = this.config.immediateManifestAds) !== null && _this_config_immediateManifestAds !== void 0 ? _this_config_immediateManifestAds : true;
3941
3941
  if (this.config.debugAdTiming) {
3942
3942
  console.log("[StormcloudVideoPlayer] Ad start decision:", {
@@ -4091,9 +4091,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4091
4091
  var regex = /([A-Z0-9-]+)=(("[^"]*")|([^",]*))(?:,|$)/gi;
4092
4092
  var match;
4093
4093
  while((match = regex.exec(value)) !== null){
4094
- var _match_;
4094
+ var _match_, _ref, _match_1;
4095
4095
  var key = (_match_ = match[1]) !== null && _match_ !== void 0 ? _match_ : "";
4096
- var _match_1, _ref;
4097
4096
  var rawVal = (_ref = (_match_1 = match[3]) !== null && _match_1 !== void 0 ? _match_1 : match[4]) !== null && _ref !== void 0 ? _ref : "";
4098
4097
  if (rawVal.startsWith('"') && rawVal.endsWith('"')) {
4099
4098
  rawVal = rawVal.slice(1, -1);
@@ -4438,13 +4437,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4438
4437
  {
4439
4438
  key: "shouldShowNativeControls",
4440
4439
  value: function shouldShowNativeControls() {
4440
+ var _this_config_showCustomControls;
4441
4441
  var streamType = this.getStreamType();
4442
4442
  if (streamType === "other") {
4443
- var _this_config_showCustomControls;
4444
- return !((_this_config_showCustomControls = this.config.showCustomControls) !== null && _this_config_showCustomControls !== void 0 ? _this_config_showCustomControls : false);
4443
+ var _this_config_showCustomControls1;
4444
+ return !((_this_config_showCustomControls1 = this.config.showCustomControls) !== null && _this_config_showCustomControls1 !== void 0 ? _this_config_showCustomControls1 : false);
4445
4445
  }
4446
- var _this_config_showCustomControls1;
4447
- return !!(this.config.allowNativeHls && !((_this_config_showCustomControls1 = this.config.showCustomControls) !== null && _this_config_showCustomControls1 !== void 0 ? _this_config_showCustomControls1 : false));
4446
+ return !!(this.config.allowNativeHls && !((_this_config_showCustomControls = this.config.showCustomControls) !== null && _this_config_showCustomControls !== void 0 ? _this_config_showCustomControls : false));
4448
4447
  }
4449
4448
  },
4450
4449
  {
@@ -4552,6 +4551,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4552
4551
  var _this, loadPromise;
4553
4552
  return _ts_generator(this, function(_state) {
4554
4553
  _this = this;
4554
+ if (this.isGamInCooldown()) {
4555
+ if (this.config.debugAdTiming) {
4556
+ console.log("[CIRCUIT-BREAKER] GAM in cooldown, skipping preload");
4557
+ }
4558
+ return [
4559
+ 2
4560
+ ];
4561
+ }
4555
4562
  if (this.preloadPool.some(function(entry) {
4556
4563
  return entry.vastUrl === vastUrl;
4557
4564
  }) || this.failedVastUrls.has(vastUrl) || this.isUrlInCooldown(vastUrl)) {
@@ -4581,26 +4588,32 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4581
4588
  case 1:
4582
4589
  _state.trys.push([
4583
4590
  1,
4584
- 4,
4591
+ 5,
4585
4592
  ,
4586
- 5
4593
+ 6
4587
4594
  ]);
4588
4595
  continueLiveStreamDuringAds = this.shouldContinueLiveStreamDuringAds();
4589
4596
  preloadIma = this.createAdPlayer(continueLiveStreamDuringAds);
4590
4597
  preloadIma.initialize();
4591
- errorListener = function(payload) {
4598
+ errorListener = function errorListener(payload) {
4592
4599
  hasAdError = true;
4593
4600
  adErrorPayload = payload;
4594
4601
  };
4595
4602
  preloadIma.on("ad_error", errorListener);
4596
- errorListenerCleanup = function() {
4603
+ errorListenerCleanup = function errorListenerCleanup() {
4597
4604
  return preloadIma.off("ad_error", errorListener);
4598
4605
  };
4599
4606
  return [
4600
4607
  4,
4601
- preloadIma.requestAds(vastUrl)
4608
+ this.enforceGlobalRateLimit()
4602
4609
  ];
4603
4610
  case 2:
4611
+ _state.sent();
4612
+ return [
4613
+ 4,
4614
+ preloadIma.requestAds(vastUrl)
4615
+ ];
4616
+ case 3:
4604
4617
  _state.sent();
4605
4618
  preloadIma.pause();
4606
4619
  return [
@@ -4609,7 +4622,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4609
4622
  return setTimeout(resolve, 1500);
4610
4623
  })
4611
4624
  ];
4612
- case 3:
4625
+ case 4:
4613
4626
  _state.sent();
4614
4627
  preloadIma.pause();
4615
4628
  if (hasAdError) {
@@ -4618,6 +4631,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4618
4631
  errorListenerCleanup();
4619
4632
  }
4620
4633
  preloadIma.destroy();
4634
+ this.recordGamNoFill();
4621
4635
  if (isNoFill) {
4622
4636
  if (this.config.debugAdTiming) {
4623
4637
  console.log("[PRELOAD-POOL] ⚠️ Ad preload returned no-fill: ".concat(vastUrl));
@@ -4644,7 +4658,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4644
4658
  isReady: true,
4645
4659
  loadPromise: Promise.resolve()
4646
4660
  };
4647
- lateErrorListener = function(payload) {
4661
+ lateErrorListener = function lateErrorListener(payload) {
4648
4662
  var index = _this.preloadPool.findIndex(function(entry) {
4649
4663
  return entry.vastUrl === vastUrl;
4650
4664
  });
@@ -4655,7 +4669,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4655
4669
  }
4656
4670
  try {
4657
4671
  preloadIma.destroy();
4658
- } catch (e) {}
4672
+ } catch (unused) {}
4659
4673
  }
4660
4674
  };
4661
4675
  preloadIma.on("ad_error", lateErrorListener);
@@ -4668,13 +4682,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4668
4682
  }
4669
4683
  return [
4670
4684
  3,
4671
- 5
4685
+ 6
4672
4686
  ];
4673
- case 4:
4687
+ case 5:
4674
4688
  error = _state.sent();
4675
4689
  if (errorListenerCleanup) {
4676
4690
  errorListenerCleanup();
4677
4691
  }
4692
+ this.recordGamNoFill();
4678
4693
  if (this.config.debugAdTiming) {
4679
4694
  console.warn("[PRELOAD-POOL] ⚠️ Failed to preload ad: ".concat(vastUrl), error);
4680
4695
  }
@@ -4685,9 +4700,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4685
4700
  }
4686
4701
  return [
4687
4702
  3,
4688
- 5
4703
+ 6
4689
4704
  ];
4690
- case 5:
4705
+ case 6:
4691
4706
  return [
4692
4707
  2
4693
4708
  ];
@@ -4726,6 +4741,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4726
4741
  3,
4727
4742
  10
4728
4743
  ];
4744
+ if (this.isGamInCooldown()) {
4745
+ if (this.config.debugAdTiming) {
4746
+ console.log("[CIRCUIT-BREAKER] GAM in cooldown, stopping preload pool loop");
4747
+ }
4748
+ return [
4749
+ 3,
4750
+ 10
4751
+ ];
4752
+ }
4729
4753
  if (!(!this.inAdBreak && this.preloadPool.length >= this.maxPreloadPoolSize)) return [
4730
4754
  3,
4731
4755
  3
@@ -4758,7 +4782,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4758
4782
  3,
4759
4783
  8
4760
4784
  ];
4761
- if (!this.preloadPoolActive) {
4785
+ if (!this.preloadPoolActive || this.isGamInCooldown()) {
4762
4786
  return [
4763
4787
  3,
4764
4788
  8
@@ -4974,9 +4998,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4974
4998
  case 1:
4975
4999
  _state.trys.push([
4976
5000
  1,
4977
- 7,
5001
+ 8,
4978
5002
  ,
4979
- 13
5003
+ 14
4980
5004
  ]);
4981
5005
  if (!(usePreloadedAd && preloadedController)) return [
4982
5006
  3,
@@ -5012,15 +5036,21 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5012
5036
  this.ima.setAdVolume(adVolume);
5013
5037
  return [
5014
5038
  3,
5015
- 6
5039
+ 7
5016
5040
  ];
5017
5041
  case 3:
5042
+ return [
5043
+ 4,
5044
+ this.enforceGlobalRateLimit()
5045
+ ];
5046
+ case 4:
5047
+ _state.sent();
5018
5048
  this.lastAdRequestTime = Date.now();
5019
5049
  return [
5020
5050
  4,
5021
5051
  this.ima.requestAds(firstAdUrl)
5022
5052
  ];
5023
- case 4:
5053
+ case 5:
5024
5054
  _state.sent();
5025
5055
  if (this.config.debugAdTiming) {
5026
5056
  console.log("[CONTINUOUS-FETCH] \u2705 First ad request successful, starting playback");
@@ -5035,7 +5065,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5035
5065
  4,
5036
5066
  this.ima.play()
5037
5067
  ];
5038
- case 5:
5068
+ case 6:
5039
5069
  _state.sent();
5040
5070
  if (this.expectedAdBreakDurationMs != null) {
5041
5071
  this.currentAdBreakStartWallClockMs = Date.now();
@@ -5043,36 +5073,36 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5043
5073
  }
5044
5074
  adVolume1 = currentMuted ? 0 : currentVolume;
5045
5075
  this.ima.setAdVolume(adVolume1);
5046
- _state.label = 6;
5047
- case 6:
5076
+ _state.label = 7;
5077
+ case 7:
5048
5078
  return [
5049
5079
  3,
5050
- 13
5080
+ 14
5051
5081
  ];
5052
- case 7:
5082
+ case 8:
5053
5083
  error = _state.sent();
5054
5084
  if (this.config.debugAdTiming) {
5055
5085
  console.warn("[CONTINUOUS-FETCH] \u26A0\uFE0F First ad request failed:", error);
5056
5086
  }
5057
5087
  if (!!usePreloadedAd) return [
5058
5088
  3,
5059
- 11
5089
+ 12
5060
5090
  ];
5061
5091
  fallbackPreloaded = this.getPreloadedAd();
5062
5092
  if (!fallbackPreloaded) return [
5063
5093
  3,
5064
- 11
5094
+ 12
5065
5095
  ];
5066
5096
  if (this.config.debugAdTiming) {
5067
5097
  console.log("[CONTINUOUS-FETCH] \uD83D\uDD04 First ad failed, using preloaded fallback");
5068
5098
  }
5069
- _state.label = 8;
5070
- case 8:
5099
+ _state.label = 9;
5100
+ case 9:
5071
5101
  _state.trys.push([
5072
- 8,
5073
- 10,
5102
+ 9,
5103
+ 11,
5074
5104
  ,
5075
- 11
5105
+ 12
5076
5106
  ]);
5077
5107
  this.ima.destroy();
5078
5108
  this.video.muted = true;
@@ -5091,7 +5121,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5091
5121
  4,
5092
5122
  this.ima.play()
5093
5123
  ];
5094
- case 9:
5124
+ case 10:
5095
5125
  _state.sent();
5096
5126
  if (this.expectedAdBreakDurationMs != null) {
5097
5127
  this.currentAdBreakStartWallClockMs = Date.now();
@@ -5102,16 +5132,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5102
5132
  return [
5103
5133
  2
5104
5134
  ];
5105
- case 10:
5135
+ case 11:
5106
5136
  fallbackError = _state.sent();
5107
5137
  if (this.config.debugAdTiming) {
5108
5138
  console.warn("[CONTINUOUS-FETCH] \u26A0\uFE0F Preloaded fallback also failed:", fallbackError);
5109
5139
  }
5110
5140
  return [
5111
5141
  3,
5112
- 11
5142
+ 12
5113
5143
  ];
5114
- case 11:
5144
+ case 12:
5115
5145
  if (this.isTemporaryAdError(error)) {
5116
5146
  this.temporaryFailureUrls.set(firstAdUrl, Date.now());
5117
5147
  if (this.config.debugAdTiming) {
@@ -5129,13 +5159,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5129
5159
  4,
5130
5160
  this.tryNextAvailableAdWithRateLimit()
5131
5161
  ];
5132
- case 12:
5162
+ case 13:
5133
5163
  _state.sent();
5134
5164
  return [
5135
5165
  3,
5136
- 13
5166
+ 14
5137
5167
  ];
5138
- case 13:
5168
+ case 14:
5139
5169
  return [
5140
5170
  2
5141
5171
  ];
@@ -5186,6 +5216,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5186
5216
  "break"
5187
5217
  ];
5188
5218
  }
5219
+ if (_this.isGamInCooldown()) {
5220
+ if (_this.config.debugAdTiming) {
5221
+ console.log("[CIRCUIT-BREAKER] GAM in cooldown, stopping URL generation");
5222
+ }
5223
+ return [
5224
+ 2,
5225
+ "break"
5226
+ ];
5227
+ }
5189
5228
  if (_this.consecutiveFailures >= _this.maxConsecutiveFailures) {
5190
5229
  if (_this.config.debugAdTiming) {
5191
5230
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Too many consecutive failures (".concat(_this.consecutiveFailures, "), stopping URL generation"));
@@ -5382,6 +5421,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5382
5421
  2
5383
5422
  ];
5384
5423
  }
5424
+ if (this.isGamInCooldown()) {
5425
+ if (this.config.debugAdTiming) {
5426
+ console.log("[CIRCUIT-BREAKER] GAM in cooldown, ending ad break gracefully");
5427
+ }
5428
+ this.handleAdPodComplete();
5429
+ return [
5430
+ 2
5431
+ ];
5432
+ }
5385
5433
  if (this.consecutiveFailures >= this.maxConsecutiveFailures) {
5386
5434
  if (this.config.debugAdTiming) {
5387
5435
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Too many consecutive failures (".concat(this.consecutiveFailures, "), ending ad break"));
@@ -5578,6 +5626,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5578
5626
  case 0:
5579
5627
  remaining = this.getRemainingAdMs();
5580
5628
  waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);
5629
+ if (this.isGamInCooldown()) {
5630
+ if (this.config.debugAdTiming) {
5631
+ console.log("[CIRCUIT-BREAKER] GAM in cooldown, skipping placeholder wait");
5632
+ }
5633
+ this.handleAdPodComplete();
5634
+ return [
5635
+ 2
5636
+ ];
5637
+ }
5581
5638
  if (this.consecutiveFailures >= this.maxConsecutiveFailures) {
5582
5639
  if (this.config.debugAdTiming) {
5583
5640
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Skipping placeholder - too many consecutive failures");
@@ -5841,11 +5898,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5841
5898
  {
5842
5899
  key: "ensureAdStoppedByTimer",
5843
5900
  value: function ensureAdStoppedByTimer() {
5901
+ var _this_config_adBreakCheckIntervalMs, _this_expectedAdBreakDurationMs;
5844
5902
  if (!this.inAdBreak) return;
5845
5903
  this.adStopTimerId = void 0;
5846
5904
  var adPlaying = this.ima.isAdPlaying();
5847
5905
  var pendingAds = this.adPodQueue.length > 0;
5848
- var _this_config_adBreakCheckIntervalMs;
5849
5906
  var checkIntervalMs = Math.max(250, Math.floor((_this_config_adBreakCheckIntervalMs = this.config.adBreakCheckIntervalMs) !== null && _this_config_adBreakCheckIntervalMs !== void 0 ? _this_config_adBreakCheckIntervalMs : 1e3));
5850
5907
  var maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;
5851
5908
  var maxExtensionMs = typeof maxExtensionMsConfig === "number" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 6e4;
@@ -5853,7 +5910,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5853
5910
  if (this.currentAdBreakStartWallClockMs != null) {
5854
5911
  elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;
5855
5912
  }
5856
- var _this_expectedAdBreakDurationMs;
5857
5913
  var expectedDurationMs = (_this_expectedAdBreakDurationMs = this.expectedAdBreakDurationMs) !== null && _this_expectedAdBreakDurationMs !== void 0 ? _this_expectedAdBreakDurationMs : 0;
5858
5914
  var overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);
5859
5915
  var shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;
@@ -5967,6 +6023,73 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5967
6023
  }
5968
6024
  }
5969
6025
  },
6026
+ {
6027
+ key: "isGamInCooldown",
6028
+ value: function isGamInCooldown() {
6029
+ return Date.now() < this.globalNoFillCooldownUntil;
6030
+ }
6031
+ },
6032
+ {
6033
+ key: "recordGamNoFill",
6034
+ value: function recordGamNoFill() {
6035
+ this.globalConsecutiveNoFills++;
6036
+ if (this.globalConsecutiveNoFills >= this.globalNoFillThreshold) {
6037
+ var exponent = this.globalConsecutiveNoFills - this.globalNoFillThreshold;
6038
+ var backoff = Math.min(this.globalNoFillBackoffBaseMs * Math.pow(2, exponent), this.globalNoFillBackoffMaxMs);
6039
+ this.globalNoFillCooldownUntil = Date.now() + backoff;
6040
+ if (this.config.debugAdTiming) {
6041
+ console.log("[CIRCUIT-BREAKER] GAM cooldown activated: ".concat(backoff, "ms (").concat(this.globalConsecutiveNoFills, " consecutive no-fills)"));
6042
+ }
6043
+ }
6044
+ }
6045
+ },
6046
+ {
6047
+ key: "resetGamNoFillCounter",
6048
+ value: function resetGamNoFillCounter() {
6049
+ if (this.globalConsecutiveNoFills > 0 && this.config.debugAdTiming) {
6050
+ console.log("[CIRCUIT-BREAKER] Resetting no-fill counter (was ".concat(this.globalConsecutiveNoFills, ")"));
6051
+ }
6052
+ this.globalConsecutiveNoFills = 0;
6053
+ this.globalNoFillCooldownUntil = 0;
6054
+ }
6055
+ },
6056
+ {
6057
+ key: "enforceGlobalRateLimit",
6058
+ value: function enforceGlobalRateLimit() {
6059
+ return _async_to_generator(function() {
6060
+ var now, elapsed, waitMs;
6061
+ return _ts_generator(this, function(_state) {
6062
+ switch(_state.label){
6063
+ case 0:
6064
+ now = Date.now();
6065
+ elapsed = now - this.globalLastGamRequestTime;
6066
+ if (!(elapsed < this.globalMinGamIntervalMs)) return [
6067
+ 3,
6068
+ 2
6069
+ ];
6070
+ waitMs = this.globalMinGamIntervalMs - elapsed;
6071
+ if (this.config.debugAdTiming) {
6072
+ console.log("[RATE-LIMIT] Waiting ".concat(waitMs, "ms before next GAM request"));
6073
+ }
6074
+ return [
6075
+ 4,
6076
+ new Promise(function(resolve) {
6077
+ return setTimeout(resolve, waitMs);
6078
+ })
6079
+ ];
6080
+ case 1:
6081
+ _state.sent();
6082
+ _state.label = 2;
6083
+ case 2:
6084
+ this.globalLastGamRequestTime = Date.now();
6085
+ return [
6086
+ 2
6087
+ ];
6088
+ }
6089
+ });
6090
+ }).call(this);
6091
+ }
6092
+ },
5970
6093
  {
5971
6094
  key: "playSingleAd",
5972
6095
  value: function playSingleAd(vastTagUrl) {
@@ -5998,6 +6121,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5998
6121
  }
5999
6122
  throw new Error("Too many consecutive failures");
6000
6123
  }
6124
+ if (this.isGamInCooldown()) {
6125
+ if (this.config.debugAdTiming) {
6126
+ console.warn("[CIRCUIT-BREAKER] GAM in cooldown, skipping ad request");
6127
+ }
6128
+ throw new Error("GAM in cooldown");
6129
+ }
6001
6130
  this.recreateImaController();
6002
6131
  requestToken = ++this.adRequestTokenCounter;
6003
6132
  this.activeAdRequestToken = requestToken;
@@ -6006,16 +6135,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6006
6135
  case 1:
6007
6136
  _state.trys.push([
6008
6137
  1,
6009
- 11,
6138
+ 12,
6010
6139
  ,
6011
- 16
6140
+ 17
6012
6141
  ]);
6142
+ return [
6143
+ 4,
6144
+ this.enforceGlobalRateLimit()
6145
+ ];
6146
+ case 2:
6147
+ _state.sent();
6013
6148
  this.lastAdRequestTime = Date.now();
6014
6149
  return [
6015
6150
  4,
6016
6151
  this.ima.requestAds(vastTagUrl)
6017
6152
  ];
6018
- case 2:
6153
+ case 3:
6019
6154
  _state.sent();
6020
6155
  this.clearAdRequestWatchdog();
6021
6156
  if (this.activeAdRequestToken !== requestToken) {
@@ -6023,20 +6158,20 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6023
6158
  2
6024
6159
  ];
6025
6160
  }
6026
- _state.label = 3;
6027
- case 3:
6161
+ _state.label = 4;
6162
+ case 4:
6028
6163
  _state.trys.push([
6029
- 3,
6030
- 5,
6164
+ 4,
6165
+ 6,
6031
6166
  ,
6032
- 10
6167
+ 11
6033
6168
  ]);
6034
6169
  this.startAdFailsafeTimer(requestToken);
6035
6170
  return [
6036
6171
  4,
6037
6172
  this.ima.play()
6038
6173
  ];
6039
- case 4:
6174
+ case 5:
6040
6175
  _state.sent();
6041
6176
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
6042
6177
  this.currentAdBreakStartWallClockMs = Date.now();
@@ -6050,9 +6185,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6050
6185
  this.temporaryFailureUrls.delete(vastTagUrl);
6051
6186
  return [
6052
6187
  3,
6053
- 10
6188
+ 11
6054
6189
  ];
6055
- case 5:
6190
+ case 6:
6056
6191
  playError = _state.sent();
6057
6192
  if (this.config.debugAdTiming) {
6058
6193
  console.error("[AD-ERROR] Failed to play ad:", playError);
@@ -6060,18 +6195,18 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6060
6195
  preloadedFallback = this.getPreloadedAd();
6061
6196
  if (!preloadedFallback) return [
6062
6197
  3,
6063
- 9
6198
+ 10
6064
6199
  ];
6065
6200
  if (this.config.debugAdTiming) {
6066
6201
  console.log("[AD-ERROR] Play failed, trying preloaded fallback ad");
6067
6202
  }
6068
- _state.label = 6;
6069
- case 6:
6203
+ _state.label = 7;
6204
+ case 7:
6070
6205
  _state.trys.push([
6071
- 6,
6072
- 8,
6206
+ 7,
6207
+ 9,
6073
6208
  ,
6074
- 9
6209
+ 10
6075
6210
  ]);
6076
6211
  this.clearAdFailsafeTimer();
6077
6212
  this.ima.destroy();
@@ -6087,7 +6222,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6087
6222
  4,
6088
6223
  this.ima.play()
6089
6224
  ];
6090
- case 7:
6225
+ case 8:
6091
6226
  _state.sent();
6092
6227
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
6093
6228
  this.currentAdBreakStartWallClockMs = Date.now();
@@ -6100,16 +6235,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6100
6235
  return [
6101
6236
  2
6102
6237
  ];
6103
- case 8:
6238
+ case 9:
6104
6239
  fallbackError = _state.sent();
6105
6240
  if (this.config.debugAdTiming) {
6106
6241
  console.warn("[AD-ERROR] Preloaded fallback also failed:", fallbackError);
6107
6242
  }
6108
6243
  return [
6109
6244
  3,
6110
- 9
6245
+ 10
6111
6246
  ];
6112
- case 9:
6247
+ case 10:
6113
6248
  if (this.isTemporaryAdError(playError)) {
6114
6249
  this.temporaryFailureUrls.set(vastTagUrl, Date.now());
6115
6250
  if (this.config.debugAdTiming) {
@@ -6126,12 +6261,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6126
6261
  this.activeAdRequestToken = null;
6127
6262
  }
6128
6263
  throw playError;
6129
- case 10:
6264
+ case 11:
6130
6265
  return [
6131
6266
  3,
6132
- 16
6267
+ 17
6133
6268
  ];
6134
- case 11:
6269
+ case 12:
6135
6270
  error = _state.sent();
6136
6271
  errorMessage = (error === null || error === void 0 ? void 0 : error.message) || "";
6137
6272
  if (this.config.debugAdTiming) {
@@ -6140,18 +6275,18 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6140
6275
  preloadedFallback1 = this.getPreloadedAd();
6141
6276
  if (!preloadedFallback1) return [
6142
6277
  3,
6143
- 15
6278
+ 16
6144
6279
  ];
6145
6280
  if (this.config.debugAdTiming) {
6146
6281
  console.log("[AD-ERROR] Request failed, trying preloaded fallback ad");
6147
6282
  }
6148
- _state.label = 12;
6149
- case 12:
6283
+ _state.label = 13;
6284
+ case 13:
6150
6285
  _state.trys.push([
6151
- 12,
6152
- 14,
6286
+ 13,
6287
+ 15,
6153
6288
  ,
6154
- 15
6289
+ 16
6155
6290
  ]);
6156
6291
  this.clearAdRequestWatchdog();
6157
6292
  this.clearAdFailsafeTimer();
@@ -6168,7 +6303,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6168
6303
  4,
6169
6304
  this.ima.play()
6170
6305
  ];
6171
- case 13:
6306
+ case 14:
6172
6307
  _state.sent();
6173
6308
  currentMuted2 = this.video.muted;
6174
6309
  currentVolume2 = this.video.volume;
@@ -6177,16 +6312,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6177
6312
  return [
6178
6313
  2
6179
6314
  ];
6180
- case 14:
6315
+ case 15:
6181
6316
  fallbackError1 = _state.sent();
6182
6317
  if (this.config.debugAdTiming) {
6183
6318
  console.warn("[AD-ERROR] Preloaded fallback also failed:", fallbackError1);
6184
6319
  }
6185
6320
  return [
6186
6321
  3,
6187
- 15
6322
+ 16
6188
6323
  ];
6189
- case 15:
6324
+ case 16:
6190
6325
  if (this.isTemporaryAdError(error)) {
6191
6326
  this.temporaryFailureUrls.set(vastTagUrl, Date.now());
6192
6327
  if (this.config.debugAdTiming) {
@@ -6204,7 +6339,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6204
6339
  this.activeAdRequestToken = null;
6205
6340
  }
6206
6341
  throw error;
6207
- case 16:
6342
+ case 17:
6208
6343
  return [
6209
6344
  2
6210
6345
  ];
@@ -6240,6 +6375,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6240
6375
  this.currentAdIndex = 0;
6241
6376
  this.totalAdsInBreak = 0;
6242
6377
  this.consecutiveFailures = 0;
6378
+ this.globalConsecutiveNoFills = 0;
6243
6379
  this.ima.stop().catch(function() {});
6244
6380
  var restoredMuted = this.ima.getOriginalMutedState();
6245
6381
  var restoredVolume = this.ima.getOriginalVolume();
@@ -6271,6 +6407,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6271
6407
  key: "handleAdFailure",
6272
6408
  value: function handleAdFailure() {
6273
6409
  this.consecutiveFailures++;
6410
+ this.recordGamNoFill();
6274
6411
  var remaining = this.getRemainingAdMs();
6275
6412
  if (this.config.debugAdTiming) {
6276
6413
  console.log("[CONTINUOUS-FETCH] Ad failure: remaining=".concat(remaining, "ms, queued ads=").concat(this.adRequestQueue.length, ", consecutiveFailures=").concat(this.consecutiveFailures), this.adRequestQueue.length > 0 ? {
@@ -6298,8 +6435,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6298
6435
  key: "startAdRequestWatchdog",
6299
6436
  value: function startAdRequestWatchdog(token) {
6300
6437
  var _this = this;
6301
- this.clearAdRequestWatchdog();
6302
6438
  var _this_config_adFailsafeTimeoutMs;
6439
+ this.clearAdRequestWatchdog();
6303
6440
  var timeoutMs = (_this_config_adFailsafeTimeoutMs = this.config.adFailsafeTimeoutMs) !== null && _this_config_adFailsafeTimeoutMs !== void 0 ? _this_config_adFailsafeTimeoutMs : 1e4;
6304
6441
  this.adRequestWatchdogToken = token;
6305
6442
  this.adRequestWatchdogId = window.setTimeout(function() {
@@ -6342,8 +6479,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6342
6479
  key: "startAdFailsafeTimer",
6343
6480
  value: function startAdFailsafeTimer(token) {
6344
6481
  var _this = this;
6345
- this.clearAdFailsafeTimer();
6346
6482
  var _this_config_adFailsafeTimeoutMs;
6483
+ this.clearAdFailsafeTimer();
6347
6484
  var failsafeMs = (_this_config_adFailsafeTimeoutMs = this.config.adFailsafeTimeoutMs) !== null && _this_config_adFailsafeTimeoutMs !== void 0 ? _this_config_adFailsafeTimeoutMs : 1e4;
6348
6485
  this.adFailsafeToken = token;
6349
6486
  this.adFailsafeTimerId = window.setTimeout(function() {