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.
package/lib/index.cjs CHANGED
@@ -2919,6 +2919,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2919
2919
  this.maxConsecutiveFailures = 5;
2920
2920
  this.lastAdRequestTime = 0;
2921
2921
  this.minAdRequestIntervalMs = 3e3;
2922
+ this.defaultMinRemainingMsToStartAd = 4e3;
2922
2923
  this.backoffBaseMs = 1e3;
2923
2924
  this.maxBackoffMs = 15e3;
2924
2925
  this.globalConsecutiveNoFills = 0;
@@ -2933,6 +2934,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2933
2934
  this.preloadPoolActive = false;
2934
2935
  this.preloadPoolLoopRunning = false;
2935
2936
  this.adDetectSentForCurrentBreak = false;
2937
+ this.adBreakEpoch = 0;
2936
2938
  this.palPlaybackStarted = false;
2937
2939
  this.streamCorrelator = generateCorrelator();
2938
2940
  this.consentSignals = {};
@@ -3437,7 +3439,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3437
3439
  } : {});
3438
3440
  }
3439
3441
  if (_this.inAdBreak) {
3440
- if (remaining > 500) {
3442
+ if (_this.hasTimeToStartAnotherAd()) {
3441
3443
  _this.tryNextAvailableAdWithRateLimit();
3442
3444
  } else {
3443
3445
  _this.handleAdPodComplete();
@@ -3510,7 +3512,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3510
3512
  queuedUrls: _to_consumable_array(_this.adRequestQueue)
3511
3513
  } : {});
3512
3514
  }
3513
- if (remaining > 500) {
3515
+ if (_this.hasTimeToStartAnotherAd()) {
3514
3516
  _this.tryNextAvailableAdWithRateLimit();
3515
3517
  } else {
3516
3518
  _this.handleAdPodComplete();
@@ -4210,7 +4212,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4210
4212
  var remainingMs1 = Math.max(0, this.expectedAdBreakDurationMs - elapsedMs1);
4211
4213
  this.scheduleAdStopCountdown(remainingMs1);
4212
4214
  }
4213
- if (!this.adPlayer.isAdPlaying() && this.activeAdRequestToken === null && this.adRequestQueue.length > 0) {
4215
+ if (!this.adPlayer.isAdPlaying() && this.activeAdRequestToken === null && this.adRequestQueue.length > 0 && this.hasTimeToStartAnotherAd()) {
4214
4216
  this.tryNextAvailableAdWithRateLimit();
4215
4217
  }
4216
4218
  return;
@@ -5480,7 +5482,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5480
5482
  key: "preloadAdIntoPool",
5481
5483
  value: function preloadAdIntoPool(vastUrl) {
5482
5484
  return _async_to_generator(function() {
5483
- var _this, loadPromise;
5485
+ var _this, epoch, loadPromise;
5484
5486
  return _ts_generator(this, function(_state) {
5485
5487
  _this = this;
5486
5488
  if (this.isGamInCooldown()) {
@@ -5506,6 +5508,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5506
5508
  if (this.config.debugAdTiming) {
5507
5509
  console.log("[PRELOAD-POOL] \uD83D\uDCE5 Preloading ad into pool: ".concat(vastUrl));
5508
5510
  }
5511
+ epoch = this.adBreakEpoch;
5509
5512
  loadPromise = function() {
5510
5513
  return _async_to_generator(function() {
5511
5514
  var _this, hasAdError, adErrorPayload, errorListenerCleanup, continueLiveStreamDuringAds, preloadAd, errorListener, isNoFill, poolEntry, lateErrorListener, error;
@@ -5583,6 +5586,20 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5583
5586
  2
5584
5587
  ];
5585
5588
  }
5589
+ if (!this.preloadPoolActive || epoch !== this.adBreakEpoch) {
5590
+ if (this.config.debugAdTiming) {
5591
+ console.log("[PRELOAD-POOL] \uD83D\uDEAB Discarding preloaded ad - break ended during fetch");
5592
+ }
5593
+ if (errorListenerCleanup) {
5594
+ errorListenerCleanup();
5595
+ }
5596
+ try {
5597
+ preloadAd.destroy();
5598
+ } catch (unused) {}
5599
+ return [
5600
+ 2
5601
+ ];
5602
+ }
5586
5603
  poolEntry = {
5587
5604
  vastUrl: vastUrl,
5588
5605
  adController: preloadAd,
@@ -5654,7 +5671,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5654
5671
  key: "preloadPoolLoop",
5655
5672
  value: function preloadPoolLoop(baseVastUrl) {
5656
5673
  return _async_to_generator(function() {
5657
- var remaining, newUrls, newUrl;
5674
+ var epoch, newUrls, newUrl;
5658
5675
  return _ts_generator(this, function(_state) {
5659
5676
  switch(_state.label){
5660
5677
  case 0:
@@ -5664,12 +5681,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5664
5681
  ];
5665
5682
  }
5666
5683
  this.preloadPoolLoopRunning = true;
5684
+ epoch = this.adBreakEpoch;
5667
5685
  if (this.config.debugAdTiming) {
5668
5686
  console.log("[PRELOAD-POOL] \uD83D\uDD04 Starting continuous preload loop");
5669
5687
  }
5670
5688
  _state.label = 1;
5671
5689
  case 1:
5672
- if (!this.preloadPoolActive) return [
5690
+ if (!(this.preloadPoolActive && epoch === this.adBreakEpoch)) return [
5673
5691
  3,
5674
5692
  10
5675
5693
  ];
@@ -5714,20 +5732,20 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5714
5732
  3,
5715
5733
  8
5716
5734
  ];
5717
- if (!this.preloadPoolActive || this.isGamInCooldown()) {
5735
+ if (!this.preloadPoolActive || epoch !== this.adBreakEpoch || this.isGamInCooldown()) {
5718
5736
  return [
5719
5737
  3,
5720
5738
  8
5721
5739
  ];
5722
5740
  }
5723
- if (this.inAdBreak) {
5724
- remaining = this.getRemainingAdMs();
5725
- if (remaining <= 0) {
5726
- return [
5727
- 3,
5728
- 8
5729
- ];
5741
+ if (this.inAdBreak && !this.hasTimeToStartAnotherAd()) {
5742
+ if (this.config.debugAdTiming) {
5743
+ console.log("[PRELOAD-POOL] Not enough ad break time left, stopping preload");
5730
5744
  }
5745
+ return [
5746
+ 3,
5747
+ 8
5748
+ ];
5731
5749
  }
5732
5750
  newUrls = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);
5733
5751
  newUrl = newUrls[0];
@@ -6147,7 +6165,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6147
6165
  key: "continuousFetchLoop",
6148
6166
  value: function continuousFetchLoop(baseVastUrl) {
6149
6167
  return _async_to_generator(function() {
6150
- var _this, _loop, _ret;
6168
+ var _this, _loop, epoch, _ret;
6151
6169
  return _ts_generator(this, function(_state) {
6152
6170
  switch(_state.label){
6153
6171
  case 0:
@@ -6157,9 +6175,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6157
6175
  switch(_state.label){
6158
6176
  case 0:
6159
6177
  remaining = _this.getRemainingAdMs();
6160
- if (remaining <= 0) {
6178
+ if (remaining <= _this.getMinRemainingMsToStartAd()) {
6161
6179
  if (_this.config.debugAdTiming) {
6162
- console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F Ad break time expired, stopping URL generation");
6180
+ console.log("[CONTINUOUS-FETCH] ⏹️ Not enough ad break time left (".concat(remaining, "ms), stopping URL generation"));
6163
6181
  }
6164
6182
  return [
6165
6183
  2,
@@ -6257,9 +6275,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6257
6275
  }
6258
6276
  });
6259
6277
  };
6278
+ epoch = this.adBreakEpoch;
6260
6279
  _state.label = 1;
6261
6280
  case 1:
6262
- if (!(this.continuousFetchingActive && this.inAdBreak)) return [
6281
+ if (!(this.continuousFetchingActive && this.inAdBreak && epoch === this.adBreakEpoch)) return [
6263
6282
  3,
6264
6283
  3
6265
6284
  ];
@@ -6308,10 +6327,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6308
6327
  key: "tryNextAvailableAdWithRateLimit",
6309
6328
  value: function tryNextAvailableAdWithRateLimit() {
6310
6329
  return _async_to_generator(function() {
6311
- var backoffMultiplier, backoffDelay, effectiveMinInterval, timeSinceLastRequest, waitTime;
6330
+ var epoch, backoffMultiplier, backoffDelay, effectiveMinInterval, timeSinceLastRequest, waitTime;
6312
6331
  return _ts_generator(this, function(_state) {
6313
6332
  switch(_state.label){
6314
6333
  case 0:
6334
+ if (!this.inAdBreak) {
6335
+ return [
6336
+ 2
6337
+ ];
6338
+ }
6339
+ epoch = this.adBreakEpoch;
6315
6340
  if (this.consecutiveFailures >= this.maxConsecutiveFailures) {
6316
6341
  if (this.config.debugAdTiming) {
6317
6342
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Too many consecutive failures (".concat(this.consecutiveFailures, "), ending ad break gracefully"));
@@ -6343,6 +6368,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6343
6368
  _state.sent();
6344
6369
  _state.label = 2;
6345
6370
  case 2:
6371
+ if (!this.inAdBreak || epoch !== this.adBreakEpoch) {
6372
+ return [
6373
+ 2
6374
+ ];
6375
+ }
6346
6376
  return [
6347
6377
  2,
6348
6378
  this.tryNextAvailableAd(0)
@@ -6361,10 +6391,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6361
6391
  return _ts_generator(this, function(_state) {
6362
6392
  switch(_state.label){
6363
6393
  case 0:
6394
+ if (!this.inAdBreak) {
6395
+ return [
6396
+ 2
6397
+ ];
6398
+ }
6364
6399
  remaining = this.getRemainingAdMs();
6365
- if (remaining <= 500) {
6400
+ if (!this.hasTimeToStartAnotherAd()) {
6366
6401
  if (this.config.debugAdTiming) {
6367
- console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F No time remaining, ending ad break");
6402
+ console.log("[CONTINUOUS-FETCH] ⏹️ Not enough time remaining (".concat(remaining, "ms) to start another ad, ending ad break"));
6368
6403
  }
6369
6404
  this.handleAdPodComplete();
6370
6405
  return [
@@ -6636,12 +6671,27 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6636
6671
  10
6637
6672
  ];
6638
6673
  }
6674
+ if (!this.hasTimeToStartAnotherAd()) {
6675
+ if (this.config.debugAdTiming) {
6676
+ console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F Not enough time remaining during placeholder wait, ending ad break");
6677
+ }
6678
+ return [
6679
+ 3,
6680
+ 10
6681
+ ];
6682
+ }
6639
6683
  _state.label = 3;
6640
6684
  case 3:
6641
6685
  if (!(this.adRequestQueue.length > 0)) return [
6642
6686
  3,
6643
6687
  9
6644
6688
  ];
6689
+ if (!this.hasTimeToStartAnotherAd()) {
6690
+ return [
6691
+ 3,
6692
+ 9
6693
+ ];
6694
+ }
6645
6695
  nextAdUrl = this.adRequestQueue.shift();
6646
6696
  if (!nextAdUrl) {
6647
6697
  return [
@@ -6924,21 +6974,23 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6924
6974
  if (!this.inAdBreak) return;
6925
6975
  this.adStopTimerId = void 0;
6926
6976
  var adPlaying = this.adPlayer.isAdPlaying();
6927
- var pendingAds = this.adPodQueue.length > 0;
6928
6977
  var checkIntervalMs = Math.max(250, Math.floor((_this_config_adBreakCheckIntervalMs = this.config.adBreakCheckIntervalMs) !== null && _this_config_adBreakCheckIntervalMs !== void 0 ? _this_config_adBreakCheckIntervalMs : 1e3));
6929
6978
  var maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;
6930
- var maxExtensionMs = typeof maxExtensionMsConfig === "number" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 6e4;
6979
+ var maxExtensionMs = typeof maxExtensionMsConfig === "number" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 0;
6931
6980
  var elapsedSinceStartMs = 0;
6932
6981
  if (this.currentAdBreakStartWallClockMs != null) {
6933
6982
  elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;
6934
6983
  }
6935
6984
  var expectedDurationMs = (_this_expectedAdBreakDurationMs = this.expectedAdBreakDurationMs) !== null && _this_expectedAdBreakDurationMs !== void 0 ? _this_expectedAdBreakDurationMs : 0;
6936
6985
  var overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);
6937
- var shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;
6986
+ var shouldExtendAdBreak = adPlaying && overrunMs < maxExtensionMs;
6938
6987
  if (shouldExtendAdBreak) {
6939
6988
  this.scheduleAdStopCountdown(checkIntervalMs);
6940
6989
  return;
6941
6990
  }
6991
+ if (this.config.debugAdTiming) {
6992
+ console.log("[StormcloudVideoPlayer] ⏱️ Ad break boundary reached (overrun=".concat(overrunMs, "ms) - hard-stopping ads and resuming stream"));
6993
+ }
6942
6994
  if (adPlaying) {
6943
6995
  this.adPlayer.stop().catch(function() {});
6944
6996
  }
@@ -7373,6 +7425,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7373
7425
  if (this.config.debugAdTiming) {
7374
7426
  console.log("[StormcloudVideoPlayer] \uD83C\uDFC1 Ad pod complete - cleaning up");
7375
7427
  }
7428
+ this.adBreakEpoch++;
7376
7429
  this.clearAdRequestWatchdog();
7377
7430
  this.clearAdFailsafeTimer();
7378
7431
  this.activeAdRequestToken = null;
@@ -7443,11 +7496,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7443
7496
  this.handleAdPodComplete();
7444
7497
  return;
7445
7498
  }
7446
- if (remaining > 500) {
7499
+ if (this.hasTimeToStartAnotherAd()) {
7447
7500
  this.tryNextAvailableAdWithRateLimit();
7448
7501
  } else {
7449
7502
  if (this.config.debugAdTiming) {
7450
- console.log("[AD-ERROR] Ad failed and no time remaining. Failed URLs:", this.failedVastUrls.size);
7503
+ console.log("[AD-ERROR] Ad failed and not enough time remaining for another ad. Failed URLs:", this.failedVastUrls.size);
7451
7504
  }
7452
7505
  this.handleAdPodComplete();
7453
7506
  }
@@ -7582,6 +7635,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7582
7635
  return Math.max(0, this.expectedAdBreakDurationMs - elapsed);
7583
7636
  }
7584
7637
  },
7638
+ {
7639
+ key: "getMinRemainingMsToStartAd",
7640
+ value: function getMinRemainingMsToStartAd() {
7641
+ var configured = this.config.minRemainingMsToStartAd;
7642
+ if (typeof configured === "number" && configured >= 0) {
7643
+ return configured;
7644
+ }
7645
+ return this.defaultMinRemainingMsToStartAd;
7646
+ }
7647
+ },
7648
+ {
7649
+ key: "hasTimeToStartAnotherAd",
7650
+ value: function hasTimeToStartAnotherAd() {
7651
+ return this.getRemainingAdMs() > this.getMinRemainingMsToStartAd();
7652
+ }
7653
+ },
7585
7654
  {
7586
7655
  key: "findBreakForTime",
7587
7656
  value: function findBreakForTime(nowMs) {