stormcloud-video-player 0.5.4 → 0.5.5

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
@@ -2229,10 +2229,10 @@ function createHlsAdPlayer(contentVideo, options) {
2229
2229
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2230
2230
  if (contentVideo.paused) {
2231
2231
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback");
2232
- contentVideo.play().catch(function() {});
2233
2232
  } else {
2234
2233
  console.log("[HlsAdPlayer] Content video already playing in live mode");
2235
2234
  }
2235
+ contentVideo.play().catch(function() {});
2236
2236
  }
2237
2237
  emit("content_resume");
2238
2238
  }
@@ -2505,8 +2505,8 @@ function createHlsAdPlayer(contentVideo, options) {
2505
2505
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2506
2506
  if (contentVideo.paused) {
2507
2507
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback on stop");
2508
- contentVideo.play().catch(function() {});
2509
2508
  }
2509
+ contentVideo.play().catch(function() {});
2510
2510
  }
2511
2511
  if (adHls) {
2512
2512
  adHls.destroy();
@@ -2515,6 +2515,8 @@ function createHlsAdPlayer(contentVideo, options) {
2515
2515
  if (adVideoElement) {
2516
2516
  adVideoElement.pause();
2517
2517
  adVideoElement.src = "";
2518
+ adVideoElement.remove();
2519
+ adVideoElement = void 0;
2518
2520
  }
2519
2521
  currentAd = void 0;
2520
2522
  return [
@@ -3165,10 +3167,10 @@ function createPrebidController(contentVideo, options) {
3165
3167
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
3166
3168
  if (contentVideo.paused) {
3167
3169
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback"));
3168
- contentVideo.play().catch(function() {});
3169
3170
  } else {
3170
3171
  console.log("".concat(LOG, " Content video already playing in live mode"));
3171
3172
  }
3173
+ contentVideo.play().catch(function() {});
3172
3174
  }
3173
3175
  emit("content_resume");
3174
3176
  }
@@ -3534,8 +3536,8 @@ function createPrebidController(contentVideo, options) {
3534
3536
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
3535
3537
  if (contentVideo.paused) {
3536
3538
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback on stop"));
3537
- contentVideo.play().catch(function() {});
3538
3539
  }
3540
+ contentVideo.play().catch(function() {});
3539
3541
  }
3540
3542
  if (adHls) {
3541
3543
  adHls.destroy();
@@ -3544,6 +3546,8 @@ function createPrebidController(contentVideo, options) {
3544
3546
  if (adVideoElement) {
3545
3547
  adVideoElement.pause();
3546
3548
  adVideoElement.src = "";
3549
+ adVideoElement.remove();
3550
+ adVideoElement = void 0;
3547
3551
  }
3548
3552
  currentAd = void 0;
3549
3553
  return [
@@ -4312,6 +4316,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4312
4316
  this.minAdRequestIntervalMs = 2500;
4313
4317
  this.backoffBaseMs = 1e3;
4314
4318
  this.maxBackoffMs = 15e3;
4319
+ this.continuousFetchWallClockBufferMs = 3e4;
4320
+ this.continuousFetchMaxIterations = 500;
4321
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
4315
4322
  this.preloadPool = [];
4316
4323
  this.maxPreloadPoolSize = 3;
4317
4324
  this.preloadPoolActive = false;
@@ -4371,6 +4378,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4371
4378
  }
4372
4379
  }
4373
4380
  },
4381
+ {
4382
+ key: "getAdPlayerTypeLabel",
4383
+ value: function getAdPlayerTypeLabel() {
4384
+ var t = this.config.adPlayerType;
4385
+ if (t === "prebid") return "Prebid";
4386
+ if (t === "hls") return "HLS";
4387
+ return "IMA";
4388
+ }
4389
+ },
4374
4390
  {
4375
4391
  key: "load",
4376
4392
  value: function load() {
@@ -4860,6 +4876,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4860
4876
  }
4861
4877
  });
4862
4878
  this.ima.on("content_resume", function() {
4879
+ console.log("[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s", _this.inAdBreak, _this.getRemainingAdMs());
4863
4880
  if (!_this.video.muted) {
4864
4881
  _this.video.muted = true;
4865
4882
  _this.video.volume = 0;
@@ -4890,15 +4907,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4890
4907
  }
4891
4908
  },
4892
4909
  {
4893
- key: "recreateImaController",
4894
- value: function recreateImaController() {
4910
+ key: "recreateAdController",
4911
+ value: function recreateAdController() {
4912
+ var label = this.getAdPlayerTypeLabel();
4895
4913
  if (this.config.debugAdTiming) {
4896
- console.log("[StormcloudVideoPlayer] Recreating ImaController for new ad");
4914
+ console.log("[StormcloudVideoPlayer] Recreating ad controller (".concat(label, ") for new ad"));
4897
4915
  }
4898
4916
  var shouldShowPlaceholder = this.inAdBreak && this.showAds;
4899
4917
  if (shouldShowPlaceholder && this.ima) {
4900
4918
  if (this.config.debugAdTiming) {
4901
- console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ImaController");
4919
+ console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ".concat(label, " controller"));
4902
4920
  }
4903
4921
  this.showPlaceholderLayer();
4904
4922
  this.ima.showPlaceholder();
@@ -4911,7 +4929,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4911
4929
  this.video.volume = 0;
4912
4930
  } catch (error) {
4913
4931
  if (this.config.debugAdTiming) {
4914
- console.warn("[StormcloudVideoPlayer] Error destroying old ImaController:", error);
4932
+ console.warn("[StormcloudVideoPlayer] Error destroying old ".concat(label, " controller:"), error);
4915
4933
  }
4916
4934
  }
4917
4935
  }
@@ -4991,7 +5009,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4991
5009
  });
4992
5010
  }
4993
5011
  if (this.config.debugAdTiming) {
4994
- console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and IMA)");
5012
+ console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and ".concat(this.getAdPlayerTypeLabel(), ")"));
4995
5013
  }
4996
5014
  }
4997
5015
  },
@@ -5703,6 +5721,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5703
5721
  return this.config.adPlayerType === "prebid";
5704
5722
  }
5705
5723
  },
5724
+ {
5725
+ key: "isLgStbDevice",
5726
+ value: function isLgStbDevice() {
5727
+ if (typeof navigator === "undefined" || !navigator.userAgent) return false;
5728
+ var ua = navigator.userAgent;
5729
+ return /Web0S|webOS|LG Browser|LGSTB/i.test(ua);
5730
+ }
5731
+ },
5706
5732
  {
5707
5733
  key: "getCurrentAdIndex",
5708
5734
  value: function getCurrentAdIndex() {
@@ -6517,15 +6543,34 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6517
6543
  key: "continuousFetchLoop",
6518
6544
  value: function continuousFetchLoop(baseVastUrl) {
6519
6545
  return _async_to_generator(function() {
6520
- var _this, _loop, _ret;
6546
+ var loopIterations, _this, _loop, _ret;
6521
6547
  return _ts_generator(this, function(_state) {
6522
6548
  switch(_state.label){
6523
6549
  case 0:
6550
+ loopIterations = 0;
6551
+ _state.label = 1;
6552
+ case 1:
6553
+ _state.trys.push([
6554
+ 1,
6555
+ ,
6556
+ 5,
6557
+ 6
6558
+ ]);
6524
6559
  _loop = function() {
6525
- var remaining, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6560
+ var remaining, elapsedMs, maxLoopMs, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6526
6561
  return _ts_generator(this, function(_state) {
6527
6562
  switch(_state.label){
6528
6563
  case 0:
6564
+ loopIterations++;
6565
+ if (loopIterations > _this.continuousFetchMaxIterations) {
6566
+ if (_this.config.debugAdTiming) {
6567
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Max iterations reached (".concat(_this.continuousFetchMaxIterations, "), stopping URL generation"));
6568
+ }
6569
+ return [
6570
+ 2,
6571
+ "break"
6572
+ ];
6573
+ }
6529
6574
  remaining = _this.getRemainingAdMs();
6530
6575
  if (remaining <= 0) {
6531
6576
  if (_this.config.debugAdTiming) {
@@ -6536,6 +6581,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6536
6581
  "break"
6537
6582
  ];
6538
6583
  }
6584
+ if (_this.currentAdBreakStartWallClockMs != null && _this.expectedAdBreakDurationMs != null) {
6585
+ elapsedMs = Date.now() - _this.currentAdBreakStartWallClockMs;
6586
+ maxLoopMs = _this.expectedAdBreakDurationMs + _this.continuousFetchWallClockBufferMs;
6587
+ if (elapsedMs >= maxLoopMs) {
6588
+ if (_this.config.debugAdTiming) {
6589
+ console.log("[CONTINUOUS-FETCH] ⏹️ Wall-clock limit reached (".concat(elapsedMs, "ms >= ").concat(maxLoopMs, "ms), stopping URL generation"));
6590
+ }
6591
+ return [
6592
+ 2,
6593
+ "break"
6594
+ ];
6595
+ }
6596
+ }
6539
6597
  if (_this.consecutiveFailures >= _this.maxConsecutiveFailures) {
6540
6598
  if (_this.config.debugAdTiming) {
6541
6599
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Too many consecutive failures (".concat(_this.consecutiveFailures, "), stopping URL generation"));
@@ -6557,46 +6615,63 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6557
6615
  maxQueueSize = 5;
6558
6616
  if (!(_this.adRequestQueue.length >= maxQueueSize)) return [
6559
6617
  3,
6560
- 2
6618
+ 4
6619
+ ];
6620
+ if (!(_this.isPrebidMode() && _this.isLgStbDevice())) return [
6621
+ 3,
6622
+ 1
6561
6623
  ];
6624
+ _this.adRequestQueue.shift();
6625
+ _this.adRequestQueue.push("");
6626
+ _this.totalAdsInBreak++;
6627
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6562
6628
  if (_this.config.debugAdTiming) {
6563
- console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(_this.adRequestQueue.length, "), waiting..."));
6629
+ console.log("[CONTINUOUS-FETCH] Prebid slot rotated (queue full, dropped oldest); queue: ".concat(_this.adRequestQueue.length));
6564
6630
  }
6565
6631
  return [
6566
- 4,
6567
- new Promise(function(resolve) {
6568
- return setTimeout(resolve, 1e3);
6569
- })
6632
+ 3,
6633
+ 3
6570
6634
  ];
6571
6635
  case 1:
6636
+ return [
6637
+ 4,
6638
+ _this.waitForQueueWithBackoff()
6639
+ ];
6640
+ case 2:
6572
6641
  _state.sent();
6573
6642
  return [
6574
6643
  2,
6575
6644
  "continue"
6576
6645
  ];
6577
- case 2:
6646
+ case 3:
6647
+ return [
6648
+ 3,
6649
+ 8
6650
+ ];
6651
+ case 4:
6578
6652
  if (!_this.isPrebidMode()) return [
6579
6653
  3,
6580
- 3
6654
+ 5
6581
6655
  ];
6582
6656
  _this.adRequestQueue.push("");
6583
6657
  _this.totalAdsInBreak++;
6658
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6584
6659
  if (_this.config.debugAdTiming) {
6585
6660
  console.log("[CONTINUOUS-FETCH] Prebid auction slot queued (queue: ".concat(_this.adRequestQueue.length, ")"));
6586
6661
  }
6587
6662
  return [
6588
6663
  3,
6589
- 6
6664
+ 8
6590
6665
  ];
6591
- case 3:
6666
+ case 5:
6592
6667
  if (!baseVastUrl) return [
6593
6668
  3,
6594
- 6
6669
+ 8
6595
6670
  ];
6596
6671
  newAdUrl = _this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];
6597
6672
  if (!(!newAdUrl || _this.failedVastUrls.has(newAdUrl) || _this.isUrlInCooldown(newAdUrl))) return [
6598
6673
  3,
6599
- 5
6674
+ 7
6600
6675
  ];
6601
6676
  return [
6602
6677
  4,
@@ -6604,13 +6679,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6604
6679
  return setTimeout(resolve, 500);
6605
6680
  })
6606
6681
  ];
6607
- case 4:
6682
+ case 6:
6608
6683
  _state.sent();
6609
6684
  return [
6610
6685
  2,
6611
6686
  "continue"
6612
6687
  ];
6613
- case 5:
6688
+ case 7:
6614
6689
  if (_this.config.debugAdTiming) {
6615
6690
  queuedUrlsPreview = _to_consumable_array(_this.adRequestQueue).concat([
6616
6691
  newAdUrl
@@ -6621,8 +6696,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6621
6696
  }
6622
6697
  _this.adRequestQueue.push(newAdUrl);
6623
6698
  _this.totalAdsInBreak++;
6624
- _state.label = 6;
6625
- case 6:
6699
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6700
+ _state.label = 8;
6701
+ case 8:
6626
6702
  generationDelay = _this.consecutiveFailures > 0 ? Math.min(1e3 * Math.pow(2, _this.consecutiveFailures), 5e3) : 500;
6627
6703
  return [
6628
6704
  4,
@@ -6630,7 +6706,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6630
6706
  return setTimeout(resolve, generationDelay);
6631
6707
  })
6632
6708
  ];
6633
- case 7:
6709
+ case 9:
6634
6710
  _state.sent();
6635
6711
  return [
6636
6712
  2
@@ -6638,33 +6714,41 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6638
6714
  }
6639
6715
  });
6640
6716
  };
6641
- _state.label = 1;
6642
- case 1:
6717
+ _state.label = 2;
6718
+ case 2:
6643
6719
  if (!(this.continuousFetchingActive && this.inAdBreak)) return [
6644
6720
  3,
6645
- 3
6721
+ 4
6646
6722
  ];
6647
6723
  _this = this;
6648
6724
  return [
6649
6725
  5,
6650
6726
  _ts_values(_loop())
6651
6727
  ];
6652
- case 2:
6728
+ case 3:
6653
6729
  _ret = _state.sent();
6654
6730
  if (_ret === "break") return [
6655
6731
  3,
6656
- 3
6732
+ 4
6657
6733
  ];
6658
6734
  return [
6659
6735
  3,
6660
- 1
6736
+ 2
6661
6737
  ];
6662
- case 3:
6738
+ case 4:
6739
+ return [
6740
+ 3,
6741
+ 6
6742
+ ];
6743
+ case 5:
6663
6744
  this.continuousFetchLoopRunning = false;
6745
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
6746
+ return [
6747
+ 7
6748
+ ];
6749
+ case 6:
6664
6750
  if (this.config.debugAdTiming) {
6665
- console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 URL generation loop ended (queued: ".concat(this.adRequestQueue.length, ")"), this.adRequestQueue.length > 0 ? {
6666
- queuedUrls: _to_consumable_array(this.adRequestQueue)
6667
- } : {});
6751
+ this.logQueueState("URL generation loop ended");
6668
6752
  }
6669
6753
  return [
6670
6754
  2
@@ -6674,6 +6758,51 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6674
6758
  }).call(this);
6675
6759
  }
6676
6760
  },
6761
+ {
6762
+ key: "waitForQueueWithBackoff",
6763
+ value: function waitForQueueWithBackoff() {
6764
+ return _async_to_generator(function() {
6765
+ var delayMs, shouldLog;
6766
+ return _ts_generator(this, function(_state) {
6767
+ switch(_state.label){
6768
+ case 0:
6769
+ this.continuousFetchQueueFullConsecutiveWaits++;
6770
+ delayMs = Math.min(1e3 * Math.pow(2, this.continuousFetchQueueFullConsecutiveWaits - 1), 5e3);
6771
+ shouldLog = this.config.debugAdTiming && (this.continuousFetchQueueFullConsecutiveWaits <= 2 || this.continuousFetchQueueFullConsecutiveWaits % 4 === 0);
6772
+ if (shouldLog) {
6773
+ console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(this.adRequestQueue.length, "), waiting ").concat(delayMs, "ms (wait #").concat(this.continuousFetchQueueFullConsecutiveWaits, ")"));
6774
+ }
6775
+ return [
6776
+ 4,
6777
+ new Promise(function(resolve) {
6778
+ return setTimeout(resolve, delayMs);
6779
+ })
6780
+ ];
6781
+ case 1:
6782
+ _state.sent();
6783
+ return [
6784
+ 2
6785
+ ];
6786
+ }
6787
+ });
6788
+ }).call(this);
6789
+ }
6790
+ },
6791
+ {
6792
+ key: "logQueueState",
6793
+ value: function logQueueState(reason) {
6794
+ if (!this.config.debugAdTiming) return;
6795
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 ".concat(reason), {
6796
+ queueLength: this.adRequestQueue.length,
6797
+ totalAdsInBreak: this.totalAdsInBreak,
6798
+ totalAdRequestsInBreak: this.totalAdRequestsInBreak,
6799
+ consecutiveFailures: this.consecutiveFailures,
6800
+ continuousFetchingActive: this.continuousFetchingActive,
6801
+ continuousFetchLoopRunning: this.continuousFetchLoopRunning,
6802
+ inAdBreak: this.inAdBreak
6803
+ });
6804
+ }
6805
+ },
6677
6806
  {
6678
6807
  key: "stopContinuousFetching",
6679
6808
  value: function stopContinuousFetching() {
@@ -6844,8 +6973,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6844
6973
  4
6845
6974
  ];
6846
6975
  }
6976
+ console.log("[StormcloudVideoPlayer] Requesting next ad (%s), queue remaining=%s", nextAdUrl === "" ? "Prebid" : "VAST", this.adRequestQueue.length);
6847
6977
  if (this.config.debugAdTiming) {
6848
- console.log("[CONTINUOUS-FETCH] \uD83C\uDFAC Requesting next ad via IMA SDK (".concat(this.currentAdIndex + 1, "/").concat(this.totalAdsInBreak, ", ").concat(this.adRequestQueue.length, " remaining in queue)"));
6978
+ console.log("[CONTINUOUS-FETCH] \uD83C\uDFAC Requesting next ad via ".concat(this.getAdPlayerTypeLabel(), " (").concat(this.currentAdIndex + 1, "/").concat(this.totalAdsInBreak, ", ").concat(this.adRequestQueue.length, " remaining in queue)"));
6849
6979
  }
6850
6980
  currentMuted1 = this.video.muted;
6851
6981
  currentVolume1 = this.video.volume;
@@ -7025,7 +7155,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7025
7155
  ];
7026
7156
  }
7027
7157
  if (this.config.debugAdTiming) {
7028
- console.log("[CONTINUOUS-FETCH] \u2705 Ad URL available, requesting via IMA SDK");
7158
+ console.log("[CONTINUOUS-FETCH] Ad URL available, requesting via ".concat(this.getAdPlayerTypeLabel()));
7029
7159
  }
7030
7160
  this.isShowingPlaceholder = false;
7031
7161
  this.ima.hidePlaceholder();
@@ -7367,7 +7497,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7367
7497
  }
7368
7498
  throw new Error("Too many consecutive failures");
7369
7499
  }
7370
- this.recreateImaController();
7500
+ this.recreateAdController();
7371
7501
  requestToken = ++this.adRequestTokenCounter;
7372
7502
  this.activeAdRequestToken = requestToken;
7373
7503
  this.startAdRequestWatchdog(requestToken);
@@ -7612,6 +7742,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7612
7742
  this.showAds = false;
7613
7743
  this.currentAdIndex = 0;
7614
7744
  this.totalAdsInBreak = 0;
7745
+ this.totalAdRequestsInBreak = 0;
7615
7746
  this.consecutiveFailures = 0;
7616
7747
  this.ima.stop().catch(function() {});
7617
7748
  var restoredMuted = this.ima.getOriginalMutedState();
@@ -7623,17 +7754,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7623
7754
  this.video.volume = restoredVolume;
7624
7755
  }
7625
7756
  if (this.shouldContinueLiveStreamDuringAds()) {
7626
- if (this.video.paused) {
7627
- var _this_video_play;
7628
- if (this.config.debugAdTiming) {
7757
+ var _this_video_play;
7758
+ if (this.config.debugAdTiming) {
7759
+ if (this.video.paused) {
7629
7760
  console.log("[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback");
7630
- }
7631
- (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
7632
- } else {
7633
- if (this.config.debugAdTiming) {
7761
+ } else {
7634
7762
  console.log("[StormcloudVideoPlayer] Content video already playing in live mode after ads");
7635
7763
  }
7636
7764
  }
7765
+ (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
7637
7766
  } else if (this.video.paused) {
7638
7767
  var _this_video_play1;
7639
7768
  (_this_video_play1 = this.video.play()) === null || _this_video_play1 === void 0 ? void 0 : _this_video_play1.catch(function() {});