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.
@@ -2094,10 +2094,10 @@ function createHlsAdPlayer(contentVideo, options) {
2094
2094
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2095
2095
  if (contentVideo.paused) {
2096
2096
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback");
2097
- contentVideo.play().catch(function() {});
2098
2097
  } else {
2099
2098
  console.log("[HlsAdPlayer] Content video already playing in live mode");
2100
2099
  }
2100
+ contentVideo.play().catch(function() {});
2101
2101
  }
2102
2102
  emit("content_resume");
2103
2103
  }
@@ -2370,8 +2370,8 @@ function createHlsAdPlayer(contentVideo, options) {
2370
2370
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2371
2371
  if (contentVideo.paused) {
2372
2372
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback on stop");
2373
- contentVideo.play().catch(function() {});
2374
2373
  }
2374
+ contentVideo.play().catch(function() {});
2375
2375
  }
2376
2376
  if (adHls) {
2377
2377
  adHls.destroy();
@@ -2380,6 +2380,8 @@ function createHlsAdPlayer(contentVideo, options) {
2380
2380
  if (adVideoElement) {
2381
2381
  adVideoElement.pause();
2382
2382
  adVideoElement.src = "";
2383
+ adVideoElement.remove();
2384
+ adVideoElement = void 0;
2383
2385
  }
2384
2386
  currentAd = void 0;
2385
2387
  return [
@@ -3030,10 +3032,10 @@ function createPrebidController(contentVideo, options) {
3030
3032
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
3031
3033
  if (contentVideo.paused) {
3032
3034
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback"));
3033
- contentVideo.play().catch(function() {});
3034
3035
  } else {
3035
3036
  console.log("".concat(LOG, " Content video already playing in live mode"));
3036
3037
  }
3038
+ contentVideo.play().catch(function() {});
3037
3039
  }
3038
3040
  emit("content_resume");
3039
3041
  }
@@ -3399,8 +3401,8 @@ function createPrebidController(contentVideo, options) {
3399
3401
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
3400
3402
  if (contentVideo.paused) {
3401
3403
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback on stop"));
3402
- contentVideo.play().catch(function() {});
3403
3404
  }
3405
+ contentVideo.play().catch(function() {});
3404
3406
  }
3405
3407
  if (adHls) {
3406
3408
  adHls.destroy();
@@ -3409,6 +3411,8 @@ function createPrebidController(contentVideo, options) {
3409
3411
  if (adVideoElement) {
3410
3412
  adVideoElement.pause();
3411
3413
  adVideoElement.src = "";
3414
+ adVideoElement.remove();
3415
+ adVideoElement = void 0;
3412
3416
  }
3413
3417
  currentAd = void 0;
3414
3418
  return [
@@ -4177,6 +4181,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4177
4181
  this.minAdRequestIntervalMs = 2500;
4178
4182
  this.backoffBaseMs = 1e3;
4179
4183
  this.maxBackoffMs = 15e3;
4184
+ this.continuousFetchWallClockBufferMs = 3e4;
4185
+ this.continuousFetchMaxIterations = 500;
4186
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
4180
4187
  this.preloadPool = [];
4181
4188
  this.maxPreloadPoolSize = 3;
4182
4189
  this.preloadPoolActive = false;
@@ -4236,6 +4243,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4236
4243
  }
4237
4244
  }
4238
4245
  },
4246
+ {
4247
+ key: "getAdPlayerTypeLabel",
4248
+ value: function getAdPlayerTypeLabel() {
4249
+ var t = this.config.adPlayerType;
4250
+ if (t === "prebid") return "Prebid";
4251
+ if (t === "hls") return "HLS";
4252
+ return "IMA";
4253
+ }
4254
+ },
4239
4255
  {
4240
4256
  key: "load",
4241
4257
  value: function load() {
@@ -4725,6 +4741,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4725
4741
  }
4726
4742
  });
4727
4743
  this.ima.on("content_resume", function() {
4744
+ console.log("[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s", _this.inAdBreak, _this.getRemainingAdMs());
4728
4745
  if (!_this.video.muted) {
4729
4746
  _this.video.muted = true;
4730
4747
  _this.video.volume = 0;
@@ -4755,15 +4772,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4755
4772
  }
4756
4773
  },
4757
4774
  {
4758
- key: "recreateImaController",
4759
- value: function recreateImaController() {
4775
+ key: "recreateAdController",
4776
+ value: function recreateAdController() {
4777
+ var label = this.getAdPlayerTypeLabel();
4760
4778
  if (this.config.debugAdTiming) {
4761
- console.log("[StormcloudVideoPlayer] Recreating ImaController for new ad");
4779
+ console.log("[StormcloudVideoPlayer] Recreating ad controller (".concat(label, ") for new ad"));
4762
4780
  }
4763
4781
  var shouldShowPlaceholder = this.inAdBreak && this.showAds;
4764
4782
  if (shouldShowPlaceholder && this.ima) {
4765
4783
  if (this.config.debugAdTiming) {
4766
- console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ImaController");
4784
+ console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ".concat(label, " controller"));
4767
4785
  }
4768
4786
  this.showPlaceholderLayer();
4769
4787
  this.ima.showPlaceholder();
@@ -4776,7 +4794,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4776
4794
  this.video.volume = 0;
4777
4795
  } catch (error) {
4778
4796
  if (this.config.debugAdTiming) {
4779
- console.warn("[StormcloudVideoPlayer] Error destroying old ImaController:", error);
4797
+ console.warn("[StormcloudVideoPlayer] Error destroying old ".concat(label, " controller:"), error);
4780
4798
  }
4781
4799
  }
4782
4800
  }
@@ -4856,7 +4874,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4856
4874
  });
4857
4875
  }
4858
4876
  if (this.config.debugAdTiming) {
4859
- console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and IMA)");
4877
+ console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and ".concat(this.getAdPlayerTypeLabel(), ")"));
4860
4878
  }
4861
4879
  }
4862
4880
  },
@@ -5568,6 +5586,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5568
5586
  return this.config.adPlayerType === "prebid";
5569
5587
  }
5570
5588
  },
5589
+ {
5590
+ key: "isLgStbDevice",
5591
+ value: function isLgStbDevice() {
5592
+ if (typeof navigator === "undefined" || !navigator.userAgent) return false;
5593
+ var ua = navigator.userAgent;
5594
+ return /Web0S|webOS|LG Browser|LGSTB/i.test(ua);
5595
+ }
5596
+ },
5571
5597
  {
5572
5598
  key: "getCurrentAdIndex",
5573
5599
  value: function getCurrentAdIndex() {
@@ -6382,15 +6408,34 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6382
6408
  key: "continuousFetchLoop",
6383
6409
  value: function continuousFetchLoop(baseVastUrl) {
6384
6410
  return _async_to_generator(function() {
6385
- var _this, _loop, _ret;
6411
+ var loopIterations, _this, _loop, _ret;
6386
6412
  return _ts_generator(this, function(_state) {
6387
6413
  switch(_state.label){
6388
6414
  case 0:
6415
+ loopIterations = 0;
6416
+ _state.label = 1;
6417
+ case 1:
6418
+ _state.trys.push([
6419
+ 1,
6420
+ ,
6421
+ 5,
6422
+ 6
6423
+ ]);
6389
6424
  _loop = function() {
6390
- var remaining, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6425
+ var remaining, elapsedMs, maxLoopMs, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6391
6426
  return _ts_generator(this, function(_state) {
6392
6427
  switch(_state.label){
6393
6428
  case 0:
6429
+ loopIterations++;
6430
+ if (loopIterations > _this.continuousFetchMaxIterations) {
6431
+ if (_this.config.debugAdTiming) {
6432
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Max iterations reached (".concat(_this.continuousFetchMaxIterations, "), stopping URL generation"));
6433
+ }
6434
+ return [
6435
+ 2,
6436
+ "break"
6437
+ ];
6438
+ }
6394
6439
  remaining = _this.getRemainingAdMs();
6395
6440
  if (remaining <= 0) {
6396
6441
  if (_this.config.debugAdTiming) {
@@ -6401,6 +6446,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6401
6446
  "break"
6402
6447
  ];
6403
6448
  }
6449
+ if (_this.currentAdBreakStartWallClockMs != null && _this.expectedAdBreakDurationMs != null) {
6450
+ elapsedMs = Date.now() - _this.currentAdBreakStartWallClockMs;
6451
+ maxLoopMs = _this.expectedAdBreakDurationMs + _this.continuousFetchWallClockBufferMs;
6452
+ if (elapsedMs >= maxLoopMs) {
6453
+ if (_this.config.debugAdTiming) {
6454
+ console.log("[CONTINUOUS-FETCH] ⏹️ Wall-clock limit reached (".concat(elapsedMs, "ms >= ").concat(maxLoopMs, "ms), stopping URL generation"));
6455
+ }
6456
+ return [
6457
+ 2,
6458
+ "break"
6459
+ ];
6460
+ }
6461
+ }
6404
6462
  if (_this.consecutiveFailures >= _this.maxConsecutiveFailures) {
6405
6463
  if (_this.config.debugAdTiming) {
6406
6464
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Too many consecutive failures (".concat(_this.consecutiveFailures, "), stopping URL generation"));
@@ -6422,46 +6480,63 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6422
6480
  maxQueueSize = 5;
6423
6481
  if (!(_this.adRequestQueue.length >= maxQueueSize)) return [
6424
6482
  3,
6425
- 2
6483
+ 4
6484
+ ];
6485
+ if (!(_this.isPrebidMode() && _this.isLgStbDevice())) return [
6486
+ 3,
6487
+ 1
6426
6488
  ];
6489
+ _this.adRequestQueue.shift();
6490
+ _this.adRequestQueue.push("");
6491
+ _this.totalAdsInBreak++;
6492
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6427
6493
  if (_this.config.debugAdTiming) {
6428
- console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(_this.adRequestQueue.length, "), waiting..."));
6494
+ console.log("[CONTINUOUS-FETCH] Prebid slot rotated (queue full, dropped oldest); queue: ".concat(_this.adRequestQueue.length));
6429
6495
  }
6430
6496
  return [
6431
- 4,
6432
- new Promise(function(resolve) {
6433
- return setTimeout(resolve, 1e3);
6434
- })
6497
+ 3,
6498
+ 3
6435
6499
  ];
6436
6500
  case 1:
6501
+ return [
6502
+ 4,
6503
+ _this.waitForQueueWithBackoff()
6504
+ ];
6505
+ case 2:
6437
6506
  _state.sent();
6438
6507
  return [
6439
6508
  2,
6440
6509
  "continue"
6441
6510
  ];
6442
- case 2:
6511
+ case 3:
6512
+ return [
6513
+ 3,
6514
+ 8
6515
+ ];
6516
+ case 4:
6443
6517
  if (!_this.isPrebidMode()) return [
6444
6518
  3,
6445
- 3
6519
+ 5
6446
6520
  ];
6447
6521
  _this.adRequestQueue.push("");
6448
6522
  _this.totalAdsInBreak++;
6523
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6449
6524
  if (_this.config.debugAdTiming) {
6450
6525
  console.log("[CONTINUOUS-FETCH] Prebid auction slot queued (queue: ".concat(_this.adRequestQueue.length, ")"));
6451
6526
  }
6452
6527
  return [
6453
6528
  3,
6454
- 6
6529
+ 8
6455
6530
  ];
6456
- case 3:
6531
+ case 5:
6457
6532
  if (!baseVastUrl) return [
6458
6533
  3,
6459
- 6
6534
+ 8
6460
6535
  ];
6461
6536
  newAdUrl = _this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];
6462
6537
  if (!(!newAdUrl || _this.failedVastUrls.has(newAdUrl) || _this.isUrlInCooldown(newAdUrl))) return [
6463
6538
  3,
6464
- 5
6539
+ 7
6465
6540
  ];
6466
6541
  return [
6467
6542
  4,
@@ -6469,13 +6544,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6469
6544
  return setTimeout(resolve, 500);
6470
6545
  })
6471
6546
  ];
6472
- case 4:
6547
+ case 6:
6473
6548
  _state.sent();
6474
6549
  return [
6475
6550
  2,
6476
6551
  "continue"
6477
6552
  ];
6478
- case 5:
6553
+ case 7:
6479
6554
  if (_this.config.debugAdTiming) {
6480
6555
  queuedUrlsPreview = _to_consumable_array(_this.adRequestQueue).concat([
6481
6556
  newAdUrl
@@ -6486,8 +6561,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6486
6561
  }
6487
6562
  _this.adRequestQueue.push(newAdUrl);
6488
6563
  _this.totalAdsInBreak++;
6489
- _state.label = 6;
6490
- case 6:
6564
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6565
+ _state.label = 8;
6566
+ case 8:
6491
6567
  generationDelay = _this.consecutiveFailures > 0 ? Math.min(1e3 * Math.pow(2, _this.consecutiveFailures), 5e3) : 500;
6492
6568
  return [
6493
6569
  4,
@@ -6495,7 +6571,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6495
6571
  return setTimeout(resolve, generationDelay);
6496
6572
  })
6497
6573
  ];
6498
- case 7:
6574
+ case 9:
6499
6575
  _state.sent();
6500
6576
  return [
6501
6577
  2
@@ -6503,33 +6579,41 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6503
6579
  }
6504
6580
  });
6505
6581
  };
6506
- _state.label = 1;
6507
- case 1:
6582
+ _state.label = 2;
6583
+ case 2:
6508
6584
  if (!(this.continuousFetchingActive && this.inAdBreak)) return [
6509
6585
  3,
6510
- 3
6586
+ 4
6511
6587
  ];
6512
6588
  _this = this;
6513
6589
  return [
6514
6590
  5,
6515
6591
  _ts_values(_loop())
6516
6592
  ];
6517
- case 2:
6593
+ case 3:
6518
6594
  _ret = _state.sent();
6519
6595
  if (_ret === "break") return [
6520
6596
  3,
6521
- 3
6597
+ 4
6522
6598
  ];
6523
6599
  return [
6524
6600
  3,
6525
- 1
6601
+ 2
6526
6602
  ];
6527
- case 3:
6603
+ case 4:
6604
+ return [
6605
+ 3,
6606
+ 6
6607
+ ];
6608
+ case 5:
6528
6609
  this.continuousFetchLoopRunning = false;
6610
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
6611
+ return [
6612
+ 7
6613
+ ];
6614
+ case 6:
6529
6615
  if (this.config.debugAdTiming) {
6530
- console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 URL generation loop ended (queued: ".concat(this.adRequestQueue.length, ")"), this.adRequestQueue.length > 0 ? {
6531
- queuedUrls: _to_consumable_array(this.adRequestQueue)
6532
- } : {});
6616
+ this.logQueueState("URL generation loop ended");
6533
6617
  }
6534
6618
  return [
6535
6619
  2
@@ -6539,6 +6623,51 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6539
6623
  }).call(this);
6540
6624
  }
6541
6625
  },
6626
+ {
6627
+ key: "waitForQueueWithBackoff",
6628
+ value: function waitForQueueWithBackoff() {
6629
+ return _async_to_generator(function() {
6630
+ var delayMs, shouldLog;
6631
+ return _ts_generator(this, function(_state) {
6632
+ switch(_state.label){
6633
+ case 0:
6634
+ this.continuousFetchQueueFullConsecutiveWaits++;
6635
+ delayMs = Math.min(1e3 * Math.pow(2, this.continuousFetchQueueFullConsecutiveWaits - 1), 5e3);
6636
+ shouldLog = this.config.debugAdTiming && (this.continuousFetchQueueFullConsecutiveWaits <= 2 || this.continuousFetchQueueFullConsecutiveWaits % 4 === 0);
6637
+ if (shouldLog) {
6638
+ console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(this.adRequestQueue.length, "), waiting ").concat(delayMs, "ms (wait #").concat(this.continuousFetchQueueFullConsecutiveWaits, ")"));
6639
+ }
6640
+ return [
6641
+ 4,
6642
+ new Promise(function(resolve) {
6643
+ return setTimeout(resolve, delayMs);
6644
+ })
6645
+ ];
6646
+ case 1:
6647
+ _state.sent();
6648
+ return [
6649
+ 2
6650
+ ];
6651
+ }
6652
+ });
6653
+ }).call(this);
6654
+ }
6655
+ },
6656
+ {
6657
+ key: "logQueueState",
6658
+ value: function logQueueState(reason) {
6659
+ if (!this.config.debugAdTiming) return;
6660
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 ".concat(reason), {
6661
+ queueLength: this.adRequestQueue.length,
6662
+ totalAdsInBreak: this.totalAdsInBreak,
6663
+ totalAdRequestsInBreak: this.totalAdRequestsInBreak,
6664
+ consecutiveFailures: this.consecutiveFailures,
6665
+ continuousFetchingActive: this.continuousFetchingActive,
6666
+ continuousFetchLoopRunning: this.continuousFetchLoopRunning,
6667
+ inAdBreak: this.inAdBreak
6668
+ });
6669
+ }
6670
+ },
6542
6671
  {
6543
6672
  key: "stopContinuousFetching",
6544
6673
  value: function stopContinuousFetching() {
@@ -6709,8 +6838,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6709
6838
  4
6710
6839
  ];
6711
6840
  }
6841
+ console.log("[StormcloudVideoPlayer] Requesting next ad (%s), queue remaining=%s", nextAdUrl === "" ? "Prebid" : "VAST", this.adRequestQueue.length);
6712
6842
  if (this.config.debugAdTiming) {
6713
- 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)"));
6843
+ 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)"));
6714
6844
  }
6715
6845
  currentMuted1 = this.video.muted;
6716
6846
  currentVolume1 = this.video.volume;
@@ -6890,7 +7020,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6890
7020
  ];
6891
7021
  }
6892
7022
  if (this.config.debugAdTiming) {
6893
- console.log("[CONTINUOUS-FETCH] \u2705 Ad URL available, requesting via IMA SDK");
7023
+ console.log("[CONTINUOUS-FETCH] Ad URL available, requesting via ".concat(this.getAdPlayerTypeLabel()));
6894
7024
  }
6895
7025
  this.isShowingPlaceholder = false;
6896
7026
  this.ima.hidePlaceholder();
@@ -7232,7 +7362,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7232
7362
  }
7233
7363
  throw new Error("Too many consecutive failures");
7234
7364
  }
7235
- this.recreateImaController();
7365
+ this.recreateAdController();
7236
7366
  requestToken = ++this.adRequestTokenCounter;
7237
7367
  this.activeAdRequestToken = requestToken;
7238
7368
  this.startAdRequestWatchdog(requestToken);
@@ -7477,6 +7607,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7477
7607
  this.showAds = false;
7478
7608
  this.currentAdIndex = 0;
7479
7609
  this.totalAdsInBreak = 0;
7610
+ this.totalAdRequestsInBreak = 0;
7480
7611
  this.consecutiveFailures = 0;
7481
7612
  this.ima.stop().catch(function() {});
7482
7613
  var restoredMuted = this.ima.getOriginalMutedState();
@@ -7488,17 +7619,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7488
7619
  this.video.volume = restoredVolume;
7489
7620
  }
7490
7621
  if (this.shouldContinueLiveStreamDuringAds()) {
7491
- if (this.video.paused) {
7492
- var _this_video_play;
7493
- if (this.config.debugAdTiming) {
7622
+ var _this_video_play;
7623
+ if (this.config.debugAdTiming) {
7624
+ if (this.video.paused) {
7494
7625
  console.log("[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback");
7495
- }
7496
- (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
7497
- } else {
7498
- if (this.config.debugAdTiming) {
7626
+ } else {
7499
7627
  console.log("[StormcloudVideoPlayer] Content video already playing in live mode after ads");
7500
7628
  }
7501
7629
  }
7630
+ (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
7502
7631
  } else if (this.video.paused) {
7503
7632
  var _this_video_play1;
7504
7633
  (_this_video_play1 = this.video.play()) === null || _this_video_play1 === void 0 ? void 0 : _this_video_play1.catch(function() {});