stormcloud-video-player 0.5.4 → 0.5.6

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.
Files changed (38) hide show
  1. package/dist/stormcloud-vp.min.js +1 -1
  2. package/lib/index.cjs +438 -53
  3. package/lib/index.cjs.map +1 -1
  4. package/lib/index.d.cts +9 -1
  5. package/lib/index.d.ts +9 -1
  6. package/lib/index.js +438 -53
  7. package/lib/index.js.map +1 -1
  8. package/lib/player/StormcloudVideoPlayer.cjs +438 -53
  9. package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
  10. package/lib/player/StormcloudVideoPlayer.d.cts +10 -2
  11. package/lib/players/FilePlayer.cjs.map +1 -1
  12. package/lib/players/HlsPlayer.cjs +438 -53
  13. package/lib/players/HlsPlayer.cjs.map +1 -1
  14. package/lib/players/HlsPlayer.d.cts +1 -1
  15. package/lib/players/index.cjs +438 -53
  16. package/lib/players/index.cjs.map +1 -1
  17. package/lib/sdk/hlsAdPlayer.cjs +5 -2
  18. package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
  19. package/lib/sdk/hlsAdPlayer.d.cts +1 -1
  20. package/lib/sdk/ima.cjs +1 -0
  21. package/lib/sdk/ima.cjs.map +1 -1
  22. package/lib/sdk/ima.d.cts +1 -1
  23. package/lib/sdk/prebid.cjs.map +1 -1
  24. package/lib/sdk/prebid.d.cts +1 -1
  25. package/lib/sdk/prebidController.cjs +5 -2
  26. package/lib/sdk/prebidController.cjs.map +1 -1
  27. package/lib/sdk/prebidController.d.cts +1 -1
  28. package/lib/sdk/vastParser.cjs.map +1 -1
  29. package/lib/{types-CRi_KrjM.d.cts → types-Bwp6-yys.d.cts} +20 -1
  30. package/lib/ui/StormcloudVideoPlayer.cjs +438 -53
  31. package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
  32. package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
  33. package/lib/utils/browserCompat.cjs.map +1 -1
  34. package/lib/utils/polyfills.cjs.map +1 -1
  35. package/lib/utils/tracking.cjs +226 -1
  36. package/lib/utils/tracking.cjs.map +1 -1
  37. package/lib/utils/tracking.d.cts +5 -2
  38. package/package.json +1 -1
package/lib/index.cjs CHANGED
@@ -1428,6 +1428,7 @@ function createImaController(video, options) {
1428
1428
  adContainerEl.offsetHeight;
1429
1429
  adContainerEl.style.opacity = "1";
1430
1430
  }
1431
+ emit("ad_impression");
1431
1432
  });
1432
1433
  adsManager.addEventListener(AdEvent.CONTENT_RESUME_REQUESTED, function() {
1433
1434
  adPlaying = false;
@@ -2229,11 +2230,12 @@ function createHlsAdPlayer(contentVideo, options) {
2229
2230
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2230
2231
  if (contentVideo.paused) {
2231
2232
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback");
2232
- contentVideo.play().catch(function() {});
2233
2233
  } else {
2234
2234
  console.log("[HlsAdPlayer] Content video already playing in live mode");
2235
2235
  }
2236
+ contentVideo.play().catch(function() {});
2236
2237
  }
2238
+ emit("ad_impression");
2237
2239
  emit("content_resume");
2238
2240
  }
2239
2241
  function handleAdError() {
@@ -2505,8 +2507,8 @@ function createHlsAdPlayer(contentVideo, options) {
2505
2507
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2506
2508
  if (contentVideo.paused) {
2507
2509
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback on stop");
2508
- contentVideo.play().catch(function() {});
2509
2510
  }
2511
+ contentVideo.play().catch(function() {});
2510
2512
  }
2511
2513
  if (adHls) {
2512
2514
  adHls.destroy();
@@ -2515,6 +2517,8 @@ function createHlsAdPlayer(contentVideo, options) {
2515
2517
  if (adVideoElement) {
2516
2518
  adVideoElement.pause();
2517
2519
  adVideoElement.src = "";
2520
+ adVideoElement.remove();
2521
+ adVideoElement = void 0;
2518
2522
  }
2519
2523
  currentAd = void 0;
2520
2524
  return [
@@ -3165,11 +3169,12 @@ function createPrebidController(contentVideo, options) {
3165
3169
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
3166
3170
  if (contentVideo.paused) {
3167
3171
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback"));
3168
- contentVideo.play().catch(function() {});
3169
3172
  } else {
3170
3173
  console.log("".concat(LOG, " Content video already playing in live mode"));
3171
3174
  }
3175
+ contentVideo.play().catch(function() {});
3172
3176
  }
3177
+ emit("ad_impression");
3173
3178
  emit("content_resume");
3174
3179
  }
3175
3180
  function handleAdError() {
@@ -3534,8 +3539,8 @@ function createPrebidController(contentVideo, options) {
3534
3539
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
3535
3540
  if (contentVideo.paused) {
3536
3541
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback on stop"));
3537
- contentVideo.play().catch(function() {});
3538
3542
  }
3543
+ contentVideo.play().catch(function() {});
3539
3544
  }
3540
3545
  if (adHls) {
3541
3546
  adHls.destroy();
@@ -3544,6 +3549,8 @@ function createPrebidController(contentVideo, options) {
3544
3549
  if (adVideoElement) {
3545
3550
  adVideoElement.pause();
3546
3551
  adVideoElement.src = "";
3552
+ adVideoElement.remove();
3553
+ adVideoElement = void 0;
3547
3554
  }
3548
3555
  currentAd = void 0;
3549
3556
  return [
@@ -3890,6 +3897,45 @@ function getBrowserID(clientInfo) {
3890
3897
  });
3891
3898
  })();
3892
3899
  }
3900
+ var TRACK_URL = "https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track";
3901
+ function sendTrackRequest(licenseKey, body) {
3902
+ return _async_to_generator(function() {
3903
+ var headers, response;
3904
+ return _ts_generator(this, function(_state) {
3905
+ switch(_state.label){
3906
+ case 0:
3907
+ headers = {
3908
+ "Content-Type": "application/json"
3909
+ };
3910
+ if (licenseKey) {
3911
+ headers["Authorization"] = "Bearer ".concat(licenseKey);
3912
+ }
3913
+ return [
3914
+ 4,
3915
+ fetch(TRACK_URL, {
3916
+ method: "POST",
3917
+ headers: headers,
3918
+ body: JSON.stringify(body)
3919
+ })
3920
+ ];
3921
+ case 1:
3922
+ response = _state.sent();
3923
+ if (!response.ok) {
3924
+ throw new Error("HTTP error! status: ".concat(response.status));
3925
+ }
3926
+ return [
3927
+ 4,
3928
+ response.json()
3929
+ ];
3930
+ case 2:
3931
+ _state.sent();
3932
+ return [
3933
+ 2
3934
+ ];
3935
+ }
3936
+ });
3937
+ })();
3938
+ }
3893
3939
  function sendInitialTracking(licenseKey) {
3894
3940
  return _async_to_generator(function() {
3895
3941
  var clientInfo, browserId, trackingData, headers, response, error;
@@ -3920,7 +3966,7 @@ function sendInitialTracking(licenseKey) {
3920
3966
  }
3921
3967
  return [
3922
3968
  4,
3923
- fetch("https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track", {
3969
+ fetch(TRACK_URL, {
3924
3970
  method: "POST",
3925
3971
  headers: headers,
3926
3972
  body: JSON.stringify(trackingData)
@@ -3956,6 +4002,156 @@ function sendInitialTracking(licenseKey) {
3956
4002
  });
3957
4003
  })();
3958
4004
  }
4005
+ function sendAdDetectTracking(licenseKey, adDetectInfo) {
4006
+ return _async_to_generator(function() {
4007
+ var clientInfo, browserId, trackingData, error;
4008
+ return _ts_generator(this, function(_state) {
4009
+ switch(_state.label){
4010
+ case 0:
4011
+ _state.trys.push([
4012
+ 0,
4013
+ 3,
4014
+ ,
4015
+ 4
4016
+ ]);
4017
+ clientInfo = getClientInfo();
4018
+ return [
4019
+ 4,
4020
+ getBrowserID(clientInfo)
4021
+ ];
4022
+ case 1:
4023
+ browserId = _state.sent();
4024
+ trackingData = _object_spread({
4025
+ browserId: browserId
4026
+ }, clientInfo);
4027
+ return [
4028
+ 4,
4029
+ sendTrackRequest(licenseKey, _object_spread_props(_object_spread({}, trackingData), {
4030
+ licenseKey: licenseKey,
4031
+ adDetectInfo: adDetectInfo
4032
+ }))
4033
+ ];
4034
+ case 2:
4035
+ _state.sent();
4036
+ return [
4037
+ 3,
4038
+ 4
4039
+ ];
4040
+ case 3:
4041
+ error = _state.sent();
4042
+ console.error("[StormcloudVideoPlayer] Error sending ad detect tracking:", error);
4043
+ return [
4044
+ 3,
4045
+ 4
4046
+ ];
4047
+ case 4:
4048
+ return [
4049
+ 2
4050
+ ];
4051
+ }
4052
+ });
4053
+ })();
4054
+ }
4055
+ function sendAdLoadedTracking(licenseKey, adLoadedInfo) {
4056
+ return _async_to_generator(function() {
4057
+ var clientInfo, browserId, trackingData, error;
4058
+ return _ts_generator(this, function(_state) {
4059
+ switch(_state.label){
4060
+ case 0:
4061
+ _state.trys.push([
4062
+ 0,
4063
+ 3,
4064
+ ,
4065
+ 4
4066
+ ]);
4067
+ clientInfo = getClientInfo();
4068
+ return [
4069
+ 4,
4070
+ getBrowserID(clientInfo)
4071
+ ];
4072
+ case 1:
4073
+ browserId = _state.sent();
4074
+ trackingData = _object_spread({
4075
+ browserId: browserId
4076
+ }, clientInfo);
4077
+ return [
4078
+ 4,
4079
+ sendTrackRequest(licenseKey, _object_spread_props(_object_spread({}, trackingData), {
4080
+ licenseKey: licenseKey,
4081
+ adLoadedInfo: adLoadedInfo
4082
+ }))
4083
+ ];
4084
+ case 2:
4085
+ _state.sent();
4086
+ return [
4087
+ 3,
4088
+ 4
4089
+ ];
4090
+ case 3:
4091
+ error = _state.sent();
4092
+ console.error("[StormcloudVideoPlayer] Error sending ad loaded tracking:", error);
4093
+ return [
4094
+ 3,
4095
+ 4
4096
+ ];
4097
+ case 4:
4098
+ return [
4099
+ 2
4100
+ ];
4101
+ }
4102
+ });
4103
+ })();
4104
+ }
4105
+ function sendAdImpressionTracking(licenseKey, adImpressionInfo) {
4106
+ return _async_to_generator(function() {
4107
+ var clientInfo, browserId, trackingData, error;
4108
+ return _ts_generator(this, function(_state) {
4109
+ switch(_state.label){
4110
+ case 0:
4111
+ _state.trys.push([
4112
+ 0,
4113
+ 3,
4114
+ ,
4115
+ 4
4116
+ ]);
4117
+ clientInfo = getClientInfo();
4118
+ return [
4119
+ 4,
4120
+ getBrowserID(clientInfo)
4121
+ ];
4122
+ case 1:
4123
+ browserId = _state.sent();
4124
+ trackingData = _object_spread({
4125
+ browserId: browserId
4126
+ }, clientInfo);
4127
+ return [
4128
+ 4,
4129
+ sendTrackRequest(licenseKey, _object_spread_props(_object_spread({}, trackingData), {
4130
+ licenseKey: licenseKey,
4131
+ adImpressionInfo: adImpressionInfo
4132
+ }))
4133
+ ];
4134
+ case 2:
4135
+ _state.sent();
4136
+ return [
4137
+ 3,
4138
+ 4
4139
+ ];
4140
+ case 3:
4141
+ error = _state.sent();
4142
+ console.error("[StormcloudVideoPlayer] Error sending ad impression tracking:", error);
4143
+ return [
4144
+ 3,
4145
+ 4
4146
+ ];
4147
+ case 4:
4148
+ return [
4149
+ 2
4150
+ ];
4151
+ }
4152
+ });
4153
+ })();
4154
+ }
3959
4155
  function sendHeartbeat(licenseKey) {
3960
4156
  return _async_to_generator(function() {
3961
4157
  var clientInfo, browserId, heartbeatData, headers, response, error;
@@ -4312,6 +4508,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4312
4508
  this.minAdRequestIntervalMs = 2500;
4313
4509
  this.backoffBaseMs = 1e3;
4314
4510
  this.maxBackoffMs = 15e3;
4511
+ this.continuousFetchWallClockBufferMs = 3e4;
4512
+ this.continuousFetchMaxIterations = 500;
4513
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
4315
4514
  this.preloadPool = [];
4316
4515
  this.maxPreloadPoolSize = 3;
4317
4516
  this.preloadPoolActive = false;
@@ -4371,6 +4570,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4371
4570
  }
4372
4571
  }
4373
4572
  },
4573
+ {
4574
+ key: "getAdPlayerTypeLabel",
4575
+ value: function getAdPlayerTypeLabel() {
4576
+ var t = this.config.adPlayerType;
4577
+ if (t === "prebid") return "Prebid";
4578
+ if (t === "hls") return "HLS";
4579
+ return "IMA";
4580
+ }
4581
+ },
4374
4582
  {
4375
4583
  key: "load",
4376
4584
  value: function load() {
@@ -4794,10 +5002,26 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4794
5002
  }).call(this);
4795
5003
  }
4796
5004
  },
5005
+ {
5006
+ key: "getAdSource",
5007
+ value: function getAdSource() {
5008
+ var _this_config_adPlayerType;
5009
+ return (_this_config_adPlayerType = this.config.adPlayerType) !== null && _this_config_adPlayerType !== void 0 ? _this_config_adPlayerType : "ima";
5010
+ }
5011
+ },
4797
5012
  {
4798
5013
  key: "attachImaEventListeners",
4799
5014
  value: function attachImaEventListeners() {
4800
5015
  var _this = this;
5016
+ this.ima.on("ad_impression", function() {
5017
+ if (_this.config.licenseKey) {
5018
+ sendAdImpressionTracking(_this.config.licenseKey, {
5019
+ source: _this.getAdSource(),
5020
+ adIndex: _this.currentAdIndex,
5021
+ timestamp: /* @__PURE__ */ new Date().toISOString()
5022
+ });
5023
+ }
5024
+ });
4801
5025
  this.ima.on("all_ads_completed", function() {
4802
5026
  var remaining = _this.getRemainingAdMs();
4803
5027
  _this.consecutiveFailures = 0;
@@ -4860,6 +5084,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4860
5084
  }
4861
5085
  });
4862
5086
  this.ima.on("content_resume", function() {
5087
+ console.log("[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s", _this.inAdBreak, _this.getRemainingAdMs());
4863
5088
  if (!_this.video.muted) {
4864
5089
  _this.video.muted = true;
4865
5090
  _this.video.volume = 0;
@@ -4890,15 +5115,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4890
5115
  }
4891
5116
  },
4892
5117
  {
4893
- key: "recreateImaController",
4894
- value: function recreateImaController() {
5118
+ key: "recreateAdController",
5119
+ value: function recreateAdController() {
5120
+ var label = this.getAdPlayerTypeLabel();
4895
5121
  if (this.config.debugAdTiming) {
4896
- console.log("[StormcloudVideoPlayer] Recreating ImaController for new ad");
5122
+ console.log("[StormcloudVideoPlayer] Recreating ad controller (".concat(label, ") for new ad"));
4897
5123
  }
4898
5124
  var shouldShowPlaceholder = this.inAdBreak && this.showAds;
4899
5125
  if (shouldShowPlaceholder && this.ima) {
4900
5126
  if (this.config.debugAdTiming) {
4901
- console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ImaController");
5127
+ console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ".concat(label, " controller"));
4902
5128
  }
4903
5129
  this.showPlaceholderLayer();
4904
5130
  this.ima.showPlaceholder();
@@ -4911,7 +5137,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4911
5137
  this.video.volume = 0;
4912
5138
  } catch (error) {
4913
5139
  if (this.config.debugAdTiming) {
4914
- console.warn("[StormcloudVideoPlayer] Error destroying old ImaController:", error);
5140
+ console.warn("[StormcloudVideoPlayer] Error destroying old ".concat(label, " controller:"), error);
4915
5141
  }
4916
5142
  }
4917
5143
  }
@@ -4991,7 +5217,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4991
5217
  });
4992
5218
  }
4993
5219
  if (this.config.debugAdTiming) {
4994
- console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and IMA)");
5220
+ console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and ".concat(this.getAdPlayerTypeLabel(), ")"));
4995
5221
  }
4996
5222
  }
4997
5223
  },
@@ -5248,6 +5474,20 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5248
5474
  var durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : ((_this_pendingAdBreak = this.pendingAdBreak) === null || _this_pendingAdBreak === void 0 ? void 0 : _this_pendingAdBreak.marker.durationSeconds) != null ? this.pendingAdBreak.marker.durationSeconds * 1e3 : void 0;
5249
5475
  this.expectedAdBreakDurationMs = durationMs;
5250
5476
  this.currentAdBreakStartWallClockMs = Date.now();
5477
+ if (this.config.licenseKey) {
5478
+ var _this_pendingAdBreak1;
5479
+ var adDetectInfo = _object_spread({
5480
+ source: "scte35",
5481
+ timestamp: /* @__PURE__ */ new Date().toISOString()
5482
+ }, marker.durationSeconds != null && {
5483
+ durationSeconds: marker.durationSeconds
5484
+ }, marker.ptsSeconds != null && {
5485
+ ptsSeconds: marker.ptsSeconds
5486
+ }, ((_this_pendingAdBreak1 = this.pendingAdBreak) === null || _this_pendingAdBreak1 === void 0 ? void 0 : _this_pendingAdBreak1.detectedAtFragmentSn) != null && {
5487
+ detectedAtFragmentSn: this.pendingAdBreak.detectedAtFragmentSn
5488
+ });
5489
+ sendAdDetectTracking(this.config.licenseKey, adDetectInfo);
5490
+ }
5251
5491
  var isManifestMarker = this.isManifestBasedMarker(marker);
5252
5492
  var forceImmediate = (_this_config_immediateManifestAds = this.config.immediateManifestAds) !== null && _this_config_immediateManifestAds !== void 0 ? _this_config_immediateManifestAds : true;
5253
5493
  if (this.config.debugAdTiming) {
@@ -5703,6 +5943,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5703
5943
  return this.config.adPlayerType === "prebid";
5704
5944
  }
5705
5945
  },
5946
+ {
5947
+ key: "isLgStbDevice",
5948
+ value: function isLgStbDevice() {
5949
+ if (typeof navigator === "undefined" || !navigator.userAgent) return false;
5950
+ var ua = navigator.userAgent;
5951
+ return /Web0S|webOS|LG Browser|LGSTB/i.test(ua);
5952
+ }
5953
+ },
5706
5954
  {
5707
5955
  key: "getCurrentAdIndex",
5708
5956
  value: function getCurrentAdIndex() {
@@ -6225,7 +6473,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6225
6473
  key: "handleAdStart",
6226
6474
  value: function handleAdStart(_marker) {
6227
6475
  return _async_to_generator(function() {
6228
- var scheduled, tags, isPrebid, baseVastUrl, adBreakDurationMs, mode, currentMuted, currentVolume, firstAdUrl, usePreloadedAd, preloadedController, preloaded, firstAdUrlArray, adVolume, adVolume1, error, fallbackPreloaded, adVolume2, fallbackError;
6476
+ var scheduled, tags, isPrebid, baseVastUrl, adBreakDurationMs, mode, currentMuted, currentVolume, firstAdUrl, usePreloadedAd, preloadedController, preloaded, firstAdUrlArray, adLoadedInfo, adVolume, adLoadedInfo1, adVolume1, error, fallbackPreloaded, adVolume2, fallbackError;
6229
6477
  return _ts_generator(this, function(_state) {
6230
6478
  switch(_state.label){
6231
6479
  case 0:
@@ -6337,6 +6585,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6337
6585
  this.video.volume = 0;
6338
6586
  this.ima = preloadedController;
6339
6587
  this.attachImaEventListeners();
6588
+ if (this.config.licenseKey) {
6589
+ adLoadedInfo = _object_spread({
6590
+ source: this.getAdSource(),
6591
+ timestamp: /* @__PURE__ */ new Date().toISOString()
6592
+ }, firstAdUrl && {
6593
+ vastUrl: firstAdUrl
6594
+ });
6595
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
6596
+ }
6340
6597
  if (this.config.debugAdTiming) {
6341
6598
  console.log("[CONTINUOUS-FETCH] \u2705 Using preloaded ad, resuming and starting playback immediately (no request delay!)");
6342
6599
  }
@@ -6372,6 +6629,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6372
6629
  ];
6373
6630
  case 4:
6374
6631
  _state.sent();
6632
+ if (this.config.licenseKey) {
6633
+ adLoadedInfo1 = _object_spread({
6634
+ source: this.getAdSource(),
6635
+ timestamp: /* @__PURE__ */ new Date().toISOString()
6636
+ }, firstAdUrl && {
6637
+ vastUrl: firstAdUrl
6638
+ });
6639
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo1);
6640
+ }
6375
6641
  if (this.config.debugAdTiming) {
6376
6642
  console.log("[CONTINUOUS-FETCH] \u2705 First ad request successful, starting playback");
6377
6643
  }
@@ -6517,15 +6783,34 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6517
6783
  key: "continuousFetchLoop",
6518
6784
  value: function continuousFetchLoop(baseVastUrl) {
6519
6785
  return _async_to_generator(function() {
6520
- var _this, _loop, _ret;
6786
+ var loopIterations, _this, _loop, _ret;
6521
6787
  return _ts_generator(this, function(_state) {
6522
6788
  switch(_state.label){
6523
6789
  case 0:
6790
+ loopIterations = 0;
6791
+ _state.label = 1;
6792
+ case 1:
6793
+ _state.trys.push([
6794
+ 1,
6795
+ ,
6796
+ 5,
6797
+ 6
6798
+ ]);
6524
6799
  _loop = function() {
6525
- var remaining, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6800
+ var remaining, elapsedMs, maxLoopMs, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6526
6801
  return _ts_generator(this, function(_state) {
6527
6802
  switch(_state.label){
6528
6803
  case 0:
6804
+ loopIterations++;
6805
+ if (loopIterations > _this.continuousFetchMaxIterations) {
6806
+ if (_this.config.debugAdTiming) {
6807
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Max iterations reached (".concat(_this.continuousFetchMaxIterations, "), stopping URL generation"));
6808
+ }
6809
+ return [
6810
+ 2,
6811
+ "break"
6812
+ ];
6813
+ }
6529
6814
  remaining = _this.getRemainingAdMs();
6530
6815
  if (remaining <= 0) {
6531
6816
  if (_this.config.debugAdTiming) {
@@ -6536,6 +6821,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6536
6821
  "break"
6537
6822
  ];
6538
6823
  }
6824
+ if (_this.currentAdBreakStartWallClockMs != null && _this.expectedAdBreakDurationMs != null) {
6825
+ elapsedMs = Date.now() - _this.currentAdBreakStartWallClockMs;
6826
+ maxLoopMs = _this.expectedAdBreakDurationMs + _this.continuousFetchWallClockBufferMs;
6827
+ if (elapsedMs >= maxLoopMs) {
6828
+ if (_this.config.debugAdTiming) {
6829
+ console.log("[CONTINUOUS-FETCH] ⏹️ Wall-clock limit reached (".concat(elapsedMs, "ms >= ").concat(maxLoopMs, "ms), stopping URL generation"));
6830
+ }
6831
+ return [
6832
+ 2,
6833
+ "break"
6834
+ ];
6835
+ }
6836
+ }
6539
6837
  if (_this.consecutiveFailures >= _this.maxConsecutiveFailures) {
6540
6838
  if (_this.config.debugAdTiming) {
6541
6839
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Too many consecutive failures (".concat(_this.consecutiveFailures, "), stopping URL generation"));
@@ -6557,46 +6855,63 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6557
6855
  maxQueueSize = 5;
6558
6856
  if (!(_this.adRequestQueue.length >= maxQueueSize)) return [
6559
6857
  3,
6560
- 2
6858
+ 4
6561
6859
  ];
6860
+ if (!(_this.isPrebidMode() && _this.isLgStbDevice())) return [
6861
+ 3,
6862
+ 1
6863
+ ];
6864
+ _this.adRequestQueue.shift();
6865
+ _this.adRequestQueue.push("");
6866
+ _this.totalAdsInBreak++;
6867
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6562
6868
  if (_this.config.debugAdTiming) {
6563
- console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(_this.adRequestQueue.length, "), waiting..."));
6869
+ console.log("[CONTINUOUS-FETCH] Prebid slot rotated (queue full, dropped oldest); queue: ".concat(_this.adRequestQueue.length));
6564
6870
  }
6565
6871
  return [
6566
- 4,
6567
- new Promise(function(resolve) {
6568
- return setTimeout(resolve, 1e3);
6569
- })
6872
+ 3,
6873
+ 3
6570
6874
  ];
6571
6875
  case 1:
6876
+ return [
6877
+ 4,
6878
+ _this.waitForQueueWithBackoff()
6879
+ ];
6880
+ case 2:
6572
6881
  _state.sent();
6573
6882
  return [
6574
6883
  2,
6575
6884
  "continue"
6576
6885
  ];
6577
- case 2:
6886
+ case 3:
6887
+ return [
6888
+ 3,
6889
+ 8
6890
+ ];
6891
+ case 4:
6578
6892
  if (!_this.isPrebidMode()) return [
6579
6893
  3,
6580
- 3
6894
+ 5
6581
6895
  ];
6582
6896
  _this.adRequestQueue.push("");
6583
6897
  _this.totalAdsInBreak++;
6898
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6584
6899
  if (_this.config.debugAdTiming) {
6585
6900
  console.log("[CONTINUOUS-FETCH] Prebid auction slot queued (queue: ".concat(_this.adRequestQueue.length, ")"));
6586
6901
  }
6587
6902
  return [
6588
6903
  3,
6589
- 6
6904
+ 8
6590
6905
  ];
6591
- case 3:
6906
+ case 5:
6592
6907
  if (!baseVastUrl) return [
6593
6908
  3,
6594
- 6
6909
+ 8
6595
6910
  ];
6596
6911
  newAdUrl = _this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];
6597
6912
  if (!(!newAdUrl || _this.failedVastUrls.has(newAdUrl) || _this.isUrlInCooldown(newAdUrl))) return [
6598
6913
  3,
6599
- 5
6914
+ 7
6600
6915
  ];
6601
6916
  return [
6602
6917
  4,
@@ -6604,13 +6919,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6604
6919
  return setTimeout(resolve, 500);
6605
6920
  })
6606
6921
  ];
6607
- case 4:
6922
+ case 6:
6608
6923
  _state.sent();
6609
6924
  return [
6610
6925
  2,
6611
6926
  "continue"
6612
6927
  ];
6613
- case 5:
6928
+ case 7:
6614
6929
  if (_this.config.debugAdTiming) {
6615
6930
  queuedUrlsPreview = _to_consumable_array(_this.adRequestQueue).concat([
6616
6931
  newAdUrl
@@ -6621,8 +6936,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6621
6936
  }
6622
6937
  _this.adRequestQueue.push(newAdUrl);
6623
6938
  _this.totalAdsInBreak++;
6624
- _state.label = 6;
6625
- case 6:
6939
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6940
+ _state.label = 8;
6941
+ case 8:
6626
6942
  generationDelay = _this.consecutiveFailures > 0 ? Math.min(1e3 * Math.pow(2, _this.consecutiveFailures), 5e3) : 500;
6627
6943
  return [
6628
6944
  4,
@@ -6630,7 +6946,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6630
6946
  return setTimeout(resolve, generationDelay);
6631
6947
  })
6632
6948
  ];
6633
- case 7:
6949
+ case 9:
6634
6950
  _state.sent();
6635
6951
  return [
6636
6952
  2
@@ -6638,33 +6954,41 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6638
6954
  }
6639
6955
  });
6640
6956
  };
6641
- _state.label = 1;
6642
- case 1:
6957
+ _state.label = 2;
6958
+ case 2:
6643
6959
  if (!(this.continuousFetchingActive && this.inAdBreak)) return [
6644
6960
  3,
6645
- 3
6961
+ 4
6646
6962
  ];
6647
6963
  _this = this;
6648
6964
  return [
6649
6965
  5,
6650
6966
  _ts_values(_loop())
6651
6967
  ];
6652
- case 2:
6968
+ case 3:
6653
6969
  _ret = _state.sent();
6654
6970
  if (_ret === "break") return [
6655
6971
  3,
6656
- 3
6972
+ 4
6657
6973
  ];
6658
6974
  return [
6659
6975
  3,
6660
- 1
6976
+ 2
6661
6977
  ];
6662
- case 3:
6978
+ case 4:
6979
+ return [
6980
+ 3,
6981
+ 6
6982
+ ];
6983
+ case 5:
6663
6984
  this.continuousFetchLoopRunning = false;
6985
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
6986
+ return [
6987
+ 7
6988
+ ];
6989
+ case 6:
6664
6990
  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
- } : {});
6991
+ this.logQueueState("URL generation loop ended");
6668
6992
  }
6669
6993
  return [
6670
6994
  2
@@ -6674,6 +6998,51 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6674
6998
  }).call(this);
6675
6999
  }
6676
7000
  },
7001
+ {
7002
+ key: "waitForQueueWithBackoff",
7003
+ value: function waitForQueueWithBackoff() {
7004
+ return _async_to_generator(function() {
7005
+ var delayMs, shouldLog;
7006
+ return _ts_generator(this, function(_state) {
7007
+ switch(_state.label){
7008
+ case 0:
7009
+ this.continuousFetchQueueFullConsecutiveWaits++;
7010
+ delayMs = Math.min(1e3 * Math.pow(2, this.continuousFetchQueueFullConsecutiveWaits - 1), 5e3);
7011
+ shouldLog = this.config.debugAdTiming && (this.continuousFetchQueueFullConsecutiveWaits <= 2 || this.continuousFetchQueueFullConsecutiveWaits % 4 === 0);
7012
+ if (shouldLog) {
7013
+ console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(this.adRequestQueue.length, "), waiting ").concat(delayMs, "ms (wait #").concat(this.continuousFetchQueueFullConsecutiveWaits, ")"));
7014
+ }
7015
+ return [
7016
+ 4,
7017
+ new Promise(function(resolve) {
7018
+ return setTimeout(resolve, delayMs);
7019
+ })
7020
+ ];
7021
+ case 1:
7022
+ _state.sent();
7023
+ return [
7024
+ 2
7025
+ ];
7026
+ }
7027
+ });
7028
+ }).call(this);
7029
+ }
7030
+ },
7031
+ {
7032
+ key: "logQueueState",
7033
+ value: function logQueueState(reason) {
7034
+ if (!this.config.debugAdTiming) return;
7035
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 ".concat(reason), {
7036
+ queueLength: this.adRequestQueue.length,
7037
+ totalAdsInBreak: this.totalAdsInBreak,
7038
+ totalAdRequestsInBreak: this.totalAdRequestsInBreak,
7039
+ consecutiveFailures: this.consecutiveFailures,
7040
+ continuousFetchingActive: this.continuousFetchingActive,
7041
+ continuousFetchLoopRunning: this.continuousFetchLoopRunning,
7042
+ inAdBreak: this.inAdBreak
7043
+ });
7044
+ }
7045
+ },
6677
7046
  {
6678
7047
  key: "stopContinuousFetching",
6679
7048
  value: function stopContinuousFetching() {
@@ -6738,7 +7107,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6738
7107
  value: function tryNextAvailableAd() {
6739
7108
  var retryCount = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 0;
6740
7109
  return _async_to_generator(function() {
6741
- var remaining, preloaded, currentMuted, currentVolume, adVolume, error, nextAdUrl, currentMuted1, currentVolume1, error1, errorMessage, maxRetries;
7110
+ var remaining, preloaded, adLoadedInfo, currentMuted, currentVolume, adVolume, error, nextAdUrl, currentMuted1, currentVolume1, error1, errorMessage, maxRetries;
6742
7111
  return _ts_generator(this, function(_state) {
6743
7112
  switch(_state.label){
6744
7113
  case 0:
@@ -6783,6 +7152,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6783
7152
  this.video.volume = 0;
6784
7153
  this.ima = preloaded.imaController;
6785
7154
  this.attachImaEventListeners();
7155
+ if (this.config.licenseKey) {
7156
+ adLoadedInfo = {
7157
+ source: this.getAdSource(),
7158
+ timestamp: /* @__PURE__ */ new Date().toISOString()
7159
+ };
7160
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
7161
+ }
6786
7162
  this.ima.resume();
6787
7163
  this.currentAdIndex++;
6788
7164
  this.totalAdRequestsInBreak++;
@@ -6844,8 +7220,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6844
7220
  4
6845
7221
  ];
6846
7222
  }
7223
+ console.log("[StormcloudVideoPlayer] Requesting next ad (%s), queue remaining=%s", nextAdUrl === "" ? "Prebid" : "VAST", this.adRequestQueue.length);
6847
7224
  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)"));
7225
+ 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
7226
  }
6850
7227
  currentMuted1 = this.video.muted;
6851
7228
  currentVolume1 = this.video.volume;
@@ -7025,7 +7402,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7025
7402
  ];
7026
7403
  }
7027
7404
  if (this.config.debugAdTiming) {
7028
- console.log("[CONTINUOUS-FETCH] \u2705 Ad URL available, requesting via IMA SDK");
7405
+ console.log("[CONTINUOUS-FETCH] Ad URL available, requesting via ".concat(this.getAdPlayerTypeLabel()));
7029
7406
  }
7030
7407
  this.isShowingPlaceholder = false;
7031
7408
  this.ima.hidePlaceholder();
@@ -7340,7 +7717,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7340
7717
  key: "playSingleAd",
7341
7718
  value: function playSingleAd(vastTagUrl) {
7342
7719
  return _async_to_generator(function() {
7343
- var requestToken, currentMuted, currentVolume, adVolume, playError, preloadedFallback, currentMuted1, currentVolume1, adVolume1, fallbackError, error, errorMessage, preloadedFallback1, currentMuted2, currentVolume2, adVolume2, fallbackError1;
7720
+ var requestToken, adLoadedInfo, currentMuted, currentVolume, adVolume, playError, preloadedFallback, currentMuted1, currentVolume1, adVolume1, fallbackError, error, errorMessage, preloadedFallback1, currentMuted2, currentVolume2, adVolume2, fallbackError1;
7344
7721
  return _ts_generator(this, function(_state) {
7345
7722
  switch(_state.label){
7346
7723
  case 0:
@@ -7367,7 +7744,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7367
7744
  }
7368
7745
  throw new Error("Too many consecutive failures");
7369
7746
  }
7370
- this.recreateImaController();
7747
+ this.recreateAdController();
7371
7748
  requestToken = ++this.adRequestTokenCounter;
7372
7749
  this.activeAdRequestToken = requestToken;
7373
7750
  this.startAdRequestWatchdog(requestToken);
@@ -7392,6 +7769,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7392
7769
  2
7393
7770
  ];
7394
7771
  }
7772
+ if (this.config.licenseKey) {
7773
+ adLoadedInfo = _object_spread({
7774
+ source: this.getAdSource(),
7775
+ timestamp: /* @__PURE__ */ new Date().toISOString()
7776
+ }, vastTagUrl && {
7777
+ vastUrl: vastTagUrl
7778
+ });
7779
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
7780
+ }
7395
7781
  _state.label = 3;
7396
7782
  case 3:
7397
7783
  _state.trys.push([
@@ -7612,6 +7998,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7612
7998
  this.showAds = false;
7613
7999
  this.currentAdIndex = 0;
7614
8000
  this.totalAdsInBreak = 0;
8001
+ this.totalAdRequestsInBreak = 0;
7615
8002
  this.consecutiveFailures = 0;
7616
8003
  this.ima.stop().catch(function() {});
7617
8004
  var restoredMuted = this.ima.getOriginalMutedState();
@@ -7623,17 +8010,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7623
8010
  this.video.volume = restoredVolume;
7624
8011
  }
7625
8012
  if (this.shouldContinueLiveStreamDuringAds()) {
7626
- if (this.video.paused) {
7627
- var _this_video_play;
7628
- if (this.config.debugAdTiming) {
8013
+ var _this_video_play;
8014
+ if (this.config.debugAdTiming) {
8015
+ if (this.video.paused) {
7629
8016
  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) {
8017
+ } else {
7634
8018
  console.log("[StormcloudVideoPlayer] Content video already playing in live mode after ads");
7635
8019
  }
7636
8020
  }
8021
+ (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
7637
8022
  } else if (this.video.paused) {
7638
8023
  var _this_video_play1;
7639
8024
  (_this_video_play1 = this.video.play()) === null || _this_video_play1 === void 0 ? void 0 : _this_video_play1.catch(function() {});