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
@@ -1257,6 +1257,7 @@ function createImaController(video, options) {
1257
1257
  adContainerEl.offsetHeight;
1258
1258
  adContainerEl.style.opacity = "1";
1259
1259
  }
1260
+ emit("ad_impression");
1260
1261
  });
1261
1262
  adsManager.addEventListener(AdEvent.CONTENT_RESUME_REQUESTED, function() {
1262
1263
  adPlaying = false;
@@ -2058,11 +2059,12 @@ function createHlsAdPlayer(contentVideo, options) {
2058
2059
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2059
2060
  if (contentVideo.paused) {
2060
2061
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback");
2061
- contentVideo.play().catch(function() {});
2062
2062
  } else {
2063
2063
  console.log("[HlsAdPlayer] Content video already playing in live mode");
2064
2064
  }
2065
+ contentVideo.play().catch(function() {});
2065
2066
  }
2067
+ emit("ad_impression");
2066
2068
  emit("content_resume");
2067
2069
  }
2068
2070
  function handleAdError() {
@@ -2334,8 +2336,8 @@ function createHlsAdPlayer(contentVideo, options) {
2334
2336
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2335
2337
  if (contentVideo.paused) {
2336
2338
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback on stop");
2337
- contentVideo.play().catch(function() {});
2338
2339
  }
2340
+ contentVideo.play().catch(function() {});
2339
2341
  }
2340
2342
  if (adHls) {
2341
2343
  adHls.destroy();
@@ -2344,6 +2346,8 @@ function createHlsAdPlayer(contentVideo, options) {
2344
2346
  if (adVideoElement) {
2345
2347
  adVideoElement.pause();
2346
2348
  adVideoElement.src = "";
2349
+ adVideoElement.remove();
2350
+ adVideoElement = void 0;
2347
2351
  }
2348
2352
  currentAd = void 0;
2349
2353
  return [
@@ -2994,11 +2998,12 @@ function createPrebidController(contentVideo, options) {
2994
2998
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
2995
2999
  if (contentVideo.paused) {
2996
3000
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback"));
2997
- contentVideo.play().catch(function() {});
2998
3001
  } else {
2999
3002
  console.log("".concat(LOG, " Content video already playing in live mode"));
3000
3003
  }
3004
+ contentVideo.play().catch(function() {});
3001
3005
  }
3006
+ emit("ad_impression");
3002
3007
  emit("content_resume");
3003
3008
  }
3004
3009
  function handleAdError() {
@@ -3363,8 +3368,8 @@ function createPrebidController(contentVideo, options) {
3363
3368
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
3364
3369
  if (contentVideo.paused) {
3365
3370
  console.log("".concat(LOG, " Content video paused in live mode, resuming playback on stop"));
3366
- contentVideo.play().catch(function() {});
3367
3371
  }
3372
+ contentVideo.play().catch(function() {});
3368
3373
  }
3369
3374
  if (adHls) {
3370
3375
  adHls.destroy();
@@ -3373,6 +3378,8 @@ function createPrebidController(contentVideo, options) {
3373
3378
  if (adVideoElement) {
3374
3379
  adVideoElement.pause();
3375
3380
  adVideoElement.src = "";
3381
+ adVideoElement.remove();
3382
+ adVideoElement = void 0;
3376
3383
  }
3377
3384
  currentAd = void 0;
3378
3385
  return [
@@ -3719,6 +3726,45 @@ function getBrowserID(clientInfo) {
3719
3726
  });
3720
3727
  })();
3721
3728
  }
3729
+ var TRACK_URL = "https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track";
3730
+ function sendTrackRequest(licenseKey, body) {
3731
+ return _async_to_generator(function() {
3732
+ var headers, response;
3733
+ return _ts_generator(this, function(_state) {
3734
+ switch(_state.label){
3735
+ case 0:
3736
+ headers = {
3737
+ "Content-Type": "application/json"
3738
+ };
3739
+ if (licenseKey) {
3740
+ headers["Authorization"] = "Bearer ".concat(licenseKey);
3741
+ }
3742
+ return [
3743
+ 4,
3744
+ fetch(TRACK_URL, {
3745
+ method: "POST",
3746
+ headers: headers,
3747
+ body: JSON.stringify(body)
3748
+ })
3749
+ ];
3750
+ case 1:
3751
+ response = _state.sent();
3752
+ if (!response.ok) {
3753
+ throw new Error("HTTP error! status: ".concat(response.status));
3754
+ }
3755
+ return [
3756
+ 4,
3757
+ response.json()
3758
+ ];
3759
+ case 2:
3760
+ _state.sent();
3761
+ return [
3762
+ 2
3763
+ ];
3764
+ }
3765
+ });
3766
+ })();
3767
+ }
3722
3768
  function sendInitialTracking(licenseKey) {
3723
3769
  return _async_to_generator(function() {
3724
3770
  var clientInfo, browserId, trackingData, headers, response, error;
@@ -3749,7 +3795,7 @@ function sendInitialTracking(licenseKey) {
3749
3795
  }
3750
3796
  return [
3751
3797
  4,
3752
- fetch("https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track", {
3798
+ fetch(TRACK_URL, {
3753
3799
  method: "POST",
3754
3800
  headers: headers,
3755
3801
  body: JSON.stringify(trackingData)
@@ -3785,6 +3831,156 @@ function sendInitialTracking(licenseKey) {
3785
3831
  });
3786
3832
  })();
3787
3833
  }
3834
+ function sendAdDetectTracking(licenseKey, adDetectInfo) {
3835
+ return _async_to_generator(function() {
3836
+ var clientInfo, browserId, trackingData, error;
3837
+ return _ts_generator(this, function(_state) {
3838
+ switch(_state.label){
3839
+ case 0:
3840
+ _state.trys.push([
3841
+ 0,
3842
+ 3,
3843
+ ,
3844
+ 4
3845
+ ]);
3846
+ clientInfo = getClientInfo();
3847
+ return [
3848
+ 4,
3849
+ getBrowserID(clientInfo)
3850
+ ];
3851
+ case 1:
3852
+ browserId = _state.sent();
3853
+ trackingData = _object_spread({
3854
+ browserId: browserId
3855
+ }, clientInfo);
3856
+ return [
3857
+ 4,
3858
+ sendTrackRequest(licenseKey, _object_spread_props(_object_spread({}, trackingData), {
3859
+ licenseKey: licenseKey,
3860
+ adDetectInfo: adDetectInfo
3861
+ }))
3862
+ ];
3863
+ case 2:
3864
+ _state.sent();
3865
+ return [
3866
+ 3,
3867
+ 4
3868
+ ];
3869
+ case 3:
3870
+ error = _state.sent();
3871
+ console.error("[StormcloudVideoPlayer] Error sending ad detect tracking:", error);
3872
+ return [
3873
+ 3,
3874
+ 4
3875
+ ];
3876
+ case 4:
3877
+ return [
3878
+ 2
3879
+ ];
3880
+ }
3881
+ });
3882
+ })();
3883
+ }
3884
+ function sendAdLoadedTracking(licenseKey, adLoadedInfo) {
3885
+ return _async_to_generator(function() {
3886
+ var clientInfo, browserId, trackingData, error;
3887
+ return _ts_generator(this, function(_state) {
3888
+ switch(_state.label){
3889
+ case 0:
3890
+ _state.trys.push([
3891
+ 0,
3892
+ 3,
3893
+ ,
3894
+ 4
3895
+ ]);
3896
+ clientInfo = getClientInfo();
3897
+ return [
3898
+ 4,
3899
+ getBrowserID(clientInfo)
3900
+ ];
3901
+ case 1:
3902
+ browserId = _state.sent();
3903
+ trackingData = _object_spread({
3904
+ browserId: browserId
3905
+ }, clientInfo);
3906
+ return [
3907
+ 4,
3908
+ sendTrackRequest(licenseKey, _object_spread_props(_object_spread({}, trackingData), {
3909
+ licenseKey: licenseKey,
3910
+ adLoadedInfo: adLoadedInfo
3911
+ }))
3912
+ ];
3913
+ case 2:
3914
+ _state.sent();
3915
+ return [
3916
+ 3,
3917
+ 4
3918
+ ];
3919
+ case 3:
3920
+ error = _state.sent();
3921
+ console.error("[StormcloudVideoPlayer] Error sending ad loaded tracking:", error);
3922
+ return [
3923
+ 3,
3924
+ 4
3925
+ ];
3926
+ case 4:
3927
+ return [
3928
+ 2
3929
+ ];
3930
+ }
3931
+ });
3932
+ })();
3933
+ }
3934
+ function sendAdImpressionTracking(licenseKey, adImpressionInfo) {
3935
+ return _async_to_generator(function() {
3936
+ var clientInfo, browserId, trackingData, error;
3937
+ return _ts_generator(this, function(_state) {
3938
+ switch(_state.label){
3939
+ case 0:
3940
+ _state.trys.push([
3941
+ 0,
3942
+ 3,
3943
+ ,
3944
+ 4
3945
+ ]);
3946
+ clientInfo = getClientInfo();
3947
+ return [
3948
+ 4,
3949
+ getBrowserID(clientInfo)
3950
+ ];
3951
+ case 1:
3952
+ browserId = _state.sent();
3953
+ trackingData = _object_spread({
3954
+ browserId: browserId
3955
+ }, clientInfo);
3956
+ return [
3957
+ 4,
3958
+ sendTrackRequest(licenseKey, _object_spread_props(_object_spread({}, trackingData), {
3959
+ licenseKey: licenseKey,
3960
+ adImpressionInfo: adImpressionInfo
3961
+ }))
3962
+ ];
3963
+ case 2:
3964
+ _state.sent();
3965
+ return [
3966
+ 3,
3967
+ 4
3968
+ ];
3969
+ case 3:
3970
+ error = _state.sent();
3971
+ console.error("[StormcloudVideoPlayer] Error sending ad impression tracking:", error);
3972
+ return [
3973
+ 3,
3974
+ 4
3975
+ ];
3976
+ case 4:
3977
+ return [
3978
+ 2
3979
+ ];
3980
+ }
3981
+ });
3982
+ })();
3983
+ }
3788
3984
  function sendHeartbeat(licenseKey) {
3789
3985
  return _async_to_generator(function() {
3790
3986
  var clientInfo, browserId, heartbeatData, headers, response, error;
@@ -4141,6 +4337,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4141
4337
  this.minAdRequestIntervalMs = 2500;
4142
4338
  this.backoffBaseMs = 1e3;
4143
4339
  this.maxBackoffMs = 15e3;
4340
+ this.continuousFetchWallClockBufferMs = 3e4;
4341
+ this.continuousFetchMaxIterations = 500;
4342
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
4144
4343
  this.preloadPool = [];
4145
4344
  this.maxPreloadPoolSize = 3;
4146
4345
  this.preloadPoolActive = false;
@@ -4200,6 +4399,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4200
4399
  }
4201
4400
  }
4202
4401
  },
4402
+ {
4403
+ key: "getAdPlayerTypeLabel",
4404
+ value: function getAdPlayerTypeLabel() {
4405
+ var t = this.config.adPlayerType;
4406
+ if (t === "prebid") return "Prebid";
4407
+ if (t === "hls") return "HLS";
4408
+ return "IMA";
4409
+ }
4410
+ },
4203
4411
  {
4204
4412
  key: "load",
4205
4413
  value: function load() {
@@ -4623,10 +4831,26 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4623
4831
  }).call(this);
4624
4832
  }
4625
4833
  },
4834
+ {
4835
+ key: "getAdSource",
4836
+ value: function getAdSource() {
4837
+ var _this_config_adPlayerType;
4838
+ return (_this_config_adPlayerType = this.config.adPlayerType) !== null && _this_config_adPlayerType !== void 0 ? _this_config_adPlayerType : "ima";
4839
+ }
4840
+ },
4626
4841
  {
4627
4842
  key: "attachImaEventListeners",
4628
4843
  value: function attachImaEventListeners() {
4629
4844
  var _this = this;
4845
+ this.ima.on("ad_impression", function() {
4846
+ if (_this.config.licenseKey) {
4847
+ sendAdImpressionTracking(_this.config.licenseKey, {
4848
+ source: _this.getAdSource(),
4849
+ adIndex: _this.currentAdIndex,
4850
+ timestamp: /* @__PURE__ */ new Date().toISOString()
4851
+ });
4852
+ }
4853
+ });
4630
4854
  this.ima.on("all_ads_completed", function() {
4631
4855
  var remaining = _this.getRemainingAdMs();
4632
4856
  _this.consecutiveFailures = 0;
@@ -4689,6 +4913,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4689
4913
  }
4690
4914
  });
4691
4915
  this.ima.on("content_resume", function() {
4916
+ console.log("[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s", _this.inAdBreak, _this.getRemainingAdMs());
4692
4917
  if (!_this.video.muted) {
4693
4918
  _this.video.muted = true;
4694
4919
  _this.video.volume = 0;
@@ -4719,15 +4944,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4719
4944
  }
4720
4945
  },
4721
4946
  {
4722
- key: "recreateImaController",
4723
- value: function recreateImaController() {
4947
+ key: "recreateAdController",
4948
+ value: function recreateAdController() {
4949
+ var label = this.getAdPlayerTypeLabel();
4724
4950
  if (this.config.debugAdTiming) {
4725
- console.log("[StormcloudVideoPlayer] Recreating ImaController for new ad");
4951
+ console.log("[StormcloudVideoPlayer] Recreating ad controller (".concat(label, ") for new ad"));
4726
4952
  }
4727
4953
  var shouldShowPlaceholder = this.inAdBreak && this.showAds;
4728
4954
  if (shouldShowPlaceholder && this.ima) {
4729
4955
  if (this.config.debugAdTiming) {
4730
- console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ImaController");
4956
+ console.log("[StormcloudVideoPlayer] Showing placeholder before destroying old ".concat(label, " controller"));
4731
4957
  }
4732
4958
  this.showPlaceholderLayer();
4733
4959
  this.ima.showPlaceholder();
@@ -4740,7 +4966,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4740
4966
  this.video.volume = 0;
4741
4967
  } catch (error) {
4742
4968
  if (this.config.debugAdTiming) {
4743
- console.warn("[StormcloudVideoPlayer] Error destroying old ImaController:", error);
4969
+ console.warn("[StormcloudVideoPlayer] Error destroying old ".concat(label, " controller:"), error);
4744
4970
  }
4745
4971
  }
4746
4972
  }
@@ -4820,7 +5046,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4820
5046
  });
4821
5047
  }
4822
5048
  if (this.config.debugAdTiming) {
4823
- console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and IMA)");
5049
+ console.log("[StormcloudVideoPlayer] Showing placeholder layer (between content and ".concat(this.getAdPlayerTypeLabel(), ")"));
4824
5050
  }
4825
5051
  }
4826
5052
  },
@@ -5077,6 +5303,20 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5077
5303
  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;
5078
5304
  this.expectedAdBreakDurationMs = durationMs;
5079
5305
  this.currentAdBreakStartWallClockMs = Date.now();
5306
+ if (this.config.licenseKey) {
5307
+ var _this_pendingAdBreak1;
5308
+ var adDetectInfo = _object_spread({
5309
+ source: "scte35",
5310
+ timestamp: /* @__PURE__ */ new Date().toISOString()
5311
+ }, marker.durationSeconds != null && {
5312
+ durationSeconds: marker.durationSeconds
5313
+ }, marker.ptsSeconds != null && {
5314
+ ptsSeconds: marker.ptsSeconds
5315
+ }, ((_this_pendingAdBreak1 = this.pendingAdBreak) === null || _this_pendingAdBreak1 === void 0 ? void 0 : _this_pendingAdBreak1.detectedAtFragmentSn) != null && {
5316
+ detectedAtFragmentSn: this.pendingAdBreak.detectedAtFragmentSn
5317
+ });
5318
+ sendAdDetectTracking(this.config.licenseKey, adDetectInfo);
5319
+ }
5080
5320
  var isManifestMarker = this.isManifestBasedMarker(marker);
5081
5321
  var forceImmediate = (_this_config_immediateManifestAds = this.config.immediateManifestAds) !== null && _this_config_immediateManifestAds !== void 0 ? _this_config_immediateManifestAds : true;
5082
5322
  if (this.config.debugAdTiming) {
@@ -5532,6 +5772,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5532
5772
  return this.config.adPlayerType === "prebid";
5533
5773
  }
5534
5774
  },
5775
+ {
5776
+ key: "isLgStbDevice",
5777
+ value: function isLgStbDevice() {
5778
+ if (typeof navigator === "undefined" || !navigator.userAgent) return false;
5779
+ var ua = navigator.userAgent;
5780
+ return /Web0S|webOS|LG Browser|LGSTB/i.test(ua);
5781
+ }
5782
+ },
5535
5783
  {
5536
5784
  key: "getCurrentAdIndex",
5537
5785
  value: function getCurrentAdIndex() {
@@ -6054,7 +6302,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6054
6302
  key: "handleAdStart",
6055
6303
  value: function handleAdStart(_marker) {
6056
6304
  return _async_to_generator(function() {
6057
- var scheduled, tags, isPrebid, baseVastUrl, adBreakDurationMs, mode, currentMuted, currentVolume, firstAdUrl, usePreloadedAd, preloadedController, preloaded, firstAdUrlArray, adVolume, adVolume1, error, fallbackPreloaded, adVolume2, fallbackError;
6305
+ var scheduled, tags, isPrebid, baseVastUrl, adBreakDurationMs, mode, currentMuted, currentVolume, firstAdUrl, usePreloadedAd, preloadedController, preloaded, firstAdUrlArray, adLoadedInfo, adVolume, adLoadedInfo1, adVolume1, error, fallbackPreloaded, adVolume2, fallbackError;
6058
6306
  return _ts_generator(this, function(_state) {
6059
6307
  switch(_state.label){
6060
6308
  case 0:
@@ -6166,6 +6414,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6166
6414
  this.video.volume = 0;
6167
6415
  this.ima = preloadedController;
6168
6416
  this.attachImaEventListeners();
6417
+ if (this.config.licenseKey) {
6418
+ adLoadedInfo = _object_spread({
6419
+ source: this.getAdSource(),
6420
+ timestamp: /* @__PURE__ */ new Date().toISOString()
6421
+ }, firstAdUrl && {
6422
+ vastUrl: firstAdUrl
6423
+ });
6424
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
6425
+ }
6169
6426
  if (this.config.debugAdTiming) {
6170
6427
  console.log("[CONTINUOUS-FETCH] \u2705 Using preloaded ad, resuming and starting playback immediately (no request delay!)");
6171
6428
  }
@@ -6201,6 +6458,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6201
6458
  ];
6202
6459
  case 4:
6203
6460
  _state.sent();
6461
+ if (this.config.licenseKey) {
6462
+ adLoadedInfo1 = _object_spread({
6463
+ source: this.getAdSource(),
6464
+ timestamp: /* @__PURE__ */ new Date().toISOString()
6465
+ }, firstAdUrl && {
6466
+ vastUrl: firstAdUrl
6467
+ });
6468
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo1);
6469
+ }
6204
6470
  if (this.config.debugAdTiming) {
6205
6471
  console.log("[CONTINUOUS-FETCH] \u2705 First ad request successful, starting playback");
6206
6472
  }
@@ -6346,15 +6612,34 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6346
6612
  key: "continuousFetchLoop",
6347
6613
  value: function continuousFetchLoop(baseVastUrl) {
6348
6614
  return _async_to_generator(function() {
6349
- var _this, _loop, _ret;
6615
+ var loopIterations, _this, _loop, _ret;
6350
6616
  return _ts_generator(this, function(_state) {
6351
6617
  switch(_state.label){
6352
6618
  case 0:
6619
+ loopIterations = 0;
6620
+ _state.label = 1;
6621
+ case 1:
6622
+ _state.trys.push([
6623
+ 1,
6624
+ ,
6625
+ 5,
6626
+ 6
6627
+ ]);
6353
6628
  _loop = function() {
6354
- var remaining, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6629
+ var remaining, elapsedMs, maxLoopMs, maxQueueSize, newAdUrl, queuedUrlsPreview, generationDelay;
6355
6630
  return _ts_generator(this, function(_state) {
6356
6631
  switch(_state.label){
6357
6632
  case 0:
6633
+ loopIterations++;
6634
+ if (loopIterations > _this.continuousFetchMaxIterations) {
6635
+ if (_this.config.debugAdTiming) {
6636
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Max iterations reached (".concat(_this.continuousFetchMaxIterations, "), stopping URL generation"));
6637
+ }
6638
+ return [
6639
+ 2,
6640
+ "break"
6641
+ ];
6642
+ }
6358
6643
  remaining = _this.getRemainingAdMs();
6359
6644
  if (remaining <= 0) {
6360
6645
  if (_this.config.debugAdTiming) {
@@ -6365,6 +6650,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6365
6650
  "break"
6366
6651
  ];
6367
6652
  }
6653
+ if (_this.currentAdBreakStartWallClockMs != null && _this.expectedAdBreakDurationMs != null) {
6654
+ elapsedMs = Date.now() - _this.currentAdBreakStartWallClockMs;
6655
+ maxLoopMs = _this.expectedAdBreakDurationMs + _this.continuousFetchWallClockBufferMs;
6656
+ if (elapsedMs >= maxLoopMs) {
6657
+ if (_this.config.debugAdTiming) {
6658
+ console.log("[CONTINUOUS-FETCH] ⏹️ Wall-clock limit reached (".concat(elapsedMs, "ms >= ").concat(maxLoopMs, "ms), stopping URL generation"));
6659
+ }
6660
+ return [
6661
+ 2,
6662
+ "break"
6663
+ ];
6664
+ }
6665
+ }
6368
6666
  if (_this.consecutiveFailures >= _this.maxConsecutiveFailures) {
6369
6667
  if (_this.config.debugAdTiming) {
6370
6668
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Too many consecutive failures (".concat(_this.consecutiveFailures, "), stopping URL generation"));
@@ -6386,46 +6684,63 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6386
6684
  maxQueueSize = 5;
6387
6685
  if (!(_this.adRequestQueue.length >= maxQueueSize)) return [
6388
6686
  3,
6389
- 2
6687
+ 4
6390
6688
  ];
6689
+ if (!(_this.isPrebidMode() && _this.isLgStbDevice())) return [
6690
+ 3,
6691
+ 1
6692
+ ];
6693
+ _this.adRequestQueue.shift();
6694
+ _this.adRequestQueue.push("");
6695
+ _this.totalAdsInBreak++;
6696
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6391
6697
  if (_this.config.debugAdTiming) {
6392
- console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(_this.adRequestQueue.length, "), waiting..."));
6698
+ console.log("[CONTINUOUS-FETCH] Prebid slot rotated (queue full, dropped oldest); queue: ".concat(_this.adRequestQueue.length));
6393
6699
  }
6394
6700
  return [
6395
- 4,
6396
- new Promise(function(resolve) {
6397
- return setTimeout(resolve, 1e3);
6398
- })
6701
+ 3,
6702
+ 3
6399
6703
  ];
6400
6704
  case 1:
6705
+ return [
6706
+ 4,
6707
+ _this.waitForQueueWithBackoff()
6708
+ ];
6709
+ case 2:
6401
6710
  _state.sent();
6402
6711
  return [
6403
6712
  2,
6404
6713
  "continue"
6405
6714
  ];
6406
- case 2:
6715
+ case 3:
6716
+ return [
6717
+ 3,
6718
+ 8
6719
+ ];
6720
+ case 4:
6407
6721
  if (!_this.isPrebidMode()) return [
6408
6722
  3,
6409
- 3
6723
+ 5
6410
6724
  ];
6411
6725
  _this.adRequestQueue.push("");
6412
6726
  _this.totalAdsInBreak++;
6727
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6413
6728
  if (_this.config.debugAdTiming) {
6414
6729
  console.log("[CONTINUOUS-FETCH] Prebid auction slot queued (queue: ".concat(_this.adRequestQueue.length, ")"));
6415
6730
  }
6416
6731
  return [
6417
6732
  3,
6418
- 6
6733
+ 8
6419
6734
  ];
6420
- case 3:
6735
+ case 5:
6421
6736
  if (!baseVastUrl) return [
6422
6737
  3,
6423
- 6
6738
+ 8
6424
6739
  ];
6425
6740
  newAdUrl = _this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];
6426
6741
  if (!(!newAdUrl || _this.failedVastUrls.has(newAdUrl) || _this.isUrlInCooldown(newAdUrl))) return [
6427
6742
  3,
6428
- 5
6743
+ 7
6429
6744
  ];
6430
6745
  return [
6431
6746
  4,
@@ -6433,13 +6748,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6433
6748
  return setTimeout(resolve, 500);
6434
6749
  })
6435
6750
  ];
6436
- case 4:
6751
+ case 6:
6437
6752
  _state.sent();
6438
6753
  return [
6439
6754
  2,
6440
6755
  "continue"
6441
6756
  ];
6442
- case 5:
6757
+ case 7:
6443
6758
  if (_this.config.debugAdTiming) {
6444
6759
  queuedUrlsPreview = _to_consumable_array(_this.adRequestQueue).concat([
6445
6760
  newAdUrl
@@ -6450,8 +6765,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6450
6765
  }
6451
6766
  _this.adRequestQueue.push(newAdUrl);
6452
6767
  _this.totalAdsInBreak++;
6453
- _state.label = 6;
6454
- case 6:
6768
+ _this.continuousFetchQueueFullConsecutiveWaits = 0;
6769
+ _state.label = 8;
6770
+ case 8:
6455
6771
  generationDelay = _this.consecutiveFailures > 0 ? Math.min(1e3 * Math.pow(2, _this.consecutiveFailures), 5e3) : 500;
6456
6772
  return [
6457
6773
  4,
@@ -6459,7 +6775,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6459
6775
  return setTimeout(resolve, generationDelay);
6460
6776
  })
6461
6777
  ];
6462
- case 7:
6778
+ case 9:
6463
6779
  _state.sent();
6464
6780
  return [
6465
6781
  2
@@ -6467,33 +6783,41 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6467
6783
  }
6468
6784
  });
6469
6785
  };
6470
- _state.label = 1;
6471
- case 1:
6786
+ _state.label = 2;
6787
+ case 2:
6472
6788
  if (!(this.continuousFetchingActive && this.inAdBreak)) return [
6473
6789
  3,
6474
- 3
6790
+ 4
6475
6791
  ];
6476
6792
  _this = this;
6477
6793
  return [
6478
6794
  5,
6479
6795
  _ts_values(_loop())
6480
6796
  ];
6481
- case 2:
6797
+ case 3:
6482
6798
  _ret = _state.sent();
6483
6799
  if (_ret === "break") return [
6484
6800
  3,
6485
- 3
6801
+ 4
6486
6802
  ];
6487
6803
  return [
6488
6804
  3,
6489
- 1
6805
+ 2
6490
6806
  ];
6491
- case 3:
6807
+ case 4:
6808
+ return [
6809
+ 3,
6810
+ 6
6811
+ ];
6812
+ case 5:
6492
6813
  this.continuousFetchLoopRunning = false;
6814
+ this.continuousFetchQueueFullConsecutiveWaits = 0;
6815
+ return [
6816
+ 7
6817
+ ];
6818
+ case 6:
6493
6819
  if (this.config.debugAdTiming) {
6494
- console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 URL generation loop ended (queued: ".concat(this.adRequestQueue.length, ")"), this.adRequestQueue.length > 0 ? {
6495
- queuedUrls: _to_consumable_array(this.adRequestQueue)
6496
- } : {});
6820
+ this.logQueueState("URL generation loop ended");
6497
6821
  }
6498
6822
  return [
6499
6823
  2
@@ -6503,6 +6827,51 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6503
6827
  }).call(this);
6504
6828
  }
6505
6829
  },
6830
+ {
6831
+ key: "waitForQueueWithBackoff",
6832
+ value: function waitForQueueWithBackoff() {
6833
+ return _async_to_generator(function() {
6834
+ var delayMs, shouldLog;
6835
+ return _ts_generator(this, function(_state) {
6836
+ switch(_state.label){
6837
+ case 0:
6838
+ this.continuousFetchQueueFullConsecutiveWaits++;
6839
+ delayMs = Math.min(1e3 * Math.pow(2, this.continuousFetchQueueFullConsecutiveWaits - 1), 5e3);
6840
+ shouldLog = this.config.debugAdTiming && (this.continuousFetchQueueFullConsecutiveWaits <= 2 || this.continuousFetchQueueFullConsecutiveWaits % 4 === 0);
6841
+ if (shouldLog) {
6842
+ console.log("[CONTINUOUS-FETCH] ⏸️ URL queue full (".concat(this.adRequestQueue.length, "), waiting ").concat(delayMs, "ms (wait #").concat(this.continuousFetchQueueFullConsecutiveWaits, ")"));
6843
+ }
6844
+ return [
6845
+ 4,
6846
+ new Promise(function(resolve) {
6847
+ return setTimeout(resolve, delayMs);
6848
+ })
6849
+ ];
6850
+ case 1:
6851
+ _state.sent();
6852
+ return [
6853
+ 2
6854
+ ];
6855
+ }
6856
+ });
6857
+ }).call(this);
6858
+ }
6859
+ },
6860
+ {
6861
+ key: "logQueueState",
6862
+ value: function logQueueState(reason) {
6863
+ if (!this.config.debugAdTiming) return;
6864
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 ".concat(reason), {
6865
+ queueLength: this.adRequestQueue.length,
6866
+ totalAdsInBreak: this.totalAdsInBreak,
6867
+ totalAdRequestsInBreak: this.totalAdRequestsInBreak,
6868
+ consecutiveFailures: this.consecutiveFailures,
6869
+ continuousFetchingActive: this.continuousFetchingActive,
6870
+ continuousFetchLoopRunning: this.continuousFetchLoopRunning,
6871
+ inAdBreak: this.inAdBreak
6872
+ });
6873
+ }
6874
+ },
6506
6875
  {
6507
6876
  key: "stopContinuousFetching",
6508
6877
  value: function stopContinuousFetching() {
@@ -6567,7 +6936,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6567
6936
  value: function tryNextAvailableAd() {
6568
6937
  var retryCount = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 0;
6569
6938
  return _async_to_generator(function() {
6570
- var remaining, preloaded, currentMuted, currentVolume, adVolume, error, nextAdUrl, currentMuted1, currentVolume1, error1, errorMessage, maxRetries;
6939
+ var remaining, preloaded, adLoadedInfo, currentMuted, currentVolume, adVolume, error, nextAdUrl, currentMuted1, currentVolume1, error1, errorMessage, maxRetries;
6571
6940
  return _ts_generator(this, function(_state) {
6572
6941
  switch(_state.label){
6573
6942
  case 0:
@@ -6612,6 +6981,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6612
6981
  this.video.volume = 0;
6613
6982
  this.ima = preloaded.imaController;
6614
6983
  this.attachImaEventListeners();
6984
+ if (this.config.licenseKey) {
6985
+ adLoadedInfo = {
6986
+ source: this.getAdSource(),
6987
+ timestamp: /* @__PURE__ */ new Date().toISOString()
6988
+ };
6989
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
6990
+ }
6615
6991
  this.ima.resume();
6616
6992
  this.currentAdIndex++;
6617
6993
  this.totalAdRequestsInBreak++;
@@ -6673,8 +7049,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6673
7049
  4
6674
7050
  ];
6675
7051
  }
7052
+ console.log("[StormcloudVideoPlayer] Requesting next ad (%s), queue remaining=%s", nextAdUrl === "" ? "Prebid" : "VAST", this.adRequestQueue.length);
6676
7053
  if (this.config.debugAdTiming) {
6677
- 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)"));
7054
+ 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)"));
6678
7055
  }
6679
7056
  currentMuted1 = this.video.muted;
6680
7057
  currentVolume1 = this.video.volume;
@@ -6854,7 +7231,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6854
7231
  ];
6855
7232
  }
6856
7233
  if (this.config.debugAdTiming) {
6857
- console.log("[CONTINUOUS-FETCH] \u2705 Ad URL available, requesting via IMA SDK");
7234
+ console.log("[CONTINUOUS-FETCH] Ad URL available, requesting via ".concat(this.getAdPlayerTypeLabel()));
6858
7235
  }
6859
7236
  this.isShowingPlaceholder = false;
6860
7237
  this.ima.hidePlaceholder();
@@ -7169,7 +7546,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7169
7546
  key: "playSingleAd",
7170
7547
  value: function playSingleAd(vastTagUrl) {
7171
7548
  return _async_to_generator(function() {
7172
- var requestToken, currentMuted, currentVolume, adVolume, playError, preloadedFallback, currentMuted1, currentVolume1, adVolume1, fallbackError, error, errorMessage, preloadedFallback1, currentMuted2, currentVolume2, adVolume2, fallbackError1;
7549
+ var requestToken, adLoadedInfo, currentMuted, currentVolume, adVolume, playError, preloadedFallback, currentMuted1, currentVolume1, adVolume1, fallbackError, error, errorMessage, preloadedFallback1, currentMuted2, currentVolume2, adVolume2, fallbackError1;
7173
7550
  return _ts_generator(this, function(_state) {
7174
7551
  switch(_state.label){
7175
7552
  case 0:
@@ -7196,7 +7573,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7196
7573
  }
7197
7574
  throw new Error("Too many consecutive failures");
7198
7575
  }
7199
- this.recreateImaController();
7576
+ this.recreateAdController();
7200
7577
  requestToken = ++this.adRequestTokenCounter;
7201
7578
  this.activeAdRequestToken = requestToken;
7202
7579
  this.startAdRequestWatchdog(requestToken);
@@ -7221,6 +7598,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7221
7598
  2
7222
7599
  ];
7223
7600
  }
7601
+ if (this.config.licenseKey) {
7602
+ adLoadedInfo = _object_spread({
7603
+ source: this.getAdSource(),
7604
+ timestamp: /* @__PURE__ */ new Date().toISOString()
7605
+ }, vastTagUrl && {
7606
+ vastUrl: vastTagUrl
7607
+ });
7608
+ sendAdLoadedTracking(this.config.licenseKey, adLoadedInfo);
7609
+ }
7224
7610
  _state.label = 3;
7225
7611
  case 3:
7226
7612
  _state.trys.push([
@@ -7441,6 +7827,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7441
7827
  this.showAds = false;
7442
7828
  this.currentAdIndex = 0;
7443
7829
  this.totalAdsInBreak = 0;
7830
+ this.totalAdRequestsInBreak = 0;
7444
7831
  this.consecutiveFailures = 0;
7445
7832
  this.ima.stop().catch(function() {});
7446
7833
  var restoredMuted = this.ima.getOriginalMutedState();
@@ -7452,17 +7839,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7452
7839
  this.video.volume = restoredVolume;
7453
7840
  }
7454
7841
  if (this.shouldContinueLiveStreamDuringAds()) {
7455
- if (this.video.paused) {
7456
- var _this_video_play;
7457
- if (this.config.debugAdTiming) {
7842
+ var _this_video_play;
7843
+ if (this.config.debugAdTiming) {
7844
+ if (this.video.paused) {
7458
7845
  console.log("[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback");
7459
- }
7460
- (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
7461
- } else {
7462
- if (this.config.debugAdTiming) {
7846
+ } else {
7463
7847
  console.log("[StormcloudVideoPlayer] Content video already playing in live mode after ads");
7464
7848
  }
7465
7849
  }
7850
+ (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
7466
7851
  } else if (this.video.paused) {
7467
7852
  var _this_video_play1;
7468
7853
  (_this_video_play1 = this.video.play()) === null || _this_video_play1 === void 0 ? void 0 : _this_video_play1.catch(function() {});