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
@@ -1293,6 +1293,7 @@ function createImaController(video, options) {
1293
1293
  adContainerEl.offsetHeight;
1294
1294
  adContainerEl.style.opacity = "1";
1295
1295
  }
1296
+ emit("ad_impression");
1296
1297
  });
1297
1298
  adsManager.addEventListener(AdEvent.CONTENT_RESUME_REQUESTED, function() {
1298
1299
  adPlaying = false;
@@ -2094,11 +2095,12 @@ function createHlsAdPlayer(contentVideo, options) {
2094
2095
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2095
2096
  if (contentVideo.paused) {
2096
2097
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback");
2097
- contentVideo.play().catch(function() {});
2098
2098
  } else {
2099
2099
  console.log("[HlsAdPlayer] Content video already playing in live mode");
2100
2100
  }
2101
+ contentVideo.play().catch(function() {});
2101
2102
  }
2103
+ emit("ad_impression");
2102
2104
  emit("content_resume");
2103
2105
  }
2104
2106
  function handleAdError() {
@@ -2370,8 +2372,8 @@ function createHlsAdPlayer(contentVideo, options) {
2370
2372
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2371
2373
  if (contentVideo.paused) {
2372
2374
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback on stop");
2373
- contentVideo.play().catch(function() {});
2374
2375
  }
2376
+ contentVideo.play().catch(function() {});
2375
2377
  }
2376
2378
  if (adHls) {
2377
2379
  adHls.destroy();
@@ -2380,6 +2382,8 @@ function createHlsAdPlayer(contentVideo, options) {
2380
2382
  if (adVideoElement) {
2381
2383
  adVideoElement.pause();
2382
2384
  adVideoElement.src = "";
2385
+ adVideoElement.remove();
2386
+ adVideoElement = void 0;
2383
2387
  }
2384
2388
  currentAd = void 0;
2385
2389
  return [
@@ -3030,11 +3034,12 @@ function createPrebidController(contentVideo, options) {
3030
3034
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
3031
3035
  if (contentVideo.paused) {
3032
3036
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback"));
3033
- contentVideo.play().catch(function() {});
3034
3037
  } else {
3035
3038
  console.log("".concat(LOG, " Content video already playing in live mode"));
3036
3039
  }
3040
+ contentVideo.play().catch(function() {});
3037
3041
  }
3042
+ emit("ad_impression");
3038
3043
  emit("content_resume");
3039
3044
  }
3040
3045
  function handleAdError() {
@@ -3399,8 +3404,8 @@ function createPrebidController(contentVideo, options) {
3399
3404
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
3400
3405
  if (contentVideo.paused) {
3401
3406
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback on stop"));
3402
- contentVideo.play().catch(function() {});
3403
3407
  }
3408
+ contentVideo.play().catch(function() {});
3404
3409
  }
3405
3410
  if (adHls) {
3406
3411
  adHls.destroy();
@@ -3409,6 +3414,8 @@ function createPrebidController(contentVideo, options) {
3409
3414
  if (adVideoElement) {
3410
3415
  adVideoElement.pause();
3411
3416
  adVideoElement.src = "";
3417
+ adVideoElement.remove();
3418
+ adVideoElement = void 0;
3412
3419
  }
3413
3420
  currentAd = void 0;
3414
3421
  return [
@@ -3755,6 +3762,45 @@ function getBrowserID(clientInfo) {
3755
3762
  });
3756
3763
  })();
3757
3764
  }
3765
+ var TRACK_URL = "https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track";
3766
+ function sendTrackRequest(licenseKey, body) {
3767
+ return _async_to_generator(function() {
3768
+ var headers, response;
3769
+ return _ts_generator(this, function(_state) {
3770
+ switch(_state.label){
3771
+ case 0:
3772
+ headers = {
3773
+ "Content-Type": "application/json"
3774
+ };
3775
+ if (licenseKey) {
3776
+ headers["Authorization"] = "Bearer ".concat(licenseKey);
3777
+ }
3778
+ return [
3779
+ 4,
3780
+ fetch(TRACK_URL, {
3781
+ method: "POST",
3782
+ headers: headers,
3783
+ body: JSON.stringify(body)
3784
+ })
3785
+ ];
3786
+ case 1:
3787
+ response = _state.sent();
3788
+ if (!response.ok) {
3789
+ throw new Error("HTTP error! status: ".concat(response.status));
3790
+ }
3791
+ return [
3792
+ 4,
3793
+ response.json()
3794
+ ];
3795
+ case 2:
3796
+ _state.sent();
3797
+ return [
3798
+ 2
3799
+ ];
3800
+ }
3801
+ });
3802
+ })();
3803
+ }
3758
3804
  function sendInitialTracking(licenseKey) {
3759
3805
  return _async_to_generator(function() {
3760
3806
  var clientInfo, browserId, trackingData, headers, response, error;
@@ -3785,7 +3831,7 @@ function sendInitialTracking(licenseKey) {
3785
3831
  }
3786
3832
  return [
3787
3833
  4,
3788
- fetch("https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track", {
3834
+ fetch(TRACK_URL, {
3789
3835
  method: "POST",
3790
3836
  headers: headers,
3791
3837
  body: JSON.stringify(trackingData)
@@ -3821,6 +3867,156 @@ function sendInitialTracking(licenseKey) {
3821
3867
  });
3822
3868
  })();
3823
3869
  }
3870
+ function sendAdDetectTracking(licenseKey, adDetectInfo) {
3871
+ return _async_to_generator(function() {
3872
+ var clientInfo, browserId, trackingData, error;
3873
+ return _ts_generator(this, function(_state) {
3874
+ switch(_state.label){
3875
+ case 0:
3876
+ _state.trys.push([
3877
+ 0,
3878
+ 3,
3879
+ ,
3880
+ 4
3881
+ ]);
3882
+ clientInfo = getClientInfo();
3883
+ return [
3884
+ 4,
3885
+ getBrowserID(clientInfo)
3886
+ ];
3887
+ case 1:
3888
+ browserId = _state.sent();
3889
+ trackingData = _object_spread({
3890
+ browserId: browserId
3891
+ }, clientInfo);
3892
+ return [
3893
+ 4,
3894
+ sendTrackRequest(licenseKey, _object_spread_props(_object_spread({}, trackingData), {
3895
+ licenseKey: licenseKey,
3896
+ adDetectInfo: adDetectInfo
3897
+ }))
3898
+ ];
3899
+ case 2:
3900
+ _state.sent();
3901
+ return [
3902
+ 3,
3903
+ 4
3904
+ ];
3905
+ case 3:
3906
+ error = _state.sent();
3907
+ console.error("[StormcloudVideoPlayer] Error sending ad detect tracking:", error);
3908
+ return [
3909
+ 3,
3910
+ 4
3911
+ ];
3912
+ case 4:
3913
+ return [
3914
+ 2
3915
+ ];
3916
+ }
3917
+ });
3918
+ })();
3919
+ }
3920
+ function sendAdLoadedTracking(licenseKey, adLoadedInfo) {
3921
+ return _async_to_generator(function() {
3922
+ var clientInfo, browserId, trackingData, error;
3923
+ return _ts_generator(this, function(_state) {
3924
+ switch(_state.label){
3925
+ case 0:
3926
+ _state.trys.push([
3927
+ 0,
3928
+ 3,
3929
+ ,
3930
+ 4
3931
+ ]);
3932
+ clientInfo = getClientInfo();
3933
+ return [
3934
+ 4,
3935
+ getBrowserID(clientInfo)
3936
+ ];
3937
+ case 1:
3938
+ browserId = _state.sent();
3939
+ trackingData = _object_spread({
3940
+ browserId: browserId
3941
+ }, clientInfo);
3942
+ return [
3943
+ 4,
3944
+ sendTrackRequest(licenseKey, _object_spread_props(_object_spread({}, trackingData), {
3945
+ licenseKey: licenseKey,
3946
+ adLoadedInfo: adLoadedInfo
3947
+ }))
3948
+ ];
3949
+ case 2:
3950
+ _state.sent();
3951
+ return [
3952
+ 3,
3953
+ 4
3954
+ ];
3955
+ case 3:
3956
+ error = _state.sent();
3957
+ console.error("[StormcloudVideoPlayer] Error sending ad loaded tracking:", error);
3958
+ return [
3959
+ 3,
3960
+ 4
3961
+ ];
3962
+ case 4:
3963
+ return [
3964
+ 2
3965
+ ];
3966
+ }
3967
+ });
3968
+ })();
3969
+ }
3970
+ function sendAdImpressionTracking(licenseKey, adImpressionInfo) {
3971
+ return _async_to_generator(function() {
3972
+ var clientInfo, browserId, trackingData, error;
3973
+ return _ts_generator(this, function(_state) {
3974
+ switch(_state.label){
3975
+ case 0:
3976
+ _state.trys.push([
3977
+ 0,
3978
+ 3,
3979
+ ,
3980
+ 4
3981
+ ]);
3982
+ clientInfo = getClientInfo();
3983
+ return [
3984
+ 4,
3985
+ getBrowserID(clientInfo)
3986
+ ];
3987
+ case 1:
3988
+ browserId = _state.sent();
3989
+ trackingData = _object_spread({
3990
+ browserId: browserId
3991
+ }, clientInfo);
3992
+ return [
3993
+ 4,
3994
+ sendTrackRequest(licenseKey, _object_spread_props(_object_spread({}, trackingData), {
3995
+ licenseKey: licenseKey,
3996
+ adImpressionInfo: adImpressionInfo
3997
+ }))
3998
+ ];
3999
+ case 2:
4000
+ _state.sent();
4001
+ return [
4002
+ 3,
4003
+ 4
4004
+ ];
4005
+ case 3:
4006
+ error = _state.sent();
4007
+ console.error("[StormcloudVideoPlayer] Error sending ad impression tracking:", error);
4008
+ return [
4009
+ 3,
4010
+ 4
4011
+ ];
4012
+ case 4:
4013
+ return [
4014
+ 2
4015
+ ];
4016
+ }
4017
+ });
4018
+ })();
4019
+ }
3824
4020
  function sendHeartbeat(licenseKey) {
3825
4021
  return _async_to_generator(function() {
3826
4022
  var clientInfo, browserId, heartbeatData, headers, response, error;
@@ -4177,6 +4373,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4177
4373
  this.minAdRequestIntervalMs = 2500;
4178
4374
  this.backoffBaseMs = 1e3;
4179
4375
  this.maxBackoffMs = 15e3;
4376
+ this.continuousFetchWallClockBufferMs = 3e4;
4377
+ this.continuousFetchMaxIterations = 500;
4378
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
4180
4379
  this.preloadPool = [];
4181
4380
  this.maxPreloadPoolSize = 3;
4182
4381
  this.preloadPoolActive = false;
@@ -4236,6 +4435,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4236
4435
  }
4237
4436
  }
4238
4437
  },
4438
+ {
4439
+ key: "getAdPlayerTypeLabel",
4440
+ value: function getAdPlayerTypeLabel() {
4441
+ var t = this.config.adPlayerType;
4442
+ if (t === "prebid") return "Prebid";
4443
+ if (t === "hls") return "HLS";
4444
+ return "IMA";
4445
+ }
4446
+ },
4239
4447
  {
4240
4448
  key: "load",
4241
4449
  value: function load() {
@@ -4659,10 +4867,26 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4659
4867
  }).call(this);
4660
4868
  }
4661
4869
  },
4870
+ {
4871
+ key: "getAdSource",
4872
+ value: function getAdSource() {
4873
+ var _this_config_adPlayerType;
4874
+ return (_this_config_adPlayerType = this.config.adPlayerType) !== null && _this_config_adPlayerType !== void 0 ? _this_config_adPlayerType : "ima";
4875
+ }
4876
+ },
4662
4877
  {
4663
4878
  key: "attachImaEventListeners",
4664
4879
  value: function attachImaEventListeners() {
4665
4880
  var _this = this;
4881
+ this.ima.on("ad_impression", function() {
4882
+ if (_this.config.licenseKey) {
4883
+ sendAdImpressionTracking(_this.config.licenseKey, {
4884
+ source: _this.getAdSource(),
4885
+ adIndex: _this.currentAdIndex,
4886
+ timestamp: /* @__PURE__ */ new Date().toISOString()
4887
+ });
4888
+ }
4889
+ });
4666
4890
  this.ima.on("all_ads_completed", function() {
4667
4891
  var remaining = _this.getRemainingAdMs();
4668
4892
  _this.consecutiveFailures = 0;
@@ -4725,6 +4949,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4725
4949
  }
4726
4950
  });
4727
4951
  this.ima.on("content_resume", function() {
4952
+ console.log("[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s", _this.inAdBreak, _this.getRemainingAdMs());
4728
4953
  if (!_this.video.muted) {
4729
4954
  _this.video.muted = true;
4730
4955
  _this.video.volume = 0;
@@ -4755,15 +4980,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4755
4980
  }
4756
4981
  },
4757
4982
  {
4758
- key: "recreateImaController",
4759
- value: function recreateImaController() {
4983
+ key: "recreateAdController",
4984
+ value: function recreateAdController() {
4985
+ var label = this.getAdPlayerTypeLabel();
4760
4986
  if (this.config.debugAdTiming) {
4761
- console.log("[StormcloudVideoPlayer] Recreating ImaController for new ad");
4987
+ console.log("[StormcloudVideoPlayer] Recreating ad controller (".concat(label, ") for new ad"));
4762
4988
  }
4763
4989
  var shouldShowPlaceholder = this.inAdBreak && this.showAds;
4764
4990
  if (shouldShowPlaceholder && this.ima) {
4765
4991
  if (this.config.debugAdTiming) {
4766
- console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ImaController");
4992
+ console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ".concat(label, " controller"));
4767
4993
  }
4768
4994
  this.showPlaceholderLayer();
4769
4995
  this.ima.showPlaceholder();
@@ -4776,7 +5002,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4776
5002
  this.video.volume = 0;
4777
5003
  } catch (error) {
4778
5004
  if (this.config.debugAdTiming) {
4779
- console.warn("[StormcloudVideoPlayer] Error destroying old ImaController:", error);
5005
+ console.warn("[StormcloudVideoPlayer] Error destroying old ".concat(label, " controller:"), error);
4780
5006
  }
4781
5007
  }
4782
5008
  }
@@ -4856,7 +5082,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4856
5082
  });
4857
5083
  }
4858
5084
  if (this.config.debugAdTiming) {
4859
- console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and IMA)");
5085
+ console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and ".concat(this.getAdPlayerTypeLabel(), ")"));
4860
5086
  }
4861
5087
  }
4862
5088
  },
@@ -5113,6 +5339,20 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5113
5339
  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;
5114
5340
  this.expectedAdBreakDurationMs = durationMs;
5115
5341
  this.currentAdBreakStartWallClockMs = Date.now();
5342
+ if (this.config.licenseKey) {
5343
+ var _this_pendingAdBreak1;
5344
+ var adDetectInfo = _object_spread({
5345
+ source: "scte35",
5346
+ timestamp: /* @__PURE__ */ new Date().toISOString()
5347
+ }, marker.durationSeconds != null && {
5348
+ durationSeconds: marker.durationSeconds
5349
+ }, marker.ptsSeconds != null && {
5350
+ ptsSeconds: marker.ptsSeconds
5351
+ }, ((_this_pendingAdBreak1 = this.pendingAdBreak) === null || _this_pendingAdBreak1 === void 0 ? void 0 : _this_pendingAdBreak1.detectedAtFragmentSn) != null && {
5352
+ detectedAtFragmentSn: this.pendingAdBreak.detectedAtFragmentSn
5353
+ });
5354
+ sendAdDetectTracking(this.config.licenseKey, adDetectInfo);
5355
+ }
5116
5356
  var isManifestMarker = this.isManifestBasedMarker(marker);
5117
5357
  var forceImmediate = (_this_config_immediateManifestAds = this.config.immediateManifestAds) !== null && _this_config_immediateManifestAds !== void 0 ? _this_config_immediateManifestAds : true;
5118
5358
  if (this.config.debugAdTiming) {
@@ -5568,6 +5808,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5568
5808
  return this.config.adPlayerType === "prebid";
5569
5809
  }
5570
5810
  },
5811
+ {
5812
+ key: "isLgStbDevice",
5813
+ value: function isLgStbDevice() {
5814
+ if (typeof navigator === "undefined" || !navigator.userAgent) return false;
5815
+ var ua = navigator.userAgent;
5816
+ return /Web0S|webOS|LG Browser|LGSTB/i.test(ua);
5817
+ }
5818
+ },
5571
5819
  {
5572
5820
  key: "getCurrentAdIndex",
5573
5821
  value: function getCurrentAdIndex() {
@@ -6090,7 +6338,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6090
6338
  key: "handleAdStart",
6091
6339
  value: function handleAdStart(_marker) {
6092
6340
  return _async_to_generator(function() {
6093
- var scheduled, tags, isPrebid, baseVastUrl, adBreakDurationMs, mode, currentMuted, currentVolume, firstAdUrl, usePreloadedAd, preloadedController, preloaded, firstAdUrlArray, adVolume, adVolume1, error, fallbackPreloaded, adVolume2, fallbackError;
6341
+ var scheduled, tags, isPrebid, baseVastUrl, adBreakDurationMs, mode, currentMuted, currentVolume, firstAdUrl, usePreloadedAd, preloadedController, preloaded, firstAdUrlArray, adLoadedInfo, adVolume, adLoadedInfo1, adVolume1, error, fallbackPreloaded, adVolume2, fallbackError;
6094
6342
  return _ts_generator(this, function(_state) {
6095
6343
  switch(_state.label){
6096
6344
  case 0:
@@ -6202,6 +6450,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6202
6450
  this.video.volume = 0;
6203
6451
  this.ima = preloadedController;
6204
6452
  this.attachImaEventListeners();
6453
+ if (this.config.licenseKey) {
6454
+ adLoadedInfo = _object_spread({
6455
+ source: this.getAdSource(),
6456
+ timestamp: /* @__PURE__ */ new Date().toISOString()
6457
+ }, firstAdUrl && {
6458
+ vastUrl: firstAdUrl
6459
+ });
6460
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
6461
+ }
6205
6462
  if (this.config.debugAdTiming) {
6206
6463
  console.log("[CONTINUOUS-FETCH] \u2705 Using preloaded ad, resuming and starting playback immediately (no request delay!)");
6207
6464
  }
@@ -6237,6 +6494,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6237
6494
  ];
6238
6495
  case 4:
6239
6496
  _state.sent();
6497
+ if (this.config.licenseKey) {
6498
+ adLoadedInfo1 = _object_spread({
6499
+ source: this.getAdSource(),
6500
+ timestamp: /* @__PURE__ */ new Date().toISOString()
6501
+ }, firstAdUrl && {
6502
+ vastUrl: firstAdUrl
6503
+ });
6504
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo1);
6505
+ }
6240
6506
  if (this.config.debugAdTiming) {
6241
6507
  console.log("[CONTINUOUS-FETCH] \u2705 First ad request successful, starting playback");
6242
6508
  }
@@ -6382,15 +6648,34 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6382
6648
  key: "continuousFetchLoop",
6383
6649
  value: function continuousFetchLoop(baseVastUrl) {
6384
6650
  return _async_to_generator(function() {
6385
- var _this, _loop, _ret;
6651
+ var loopIterations, _this, _loop, _ret;
6386
6652
  return _ts_generator(this, function(_state) {
6387
6653
  switch(_state.label){
6388
6654
  case 0:
6655
+ loopIterations = 0;
6656
+ _state.label = 1;
6657
+ case 1:
6658
+ _state.trys.push([
6659
+ 1,
6660
+ ,
6661
+ 5,
6662
+ 6
6663
+ ]);
6389
6664
  _loop = function() {
6390
- var remaining, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6665
+ var remaining, elapsedMs, maxLoopMs, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6391
6666
  return _ts_generator(this, function(_state) {
6392
6667
  switch(_state.label){
6393
6668
  case 0:
6669
+ loopIterations++;
6670
+ if (loopIterations > _this.continuousFetchMaxIterations) {
6671
+ if (_this.config.debugAdTiming) {
6672
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Max iterations reached (".concat(_this.continuousFetchMaxIterations, "), stopping URL generation"));
6673
+ }
6674
+ return [
6675
+ 2,
6676
+ "break"
6677
+ ];
6678
+ }
6394
6679
  remaining = _this.getRemainingAdMs();
6395
6680
  if (remaining <= 0) {
6396
6681
  if (_this.config.debugAdTiming) {
@@ -6401,6 +6686,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6401
6686
  "break"
6402
6687
  ];
6403
6688
  }
6689
+ if (_this.currentAdBreakStartWallClockMs != null && _this.expectedAdBreakDurationMs != null) {
6690
+ elapsedMs = Date.now() - _this.currentAdBreakStartWallClockMs;
6691
+ maxLoopMs = _this.expectedAdBreakDurationMs + _this.continuousFetchWallClockBufferMs;
6692
+ if (elapsedMs >= maxLoopMs) {
6693
+ if (_this.config.debugAdTiming) {
6694
+ console.log("[CONTINUOUS-FETCH] ⏹️ Wall-clock limit reached (".concat(elapsedMs, "ms >= ").concat(maxLoopMs, "ms), stopping URL generation"));
6695
+ }
6696
+ return [
6697
+ 2,
6698
+ "break"
6699
+ ];
6700
+ }
6701
+ }
6404
6702
  if (_this.consecutiveFailures >= _this.maxConsecutiveFailures) {
6405
6703
  if (_this.config.debugAdTiming) {
6406
6704
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Too many consecutive failures (".concat(_this.consecutiveFailures, "), stopping URL generation"));
@@ -6422,46 +6720,63 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6422
6720
  maxQueueSize = 5;
6423
6721
  if (!(_this.adRequestQueue.length >= maxQueueSize)) return [
6424
6722
  3,
6425
- 2
6723
+ 4
6426
6724
  ];
6725
+ if (!(_this.isPrebidMode() && _this.isLgStbDevice())) return [
6726
+ 3,
6727
+ 1
6728
+ ];
6729
+ _this.adRequestQueue.shift();
6730
+ _this.adRequestQueue.push("");
6731
+ _this.totalAdsInBreak++;
6732
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6427
6733
  if (_this.config.debugAdTiming) {
6428
- console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(_this.adRequestQueue.length, "), waiting..."));
6734
+ console.log("[CONTINUOUS-FETCH] Prebid slot rotated (queue full, dropped oldest); queue: ".concat(_this.adRequestQueue.length));
6429
6735
  }
6430
6736
  return [
6431
- 4,
6432
- new Promise(function(resolve) {
6433
- return setTimeout(resolve, 1e3);
6434
- })
6737
+ 3,
6738
+ 3
6435
6739
  ];
6436
6740
  case 1:
6741
+ return [
6742
+ 4,
6743
+ _this.waitForQueueWithBackoff()
6744
+ ];
6745
+ case 2:
6437
6746
  _state.sent();
6438
6747
  return [
6439
6748
  2,
6440
6749
  "continue"
6441
6750
  ];
6442
- case 2:
6751
+ case 3:
6752
+ return [
6753
+ 3,
6754
+ 8
6755
+ ];
6756
+ case 4:
6443
6757
  if (!_this.isPrebidMode()) return [
6444
6758
  3,
6445
- 3
6759
+ 5
6446
6760
  ];
6447
6761
  _this.adRequestQueue.push("");
6448
6762
  _this.totalAdsInBreak++;
6763
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6449
6764
  if (_this.config.debugAdTiming) {
6450
6765
  console.log("[CONTINUOUS-FETCH] Prebid auction slot queued (queue: ".concat(_this.adRequestQueue.length, ")"));
6451
6766
  }
6452
6767
  return [
6453
6768
  3,
6454
- 6
6769
+ 8
6455
6770
  ];
6456
- case 3:
6771
+ case 5:
6457
6772
  if (!baseVastUrl) return [
6458
6773
  3,
6459
- 6
6774
+ 8
6460
6775
  ];
6461
6776
  newAdUrl = _this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];
6462
6777
  if (!(!newAdUrl || _this.failedVastUrls.has(newAdUrl) || _this.isUrlInCooldown(newAdUrl))) return [
6463
6778
  3,
6464
- 5
6779
+ 7
6465
6780
  ];
6466
6781
  return [
6467
6782
  4,
@@ -6469,13 +6784,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6469
6784
  return setTimeout(resolve, 500);
6470
6785
  })
6471
6786
  ];
6472
- case 4:
6787
+ case 6:
6473
6788
  _state.sent();
6474
6789
  return [
6475
6790
  2,
6476
6791
  "continue"
6477
6792
  ];
6478
- case 5:
6793
+ case 7:
6479
6794
  if (_this.config.debugAdTiming) {
6480
6795
  queuedUrlsPreview = _to_consumable_array(_this.adRequestQueue).concat([
6481
6796
  newAdUrl
@@ -6486,8 +6801,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6486
6801
  }
6487
6802
  _this.adRequestQueue.push(newAdUrl);
6488
6803
  _this.totalAdsInBreak++;
6489
- _state.label = 6;
6490
- case 6:
6804
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6805
+ _state.label = 8;
6806
+ case 8:
6491
6807
  generationDelay = _this.consecutiveFailures > 0 ? Math.min(1e3 * Math.pow(2, _this.consecutiveFailures), 5e3) : 500;
6492
6808
  return [
6493
6809
  4,
@@ -6495,7 +6811,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6495
6811
  return setTimeout(resolve, generationDelay);
6496
6812
  })
6497
6813
  ];
6498
- case 7:
6814
+ case 9:
6499
6815
  _state.sent();
6500
6816
  return [
6501
6817
  2
@@ -6503,33 +6819,41 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6503
6819
  }
6504
6820
  });
6505
6821
  };
6506
- _state.label = 1;
6507
- case 1:
6822
+ _state.label = 2;
6823
+ case 2:
6508
6824
  if (!(this.continuousFetchingActive && this.inAdBreak)) return [
6509
6825
  3,
6510
- 3
6826
+ 4
6511
6827
  ];
6512
6828
  _this = this;
6513
6829
  return [
6514
6830
  5,
6515
6831
  _ts_values(_loop())
6516
6832
  ];
6517
- case 2:
6833
+ case 3:
6518
6834
  _ret = _state.sent();
6519
6835
  if (_ret === "break") return [
6520
6836
  3,
6521
- 3
6837
+ 4
6522
6838
  ];
6523
6839
  return [
6524
6840
  3,
6525
- 1
6841
+ 2
6526
6842
  ];
6527
- case 3:
6843
+ case 4:
6844
+ return [
6845
+ 3,
6846
+ 6
6847
+ ];
6848
+ case 5:
6528
6849
  this.continuousFetchLoopRunning = false;
6850
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
6851
+ return [
6852
+ 7
6853
+ ];
6854
+ case 6:
6529
6855
  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
- } : {});
6856
+ this.logQueueState("URL generation loop ended");
6533
6857
  }
6534
6858
  return [
6535
6859
  2
@@ -6539,6 +6863,51 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6539
6863
  }).call(this);
6540
6864
  }
6541
6865
  },
6866
+ {
6867
+ key: "waitForQueueWithBackoff",
6868
+ value: function waitForQueueWithBackoff() {
6869
+ return _async_to_generator(function() {
6870
+ var delayMs, shouldLog;
6871
+ return _ts_generator(this, function(_state) {
6872
+ switch(_state.label){
6873
+ case 0:
6874
+ this.continuousFetchQueueFullConsecutiveWaits++;
6875
+ delayMs = Math.min(1e3 * Math.pow(2, this.continuousFetchQueueFullConsecutiveWaits - 1), 5e3);
6876
+ shouldLog = this.config.debugAdTiming && (this.continuousFetchQueueFullConsecutiveWaits <= 2 || this.continuousFetchQueueFullConsecutiveWaits % 4 === 0);
6877
+ if (shouldLog) {
6878
+ console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(this.adRequestQueue.length, "), waiting ").concat(delayMs, "ms (wait #").concat(this.continuousFetchQueueFullConsecutiveWaits, ")"));
6879
+ }
6880
+ return [
6881
+ 4,
6882
+ new Promise(function(resolve) {
6883
+ return setTimeout(resolve, delayMs);
6884
+ })
6885
+ ];
6886
+ case 1:
6887
+ _state.sent();
6888
+ return [
6889
+ 2
6890
+ ];
6891
+ }
6892
+ });
6893
+ }).call(this);
6894
+ }
6895
+ },
6896
+ {
6897
+ key: "logQueueState",
6898
+ value: function logQueueState(reason) {
6899
+ if (!this.config.debugAdTiming) return;
6900
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 ".concat(reason), {
6901
+ queueLength: this.adRequestQueue.length,
6902
+ totalAdsInBreak: this.totalAdsInBreak,
6903
+ totalAdRequestsInBreak: this.totalAdRequestsInBreak,
6904
+ consecutiveFailures: this.consecutiveFailures,
6905
+ continuousFetchingActive: this.continuousFetchingActive,
6906
+ continuousFetchLoopRunning: this.continuousFetchLoopRunning,
6907
+ inAdBreak: this.inAdBreak
6908
+ });
6909
+ }
6910
+ },
6542
6911
  {
6543
6912
  key: "stopContinuousFetching",
6544
6913
  value: function stopContinuousFetching() {
@@ -6603,7 +6972,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6603
6972
  value: function tryNextAvailableAd() {
6604
6973
  var retryCount = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 0;
6605
6974
  return _async_to_generator(function() {
6606
- var remaining, preloaded, currentMuted, currentVolume, adVolume, error, nextAdUrl, currentMuted1, currentVolume1, error1, errorMessage, maxRetries;
6975
+ var remaining, preloaded, adLoadedInfo, currentMuted, currentVolume, adVolume, error, nextAdUrl, currentMuted1, currentVolume1, error1, errorMessage, maxRetries;
6607
6976
  return _ts_generator(this, function(_state) {
6608
6977
  switch(_state.label){
6609
6978
  case 0:
@@ -6648,6 +7017,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6648
7017
  this.video.volume = 0;
6649
7018
  this.ima = preloaded.imaController;
6650
7019
  this.attachImaEventListeners();
7020
+ if (this.config.licenseKey) {
7021
+ adLoadedInfo = {
7022
+ source: this.getAdSource(),
7023
+ timestamp: /* @__PURE__ */ new Date().toISOString()
7024
+ };
7025
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
7026
+ }
6651
7027
  this.ima.resume();
6652
7028
  this.currentAdIndex++;
6653
7029
  this.totalAdRequestsInBreak++;
@@ -6709,8 +7085,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6709
7085
  4
6710
7086
  ];
6711
7087
  }
7088
+ console.log("[StormcloudVideoPlayer] Requesting next ad (%s), queue remaining=%s", nextAdUrl === "" ? "Prebid" : "VAST", this.adRequestQueue.length);
6712
7089
  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)"));
7090
+ 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
7091
  }
6715
7092
  currentMuted1 = this.video.muted;
6716
7093
  currentVolume1 = this.video.volume;
@@ -6890,7 +7267,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6890
7267
  ];
6891
7268
  }
6892
7269
  if (this.config.debugAdTiming) {
6893
- console.log("[CONTINUOUS-FETCH] \u2705 Ad URL available, requesting via IMA SDK");
7270
+ console.log("[CONTINUOUS-FETCH] Ad URL available, requesting via ".concat(this.getAdPlayerTypeLabel()));
6894
7271
  }
6895
7272
  this.isShowingPlaceholder = false;
6896
7273
  this.ima.hidePlaceholder();
@@ -7205,7 +7582,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7205
7582
  key: "playSingleAd",
7206
7583
  value: function playSingleAd(vastTagUrl) {
7207
7584
  return _async_to_generator(function() {
7208
- var requestToken, currentMuted, currentVolume, adVolume, playError, preloadedFallback, currentMuted1, currentVolume1, adVolume1, fallbackError, error, errorMessage, preloadedFallback1, currentMuted2, currentVolume2, adVolume2, fallbackError1;
7585
+ var requestToken, adLoadedInfo, currentMuted, currentVolume, adVolume, playError, preloadedFallback, currentMuted1, currentVolume1, adVolume1, fallbackError, error, errorMessage, preloadedFallback1, currentMuted2, currentVolume2, adVolume2, fallbackError1;
7209
7586
  return _ts_generator(this, function(_state) {
7210
7587
  switch(_state.label){
7211
7588
  case 0:
@@ -7232,7 +7609,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7232
7609
  }
7233
7610
  throw new Error("Too many consecutive failures");
7234
7611
  }
7235
- this.recreateImaController();
7612
+ this.recreateAdController();
7236
7613
  requestToken = ++this.adRequestTokenCounter;
7237
7614
  this.activeAdRequestToken = requestToken;
7238
7615
  this.startAdRequestWatchdog(requestToken);
@@ -7257,6 +7634,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7257
7634
  2
7258
7635
  ];
7259
7636
  }
7637
+ if (this.config.licenseKey) {
7638
+ adLoadedInfo = _object_spread({
7639
+ source: this.getAdSource(),
7640
+ timestamp: /* @__PURE__ */ new Date().toISOString()
7641
+ }, vastTagUrl && {
7642
+ vastUrl: vastTagUrl
7643
+ });
7644
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
7645
+ }
7260
7646
  _state.label = 3;
7261
7647
  case 3:
7262
7648
  _state.trys.push([
@@ -7477,6 +7863,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7477
7863
  this.showAds = false;
7478
7864
  this.currentAdIndex = 0;
7479
7865
  this.totalAdsInBreak = 0;
7866
+ this.totalAdRequestsInBreak = 0;
7480
7867
  this.consecutiveFailures = 0;
7481
7868
  this.ima.stop().catch(function() {});
7482
7869
  var restoredMuted = this.ima.getOriginalMutedState();
@@ -7488,17 +7875,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7488
7875
  this.video.volume = restoredVolume;
7489
7876
  }
7490
7877
  if (this.shouldContinueLiveStreamDuringAds()) {
7491
- if (this.video.paused) {
7492
- var _this_video_play;
7493
- if (this.config.debugAdTiming) {
7878
+ var _this_video_play;
7879
+ if (this.config.debugAdTiming) {
7880
+ if (this.video.paused) {
7494
7881
  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) {
7882
+ } else {
7499
7883
  console.log("[StormcloudVideoPlayer] Content video already playing in live mode after ads");
7500
7884
  }
7501
7885
  }
7886
+ (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
7502
7887
  } else if (this.video.paused) {
7503
7888
  var _this_video_play1;
7504
7889
  (_this_video_play1 = this.video.play()) === null || _this_video_play1 === void 0 ? void 0 : _this_video_play1.catch(function() {});