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
@@ -1243,6 +1243,7 @@ function createImaController(video, options) {
1243
1243
  adContainerEl.offsetHeight;
1244
1244
  adContainerEl.style.opacity = "1";
1245
1245
  }
1246
+ emit("ad_impression");
1246
1247
  });
1247
1248
  adsManager.addEventListener(AdEvent.CONTENT_RESUME_REQUESTED, function() {
1248
1249
  adPlaying = false;
@@ -2044,11 +2045,12 @@ function createHlsAdPlayer(contentVideo, options) {
2044
2045
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2045
2046
  if (contentVideo.paused) {
2046
2047
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback");
2047
- contentVideo.play().catch(function() {});
2048
2048
  } else {
2049
2049
  console.log("[HlsAdPlayer] Content video already playing in live mode");
2050
2050
  }
2051
+ contentVideo.play().catch(function() {});
2051
2052
  }
2053
+ emit("ad_impression");
2052
2054
  emit("content_resume");
2053
2055
  }
2054
2056
  function handleAdError() {
@@ -2320,8 +2322,8 @@ function createHlsAdPlayer(contentVideo, options) {
2320
2322
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2321
2323
  if (contentVideo.paused) {
2322
2324
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback on stop");
2323
- contentVideo.play().catch(function() {});
2324
2325
  }
2326
+ contentVideo.play().catch(function() {});
2325
2327
  }
2326
2328
  if (adHls) {
2327
2329
  adHls.destroy();
@@ -2330,6 +2332,8 @@ function createHlsAdPlayer(contentVideo, options) {
2330
2332
  if (adVideoElement) {
2331
2333
  adVideoElement.pause();
2332
2334
  adVideoElement.src = "";
2335
+ adVideoElement.remove();
2336
+ adVideoElement = void 0;
2333
2337
  }
2334
2338
  currentAd = void 0;
2335
2339
  return [
@@ -2980,11 +2984,12 @@ function createPrebidController(contentVideo, options) {
2980
2984
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2981
2985
  if (contentVideo.paused) {
2982
2986
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback"));
2983
- contentVideo.play().catch(function() {});
2984
2987
  } else {
2985
2988
  console.log("".concat(LOG, " Content video already playing in live mode"));
2986
2989
  }
2990
+ contentVideo.play().catch(function() {});
2987
2991
  }
2992
+ emit("ad_impression");
2988
2993
  emit("content_resume");
2989
2994
  }
2990
2995
  function handleAdError() {
@@ -3349,8 +3354,8 @@ function createPrebidController(contentVideo, options) {
3349
3354
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
3350
3355
  if (contentVideo.paused) {
3351
3356
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback on stop"));
3352
- contentVideo.play().catch(function() {});
3353
3357
  }
3358
+ contentVideo.play().catch(function() {});
3354
3359
  }
3355
3360
  if (adHls) {
3356
3361
  adHls.destroy();
@@ -3359,6 +3364,8 @@ function createPrebidController(contentVideo, options) {
3359
3364
  if (adVideoElement) {
3360
3365
  adVideoElement.pause();
3361
3366
  adVideoElement.src = "";
3367
+ adVideoElement.remove();
3368
+ adVideoElement = void 0;
3362
3369
  }
3363
3370
  currentAd = void 0;
3364
3371
  return [
@@ -3705,6 +3712,45 @@ function getBrowserID(clientInfo) {
3705
3712
  });
3706
3713
  })();
3707
3714
  }
3715
+ var TRACK_URL = "https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track";
3716
+ function sendTrackRequest(licenseKey, body) {
3717
+ return _async_to_generator(function() {
3718
+ var headers, response;
3719
+ return _ts_generator(this, function(_state) {
3720
+ switch(_state.label){
3721
+ case 0:
3722
+ headers = {
3723
+ "Content-Type": "application/json"
3724
+ };
3725
+ if (licenseKey) {
3726
+ headers["Authorization"] = "Bearer ".concat(licenseKey);
3727
+ }
3728
+ return [
3729
+ 4,
3730
+ fetch(TRACK_URL, {
3731
+ method: "POST",
3732
+ headers: headers,
3733
+ body: JSON.stringify(body)
3734
+ })
3735
+ ];
3736
+ case 1:
3737
+ response = _state.sent();
3738
+ if (!response.ok) {
3739
+ throw new Error("HTTP error! status: ".concat(response.status));
3740
+ }
3741
+ return [
3742
+ 4,
3743
+ response.json()
3744
+ ];
3745
+ case 2:
3746
+ _state.sent();
3747
+ return [
3748
+ 2
3749
+ ];
3750
+ }
3751
+ });
3752
+ })();
3753
+ }
3708
3754
  function sendInitialTracking(licenseKey) {
3709
3755
  return _async_to_generator(function() {
3710
3756
  var clientInfo, browserId, trackingData, headers, response, error;
@@ -3735,7 +3781,7 @@ function sendInitialTracking(licenseKey) {
3735
3781
  }
3736
3782
  return [
3737
3783
  4,
3738
- fetch("https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track", {
3784
+ fetch(TRACK_URL, {
3739
3785
  method: "POST",
3740
3786
  headers: headers,
3741
3787
  body: JSON.stringify(trackingData)
@@ -3771,6 +3817,156 @@ function sendInitialTracking(licenseKey) {
3771
3817
  });
3772
3818
  })();
3773
3819
  }
3820
+ function sendAdDetectTracking(licenseKey, adDetectInfo) {
3821
+ return _async_to_generator(function() {
3822
+ var clientInfo, browserId, trackingData, error;
3823
+ return _ts_generator(this, function(_state) {
3824
+ switch(_state.label){
3825
+ case 0:
3826
+ _state.trys.push([
3827
+ 0,
3828
+ 3,
3829
+ ,
3830
+ 4
3831
+ ]);
3832
+ clientInfo = getClientInfo();
3833
+ return [
3834
+ 4,
3835
+ getBrowserID(clientInfo)
3836
+ ];
3837
+ case 1:
3838
+ browserId = _state.sent();
3839
+ trackingData = _object_spread({
3840
+ browserId: browserId
3841
+ }, clientInfo);
3842
+ return [
3843
+ 4,
3844
+ sendTrackRequest(licenseKey, _object_spread_props(_object_spread({}, trackingData), {
3845
+ licenseKey: licenseKey,
3846
+ adDetectInfo: adDetectInfo
3847
+ }))
3848
+ ];
3849
+ case 2:
3850
+ _state.sent();
3851
+ return [
3852
+ 3,
3853
+ 4
3854
+ ];
3855
+ case 3:
3856
+ error = _state.sent();
3857
+ console.error("[StormcloudVideoPlayer] Error sending ad detect tracking:", error);
3858
+ return [
3859
+ 3,
3860
+ 4
3861
+ ];
3862
+ case 4:
3863
+ return [
3864
+ 2
3865
+ ];
3866
+ }
3867
+ });
3868
+ })();
3869
+ }
3870
+ function sendAdLoadedTracking(licenseKey, adLoadedInfo) {
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
+ adLoadedInfo: adLoadedInfo
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 loaded tracking:", error);
3908
+ return [
3909
+ 3,
3910
+ 4
3911
+ ];
3912
+ case 4:
3913
+ return [
3914
+ 2
3915
+ ];
3916
+ }
3917
+ });
3918
+ })();
3919
+ }
3920
+ function sendAdImpressionTracking(licenseKey, adImpressionInfo) {
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
+ adImpressionInfo: adImpressionInfo
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 impression tracking:", error);
3958
+ return [
3959
+ 3,
3960
+ 4
3961
+ ];
3962
+ case 4:
3963
+ return [
3964
+ 2
3965
+ ];
3966
+ }
3967
+ });
3968
+ })();
3969
+ }
3774
3970
  function sendHeartbeat(licenseKey) {
3775
3971
  return _async_to_generator(function() {
3776
3972
  var clientInfo, browserId, heartbeatData, headers, response, error;
@@ -4127,6 +4323,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4127
4323
  this.minAdRequestIntervalMs = 2500;
4128
4324
  this.backoffBaseMs = 1e3;
4129
4325
  this.maxBackoffMs = 15e3;
4326
+ this.continuousFetchWallClockBufferMs = 3e4;
4327
+ this.continuousFetchMaxIterations = 500;
4328
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
4130
4329
  this.preloadPool = [];
4131
4330
  this.maxPreloadPoolSize = 3;
4132
4331
  this.preloadPoolActive = false;
@@ -4186,6 +4385,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4186
4385
  }
4187
4386
  }
4188
4387
  },
4388
+ {
4389
+ key: "getAdPlayerTypeLabel",
4390
+ value: function getAdPlayerTypeLabel() {
4391
+ var t = this.config.adPlayerType;
4392
+ if (t === "prebid") return "Prebid";
4393
+ if (t === "hls") return "HLS";
4394
+ return "IMA";
4395
+ }
4396
+ },
4189
4397
  {
4190
4398
  key: "load",
4191
4399
  value: function load() {
@@ -4609,10 +4817,26 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4609
4817
  }).call(this);
4610
4818
  }
4611
4819
  },
4820
+ {
4821
+ key: "getAdSource",
4822
+ value: function getAdSource() {
4823
+ var _this_config_adPlayerType;
4824
+ return (_this_config_adPlayerType = this.config.adPlayerType) !== null && _this_config_adPlayerType !== void 0 ? _this_config_adPlayerType : "ima";
4825
+ }
4826
+ },
4612
4827
  {
4613
4828
  key: "attachImaEventListeners",
4614
4829
  value: function attachImaEventListeners() {
4615
4830
  var _this = this;
4831
+ this.ima.on("ad_impression", function() {
4832
+ if (_this.config.licenseKey) {
4833
+ sendAdImpressionTracking(_this.config.licenseKey, {
4834
+ source: _this.getAdSource(),
4835
+ adIndex: _this.currentAdIndex,
4836
+ timestamp: /* @__PURE__ */ new Date().toISOString()
4837
+ });
4838
+ }
4839
+ });
4616
4840
  this.ima.on("all_ads_completed", function() {
4617
4841
  var remaining = _this.getRemainingAdMs();
4618
4842
  _this.consecutiveFailures = 0;
@@ -4675,6 +4899,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4675
4899
  }
4676
4900
  });
4677
4901
  this.ima.on("content_resume", function() {
4902
+ console.log("[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s", _this.inAdBreak, _this.getRemainingAdMs());
4678
4903
  if (!_this.video.muted) {
4679
4904
  _this.video.muted = true;
4680
4905
  _this.video.volume = 0;
@@ -4705,15 +4930,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4705
4930
  }
4706
4931
  },
4707
4932
  {
4708
- key: "recreateImaController",
4709
- value: function recreateImaController() {
4933
+ key: "recreateAdController",
4934
+ value: function recreateAdController() {
4935
+ var label = this.getAdPlayerTypeLabel();
4710
4936
  if (this.config.debugAdTiming) {
4711
- console.log("[StormcloudVideoPlayer] Recreating ImaController for new ad");
4937
+ console.log("[StormcloudVideoPlayer] Recreating ad controller (".concat(label, ") for new ad"));
4712
4938
  }
4713
4939
  var shouldShowPlaceholder = this.inAdBreak && this.showAds;
4714
4940
  if (shouldShowPlaceholder && this.ima) {
4715
4941
  if (this.config.debugAdTiming) {
4716
- console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ImaController");
4942
+ console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ".concat(label, " controller"));
4717
4943
  }
4718
4944
  this.showPlaceholderLayer();
4719
4945
  this.ima.showPlaceholder();
@@ -4726,7 +4952,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4726
4952
  this.video.volume = 0;
4727
4953
  } catch (error) {
4728
4954
  if (this.config.debugAdTiming) {
4729
- console.warn("[StormcloudVideoPlayer] Error destroying old ImaController:", error);
4955
+ console.warn("[StormcloudVideoPlayer] Error destroying old ".concat(label, " controller:"), error);
4730
4956
  }
4731
4957
  }
4732
4958
  }
@@ -4806,7 +5032,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4806
5032
  });
4807
5033
  }
4808
5034
  if (this.config.debugAdTiming) {
4809
- console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and IMA)");
5035
+ console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and ".concat(this.getAdPlayerTypeLabel(), ")"));
4810
5036
  }
4811
5037
  }
4812
5038
  },
@@ -5063,6 +5289,20 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5063
5289
  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;
5064
5290
  this.expectedAdBreakDurationMs = durationMs;
5065
5291
  this.currentAdBreakStartWallClockMs = Date.now();
5292
+ if (this.config.licenseKey) {
5293
+ var _this_pendingAdBreak1;
5294
+ var adDetectInfo = _object_spread({
5295
+ source: "scte35",
5296
+ timestamp: /* @__PURE__ */ new Date().toISOString()
5297
+ }, marker.durationSeconds != null && {
5298
+ durationSeconds: marker.durationSeconds
5299
+ }, marker.ptsSeconds != null && {
5300
+ ptsSeconds: marker.ptsSeconds
5301
+ }, ((_this_pendingAdBreak1 = this.pendingAdBreak) === null || _this_pendingAdBreak1 === void 0 ? void 0 : _this_pendingAdBreak1.detectedAtFragmentSn) != null && {
5302
+ detectedAtFragmentSn: this.pendingAdBreak.detectedAtFragmentSn
5303
+ });
5304
+ sendAdDetectTracking(this.config.licenseKey, adDetectInfo);
5305
+ }
5066
5306
  var isManifestMarker = this.isManifestBasedMarker(marker);
5067
5307
  var forceImmediate = (_this_config_immediateManifestAds = this.config.immediateManifestAds) !== null && _this_config_immediateManifestAds !== void 0 ? _this_config_immediateManifestAds : true;
5068
5308
  if (this.config.debugAdTiming) {
@@ -5518,6 +5758,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5518
5758
  return this.config.adPlayerType === "prebid";
5519
5759
  }
5520
5760
  },
5761
+ {
5762
+ key: "isLgStbDevice",
5763
+ value: function isLgStbDevice() {
5764
+ if (typeof navigator === "undefined" || !navigator.userAgent) return false;
5765
+ var ua = navigator.userAgent;
5766
+ return /Web0S|webOS|LG Browser|LGSTB/i.test(ua);
5767
+ }
5768
+ },
5521
5769
  {
5522
5770
  key: "getCurrentAdIndex",
5523
5771
  value: function getCurrentAdIndex() {
@@ -6040,7 +6288,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6040
6288
  key: "handleAdStart",
6041
6289
  value: function handleAdStart(_marker) {
6042
6290
  return _async_to_generator(function() {
6043
- var scheduled, tags, isPrebid, baseVastUrl, adBreakDurationMs, mode, currentMuted, currentVolume, firstAdUrl, usePreloadedAd, preloadedController, preloaded, firstAdUrlArray, adVolume, adVolume1, error, fallbackPreloaded, adVolume2, fallbackError;
6291
+ var scheduled, tags, isPrebid, baseVastUrl, adBreakDurationMs, mode, currentMuted, currentVolume, firstAdUrl, usePreloadedAd, preloadedController, preloaded, firstAdUrlArray, adLoadedInfo, adVolume, adLoadedInfo1, adVolume1, error, fallbackPreloaded, adVolume2, fallbackError;
6044
6292
  return _ts_generator(this, function(_state) {
6045
6293
  switch(_state.label){
6046
6294
  case 0:
@@ -6152,6 +6400,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6152
6400
  this.video.volume = 0;
6153
6401
  this.ima = preloadedController;
6154
6402
  this.attachImaEventListeners();
6403
+ if (this.config.licenseKey) {
6404
+ adLoadedInfo = _object_spread({
6405
+ source: this.getAdSource(),
6406
+ timestamp: /* @__PURE__ */ new Date().toISOString()
6407
+ }, firstAdUrl && {
6408
+ vastUrl: firstAdUrl
6409
+ });
6410
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
6411
+ }
6155
6412
  if (this.config.debugAdTiming) {
6156
6413
  console.log("[CONTINUOUS-FETCH] \u2705 Using preloaded ad, resuming and starting playback immediately (no request delay!)");
6157
6414
  }
@@ -6187,6 +6444,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6187
6444
  ];
6188
6445
  case 4:
6189
6446
  _state.sent();
6447
+ if (this.config.licenseKey) {
6448
+ adLoadedInfo1 = _object_spread({
6449
+ source: this.getAdSource(),
6450
+ timestamp: /* @__PURE__ */ new Date().toISOString()
6451
+ }, firstAdUrl && {
6452
+ vastUrl: firstAdUrl
6453
+ });
6454
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo1);
6455
+ }
6190
6456
  if (this.config.debugAdTiming) {
6191
6457
  console.log("[CONTINUOUS-FETCH] \u2705 First ad request successful, starting playback");
6192
6458
  }
@@ -6332,15 +6598,34 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6332
6598
  key: "continuousFetchLoop",
6333
6599
  value: function continuousFetchLoop(baseVastUrl) {
6334
6600
  return _async_to_generator(function() {
6335
- var _this, _loop, _ret;
6601
+ var loopIterations, _this, _loop, _ret;
6336
6602
  return _ts_generator(this, function(_state) {
6337
6603
  switch(_state.label){
6338
6604
  case 0:
6605
+ loopIterations = 0;
6606
+ _state.label = 1;
6607
+ case 1:
6608
+ _state.trys.push([
6609
+ 1,
6610
+ ,
6611
+ 5,
6612
+ 6
6613
+ ]);
6339
6614
  _loop = function() {
6340
- var remaining, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6615
+ var remaining, elapsedMs, maxLoopMs, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6341
6616
  return _ts_generator(this, function(_state) {
6342
6617
  switch(_state.label){
6343
6618
  case 0:
6619
+ loopIterations++;
6620
+ if (loopIterations > _this.continuousFetchMaxIterations) {
6621
+ if (_this.config.debugAdTiming) {
6622
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Max iterations reached (".concat(_this.continuousFetchMaxIterations, "), stopping URL generation"));
6623
+ }
6624
+ return [
6625
+ 2,
6626
+ "break"
6627
+ ];
6628
+ }
6344
6629
  remaining = _this.getRemainingAdMs();
6345
6630
  if (remaining <= 0) {
6346
6631
  if (_this.config.debugAdTiming) {
@@ -6351,6 +6636,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6351
6636
  "break"
6352
6637
  ];
6353
6638
  }
6639
+ if (_this.currentAdBreakStartWallClockMs != null && _this.expectedAdBreakDurationMs != null) {
6640
+ elapsedMs = Date.now() - _this.currentAdBreakStartWallClockMs;
6641
+ maxLoopMs = _this.expectedAdBreakDurationMs + _this.continuousFetchWallClockBufferMs;
6642
+ if (elapsedMs >= maxLoopMs) {
6643
+ if (_this.config.debugAdTiming) {
6644
+ console.log("[CONTINUOUS-FETCH] ⏹️ Wall-clock limit reached (".concat(elapsedMs, "ms >= ").concat(maxLoopMs, "ms), stopping URL generation"));
6645
+ }
6646
+ return [
6647
+ 2,
6648
+ "break"
6649
+ ];
6650
+ }
6651
+ }
6354
6652
  if (_this.consecutiveFailures >= _this.maxConsecutiveFailures) {
6355
6653
  if (_this.config.debugAdTiming) {
6356
6654
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Too many consecutive failures (".concat(_this.consecutiveFailures, "), stopping URL generation"));
@@ -6372,46 +6670,63 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6372
6670
  maxQueueSize = 5;
6373
6671
  if (!(_this.adRequestQueue.length >= maxQueueSize)) return [
6374
6672
  3,
6375
- 2
6673
+ 4
6376
6674
  ];
6675
+ if (!(_this.isPrebidMode() && _this.isLgStbDevice())) return [
6676
+ 3,
6677
+ 1
6678
+ ];
6679
+ _this.adRequestQueue.shift();
6680
+ _this.adRequestQueue.push("");
6681
+ _this.totalAdsInBreak++;
6682
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6377
6683
  if (_this.config.debugAdTiming) {
6378
- console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(_this.adRequestQueue.length, "), waiting..."));
6684
+ console.log("[CONTINUOUS-FETCH] Prebid slot rotated (queue full, dropped oldest); queue: ".concat(_this.adRequestQueue.length));
6379
6685
  }
6380
6686
  return [
6381
- 4,
6382
- new Promise(function(resolve) {
6383
- return setTimeout(resolve, 1e3);
6384
- })
6687
+ 3,
6688
+ 3
6385
6689
  ];
6386
6690
  case 1:
6691
+ return [
6692
+ 4,
6693
+ _this.waitForQueueWithBackoff()
6694
+ ];
6695
+ case 2:
6387
6696
  _state.sent();
6388
6697
  return [
6389
6698
  2,
6390
6699
  "continue"
6391
6700
  ];
6392
- case 2:
6701
+ case 3:
6702
+ return [
6703
+ 3,
6704
+ 8
6705
+ ];
6706
+ case 4:
6393
6707
  if (!_this.isPrebidMode()) return [
6394
6708
  3,
6395
- 3
6709
+ 5
6396
6710
  ];
6397
6711
  _this.adRequestQueue.push("");
6398
6712
  _this.totalAdsInBreak++;
6713
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6399
6714
  if (_this.config.debugAdTiming) {
6400
6715
  console.log("[CONTINUOUS-FETCH] Prebid auction slot queued (queue: ".concat(_this.adRequestQueue.length, ")"));
6401
6716
  }
6402
6717
  return [
6403
6718
  3,
6404
- 6
6719
+ 8
6405
6720
  ];
6406
- case 3:
6721
+ case 5:
6407
6722
  if (!baseVastUrl) return [
6408
6723
  3,
6409
- 6
6724
+ 8
6410
6725
  ];
6411
6726
  newAdUrl = _this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];
6412
6727
  if (!(!newAdUrl || _this.failedVastUrls.has(newAdUrl) || _this.isUrlInCooldown(newAdUrl))) return [
6413
6728
  3,
6414
- 5
6729
+ 7
6415
6730
  ];
6416
6731
  return [
6417
6732
  4,
@@ -6419,13 +6734,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6419
6734
  return setTimeout(resolve, 500);
6420
6735
  })
6421
6736
  ];
6422
- case 4:
6737
+ case 6:
6423
6738
  _state.sent();
6424
6739
  return [
6425
6740
  2,
6426
6741
  "continue"
6427
6742
  ];
6428
- case 5:
6743
+ case 7:
6429
6744
  if (_this.config.debugAdTiming) {
6430
6745
  queuedUrlsPreview = _to_consumable_array(_this.adRequestQueue).concat([
6431
6746
  newAdUrl
@@ -6436,8 +6751,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6436
6751
  }
6437
6752
  _this.adRequestQueue.push(newAdUrl);
6438
6753
  _this.totalAdsInBreak++;
6439
- _state.label = 6;
6440
- case 6:
6754
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6755
+ _state.label = 8;
6756
+ case 8:
6441
6757
  generationDelay = _this.consecutiveFailures > 0 ? Math.min(1e3 * Math.pow(2, _this.consecutiveFailures), 5e3) : 500;
6442
6758
  return [
6443
6759
  4,
@@ -6445,7 +6761,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6445
6761
  return setTimeout(resolve, generationDelay);
6446
6762
  })
6447
6763
  ];
6448
- case 7:
6764
+ case 9:
6449
6765
  _state.sent();
6450
6766
  return [
6451
6767
  2
@@ -6453,33 +6769,41 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6453
6769
  }
6454
6770
  });
6455
6771
  };
6456
- _state.label = 1;
6457
- case 1:
6772
+ _state.label = 2;
6773
+ case 2:
6458
6774
  if (!(this.continuousFetchingActive && this.inAdBreak)) return [
6459
6775
  3,
6460
- 3
6776
+ 4
6461
6777
  ];
6462
6778
  _this = this;
6463
6779
  return [
6464
6780
  5,
6465
6781
  _ts_values(_loop())
6466
6782
  ];
6467
- case 2:
6783
+ case 3:
6468
6784
  _ret = _state.sent();
6469
6785
  if (_ret === "break") return [
6470
6786
  3,
6471
- 3
6787
+ 4
6472
6788
  ];
6473
6789
  return [
6474
6790
  3,
6475
- 1
6791
+ 2
6476
6792
  ];
6477
- case 3:
6793
+ case 4:
6794
+ return [
6795
+ 3,
6796
+ 6
6797
+ ];
6798
+ case 5:
6478
6799
  this.continuousFetchLoopRunning = false;
6800
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
6801
+ return [
6802
+ 7
6803
+ ];
6804
+ case 6:
6479
6805
  if (this.config.debugAdTiming) {
6480
- console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 URL generation loop ended (queued: ".concat(this.adRequestQueue.length, ")"), this.adRequestQueue.length > 0 ? {
6481
- queuedUrls: _to_consumable_array(this.adRequestQueue)
6482
- } : {});
6806
+ this.logQueueState("URL generation loop ended");
6483
6807
  }
6484
6808
  return [
6485
6809
  2
@@ -6489,6 +6813,51 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6489
6813
  }).call(this);
6490
6814
  }
6491
6815
  },
6816
+ {
6817
+ key: "waitForQueueWithBackoff",
6818
+ value: function waitForQueueWithBackoff() {
6819
+ return _async_to_generator(function() {
6820
+ var delayMs, shouldLog;
6821
+ return _ts_generator(this, function(_state) {
6822
+ switch(_state.label){
6823
+ case 0:
6824
+ this.continuousFetchQueueFullConsecutiveWaits++;
6825
+ delayMs = Math.min(1e3 * Math.pow(2, this.continuousFetchQueueFullConsecutiveWaits - 1), 5e3);
6826
+ shouldLog = this.config.debugAdTiming && (this.continuousFetchQueueFullConsecutiveWaits <= 2 || this.continuousFetchQueueFullConsecutiveWaits % 4 === 0);
6827
+ if (shouldLog) {
6828
+ console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(this.adRequestQueue.length, "), waiting ").concat(delayMs, "ms (wait #").concat(this.continuousFetchQueueFullConsecutiveWaits, ")"));
6829
+ }
6830
+ return [
6831
+ 4,
6832
+ new Promise(function(resolve) {
6833
+ return setTimeout(resolve, delayMs);
6834
+ })
6835
+ ];
6836
+ case 1:
6837
+ _state.sent();
6838
+ return [
6839
+ 2
6840
+ ];
6841
+ }
6842
+ });
6843
+ }).call(this);
6844
+ }
6845
+ },
6846
+ {
6847
+ key: "logQueueState",
6848
+ value: function logQueueState(reason) {
6849
+ if (!this.config.debugAdTiming) return;
6850
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 ".concat(reason), {
6851
+ queueLength: this.adRequestQueue.length,
6852
+ totalAdsInBreak: this.totalAdsInBreak,
6853
+ totalAdRequestsInBreak: this.totalAdRequestsInBreak,
6854
+ consecutiveFailures: this.consecutiveFailures,
6855
+ continuousFetchingActive: this.continuousFetchingActive,
6856
+ continuousFetchLoopRunning: this.continuousFetchLoopRunning,
6857
+ inAdBreak: this.inAdBreak
6858
+ });
6859
+ }
6860
+ },
6492
6861
  {
6493
6862
  key: "stopContinuousFetching",
6494
6863
  value: function stopContinuousFetching() {
@@ -6553,7 +6922,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6553
6922
  value: function tryNextAvailableAd() {
6554
6923
  var retryCount = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 0;
6555
6924
  return _async_to_generator(function() {
6556
- var remaining, preloaded, currentMuted, currentVolume, adVolume, error, nextAdUrl, currentMuted1, currentVolume1, error1, errorMessage, maxRetries;
6925
+ var remaining, preloaded, adLoadedInfo, currentMuted, currentVolume, adVolume, error, nextAdUrl, currentMuted1, currentVolume1, error1, errorMessage, maxRetries;
6557
6926
  return _ts_generator(this, function(_state) {
6558
6927
  switch(_state.label){
6559
6928
  case 0:
@@ -6598,6 +6967,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6598
6967
  this.video.volume = 0;
6599
6968
  this.ima = preloaded.imaController;
6600
6969
  this.attachImaEventListeners();
6970
+ if (this.config.licenseKey) {
6971
+ adLoadedInfo = {
6972
+ source: this.getAdSource(),
6973
+ timestamp: /* @__PURE__ */ new Date().toISOString()
6974
+ };
6975
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
6976
+ }
6601
6977
  this.ima.resume();
6602
6978
  this.currentAdIndex++;
6603
6979
  this.totalAdRequestsInBreak++;
@@ -6659,8 +7035,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6659
7035
  4
6660
7036
  ];
6661
7037
  }
7038
+ console.log("[StormcloudVideoPlayer] Requesting next ad (%s), queue remaining=%s", nextAdUrl === "" ? "Prebid" : "VAST", this.adRequestQueue.length);
6662
7039
  if (this.config.debugAdTiming) {
6663
- 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)"));
7040
+ 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)"));
6664
7041
  }
6665
7042
  currentMuted1 = this.video.muted;
6666
7043
  currentVolume1 = this.video.volume;
@@ -6840,7 +7217,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6840
7217
  ];
6841
7218
  }
6842
7219
  if (this.config.debugAdTiming) {
6843
- console.log("[CONTINUOUS-FETCH] \u2705 Ad URL available, requesting via IMA SDK");
7220
+ console.log("[CONTINUOUS-FETCH] Ad URL available, requesting via ".concat(this.getAdPlayerTypeLabel()));
6844
7221
  }
6845
7222
  this.isShowingPlaceholder = false;
6846
7223
  this.ima.hidePlaceholder();
@@ -7155,7 +7532,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7155
7532
  key: "playSingleAd",
7156
7533
  value: function playSingleAd(vastTagUrl) {
7157
7534
  return _async_to_generator(function() {
7158
- var requestToken, currentMuted, currentVolume, adVolume, playError, preloadedFallback, currentMuted1, currentVolume1, adVolume1, fallbackError, error, errorMessage, preloadedFallback1, currentMuted2, currentVolume2, adVolume2, fallbackError1;
7535
+ var requestToken, adLoadedInfo, currentMuted, currentVolume, adVolume, playError, preloadedFallback, currentMuted1, currentVolume1, adVolume1, fallbackError, error, errorMessage, preloadedFallback1, currentMuted2, currentVolume2, adVolume2, fallbackError1;
7159
7536
  return _ts_generator(this, function(_state) {
7160
7537
  switch(_state.label){
7161
7538
  case 0:
@@ -7182,7 +7559,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7182
7559
  }
7183
7560
  throw new Error("Too many consecutive failures");
7184
7561
  }
7185
- this.recreateImaController();
7562
+ this.recreateAdController();
7186
7563
  requestToken = ++this.adRequestTokenCounter;
7187
7564
  this.activeAdRequestToken = requestToken;
7188
7565
  this.startAdRequestWatchdog(requestToken);
@@ -7207,6 +7584,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7207
7584
  2
7208
7585
  ];
7209
7586
  }
7587
+ if (this.config.licenseKey) {
7588
+ adLoadedInfo = _object_spread({
7589
+ source: this.getAdSource(),
7590
+ timestamp: /* @__PURE__ */ new Date().toISOString()
7591
+ }, vastTagUrl && {
7592
+ vastUrl: vastTagUrl
7593
+ });
7594
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
7595
+ }
7210
7596
  _state.label = 3;
7211
7597
  case 3:
7212
7598
  _state.trys.push([
@@ -7427,6 +7813,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7427
7813
  this.showAds = false;
7428
7814
  this.currentAdIndex = 0;
7429
7815
  this.totalAdsInBreak = 0;
7816
+ this.totalAdRequestsInBreak = 0;
7430
7817
  this.consecutiveFailures = 0;
7431
7818
  this.ima.stop().catch(function() {});
7432
7819
  var restoredMuted = this.ima.getOriginalMutedState();
@@ -7438,17 +7825,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7438
7825
  this.video.volume = restoredVolume;
7439
7826
  }
7440
7827
  if (this.shouldContinueLiveStreamDuringAds()) {
7441
- if (this.video.paused) {
7442
- var _this_video_play;
7443
- if (this.config.debugAdTiming) {
7828
+ var _this_video_play;
7829
+ if (this.config.debugAdTiming) {
7830
+ if (this.video.paused) {
7444
7831
  console.log("[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback");
7445
- }
7446
- (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
7447
- } else {
7448
- if (this.config.debugAdTiming) {
7832
+ } else {
7449
7833
  console.log("[StormcloudVideoPlayer] Content video already playing in live mode after ads");
7450
7834
  }
7451
7835
  }
7836
+ (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
7452
7837
  } else if (this.video.paused) {
7453
7838
  var _this_video_play1;
7454
7839
  (_this_video_play1 = this.video.play()) === null || _this_video_play1 === void 0 ? void 0 : _this_video_play1.catch(function() {});