stormcloud-video-player 0.8.8 → 0.8.10

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.
@@ -2636,6 +2636,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2636
2636
  this.maxConsecutiveFailures = 5;
2637
2637
  this.lastAdRequestTime = 0;
2638
2638
  this.minAdRequestIntervalMs = 3e3;
2639
+ this.defaultMinRemainingMsToStartAd = 4e3;
2639
2640
  this.backoffBaseMs = 1e3;
2640
2641
  this.maxBackoffMs = 15e3;
2641
2642
  this.globalConsecutiveNoFills = 0;
@@ -2650,6 +2651,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2650
2651
  this.preloadPoolActive = false;
2651
2652
  this.preloadPoolLoopRunning = false;
2652
2653
  this.adDetectSentForCurrentBreak = false;
2654
+ this.adBreakEpoch = 0;
2653
2655
  this.palPlaybackStarted = false;
2654
2656
  this.streamCorrelator = generateCorrelator();
2655
2657
  this.consentSignals = {};
@@ -3154,7 +3156,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3154
3156
  } : {});
3155
3157
  }
3156
3158
  if (_this.inAdBreak) {
3157
- if (remaining > 500) {
3159
+ if (_this.hasTimeToStartAnotherAd()) {
3158
3160
  _this.tryNextAvailableAdWithRateLimit();
3159
3161
  } else {
3160
3162
  _this.handleAdPodComplete();
@@ -3227,7 +3229,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3227
3229
  queuedUrls: _to_consumable_array(_this.adRequestQueue)
3228
3230
  } : {});
3229
3231
  }
3230
- if (remaining > 500) {
3232
+ if (_this.hasTimeToStartAnotherAd()) {
3231
3233
  _this.tryNextAvailableAdWithRateLimit();
3232
3234
  } else {
3233
3235
  _this.handleAdPodComplete();
@@ -3927,7 +3929,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3927
3929
  var remainingMs1 = Math.max(0, this.expectedAdBreakDurationMs - elapsedMs1);
3928
3930
  this.scheduleAdStopCountdown(remainingMs1);
3929
3931
  }
3930
- if (!this.adPlayer.isAdPlaying() && this.activeAdRequestToken === null && this.adRequestQueue.length > 0) {
3932
+ if (!this.adPlayer.isAdPlaying() && this.activeAdRequestToken === null && this.adRequestQueue.length > 0 && this.hasTimeToStartAnotherAd()) {
3931
3933
  this.tryNextAvailableAdWithRateLimit();
3932
3934
  }
3933
3935
  return;
@@ -5197,7 +5199,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5197
5199
  key: "preloadAdIntoPool",
5198
5200
  value: function preloadAdIntoPool(vastUrl) {
5199
5201
  return _async_to_generator(function() {
5200
- var _this, loadPromise;
5202
+ var _this, epoch, loadPromise;
5201
5203
  return _ts_generator(this, function(_state) {
5202
5204
  _this = this;
5203
5205
  if (this.isGamInCooldown()) {
@@ -5223,6 +5225,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5223
5225
  if (this.config.debugAdTiming) {
5224
5226
  console.log("[PRELOAD-POOL] \uD83D\uDCE5 Preloading ad into pool: ".concat(vastUrl));
5225
5227
  }
5228
+ epoch = this.adBreakEpoch;
5226
5229
  loadPromise = function() {
5227
5230
  return _async_to_generator(function() {
5228
5231
  var _this, hasAdError, adErrorPayload, errorListenerCleanup, continueLiveStreamDuringAds, preloadAd, errorListener, isNoFill, poolEntry, lateErrorListener, error;
@@ -5300,6 +5303,20 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5300
5303
  2
5301
5304
  ];
5302
5305
  }
5306
+ if (!this.preloadPoolActive || epoch !== this.adBreakEpoch) {
5307
+ if (this.config.debugAdTiming) {
5308
+ console.log("[PRELOAD-POOL] \uD83D\uDEAB Discarding preloaded ad - break ended during fetch");
5309
+ }
5310
+ if (errorListenerCleanup) {
5311
+ errorListenerCleanup();
5312
+ }
5313
+ try {
5314
+ preloadAd.destroy();
5315
+ } catch (unused) {}
5316
+ return [
5317
+ 2
5318
+ ];
5319
+ }
5303
5320
  poolEntry = {
5304
5321
  vastUrl: vastUrl,
5305
5322
  adController: preloadAd,
@@ -5371,7 +5388,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5371
5388
  key: "preloadPoolLoop",
5372
5389
  value: function preloadPoolLoop(baseVastUrl) {
5373
5390
  return _async_to_generator(function() {
5374
- var remaining, newUrls, newUrl;
5391
+ var epoch, newUrls, newUrl;
5375
5392
  return _ts_generator(this, function(_state) {
5376
5393
  switch(_state.label){
5377
5394
  case 0:
@@ -5381,12 +5398,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5381
5398
  ];
5382
5399
  }
5383
5400
  this.preloadPoolLoopRunning = true;
5401
+ epoch = this.adBreakEpoch;
5384
5402
  if (this.config.debugAdTiming) {
5385
5403
  console.log("[PRELOAD-POOL] \uD83D\uDD04 Starting continuous preload loop");
5386
5404
  }
5387
5405
  _state.label = 1;
5388
5406
  case 1:
5389
- if (!this.preloadPoolActive) return [
5407
+ if (!(this.preloadPoolActive && epoch === this.adBreakEpoch)) return [
5390
5408
  3,
5391
5409
  10
5392
5410
  ];
@@ -5431,20 +5449,20 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5431
5449
  3,
5432
5450
  8
5433
5451
  ];
5434
- if (!this.preloadPoolActive || this.isGamInCooldown()) {
5452
+ if (!this.preloadPoolActive || epoch !== this.adBreakEpoch || this.isGamInCooldown()) {
5435
5453
  return [
5436
5454
  3,
5437
5455
  8
5438
5456
  ];
5439
5457
  }
5440
- if (this.inAdBreak) {
5441
- remaining = this.getRemainingAdMs();
5442
- if (remaining <= 0) {
5443
- return [
5444
- 3,
5445
- 8
5446
- ];
5458
+ if (this.inAdBreak && !this.hasTimeToStartAnotherAd()) {
5459
+ if (this.config.debugAdTiming) {
5460
+ console.log("[PRELOAD-POOL] Not enough ad break time left, stopping preload");
5447
5461
  }
5462
+ return [
5463
+ 3,
5464
+ 8
5465
+ ];
5448
5466
  }
5449
5467
  newUrls = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);
5450
5468
  newUrl = newUrls[0];
@@ -5864,7 +5882,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5864
5882
  key: "continuousFetchLoop",
5865
5883
  value: function continuousFetchLoop(baseVastUrl) {
5866
5884
  return _async_to_generator(function() {
5867
- var _this, _loop, _ret;
5885
+ var _this, _loop, epoch, _ret;
5868
5886
  return _ts_generator(this, function(_state) {
5869
5887
  switch(_state.label){
5870
5888
  case 0:
@@ -5874,9 +5892,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5874
5892
  switch(_state.label){
5875
5893
  case 0:
5876
5894
  remaining = _this.getRemainingAdMs();
5877
- if (remaining <= 0) {
5895
+ if (remaining <= _this.getMinRemainingMsToStartAd()) {
5878
5896
  if (_this.config.debugAdTiming) {
5879
- console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F Ad break time expired, stopping URL generation");
5897
+ console.log("[CONTINUOUS-FETCH] ⏹️ Not enough ad break time left (".concat(remaining, "ms), stopping URL generation"));
5880
5898
  }
5881
5899
  return [
5882
5900
  2,
@@ -5974,9 +5992,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5974
5992
  }
5975
5993
  });
5976
5994
  };
5995
+ epoch = this.adBreakEpoch;
5977
5996
  _state.label = 1;
5978
5997
  case 1:
5979
- if (!(this.continuousFetchingActive && this.inAdBreak)) return [
5998
+ if (!(this.continuousFetchingActive && this.inAdBreak && epoch === this.adBreakEpoch)) return [
5980
5999
  3,
5981
6000
  3
5982
6001
  ];
@@ -6025,10 +6044,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6025
6044
  key: "tryNextAvailableAdWithRateLimit",
6026
6045
  value: function tryNextAvailableAdWithRateLimit() {
6027
6046
  return _async_to_generator(function() {
6028
- var backoffMultiplier, backoffDelay, effectiveMinInterval, timeSinceLastRequest, waitTime;
6047
+ var epoch, backoffMultiplier, backoffDelay, effectiveMinInterval, timeSinceLastRequest, waitTime;
6029
6048
  return _ts_generator(this, function(_state) {
6030
6049
  switch(_state.label){
6031
6050
  case 0:
6051
+ if (!this.inAdBreak) {
6052
+ return [
6053
+ 2
6054
+ ];
6055
+ }
6056
+ epoch = this.adBreakEpoch;
6032
6057
  if (this.consecutiveFailures >= this.maxConsecutiveFailures) {
6033
6058
  if (this.config.debugAdTiming) {
6034
6059
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Too many consecutive failures (".concat(this.consecutiveFailures, "), ending ad break gracefully"));
@@ -6060,6 +6085,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6060
6085
  _state.sent();
6061
6086
  _state.label = 2;
6062
6087
  case 2:
6088
+ if (!this.inAdBreak || epoch !== this.adBreakEpoch) {
6089
+ return [
6090
+ 2
6091
+ ];
6092
+ }
6063
6093
  return [
6064
6094
  2,
6065
6095
  this.tryNextAvailableAd(0)
@@ -6078,10 +6108,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6078
6108
  return _ts_generator(this, function(_state) {
6079
6109
  switch(_state.label){
6080
6110
  case 0:
6111
+ if (!this.inAdBreak) {
6112
+ return [
6113
+ 2
6114
+ ];
6115
+ }
6081
6116
  remaining = this.getRemainingAdMs();
6082
- if (remaining <= 500) {
6117
+ if (!this.hasTimeToStartAnotherAd()) {
6083
6118
  if (this.config.debugAdTiming) {
6084
- console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F No time remaining, ending ad break");
6119
+ console.log("[CONTINUOUS-FETCH] ⏹️ Not enough time remaining (".concat(remaining, "ms) to start another ad, ending ad break"));
6085
6120
  }
6086
6121
  this.handleAdPodComplete();
6087
6122
  return [
@@ -6353,12 +6388,27 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6353
6388
  10
6354
6389
  ];
6355
6390
  }
6391
+ if (!this.hasTimeToStartAnotherAd()) {
6392
+ if (this.config.debugAdTiming) {
6393
+ console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F Not enough time remaining during placeholder wait, ending ad break");
6394
+ }
6395
+ return [
6396
+ 3,
6397
+ 10
6398
+ ];
6399
+ }
6356
6400
  _state.label = 3;
6357
6401
  case 3:
6358
6402
  if (!(this.adRequestQueue.length > 0)) return [
6359
6403
  3,
6360
6404
  9
6361
6405
  ];
6406
+ if (!this.hasTimeToStartAnotherAd()) {
6407
+ return [
6408
+ 3,
6409
+ 9
6410
+ ];
6411
+ }
6362
6412
  nextAdUrl = this.adRequestQueue.shift();
6363
6413
  if (!nextAdUrl) {
6364
6414
  return [
@@ -6641,21 +6691,23 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6641
6691
  if (!this.inAdBreak) return;
6642
6692
  this.adStopTimerId = void 0;
6643
6693
  var adPlaying = this.adPlayer.isAdPlaying();
6644
- var pendingAds = this.adPodQueue.length > 0;
6645
6694
  var checkIntervalMs = Math.max(250, Math.floor((_this_config_adBreakCheckIntervalMs = this.config.adBreakCheckIntervalMs) !== null && _this_config_adBreakCheckIntervalMs !== void 0 ? _this_config_adBreakCheckIntervalMs : 1e3));
6646
6695
  var maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;
6647
- var maxExtensionMs = typeof maxExtensionMsConfig === "number" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 6e4;
6696
+ var maxExtensionMs = typeof maxExtensionMsConfig === "number" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 0;
6648
6697
  var elapsedSinceStartMs = 0;
6649
6698
  if (this.currentAdBreakStartWallClockMs != null) {
6650
6699
  elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;
6651
6700
  }
6652
6701
  var expectedDurationMs = (_this_expectedAdBreakDurationMs = this.expectedAdBreakDurationMs) !== null && _this_expectedAdBreakDurationMs !== void 0 ? _this_expectedAdBreakDurationMs : 0;
6653
6702
  var overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);
6654
- var shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;
6703
+ var shouldExtendAdBreak = adPlaying && overrunMs < maxExtensionMs;
6655
6704
  if (shouldExtendAdBreak) {
6656
6705
  this.scheduleAdStopCountdown(checkIntervalMs);
6657
6706
  return;
6658
6707
  }
6708
+ if (this.config.debugAdTiming) {
6709
+ console.log("[StormcloudVideoPlayer] ⏱️ Ad break boundary reached (overrun=".concat(overrunMs, "ms) - hard-stopping ads and resuming stream"));
6710
+ }
6659
6711
  if (adPlaying) {
6660
6712
  this.adPlayer.stop().catch(function() {});
6661
6713
  }
@@ -7090,6 +7142,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7090
7142
  if (this.config.debugAdTiming) {
7091
7143
  console.log("[StormcloudVideoPlayer] \uD83C\uDFC1 Ad pod complete - cleaning up");
7092
7144
  }
7145
+ this.adBreakEpoch++;
7093
7146
  this.clearAdRequestWatchdog();
7094
7147
  this.clearAdFailsafeTimer();
7095
7148
  this.activeAdRequestToken = null;
@@ -7160,11 +7213,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7160
7213
  this.handleAdPodComplete();
7161
7214
  return;
7162
7215
  }
7163
- if (remaining > 500) {
7216
+ if (this.hasTimeToStartAnotherAd()) {
7164
7217
  this.tryNextAvailableAdWithRateLimit();
7165
7218
  } else {
7166
7219
  if (this.config.debugAdTiming) {
7167
- console.log("[AD-ERROR] Ad failed and no time remaining. Failed URLs:", this.failedVastUrls.size);
7220
+ console.log("[AD-ERROR] Ad failed and not enough time remaining for another ad. Failed URLs:", this.failedVastUrls.size);
7168
7221
  }
7169
7222
  this.handleAdPodComplete();
7170
7223
  }
@@ -7299,6 +7352,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7299
7352
  return Math.max(0, this.expectedAdBreakDurationMs - elapsed);
7300
7353
  }
7301
7354
  },
7355
+ {
7356
+ key: "getMinRemainingMsToStartAd",
7357
+ value: function getMinRemainingMsToStartAd() {
7358
+ var configured = this.config.minRemainingMsToStartAd;
7359
+ if (typeof configured === "number" && configured >= 0) {
7360
+ return configured;
7361
+ }
7362
+ return this.defaultMinRemainingMsToStartAd;
7363
+ }
7364
+ },
7365
+ {
7366
+ key: "hasTimeToStartAnotherAd",
7367
+ value: function hasTimeToStartAnotherAd() {
7368
+ return this.getRemainingAdMs() > this.getMinRemainingMsToStartAd();
7369
+ }
7370
+ },
7302
7371
  {
7303
7372
  key: "findBreakForTime",
7304
7373
  value: function findBreakForTime(nowMs) {