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.
@@ -2006,10 +2006,10 @@ function createHlsAdPlayer(contentVideo, options) {
2006
2006
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2007
2007
  if (contentVideo.paused) {
2008
2008
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback");
2009
- contentVideo.play().catch(function() {});
2010
2009
  } else {
2011
2010
  console.log("[HlsAdPlayer] Content video already playing in live mode");
2012
2011
  }
2012
+ contentVideo.play().catch(function() {});
2013
2013
  }
2014
2014
  emit("content_resume");
2015
2015
  }
@@ -2282,8 +2282,8 @@ function createHlsAdPlayer(contentVideo, options) {
2282
2282
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2283
2283
  if (contentVideo.paused) {
2284
2284
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback on stop");
2285
- contentVideo.play().catch(function() {});
2286
2285
  }
2286
+ contentVideo.play().catch(function() {});
2287
2287
  }
2288
2288
  if (adHls) {
2289
2289
  adHls.destroy();
@@ -2292,6 +2292,8 @@ function createHlsAdPlayer(contentVideo, options) {
2292
2292
  if (adVideoElement) {
2293
2293
  adVideoElement.pause();
2294
2294
  adVideoElement.src = "";
2295
+ adVideoElement.remove();
2296
+ adVideoElement = void 0;
2295
2297
  }
2296
2298
  currentAd = void 0;
2297
2299
  return [
@@ -2942,10 +2944,10 @@ function createPrebidController(contentVideo, options) {
2942
2944
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2943
2945
  if (contentVideo.paused) {
2944
2946
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback"));
2945
- contentVideo.play().catch(function() {});
2946
2947
  } else {
2947
2948
  console.log("".concat(LOG, " Content video already playing in live mode"));
2948
2949
  }
2950
+ contentVideo.play().catch(function() {});
2949
2951
  }
2950
2952
  emit("content_resume");
2951
2953
  }
@@ -3311,8 +3313,8 @@ function createPrebidController(contentVideo, options) {
3311
3313
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
3312
3314
  if (contentVideo.paused) {
3313
3315
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback on stop"));
3314
- contentVideo.play().catch(function() {});
3315
3316
  }
3317
+ contentVideo.play().catch(function() {});
3316
3318
  }
3317
3319
  if (adHls) {
3318
3320
  adHls.destroy();
@@ -3321,6 +3323,8 @@ function createPrebidController(contentVideo, options) {
3321
3323
  if (adVideoElement) {
3322
3324
  adVideoElement.pause();
3323
3325
  adVideoElement.src = "";
3326
+ adVideoElement.remove();
3327
+ adVideoElement = void 0;
3324
3328
  }
3325
3329
  currentAd = void 0;
3326
3330
  return [
@@ -4089,6 +4093,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4089
4093
  this.minAdRequestIntervalMs = 2500;
4090
4094
  this.backoffBaseMs = 1e3;
4091
4095
  this.maxBackoffMs = 15e3;
4096
+ this.continuousFetchWallClockBufferMs = 3e4;
4097
+ this.continuousFetchMaxIterations = 500;
4098
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
4092
4099
  this.preloadPool = [];
4093
4100
  this.maxPreloadPoolSize = 3;
4094
4101
  this.preloadPoolActive = false;
@@ -4148,6 +4155,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4148
4155
  }
4149
4156
  }
4150
4157
  },
4158
+ {
4159
+ key: "getAdPlayerTypeLabel",
4160
+ value: function getAdPlayerTypeLabel() {
4161
+ var t = this.config.adPlayerType;
4162
+ if (t === "prebid") return "Prebid";
4163
+ if (t === "hls") return "HLS";
4164
+ return "IMA";
4165
+ }
4166
+ },
4151
4167
  {
4152
4168
  key: "load",
4153
4169
  value: function load() {
@@ -4637,6 +4653,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4637
4653
  }
4638
4654
  });
4639
4655
  this.ima.on("content_resume", function() {
4656
+ console.log("[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s", _this.inAdBreak, _this.getRemainingAdMs());
4640
4657
  if (!_this.video.muted) {
4641
4658
  _this.video.muted = true;
4642
4659
  _this.video.volume = 0;
@@ -4667,15 +4684,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4667
4684
  }
4668
4685
  },
4669
4686
  {
4670
- key: "recreateImaController",
4671
- value: function recreateImaController() {
4687
+ key: "recreateAdController",
4688
+ value: function recreateAdController() {
4689
+ var label = this.getAdPlayerTypeLabel();
4672
4690
  if (this.config.debugAdTiming) {
4673
- console.log("[StormcloudVideoPlayer] Recreating ImaController for new ad");
4691
+ console.log("[StormcloudVideoPlayer] Recreating ad controller (".concat(label, ") for new ad"));
4674
4692
  }
4675
4693
  var shouldShowPlaceholder = this.inAdBreak && this.showAds;
4676
4694
  if (shouldShowPlaceholder && this.ima) {
4677
4695
  if (this.config.debugAdTiming) {
4678
- console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ImaController");
4696
+ console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ".concat(label, " controller"));
4679
4697
  }
4680
4698
  this.showPlaceholderLayer();
4681
4699
  this.ima.showPlaceholder();
@@ -4688,7 +4706,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4688
4706
  this.video.volume = 0;
4689
4707
  } catch (error) {
4690
4708
  if (this.config.debugAdTiming) {
4691
- console.warn("[StormcloudVideoPlayer] Error destroying old ImaController:", error);
4709
+ console.warn("[StormcloudVideoPlayer] Error destroying old ".concat(label, " controller:"), error);
4692
4710
  }
4693
4711
  }
4694
4712
  }
@@ -4768,7 +4786,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4768
4786
  });
4769
4787
  }
4770
4788
  if (this.config.debugAdTiming) {
4771
- console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and IMA)");
4789
+ console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and ".concat(this.getAdPlayerTypeLabel(), ")"));
4772
4790
  }
4773
4791
  }
4774
4792
  },
@@ -5480,6 +5498,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5480
5498
  return this.config.adPlayerType === "prebid";
5481
5499
  }
5482
5500
  },
5501
+ {
5502
+ key: "isLgStbDevice",
5503
+ value: function isLgStbDevice() {
5504
+ if (typeof navigator === "undefined" || !navigator.userAgent) return false;
5505
+ var ua = navigator.userAgent;
5506
+ return /Web0S|webOS|LG Browser|LGSTB/i.test(ua);
5507
+ }
5508
+ },
5483
5509
  {
5484
5510
  key: "getCurrentAdIndex",
5485
5511
  value: function getCurrentAdIndex() {
@@ -6294,15 +6320,34 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6294
6320
  key: "continuousFetchLoop",
6295
6321
  value: function continuousFetchLoop(baseVastUrl) {
6296
6322
  return _async_to_generator(function() {
6297
- var _this, _loop, _ret;
6323
+ var loopIterations, _this, _loop, _ret;
6298
6324
  return _ts_generator(this, function(_state) {
6299
6325
  switch(_state.label){
6300
6326
  case 0:
6327
+ loopIterations = 0;
6328
+ _state.label = 1;
6329
+ case 1:
6330
+ _state.trys.push([
6331
+ 1,
6332
+ ,
6333
+ 5,
6334
+ 6
6335
+ ]);
6301
6336
  _loop = function() {
6302
- var remaining, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6337
+ var remaining, elapsedMs, maxLoopMs, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6303
6338
  return _ts_generator(this, function(_state) {
6304
6339
  switch(_state.label){
6305
6340
  case 0:
6341
+ loopIterations++;
6342
+ if (loopIterations > _this.continuousFetchMaxIterations) {
6343
+ if (_this.config.debugAdTiming) {
6344
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Max iterations reached (".concat(_this.continuousFetchMaxIterations, "), stopping URL generation"));
6345
+ }
6346
+ return [
6347
+ 2,
6348
+ "break"
6349
+ ];
6350
+ }
6306
6351
  remaining = _this.getRemainingAdMs();
6307
6352
  if (remaining <= 0) {
6308
6353
  if (_this.config.debugAdTiming) {
@@ -6313,6 +6358,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6313
6358
  "break"
6314
6359
  ];
6315
6360
  }
6361
+ if (_this.currentAdBreakStartWallClockMs != null && _this.expectedAdBreakDurationMs != null) {
6362
+ elapsedMs = Date.now() - _this.currentAdBreakStartWallClockMs;
6363
+ maxLoopMs = _this.expectedAdBreakDurationMs + _this.continuousFetchWallClockBufferMs;
6364
+ if (elapsedMs >= maxLoopMs) {
6365
+ if (_this.config.debugAdTiming) {
6366
+ console.log("[CONTINUOUS-FETCH] ⏹️ Wall-clock limit reached (".concat(elapsedMs, "ms >= ").concat(maxLoopMs, "ms), stopping URL generation"));
6367
+ }
6368
+ return [
6369
+ 2,
6370
+ "break"
6371
+ ];
6372
+ }
6373
+ }
6316
6374
  if (_this.consecutiveFailures >= _this.maxConsecutiveFailures) {
6317
6375
  if (_this.config.debugAdTiming) {
6318
6376
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Too many consecutive failures (".concat(_this.consecutiveFailures, "), stopping URL generation"));
@@ -6334,46 +6392,63 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6334
6392
  maxQueueSize = 5;
6335
6393
  if (!(_this.adRequestQueue.length >= maxQueueSize)) return [
6336
6394
  3,
6337
- 2
6395
+ 4
6396
+ ];
6397
+ if (!(_this.isPrebidMode() && _this.isLgStbDevice())) return [
6398
+ 3,
6399
+ 1
6338
6400
  ];
6401
+ _this.adRequestQueue.shift();
6402
+ _this.adRequestQueue.push("");
6403
+ _this.totalAdsInBreak++;
6404
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6339
6405
  if (_this.config.debugAdTiming) {
6340
- console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(_this.adRequestQueue.length, "), waiting..."));
6406
+ console.log("[CONTINUOUS-FETCH] Prebid slot rotated (queue full, dropped oldest); queue: ".concat(_this.adRequestQueue.length));
6341
6407
  }
6342
6408
  return [
6343
- 4,
6344
- new Promise(function(resolve) {
6345
- return setTimeout(resolve, 1e3);
6346
- })
6409
+ 3,
6410
+ 3
6347
6411
  ];
6348
6412
  case 1:
6413
+ return [
6414
+ 4,
6415
+ _this.waitForQueueWithBackoff()
6416
+ ];
6417
+ case 2:
6349
6418
  _state.sent();
6350
6419
  return [
6351
6420
  2,
6352
6421
  "continue"
6353
6422
  ];
6354
- case 2:
6423
+ case 3:
6424
+ return [
6425
+ 3,
6426
+ 8
6427
+ ];
6428
+ case 4:
6355
6429
  if (!_this.isPrebidMode()) return [
6356
6430
  3,
6357
- 3
6431
+ 5
6358
6432
  ];
6359
6433
  _this.adRequestQueue.push("");
6360
6434
  _this.totalAdsInBreak++;
6435
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6361
6436
  if (_this.config.debugAdTiming) {
6362
6437
  console.log("[CONTINUOUS-FETCH] Prebid auction slot queued (queue: ".concat(_this.adRequestQueue.length, ")"));
6363
6438
  }
6364
6439
  return [
6365
6440
  3,
6366
- 6
6441
+ 8
6367
6442
  ];
6368
- case 3:
6443
+ case 5:
6369
6444
  if (!baseVastUrl) return [
6370
6445
  3,
6371
- 6
6446
+ 8
6372
6447
  ];
6373
6448
  newAdUrl = _this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];
6374
6449
  if (!(!newAdUrl || _this.failedVastUrls.has(newAdUrl) || _this.isUrlInCooldown(newAdUrl))) return [
6375
6450
  3,
6376
- 5
6451
+ 7
6377
6452
  ];
6378
6453
  return [
6379
6454
  4,
@@ -6381,13 +6456,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6381
6456
  return setTimeout(resolve, 500);
6382
6457
  })
6383
6458
  ];
6384
- case 4:
6459
+ case 6:
6385
6460
  _state.sent();
6386
6461
  return [
6387
6462
  2,
6388
6463
  "continue"
6389
6464
  ];
6390
- case 5:
6465
+ case 7:
6391
6466
  if (_this.config.debugAdTiming) {
6392
6467
  queuedUrlsPreview = _to_consumable_array(_this.adRequestQueue).concat([
6393
6468
  newAdUrl
@@ -6398,8 +6473,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6398
6473
  }
6399
6474
  _this.adRequestQueue.push(newAdUrl);
6400
6475
  _this.totalAdsInBreak++;
6401
- _state.label = 6;
6402
- case 6:
6476
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6477
+ _state.label = 8;
6478
+ case 8:
6403
6479
  generationDelay = _this.consecutiveFailures > 0 ? Math.min(1e3 * Math.pow(2, _this.consecutiveFailures), 5e3) : 500;
6404
6480
  return [
6405
6481
  4,
@@ -6407,7 +6483,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6407
6483
  return setTimeout(resolve, generationDelay);
6408
6484
  })
6409
6485
  ];
6410
- case 7:
6486
+ case 9:
6411
6487
  _state.sent();
6412
6488
  return [
6413
6489
  2
@@ -6415,33 +6491,41 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6415
6491
  }
6416
6492
  });
6417
6493
  };
6418
- _state.label = 1;
6419
- case 1:
6494
+ _state.label = 2;
6495
+ case 2:
6420
6496
  if (!(this.continuousFetchingActive && this.inAdBreak)) return [
6421
6497
  3,
6422
- 3
6498
+ 4
6423
6499
  ];
6424
6500
  _this = this;
6425
6501
  return [
6426
6502
  5,
6427
6503
  _ts_values(_loop())
6428
6504
  ];
6429
- case 2:
6505
+ case 3:
6430
6506
  _ret = _state.sent();
6431
6507
  if (_ret === "break") return [
6432
6508
  3,
6433
- 3
6509
+ 4
6434
6510
  ];
6435
6511
  return [
6436
6512
  3,
6437
- 1
6513
+ 2
6438
6514
  ];
6439
- case 3:
6515
+ case 4:
6516
+ return [
6517
+ 3,
6518
+ 6
6519
+ ];
6520
+ case 5:
6440
6521
  this.continuousFetchLoopRunning = false;
6522
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
6523
+ return [
6524
+ 7
6525
+ ];
6526
+ case 6:
6441
6527
  if (this.config.debugAdTiming) {
6442
- console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 URL generation loop ended (queued: ".concat(this.adRequestQueue.length, ")"), this.adRequestQueue.length > 0 ? {
6443
- queuedUrls: _to_consumable_array(this.adRequestQueue)
6444
- } : {});
6528
+ this.logQueueState("URL generation loop ended");
6445
6529
  }
6446
6530
  return [
6447
6531
  2
@@ -6451,6 +6535,51 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6451
6535
  }).call(this);
6452
6536
  }
6453
6537
  },
6538
+ {
6539
+ key: "waitForQueueWithBackoff",
6540
+ value: function waitForQueueWithBackoff() {
6541
+ return _async_to_generator(function() {
6542
+ var delayMs, shouldLog;
6543
+ return _ts_generator(this, function(_state) {
6544
+ switch(_state.label){
6545
+ case 0:
6546
+ this.continuousFetchQueueFullConsecutiveWaits++;
6547
+ delayMs = Math.min(1e3 * Math.pow(2, this.continuousFetchQueueFullConsecutiveWaits - 1), 5e3);
6548
+ shouldLog = this.config.debugAdTiming && (this.continuousFetchQueueFullConsecutiveWaits <= 2 || this.continuousFetchQueueFullConsecutiveWaits % 4 === 0);
6549
+ if (shouldLog) {
6550
+ console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(this.adRequestQueue.length, "), waiting ").concat(delayMs, "ms (wait #").concat(this.continuousFetchQueueFullConsecutiveWaits, ")"));
6551
+ }
6552
+ return [
6553
+ 4,
6554
+ new Promise(function(resolve) {
6555
+ return setTimeout(resolve, delayMs);
6556
+ })
6557
+ ];
6558
+ case 1:
6559
+ _state.sent();
6560
+ return [
6561
+ 2
6562
+ ];
6563
+ }
6564
+ });
6565
+ }).call(this);
6566
+ }
6567
+ },
6568
+ {
6569
+ key: "logQueueState",
6570
+ value: function logQueueState(reason) {
6571
+ if (!this.config.debugAdTiming) return;
6572
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 ".concat(reason), {
6573
+ queueLength: this.adRequestQueue.length,
6574
+ totalAdsInBreak: this.totalAdsInBreak,
6575
+ totalAdRequestsInBreak: this.totalAdRequestsInBreak,
6576
+ consecutiveFailures: this.consecutiveFailures,
6577
+ continuousFetchingActive: this.continuousFetchingActive,
6578
+ continuousFetchLoopRunning: this.continuousFetchLoopRunning,
6579
+ inAdBreak: this.inAdBreak
6580
+ });
6581
+ }
6582
+ },
6454
6583
  {
6455
6584
  key: "stopContinuousFetching",
6456
6585
  value: function stopContinuousFetching() {
@@ -6621,8 +6750,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6621
6750
  4
6622
6751
  ];
6623
6752
  }
6753
+ console.log("[StormcloudVideoPlayer] Requesting next ad (%s), queue remaining=%s", nextAdUrl === "" ? "Prebid" : "VAST", this.adRequestQueue.length);
6624
6754
  if (this.config.debugAdTiming) {
6625
- 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)"));
6755
+ 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)"));
6626
6756
  }
6627
6757
  currentMuted1 = this.video.muted;
6628
6758
  currentVolume1 = this.video.volume;
@@ -6802,7 +6932,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6802
6932
  ];
6803
6933
  }
6804
6934
  if (this.config.debugAdTiming) {
6805
- console.log("[CONTINUOUS-FETCH] \u2705 Ad URL available, requesting via IMA SDK");
6935
+ console.log("[CONTINUOUS-FETCH] Ad URL available, requesting via ".concat(this.getAdPlayerTypeLabel()));
6806
6936
  }
6807
6937
  this.isShowingPlaceholder = false;
6808
6938
  this.ima.hidePlaceholder();
@@ -7144,7 +7274,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7144
7274
  }
7145
7275
  throw new Error("Too many consecutive failures");
7146
7276
  }
7147
- this.recreateImaController();
7277
+ this.recreateAdController();
7148
7278
  requestToken = ++this.adRequestTokenCounter;
7149
7279
  this.activeAdRequestToken = requestToken;
7150
7280
  this.startAdRequestWatchdog(requestToken);
@@ -7389,6 +7519,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7389
7519
  this.showAds = false;
7390
7520
  this.currentAdIndex = 0;
7391
7521
  this.totalAdsInBreak = 0;
7522
+ this.totalAdRequestsInBreak = 0;
7392
7523
  this.consecutiveFailures = 0;
7393
7524
  this.ima.stop().catch(function() {});
7394
7525
  var restoredMuted = this.ima.getOriginalMutedState();
@@ -7400,17 +7531,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7400
7531
  this.video.volume = restoredVolume;
7401
7532
  }
7402
7533
  if (this.shouldContinueLiveStreamDuringAds()) {
7403
- if (this.video.paused) {
7404
- var _this_video_play;
7405
- if (this.config.debugAdTiming) {
7534
+ var _this_video_play;
7535
+ if (this.config.debugAdTiming) {
7536
+ if (this.video.paused) {
7406
7537
  console.log("[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback");
7407
- }
7408
- (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
7409
- } else {
7410
- if (this.config.debugAdTiming) {
7538
+ } else {
7411
7539
  console.log("[StormcloudVideoPlayer] Content video already playing in live mode after ads");
7412
7540
  }
7413
7541
  }
7542
+ (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
7414
7543
  } else if (this.video.paused) {
7415
7544
  var _this_video_play1;
7416
7545
  (_this_video_play1 = this.video.play()) === null || _this_video_play1 === void 0 ? void 0 : _this_video_play1.catch(function() {});