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
@@ -1205,6 +1205,7 @@ function createImaController(video, options) {
1205
1205
  adContainerEl.offsetHeight;
1206
1206
  adContainerEl.style.opacity = "1";
1207
1207
  }
1208
+ emit("ad_impression");
1208
1209
  });
1209
1210
  adsManager.addEventListener(AdEvent.CONTENT_RESUME_REQUESTED, function() {
1210
1211
  adPlaying = false;
@@ -2006,11 +2007,12 @@ function createHlsAdPlayer(contentVideo, options) {
2006
2007
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2007
2008
  if (contentVideo.paused) {
2008
2009
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback");
2009
- contentVideo.play().catch(function() {});
2010
2010
  } else {
2011
2011
  console.log("[HlsAdPlayer] Content video already playing in live mode");
2012
2012
  }
2013
+ contentVideo.play().catch(function() {});
2013
2014
  }
2015
+ emit("ad_impression");
2014
2016
  emit("content_resume");
2015
2017
  }
2016
2018
  function handleAdError() {
@@ -2282,8 +2284,8 @@ function createHlsAdPlayer(contentVideo, options) {
2282
2284
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2283
2285
  if (contentVideo.paused) {
2284
2286
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback on stop");
2285
- contentVideo.play().catch(function() {});
2286
2287
  }
2288
+ contentVideo.play().catch(function() {});
2287
2289
  }
2288
2290
  if (adHls) {
2289
2291
  adHls.destroy();
@@ -2292,6 +2294,8 @@ function createHlsAdPlayer(contentVideo, options) {
2292
2294
  if (adVideoElement) {
2293
2295
  adVideoElement.pause();
2294
2296
  adVideoElement.src = "";
2297
+ adVideoElement.remove();
2298
+ adVideoElement = void 0;
2295
2299
  }
2296
2300
  currentAd = void 0;
2297
2301
  return [
@@ -2942,11 +2946,12 @@ function createPrebidController(contentVideo, options) {
2942
2946
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2943
2947
  if (contentVideo.paused) {
2944
2948
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback"));
2945
- contentVideo.play().catch(function() {});
2946
2949
  } else {
2947
2950
  console.log("".concat(LOG, " Content video already playing in live mode"));
2948
2951
  }
2952
+ contentVideo.play().catch(function() {});
2949
2953
  }
2954
+ emit("ad_impression");
2950
2955
  emit("content_resume");
2951
2956
  }
2952
2957
  function handleAdError() {
@@ -3311,8 +3316,8 @@ function createPrebidController(contentVideo, options) {
3311
3316
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
3312
3317
  if (contentVideo.paused) {
3313
3318
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback on stop"));
3314
- contentVideo.play().catch(function() {});
3315
3319
  }
3320
+ contentVideo.play().catch(function() {});
3316
3321
  }
3317
3322
  if (adHls) {
3318
3323
  adHls.destroy();
@@ -3321,6 +3326,8 @@ function createPrebidController(contentVideo, options) {
3321
3326
  if (adVideoElement) {
3322
3327
  adVideoElement.pause();
3323
3328
  adVideoElement.src = "";
3329
+ adVideoElement.remove();
3330
+ adVideoElement = void 0;
3324
3331
  }
3325
3332
  currentAd = void 0;
3326
3333
  return [
@@ -3667,6 +3674,45 @@ function getBrowserID(clientInfo) {
3667
3674
  });
3668
3675
  })();
3669
3676
  }
3677
+ var TRACK_URL = "https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track";
3678
+ function sendTrackRequest(licenseKey, body) {
3679
+ return _async_to_generator(function() {
3680
+ var headers, response;
3681
+ return _ts_generator(this, function(_state) {
3682
+ switch(_state.label){
3683
+ case 0:
3684
+ headers = {
3685
+ "Content-Type": "application/json"
3686
+ };
3687
+ if (licenseKey) {
3688
+ headers["Authorization"] = "Bearer ".concat(licenseKey);
3689
+ }
3690
+ return [
3691
+ 4,
3692
+ fetch(TRACK_URL, {
3693
+ method: "POST",
3694
+ headers: headers,
3695
+ body: JSON.stringify(body)
3696
+ })
3697
+ ];
3698
+ case 1:
3699
+ response = _state.sent();
3700
+ if (!response.ok) {
3701
+ throw new Error("HTTP error! status: ".concat(response.status));
3702
+ }
3703
+ return [
3704
+ 4,
3705
+ response.json()
3706
+ ];
3707
+ case 2:
3708
+ _state.sent();
3709
+ return [
3710
+ 2
3711
+ ];
3712
+ }
3713
+ });
3714
+ })();
3715
+ }
3670
3716
  function sendInitialTracking(licenseKey) {
3671
3717
  return _async_to_generator(function() {
3672
3718
  var clientInfo, browserId, trackingData, headers, response, error;
@@ -3697,7 +3743,7 @@ function sendInitialTracking(licenseKey) {
3697
3743
  }
3698
3744
  return [
3699
3745
  4,
3700
- fetch("https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track", {
3746
+ fetch(TRACK_URL, {
3701
3747
  method: "POST",
3702
3748
  headers: headers,
3703
3749
  body: JSON.stringify(trackingData)
@@ -3733,6 +3779,156 @@ function sendInitialTracking(licenseKey) {
3733
3779
  });
3734
3780
  })();
3735
3781
  }
3782
+ function sendAdDetectTracking(licenseKey, adDetectInfo) {
3783
+ return _async_to_generator(function() {
3784
+ var clientInfo, browserId, trackingData, error;
3785
+ return _ts_generator(this, function(_state) {
3786
+ switch(_state.label){
3787
+ case 0:
3788
+ _state.trys.push([
3789
+ 0,
3790
+ 3,
3791
+ ,
3792
+ 4
3793
+ ]);
3794
+ clientInfo = getClientInfo();
3795
+ return [
3796
+ 4,
3797
+ getBrowserID(clientInfo)
3798
+ ];
3799
+ case 1:
3800
+ browserId = _state.sent();
3801
+ trackingData = _object_spread({
3802
+ browserId: browserId
3803
+ }, clientInfo);
3804
+ return [
3805
+ 4,
3806
+ sendTrackRequest(licenseKey, _object_spread_props(_object_spread({}, trackingData), {
3807
+ licenseKey: licenseKey,
3808
+ adDetectInfo: adDetectInfo
3809
+ }))
3810
+ ];
3811
+ case 2:
3812
+ _state.sent();
3813
+ return [
3814
+ 3,
3815
+ 4
3816
+ ];
3817
+ case 3:
3818
+ error = _state.sent();
3819
+ console.error("[StormcloudVideoPlayer] Error sending ad detect tracking:", error);
3820
+ return [
3821
+ 3,
3822
+ 4
3823
+ ];
3824
+ case 4:
3825
+ return [
3826
+ 2
3827
+ ];
3828
+ }
3829
+ });
3830
+ })();
3831
+ }
3832
+ function sendAdLoadedTracking(licenseKey, adLoadedInfo) {
3833
+ return _async_to_generator(function() {
3834
+ var clientInfo, browserId, trackingData, error;
3835
+ return _ts_generator(this, function(_state) {
3836
+ switch(_state.label){
3837
+ case 0:
3838
+ _state.trys.push([
3839
+ 0,
3840
+ 3,
3841
+ ,
3842
+ 4
3843
+ ]);
3844
+ clientInfo = getClientInfo();
3845
+ return [
3846
+ 4,
3847
+ getBrowserID(clientInfo)
3848
+ ];
3849
+ case 1:
3850
+ browserId = _state.sent();
3851
+ trackingData = _object_spread({
3852
+ browserId: browserId
3853
+ }, clientInfo);
3854
+ return [
3855
+ 4,
3856
+ sendTrackRequest(licenseKey, _object_spread_props(_object_spread({}, trackingData), {
3857
+ licenseKey: licenseKey,
3858
+ adLoadedInfo: adLoadedInfo
3859
+ }))
3860
+ ];
3861
+ case 2:
3862
+ _state.sent();
3863
+ return [
3864
+ 3,
3865
+ 4
3866
+ ];
3867
+ case 3:
3868
+ error = _state.sent();
3869
+ console.error("[StormcloudVideoPlayer] Error sending ad loaded tracking:", error);
3870
+ return [
3871
+ 3,
3872
+ 4
3873
+ ];
3874
+ case 4:
3875
+ return [
3876
+ 2
3877
+ ];
3878
+ }
3879
+ });
3880
+ })();
3881
+ }
3882
+ function sendAdImpressionTracking(licenseKey, adImpressionInfo) {
3883
+ return _async_to_generator(function() {
3884
+ var clientInfo, browserId, trackingData, error;
3885
+ return _ts_generator(this, function(_state) {
3886
+ switch(_state.label){
3887
+ case 0:
3888
+ _state.trys.push([
3889
+ 0,
3890
+ 3,
3891
+ ,
3892
+ 4
3893
+ ]);
3894
+ clientInfo = getClientInfo();
3895
+ return [
3896
+ 4,
3897
+ getBrowserID(clientInfo)
3898
+ ];
3899
+ case 1:
3900
+ browserId = _state.sent();
3901
+ trackingData = _object_spread({
3902
+ browserId: browserId
3903
+ }, clientInfo);
3904
+ return [
3905
+ 4,
3906
+ sendTrackRequest(licenseKey, _object_spread_props(_object_spread({}, trackingData), {
3907
+ licenseKey: licenseKey,
3908
+ adImpressionInfo: adImpressionInfo
3909
+ }))
3910
+ ];
3911
+ case 2:
3912
+ _state.sent();
3913
+ return [
3914
+ 3,
3915
+ 4
3916
+ ];
3917
+ case 3:
3918
+ error = _state.sent();
3919
+ console.error("[StormcloudVideoPlayer] Error sending ad impression tracking:", error);
3920
+ return [
3921
+ 3,
3922
+ 4
3923
+ ];
3924
+ case 4:
3925
+ return [
3926
+ 2
3927
+ ];
3928
+ }
3929
+ });
3930
+ })();
3931
+ }
3736
3932
  function sendHeartbeat(licenseKey) {
3737
3933
  return _async_to_generator(function() {
3738
3934
  var clientInfo, browserId, heartbeatData, headers, response, error;
@@ -4089,6 +4285,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4089
4285
  this.minAdRequestIntervalMs = 2500;
4090
4286
  this.backoffBaseMs = 1e3;
4091
4287
  this.maxBackoffMs = 15e3;
4288
+ this.continuousFetchWallClockBufferMs = 3e4;
4289
+ this.continuousFetchMaxIterations = 500;
4290
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
4092
4291
  this.preloadPool = [];
4093
4292
  this.maxPreloadPoolSize = 3;
4094
4293
  this.preloadPoolActive = false;
@@ -4148,6 +4347,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4148
4347
  }
4149
4348
  }
4150
4349
  },
4350
+ {
4351
+ key: "getAdPlayerTypeLabel",
4352
+ value: function getAdPlayerTypeLabel() {
4353
+ var t = this.config.adPlayerType;
4354
+ if (t === "prebid") return "Prebid";
4355
+ if (t === "hls") return "HLS";
4356
+ return "IMA";
4357
+ }
4358
+ },
4151
4359
  {
4152
4360
  key: "load",
4153
4361
  value: function load() {
@@ -4571,10 +4779,26 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4571
4779
  }).call(this);
4572
4780
  }
4573
4781
  },
4782
+ {
4783
+ key: "getAdSource",
4784
+ value: function getAdSource() {
4785
+ var _this_config_adPlayerType;
4786
+ return (_this_config_adPlayerType = this.config.adPlayerType) !== null && _this_config_adPlayerType !== void 0 ? _this_config_adPlayerType : "ima";
4787
+ }
4788
+ },
4574
4789
  {
4575
4790
  key: "attachImaEventListeners",
4576
4791
  value: function attachImaEventListeners() {
4577
4792
  var _this = this;
4793
+ this.ima.on("ad_impression", function() {
4794
+ if (_this.config.licenseKey) {
4795
+ sendAdImpressionTracking(_this.config.licenseKey, {
4796
+ source: _this.getAdSource(),
4797
+ adIndex: _this.currentAdIndex,
4798
+ timestamp: /* @__PURE__ */ new Date().toISOString()
4799
+ });
4800
+ }
4801
+ });
4578
4802
  this.ima.on("all_ads_completed", function() {
4579
4803
  var remaining = _this.getRemainingAdMs();
4580
4804
  _this.consecutiveFailures = 0;
@@ -4637,6 +4861,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4637
4861
  }
4638
4862
  });
4639
4863
  this.ima.on("content_resume", function() {
4864
+ console.log("[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s", _this.inAdBreak, _this.getRemainingAdMs());
4640
4865
  if (!_this.video.muted) {
4641
4866
  _this.video.muted = true;
4642
4867
  _this.video.volume = 0;
@@ -4667,15 +4892,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4667
4892
  }
4668
4893
  },
4669
4894
  {
4670
- key: "recreateImaController",
4671
- value: function recreateImaController() {
4895
+ key: "recreateAdController",
4896
+ value: function recreateAdController() {
4897
+ var label = this.getAdPlayerTypeLabel();
4672
4898
  if (this.config.debugAdTiming) {
4673
- console.log("[StormcloudVideoPlayer] Recreating ImaController for new ad");
4899
+ console.log("[StormcloudVideoPlayer] Recreating ad controller (".concat(label, ") for new ad"));
4674
4900
  }
4675
4901
  var shouldShowPlaceholder = this.inAdBreak && this.showAds;
4676
4902
  if (shouldShowPlaceholder && this.ima) {
4677
4903
  if (this.config.debugAdTiming) {
4678
- console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ImaController");
4904
+ console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ".concat(label, " controller"));
4679
4905
  }
4680
4906
  this.showPlaceholderLayer();
4681
4907
  this.ima.showPlaceholder();
@@ -4688,7 +4914,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4688
4914
  this.video.volume = 0;
4689
4915
  } catch (error) {
4690
4916
  if (this.config.debugAdTiming) {
4691
- console.warn("[StormcloudVideoPlayer] Error destroying old ImaController:", error);
4917
+ console.warn("[StormcloudVideoPlayer] Error destroying old ".concat(label, " controller:"), error);
4692
4918
  }
4693
4919
  }
4694
4920
  }
@@ -4768,7 +4994,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4768
4994
  });
4769
4995
  }
4770
4996
  if (this.config.debugAdTiming) {
4771
- console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and IMA)");
4997
+ console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and ".concat(this.getAdPlayerTypeLabel(), ")"));
4772
4998
  }
4773
4999
  }
4774
5000
  },
@@ -5025,6 +5251,20 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5025
5251
  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;
5026
5252
  this.expectedAdBreakDurationMs = durationMs;
5027
5253
  this.currentAdBreakStartWallClockMs = Date.now();
5254
+ if (this.config.licenseKey) {
5255
+ var _this_pendingAdBreak1;
5256
+ var adDetectInfo = _object_spread({
5257
+ source: "scte35",
5258
+ timestamp: /* @__PURE__ */ new Date().toISOString()
5259
+ }, marker.durationSeconds != null && {
5260
+ durationSeconds: marker.durationSeconds
5261
+ }, marker.ptsSeconds != null && {
5262
+ ptsSeconds: marker.ptsSeconds
5263
+ }, ((_this_pendingAdBreak1 = this.pendingAdBreak) === null || _this_pendingAdBreak1 === void 0 ? void 0 : _this_pendingAdBreak1.detectedAtFragmentSn) != null && {
5264
+ detectedAtFragmentSn: this.pendingAdBreak.detectedAtFragmentSn
5265
+ });
5266
+ sendAdDetectTracking(this.config.licenseKey, adDetectInfo);
5267
+ }
5028
5268
  var isManifestMarker = this.isManifestBasedMarker(marker);
5029
5269
  var forceImmediate = (_this_config_immediateManifestAds = this.config.immediateManifestAds) !== null && _this_config_immediateManifestAds !== void 0 ? _this_config_immediateManifestAds : true;
5030
5270
  if (this.config.debugAdTiming) {
@@ -5480,6 +5720,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5480
5720
  return this.config.adPlayerType === "prebid";
5481
5721
  }
5482
5722
  },
5723
+ {
5724
+ key: "isLgStbDevice",
5725
+ value: function isLgStbDevice() {
5726
+ if (typeof navigator === "undefined" || !navigator.userAgent) return false;
5727
+ var ua = navigator.userAgent;
5728
+ return /Web0S|webOS|LG Browser|LGSTB/i.test(ua);
5729
+ }
5730
+ },
5483
5731
  {
5484
5732
  key: "getCurrentAdIndex",
5485
5733
  value: function getCurrentAdIndex() {
@@ -6002,7 +6250,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6002
6250
  key: "handleAdStart",
6003
6251
  value: function handleAdStart(_marker) {
6004
6252
  return _async_to_generator(function() {
6005
- var scheduled, tags, isPrebid, baseVastUrl, adBreakDurationMs, mode, currentMuted, currentVolume, firstAdUrl, usePreloadedAd, preloadedController, preloaded, firstAdUrlArray, adVolume, adVolume1, error, fallbackPreloaded, adVolume2, fallbackError;
6253
+ var scheduled, tags, isPrebid, baseVastUrl, adBreakDurationMs, mode, currentMuted, currentVolume, firstAdUrl, usePreloadedAd, preloadedController, preloaded, firstAdUrlArray, adLoadedInfo, adVolume, adLoadedInfo1, adVolume1, error, fallbackPreloaded, adVolume2, fallbackError;
6006
6254
  return _ts_generator(this, function(_state) {
6007
6255
  switch(_state.label){
6008
6256
  case 0:
@@ -6114,6 +6362,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6114
6362
  this.video.volume = 0;
6115
6363
  this.ima = preloadedController;
6116
6364
  this.attachImaEventListeners();
6365
+ if (this.config.licenseKey) {
6366
+ adLoadedInfo = _object_spread({
6367
+ source: this.getAdSource(),
6368
+ timestamp: /* @__PURE__ */ new Date().toISOString()
6369
+ }, firstAdUrl && {
6370
+ vastUrl: firstAdUrl
6371
+ });
6372
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
6373
+ }
6117
6374
  if (this.config.debugAdTiming) {
6118
6375
  console.log("[CONTINUOUS-FETCH] \u2705 Using preloaded ad, resuming and starting playback immediately (no request delay!)");
6119
6376
  }
@@ -6149,6 +6406,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6149
6406
  ];
6150
6407
  case 4:
6151
6408
  _state.sent();
6409
+ if (this.config.licenseKey) {
6410
+ adLoadedInfo1 = _object_spread({
6411
+ source: this.getAdSource(),
6412
+ timestamp: /* @__PURE__ */ new Date().toISOString()
6413
+ }, firstAdUrl && {
6414
+ vastUrl: firstAdUrl
6415
+ });
6416
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo1);
6417
+ }
6152
6418
  if (this.config.debugAdTiming) {
6153
6419
  console.log("[CONTINUOUS-FETCH] \u2705 First ad request successful, starting playback");
6154
6420
  }
@@ -6294,15 +6560,34 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6294
6560
  key: "continuousFetchLoop",
6295
6561
  value: function continuousFetchLoop(baseVastUrl) {
6296
6562
  return _async_to_generator(function() {
6297
- var _this, _loop, _ret;
6563
+ var loopIterations, _this, _loop, _ret;
6298
6564
  return _ts_generator(this, function(_state) {
6299
6565
  switch(_state.label){
6300
6566
  case 0:
6567
+ loopIterations = 0;
6568
+ _state.label = 1;
6569
+ case 1:
6570
+ _state.trys.push([
6571
+ 1,
6572
+ ,
6573
+ 5,
6574
+ 6
6575
+ ]);
6301
6576
  _loop = function() {
6302
- var remaining, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6577
+ var remaining, elapsedMs, maxLoopMs, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6303
6578
  return _ts_generator(this, function(_state) {
6304
6579
  switch(_state.label){
6305
6580
  case 0:
6581
+ loopIterations++;
6582
+ if (loopIterations > _this.continuousFetchMaxIterations) {
6583
+ if (_this.config.debugAdTiming) {
6584
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Max iterations reached (".concat(_this.continuousFetchMaxIterations, "), stopping URL generation"));
6585
+ }
6586
+ return [
6587
+ 2,
6588
+ "break"
6589
+ ];
6590
+ }
6306
6591
  remaining = _this.getRemainingAdMs();
6307
6592
  if (remaining <= 0) {
6308
6593
  if (_this.config.debugAdTiming) {
@@ -6313,6 +6598,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6313
6598
  "break"
6314
6599
  ];
6315
6600
  }
6601
+ if (_this.currentAdBreakStartWallClockMs != null && _this.expectedAdBreakDurationMs != null) {
6602
+ elapsedMs = Date.now() - _this.currentAdBreakStartWallClockMs;
6603
+ maxLoopMs = _this.expectedAdBreakDurationMs + _this.continuousFetchWallClockBufferMs;
6604
+ if (elapsedMs >= maxLoopMs) {
6605
+ if (_this.config.debugAdTiming) {
6606
+ console.log("[CONTINUOUS-FETCH] ⏹️ Wall-clock limit reached (".concat(elapsedMs, "ms >= ").concat(maxLoopMs, "ms), stopping URL generation"));
6607
+ }
6608
+ return [
6609
+ 2,
6610
+ "break"
6611
+ ];
6612
+ }
6613
+ }
6316
6614
  if (_this.consecutiveFailures >= _this.maxConsecutiveFailures) {
6317
6615
  if (_this.config.debugAdTiming) {
6318
6616
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Too many consecutive failures (".concat(_this.consecutiveFailures, "), stopping URL generation"));
@@ -6334,46 +6632,63 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6334
6632
  maxQueueSize = 5;
6335
6633
  if (!(_this.adRequestQueue.length >= maxQueueSize)) return [
6336
6634
  3,
6337
- 2
6635
+ 4
6338
6636
  ];
6637
+ if (!(_this.isPrebidMode() && _this.isLgStbDevice())) return [
6638
+ 3,
6639
+ 1
6640
+ ];
6641
+ _this.adRequestQueue.shift();
6642
+ _this.adRequestQueue.push("");
6643
+ _this.totalAdsInBreak++;
6644
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6339
6645
  if (_this.config.debugAdTiming) {
6340
- console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(_this.adRequestQueue.length, "), waiting..."));
6646
+ console.log("[CONTINUOUS-FETCH] Prebid slot rotated (queue full, dropped oldest); queue: ".concat(_this.adRequestQueue.length));
6341
6647
  }
6342
6648
  return [
6343
- 4,
6344
- new Promise(function(resolve) {
6345
- return setTimeout(resolve, 1e3);
6346
- })
6649
+ 3,
6650
+ 3
6347
6651
  ];
6348
6652
  case 1:
6653
+ return [
6654
+ 4,
6655
+ _this.waitForQueueWithBackoff()
6656
+ ];
6657
+ case 2:
6349
6658
  _state.sent();
6350
6659
  return [
6351
6660
  2,
6352
6661
  "continue"
6353
6662
  ];
6354
- case 2:
6663
+ case 3:
6664
+ return [
6665
+ 3,
6666
+ 8
6667
+ ];
6668
+ case 4:
6355
6669
  if (!_this.isPrebidMode()) return [
6356
6670
  3,
6357
- 3
6671
+ 5
6358
6672
  ];
6359
6673
  _this.adRequestQueue.push("");
6360
6674
  _this.totalAdsInBreak++;
6675
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6361
6676
  if (_this.config.debugAdTiming) {
6362
6677
  console.log("[CONTINUOUS-FETCH] Prebid auction slot queued (queue: ".concat(_this.adRequestQueue.length, ")"));
6363
6678
  }
6364
6679
  return [
6365
6680
  3,
6366
- 6
6681
+ 8
6367
6682
  ];
6368
- case 3:
6683
+ case 5:
6369
6684
  if (!baseVastUrl) return [
6370
6685
  3,
6371
- 6
6686
+ 8
6372
6687
  ];
6373
6688
  newAdUrl = _this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];
6374
6689
  if (!(!newAdUrl || _this.failedVastUrls.has(newAdUrl) || _this.isUrlInCooldown(newAdUrl))) return [
6375
6690
  3,
6376
- 5
6691
+ 7
6377
6692
  ];
6378
6693
  return [
6379
6694
  4,
@@ -6381,13 +6696,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6381
6696
  return setTimeout(resolve, 500);
6382
6697
  })
6383
6698
  ];
6384
- case 4:
6699
+ case 6:
6385
6700
  _state.sent();
6386
6701
  return [
6387
6702
  2,
6388
6703
  "continue"
6389
6704
  ];
6390
- case 5:
6705
+ case 7:
6391
6706
  if (_this.config.debugAdTiming) {
6392
6707
  queuedUrlsPreview = _to_consumable_array(_this.adRequestQueue).concat([
6393
6708
  newAdUrl
@@ -6398,8 +6713,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6398
6713
  }
6399
6714
  _this.adRequestQueue.push(newAdUrl);
6400
6715
  _this.totalAdsInBreak++;
6401
- _state.label = 6;
6402
- case 6:
6716
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6717
+ _state.label = 8;
6718
+ case 8:
6403
6719
  generationDelay = _this.consecutiveFailures > 0 ? Math.min(1e3 * Math.pow(2, _this.consecutiveFailures), 5e3) : 500;
6404
6720
  return [
6405
6721
  4,
@@ -6407,7 +6723,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6407
6723
  return setTimeout(resolve, generationDelay);
6408
6724
  })
6409
6725
  ];
6410
- case 7:
6726
+ case 9:
6411
6727
  _state.sent();
6412
6728
  return [
6413
6729
  2
@@ -6415,33 +6731,41 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6415
6731
  }
6416
6732
  });
6417
6733
  };
6418
- _state.label = 1;
6419
- case 1:
6734
+ _state.label = 2;
6735
+ case 2:
6420
6736
  if (!(this.continuousFetchingActive && this.inAdBreak)) return [
6421
6737
  3,
6422
- 3
6738
+ 4
6423
6739
  ];
6424
6740
  _this = this;
6425
6741
  return [
6426
6742
  5,
6427
6743
  _ts_values(_loop())
6428
6744
  ];
6429
- case 2:
6745
+ case 3:
6430
6746
  _ret = _state.sent();
6431
6747
  if (_ret === "break") return [
6432
6748
  3,
6433
- 3
6749
+ 4
6434
6750
  ];
6435
6751
  return [
6436
6752
  3,
6437
- 1
6753
+ 2
6438
6754
  ];
6439
- case 3:
6755
+ case 4:
6756
+ return [
6757
+ 3,
6758
+ 6
6759
+ ];
6760
+ case 5:
6440
6761
  this.continuousFetchLoopRunning = false;
6762
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
6763
+ return [
6764
+ 7
6765
+ ];
6766
+ case 6:
6441
6767
  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
- } : {});
6768
+ this.logQueueState("URL generation loop ended");
6445
6769
  }
6446
6770
  return [
6447
6771
  2
@@ -6451,6 +6775,51 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6451
6775
  }).call(this);
6452
6776
  }
6453
6777
  },
6778
+ {
6779
+ key: "waitForQueueWithBackoff",
6780
+ value: function waitForQueueWithBackoff() {
6781
+ return _async_to_generator(function() {
6782
+ var delayMs, shouldLog;
6783
+ return _ts_generator(this, function(_state) {
6784
+ switch(_state.label){
6785
+ case 0:
6786
+ this.continuousFetchQueueFullConsecutiveWaits++;
6787
+ delayMs = Math.min(1e3 * Math.pow(2, this.continuousFetchQueueFullConsecutiveWaits - 1), 5e3);
6788
+ shouldLog = this.config.debugAdTiming && (this.continuousFetchQueueFullConsecutiveWaits <= 2 || this.continuousFetchQueueFullConsecutiveWaits % 4 === 0);
6789
+ if (shouldLog) {
6790
+ console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(this.adRequestQueue.length, "), waiting ").concat(delayMs, "ms (wait #").concat(this.continuousFetchQueueFullConsecutiveWaits, ")"));
6791
+ }
6792
+ return [
6793
+ 4,
6794
+ new Promise(function(resolve) {
6795
+ return setTimeout(resolve, delayMs);
6796
+ })
6797
+ ];
6798
+ case 1:
6799
+ _state.sent();
6800
+ return [
6801
+ 2
6802
+ ];
6803
+ }
6804
+ });
6805
+ }).call(this);
6806
+ }
6807
+ },
6808
+ {
6809
+ key: "logQueueState",
6810
+ value: function logQueueState(reason) {
6811
+ if (!this.config.debugAdTiming) return;
6812
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 ".concat(reason), {
6813
+ queueLength: this.adRequestQueue.length,
6814
+ totalAdsInBreak: this.totalAdsInBreak,
6815
+ totalAdRequestsInBreak: this.totalAdRequestsInBreak,
6816
+ consecutiveFailures: this.consecutiveFailures,
6817
+ continuousFetchingActive: this.continuousFetchingActive,
6818
+ continuousFetchLoopRunning: this.continuousFetchLoopRunning,
6819
+ inAdBreak: this.inAdBreak
6820
+ });
6821
+ }
6822
+ },
6454
6823
  {
6455
6824
  key: "stopContinuousFetching",
6456
6825
  value: function stopContinuousFetching() {
@@ -6515,7 +6884,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6515
6884
  value: function tryNextAvailableAd() {
6516
6885
  var retryCount = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 0;
6517
6886
  return _async_to_generator(function() {
6518
- var remaining, preloaded, currentMuted, currentVolume, adVolume, error, nextAdUrl, currentMuted1, currentVolume1, error1, errorMessage, maxRetries;
6887
+ var remaining, preloaded, adLoadedInfo, currentMuted, currentVolume, adVolume, error, nextAdUrl, currentMuted1, currentVolume1, error1, errorMessage, maxRetries;
6519
6888
  return _ts_generator(this, function(_state) {
6520
6889
  switch(_state.label){
6521
6890
  case 0:
@@ -6560,6 +6929,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6560
6929
  this.video.volume = 0;
6561
6930
  this.ima = preloaded.imaController;
6562
6931
  this.attachImaEventListeners();
6932
+ if (this.config.licenseKey) {
6933
+ adLoadedInfo = {
6934
+ source: this.getAdSource(),
6935
+ timestamp: /* @__PURE__ */ new Date().toISOString()
6936
+ };
6937
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
6938
+ }
6563
6939
  this.ima.resume();
6564
6940
  this.currentAdIndex++;
6565
6941
  this.totalAdRequestsInBreak++;
@@ -6621,8 +6997,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6621
6997
  4
6622
6998
  ];
6623
6999
  }
7000
+ console.log("[StormcloudVideoPlayer] Requesting next ad (%s), queue remaining=%s", nextAdUrl === "" ? "Prebid" : "VAST", this.adRequestQueue.length);
6624
7001
  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)"));
7002
+ 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
7003
  }
6627
7004
  currentMuted1 = this.video.muted;
6628
7005
  currentVolume1 = this.video.volume;
@@ -6802,7 +7179,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6802
7179
  ];
6803
7180
  }
6804
7181
  if (this.config.debugAdTiming) {
6805
- console.log("[CONTINUOUS-FETCH] \u2705 Ad URL available, requesting via IMA SDK");
7182
+ console.log("[CONTINUOUS-FETCH] Ad URL available, requesting via ".concat(this.getAdPlayerTypeLabel()));
6806
7183
  }
6807
7184
  this.isShowingPlaceholder = false;
6808
7185
  this.ima.hidePlaceholder();
@@ -7117,7 +7494,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7117
7494
  key: "playSingleAd",
7118
7495
  value: function playSingleAd(vastTagUrl) {
7119
7496
  return _async_to_generator(function() {
7120
- var requestToken, currentMuted, currentVolume, adVolume, playError, preloadedFallback, currentMuted1, currentVolume1, adVolume1, fallbackError, error, errorMessage, preloadedFallback1, currentMuted2, currentVolume2, adVolume2, fallbackError1;
7497
+ var requestToken, adLoadedInfo, currentMuted, currentVolume, adVolume, playError, preloadedFallback, currentMuted1, currentVolume1, adVolume1, fallbackError, error, errorMessage, preloadedFallback1, currentMuted2, currentVolume2, adVolume2, fallbackError1;
7121
7498
  return _ts_generator(this, function(_state) {
7122
7499
  switch(_state.label){
7123
7500
  case 0:
@@ -7144,7 +7521,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7144
7521
  }
7145
7522
  throw new Error("Too many consecutive failures");
7146
7523
  }
7147
- this.recreateImaController();
7524
+ this.recreateAdController();
7148
7525
  requestToken = ++this.adRequestTokenCounter;
7149
7526
  this.activeAdRequestToken = requestToken;
7150
7527
  this.startAdRequestWatchdog(requestToken);
@@ -7169,6 +7546,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7169
7546
  2
7170
7547
  ];
7171
7548
  }
7549
+ if (this.config.licenseKey) {
7550
+ adLoadedInfo = _object_spread({
7551
+ source: this.getAdSource(),
7552
+ timestamp: /* @__PURE__ */ new Date().toISOString()
7553
+ }, vastTagUrl && {
7554
+ vastUrl: vastTagUrl
7555
+ });
7556
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
7557
+ }
7172
7558
  _state.label = 3;
7173
7559
  case 3:
7174
7560
  _state.trys.push([
@@ -7389,6 +7775,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7389
7775
  this.showAds = false;
7390
7776
  this.currentAdIndex = 0;
7391
7777
  this.totalAdsInBreak = 0;
7778
+ this.totalAdRequestsInBreak = 0;
7392
7779
  this.consecutiveFailures = 0;
7393
7780
  this.ima.stop().catch(function() {});
7394
7781
  var restoredMuted = this.ima.getOriginalMutedState();
@@ -7400,17 +7787,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7400
7787
  this.video.volume = restoredVolume;
7401
7788
  }
7402
7789
  if (this.shouldContinueLiveStreamDuringAds()) {
7403
- if (this.video.paused) {
7404
- var _this_video_play;
7405
- if (this.config.debugAdTiming) {
7790
+ var _this_video_play;
7791
+ if (this.config.debugAdTiming) {
7792
+ if (this.video.paused) {
7406
7793
  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) {
7794
+ } else {
7411
7795
  console.log("[StormcloudVideoPlayer] Content video already playing in live mode after ads");
7412
7796
  }
7413
7797
  }
7798
+ (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
7414
7799
  } else if (this.video.paused) {
7415
7800
  var _this_video_play1;
7416
7801
  (_this_video_play1 = this.video.play()) === null || _this_video_play1 === void 0 ? void 0 : _this_video_play1.catch(function() {});