stormcloud-video-player 0.2.33 → 0.2.35

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.
package/lib/index.cjs CHANGED
@@ -289,7 +289,7 @@ function createImaController(video, options) {
289
289
  video.muted = true;
290
290
  video.volume = 0;
291
291
  contentVideoHidden = true;
292
- console.log("[IMA] Content video hidden and muted");
292
+ console.log("[DEBUG-LAYER] \u{1F534} Content video HIDDEN | muted=true, volume=0");
293
293
  }
294
294
  }
295
295
  function showContentVideo() {
@@ -302,7 +302,7 @@ function createImaController(video, options) {
302
302
  video.volume = originalVolume;
303
303
  contentVideoHidden = false;
304
304
  console.log(
305
- `[IMA] Content video restored (muted: ${originalMutedState}, volume: ${originalVolume})`
305
+ `[DEBUG-LAYER] \u{1F7E2} Content video RESTORED | muted=${originalMutedState}, volume=${originalVolume}`
306
306
  );
307
307
  }
308
308
  }
@@ -324,12 +324,12 @@ function createImaController(video, options) {
324
324
  "canplay",
325
325
  () => {
326
326
  adVideo.style.opacity = "1";
327
- console.log("[IMA] Ad video ready to play");
327
+ console.log("[DEBUG-LAYER] \u{1F4FA} Ad video element ready (canplay fired)");
328
328
  },
329
329
  { once: true }
330
330
  );
331
331
  console.log(
332
- `[IMA] Created dedicated ad video element with volume: ${adVideo.volume}, muted: ${adVideo.muted}`
332
+ `[DEBUG-AUDIO] \u{1F50A} Ad video created | volume=${adVideo.volume}, muted=${adVideo.muted}`
333
333
  );
334
334
  return adVideo;
335
335
  }
@@ -415,17 +415,12 @@ function createImaController(video, options) {
415
415
  let adsLoadedResolve;
416
416
  let adsLoadedReject;
417
417
  function makeAdsRequest(google, vastTagUrl) {
418
- console.log("[IMA] \u{1F4CB} === makeAdsRequest() - Building IMA request ===");
419
418
  const adsRequest = new google.ima.AdsRequest();
420
419
  const preloadedResponse = preloadedVast.get(vastTagUrl);
421
420
  if (preloadedResponse) {
422
421
  adsRequest.adsResponse = preloadedResponse;
423
- console.log(
424
- "[IMA] \u26A1 Using preloaded VAST response for immediate ad request"
425
- );
426
422
  } else {
427
423
  adsRequest.adTagUrl = vastTagUrl;
428
- console.log("[IMA] \u{1F310} Will fetch VAST from URL:", vastTagUrl);
429
424
  }
430
425
  const videoWidth = video.offsetWidth || video.clientWidth || 640;
431
426
  const videoHeight = video.offsetHeight || video.clientHeight || 360;
@@ -437,7 +432,6 @@ function createImaController(video, options) {
437
432
  try {
438
433
  const willAutoPlay = !video.paused || video.autoplay;
439
434
  adsRequest.setAdWillAutoPlay(willAutoPlay);
440
- console.log(`[IMA] Ad will autoplay: ${willAutoPlay}`);
441
435
  } catch (error) {
442
436
  console.warn("[IMA] Failed to call setAdWillAutoPlay:", error);
443
437
  }
@@ -446,17 +440,12 @@ function createImaController(video, options) {
446
440
  try {
447
441
  const willPlayMuted = video.muted || video.volume === 0;
448
442
  adsRequest.setAdWillPlayMuted(willPlayMuted);
449
- console.log(`[IMA] Ad will play muted: ${willPlayMuted}`);
450
443
  } catch (error) {
451
444
  console.warn("[IMA] Failed to call setAdWillPlayMuted:", error);
452
445
  }
453
446
  }
454
447
  adsRequest.vastLoadTimeout = 5e3;
455
- console.log(`[IMA] \u{1F4D0} Ads request dimensions: ${videoWidth}x${videoHeight}`);
456
- console.log("[IMA] \u23F1\uFE0F VAST load timeout: 5000ms");
457
- console.log("[IMA] \u{1F680} Calling adsLoader.requestAds()...");
458
448
  adsLoader.requestAds(adsRequest);
459
- console.log("[IMA] \u23F3 Waiting for ADS_MANAGER_LOADED or AD_ERROR event...");
460
449
  if (preloadedResponse) {
461
450
  preloadedVast.delete(vastTagUrl);
462
451
  }
@@ -641,85 +630,29 @@ function createImaController(video, options) {
641
630
  adsLoader.addEventListener(
642
631
  google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
643
632
  (evt) => {
644
- console.log("[IMA] \u2705 ADS_MANAGER_LOADED - Ads fetched successfully!");
645
- console.log("[IMA] Setting up ads manager with preloading enabled");
646
- console.log("[IMA] ========================================");
647
- console.log("[IMA] EXPECTED EVENT FLOW:");
648
- console.log("[IMA] 1. requestAds() \u2192 fetch VAST");
649
- console.log("[IMA] 2. ADS_MANAGER_LOADED \u2192 ads ready");
650
- console.log("[IMA] 3. play() \u2192 start playback");
651
- console.log("[IMA] 4. CONTENT_PAUSE_REQUESTED \u2192 show ad layer \u2728");
652
- console.log("[IMA] 5. STARTED \u2192 ad is playing");
653
- console.log("[IMA] 6. CONTENT_RESUME_REQUESTED \u2192 ad done");
654
- console.log("[IMA] 7. ALL_ADS_COMPLETED \u2192 hide ad layer");
655
- console.log("[IMA] ========================================");
633
+ console.log("[DEBUG-FLOW] \u2705 ADS_MANAGER_LOADED - Setting up manager");
656
634
  try {
657
635
  const adsRenderingSettings = new google.ima.AdsRenderingSettings();
658
636
  adsRenderingSettings.enablePreloading = true;
659
637
  adsManager = evt.getAdsManager(video, adsRenderingSettings);
660
638
  const AdEvent = google.ima.AdEvent.Type;
661
639
  const AdErrorEvent = google.ima.AdErrorEvent.Type;
662
- console.log("[IMA] ========== IMA EVENT LOGGING ENABLED ==========");
663
- console.log("[IMA] All IMA SDK events will be logged below");
664
- const allAdEvents = [
665
- "AD_BREAK_READY",
666
- "AD_METADATA",
667
- "ALL_ADS_COMPLETED",
668
- "CLICK",
669
- "COMPLETE",
670
- "CONTENT_PAUSE_REQUESTED",
671
- "CONTENT_RESUME_REQUESTED",
672
- "DURATION_CHANGE",
673
- "FIRST_QUARTILE",
674
- "IMPRESSION",
675
- "INTERACTION",
676
- "LINEAR_CHANGED",
677
- "LOADED",
678
- "LOG",
679
- "MIDPOINT",
680
- "PAUSED",
681
- "RESUMED",
682
- "SKIPPABLE_STATE_CHANGED",
683
- "SKIPPED",
684
- "STARTED",
685
- "THIRD_QUARTILE",
686
- "USER_CLOSE",
687
- "VOLUME_CHANGED",
688
- "VOLUME_MUTED"
689
- ];
690
- allAdEvents.forEach((eventType) => {
640
+ const keyEvents = ["STARTED", "COMPLETE", "CONTENT_PAUSE_REQUESTED", "CONTENT_RESUME_REQUESTED", "ALL_ADS_COMPLETED"];
641
+ keyEvents.forEach((eventType) => {
691
642
  if (AdEvent[eventType]) {
692
643
  adsManager.addEventListener(AdEvent[eventType], (e) => {
693
- var _a, _b, _c, _d, _e, _f;
644
+ var _a, _b;
694
645
  const ad = (_a = e.getAd) == null ? void 0 : _a.call(e);
695
- const adData = ad ? {
696
- adId: (_b = ad.getAdId) == null ? void 0 : _b.call(ad),
697
- title: (_c = ad.getTitle) == null ? void 0 : _c.call(ad),
698
- duration: (_d = ad.getDuration) == null ? void 0 : _d.call(ad),
699
- isLinear: (_e = ad.isLinear) == null ? void 0 : _e.call(ad),
700
- contentType: (_f = ad.getContentType) == null ? void 0 : _f.call(ad)
701
- } : null;
702
- console.log(`[IMA EVENT] ${eventType}`, {
703
- eventType,
704
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
705
- adData
706
- });
646
+ console.log(`[DEBUG-FLOW] \u{1F3AC} ${eventType} | title=${((_b = ad == null ? void 0 : ad.getTitle) == null ? void 0 : _b.call(ad)) || "N/A"}`);
707
647
  });
708
648
  }
709
649
  });
710
- console.log("[IMA] ========== EVENT LISTENERS ATTACHED ==========");
711
650
  adsManager.addEventListener(
712
651
  AdErrorEvent.AD_ERROR,
713
652
  (errorEvent) => {
714
- var _a, _b, _c, _d, _e, _f;
653
+ var _a, _b;
715
654
  const error = errorEvent.getError();
716
- console.error("[IMA] \u274C AD_ERROR Event:", {
717
- message: (_a = error.getMessage) == null ? void 0 : _a.call(error),
718
- errorCode: (_b = error.getErrorCode) == null ? void 0 : _b.call(error),
719
- type: (_c = error.getType) == null ? void 0 : _c.call(error),
720
- vastErrorCode: (_d = error.getVastErrorCode) == null ? void 0 : _d.call(error),
721
- innerError: (_e = error.getInnerError) == null ? void 0 : _e.call(error)
722
- });
655
+ console.error("[DEBUG-ERROR] \u274C AD_ERROR:", (_a = error.getMessage) == null ? void 0 : _a.call(error));
723
656
  destroyAdsManager();
724
657
  adPlaying = false;
725
658
  setAdPlayingFlag(false);
@@ -730,7 +663,7 @@ function createImaController(video, options) {
730
663
  if (adContainerEl) {
731
664
  adContainerEl.style.pointerEvents = "none";
732
665
  adContainerEl.style.display = "none";
733
- console.log("[IMA] Ad container hidden after error");
666
+ console.log("[DEBUG-LAYER] \u274C Ad container HIDDEN (error)");
734
667
  }
735
668
  }, 300);
736
669
  }
@@ -742,9 +675,6 @@ function createImaController(video, options) {
742
675
  }
743
676
  if (lastAdTagUrl && retryAttempts < maxRetries) {
744
677
  const delay = backoffBaseMs * Math.pow(2, retryAttempts++);
745
- console.log(
746
- `[IMA] Retrying ad request in ${delay}ms (attempt ${retryAttempts})`
747
- );
748
678
  window.setTimeout(() => {
749
679
  try {
750
680
  makeAdsRequest(google, lastAdTagUrl);
@@ -752,16 +682,10 @@ function createImaController(video, options) {
752
682
  }
753
683
  }, delay);
754
684
  } else {
755
- console.log(
756
- "[IMA] Max retries reached, emitting ad_error"
757
- );
758
685
  emit("ad_error");
759
686
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
760
687
  if (video.paused) {
761
- console.log(
762
- "[IMA] Resuming paused video after ad error"
763
- );
764
- (_f = video.play()) == null ? void 0 : _f.catch(() => {
688
+ (_b = video.play()) == null ? void 0 : _b.catch(() => {
765
689
  });
766
690
  }
767
691
  }
@@ -771,15 +695,9 @@ function createImaController(video, options) {
771
695
  adsManager.addEventListener(
772
696
  AdEvent.CONTENT_PAUSE_REQUESTED,
773
697
  () => {
774
- console.log("[IMA] \u2705 CONTENT_PAUSE_REQUESTED - Ad is ready to play!");
775
- console.log("[IMA] This is the event that triggers the ad layer to appear");
698
+ console.log("[DEBUG-FLOW] \u{1F3AF} CONTENT_PAUSE_REQUESTED - Ad starting");
776
699
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
777
700
  video.pause();
778
- console.log("[IMA] Content video paused (VOD mode)");
779
- } else {
780
- console.log(
781
- "[IMA] Content video continues in background (Live mode)"
782
- );
783
701
  }
784
702
  hideContentVideo();
785
703
  if (adContainerEl) {
@@ -788,23 +706,22 @@ function createImaController(video, options) {
788
706
  adContainerEl.style.backgroundColor = "#000";
789
707
  adContainerEl.offsetHeight;
790
708
  adContainerEl.style.opacity = "1";
791
- console.log("[IMA] \u2728 Ad container NOW VISIBLE (after content pause)");
709
+ console.log("[DEBUG-LAYER] \u{1F7E1} Ad container VISIBLE");
792
710
  }
793
711
  adPlaying = true;
794
712
  setAdPlayingFlag(true);
795
- console.log("[IMA] Emitting 'content_pause' event to player");
796
713
  emit("content_pause");
797
714
  }
798
715
  );
799
716
  adsManager.addEventListener(AdEvent.STARTED, () => {
800
- console.log("[IMA] \u25B6\uFE0F STARTED - Ad playback has begun");
717
+ console.log("[DEBUG-FLOW] \u25B6\uFE0F STARTED - Ad playing now");
801
718
  setAdPlayingFlag(true);
802
719
  hideContentVideo();
803
720
  if (adVideoElement) {
804
721
  adVideoElement.volume = originalMutedState ? 0 : originalVolume;
805
722
  adVideoElement.muted = originalMutedState;
806
723
  console.log(
807
- `[IMA] Ad video volume: ${adVideoElement.volume}, muted: ${adVideoElement.muted}`
724
+ `[DEBUG-AUDIO] \u{1F50A} Ad audio set | volume=${adVideoElement.volume}, muted=${adVideoElement.muted}`
808
725
  );
809
726
  }
810
727
  if (adContainerEl) {
@@ -813,21 +730,20 @@ function createImaController(video, options) {
813
730
  adContainerEl.style.backgroundColor = "#000";
814
731
  adContainerEl.offsetHeight;
815
732
  adContainerEl.style.opacity = "1";
816
- console.log("[IMA] Ad container now visible (STARTED event)");
817
733
  }
818
734
  });
819
735
  adsManager.addEventListener(
820
736
  AdEvent.CONTENT_RESUME_REQUESTED,
821
737
  () => {
822
- console.log("[IMA] \u23F8\uFE0F CONTENT_RESUME_REQUESTED - Single ad completed");
738
+ console.log("[DEBUG-FLOW] \u23F8\uFE0F CONTENT_RESUME - Single ad done");
823
739
  adPlaying = false;
824
740
  setAdPlayingFlag(false);
825
- console.log("[IMA] Emitting 'content_resume' event to player");
741
+ console.log("[DEBUG-LAYER] \u26A0\uFE0F Waiting for pod manager (more ads, placeholder, or done)");
826
742
  emit("content_resume");
827
743
  }
828
744
  );
829
745
  adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {
830
- console.log("[IMA] \u{1F3C1} ALL_ADS_COMPLETED - All ads in break finished");
746
+ console.log("[DEBUG-FLOW] \u{1F3C1} ALL_ADS_COMPLETED - Pod finished");
831
747
  adPlaying = false;
832
748
  setAdPlayingFlag(false);
833
749
  if (adContainerEl) {
@@ -837,18 +753,16 @@ function createImaController(video, options) {
837
753
  if (adContainerEl) {
838
754
  adContainerEl.style.pointerEvents = "none";
839
755
  adContainerEl.style.display = "none";
840
- console.log("[IMA] \u{1F648} Ad container hidden (ALL_ADS_COMPLETED)");
756
+ console.log("[DEBUG-LAYER] \u26AB Ad container HIDDEN (pod done)");
841
757
  }
842
758
  }, 300);
843
759
  }
844
760
  showContentVideo();
845
761
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds) && video.paused) {
846
- console.log("[IMA] Resuming content video playback");
847
762
  video.play().catch((e) => {
848
- console.warn("[IMA] Failed to resume content video:", e);
763
+ console.warn("[DEBUG-ERROR] Failed to resume video:", e);
849
764
  });
850
765
  }
851
- console.log("[IMA] Emitting 'all_ads_completed' event to player");
852
766
  emit("all_ads_completed");
853
767
  });
854
768
  console.log("[IMA] Ads manager event listeners attached");
@@ -868,18 +782,12 @@ function createImaController(video, options) {
868
782
  if (adContainerEl) {
869
783
  adContainerEl.style.pointerEvents = "none";
870
784
  adContainerEl.style.display = "none";
871
- console.log(
872
- "[IMA] Ad container hidden after setup error"
873
- );
874
785
  }
875
786
  }, 300);
876
787
  }
877
788
  showContentVideo();
878
789
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
879
790
  if (video.paused) {
880
- console.log(
881
- "[IMA] Resuming paused video after setup error"
882
- );
883
791
  video.play().catch(() => {
884
792
  });
885
793
  }
@@ -897,17 +805,9 @@ function createImaController(video, options) {
897
805
  adsLoader.addEventListener(
898
806
  google.ima.AdErrorEvent.Type.AD_ERROR,
899
807
  (adErrorEvent) => {
900
- var _a, _b, _c, _d;
808
+ var _a;
901
809
  const error = adErrorEvent.getError();
902
- console.error("[IMA] \u274C ADS_LOADER ERROR - Ad request failed!", {
903
- message: (_a = error.getMessage) == null ? void 0 : _a.call(error),
904
- errorCode: (_b = error.getErrorCode) == null ? void 0 : _b.call(error),
905
- type: (_c = error.getType) == null ? void 0 : _c.call(error),
906
- vastErrorCode: (_d = error.getVastErrorCode) == null ? void 0 : _d.call(error)
907
- });
908
- console.error("[IMA] This means the ad server didn't return valid ads");
909
- console.error("[IMA] Ad layer will NOT appear (no flicker)");
910
- console.error("[IMA] Full error object:", adErrorEvent.getError());
810
+ console.error("[DEBUG-ERROR] \u274C ADS_LOADER ERROR:", (_a = error.getMessage) == null ? void 0 : _a.call(error));
911
811
  adPlaying = false;
912
812
  setAdPlayingFlag(false);
913
813
  if (adContainerEl) {
@@ -917,14 +817,12 @@ function createImaController(video, options) {
917
817
  if (adContainerEl) {
918
818
  adContainerEl.style.pointerEvents = "none";
919
819
  adContainerEl.style.display = "none";
920
- console.log("[IMA] Ad container hidden after loader error");
921
820
  }
922
821
  }, 300);
923
822
  }
924
823
  showContentVideo();
925
824
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
926
825
  if (video.paused) {
927
- console.log("[IMA] Resuming paused video after loader error");
928
826
  video.play().catch(() => {
929
827
  });
930
828
  }
@@ -939,10 +837,7 @@ function createImaController(video, options) {
939
837
  false
940
838
  );
941
839
  }
942
- console.log("[IMA] \u{1F680} Making ads request to IMA SDK");
943
- console.log("[IMA] Waiting for IMA SDK response (LOADED or ERROR event)...");
944
840
  makeAdsRequest(google, vastTagUrl);
945
- console.log("[IMA] \u23F3 Returning promise that will resolve when ads are loaded");
946
841
  return adsLoadedPromise;
947
842
  } catch (error) {
948
843
  console.error("[IMA] Failed to request ads:", error);
@@ -980,23 +875,16 @@ function createImaController(video, options) {
980
875
  },
981
876
  async play() {
982
877
  var _a, _b;
983
- console.log("[IMA] \u25B6\uFE0F === play() called ===");
984
- console.log("[IMA] This initializes and starts the ad");
985
- console.log("[IMA] Ad layer will appear when CONTENT_PAUSE_REQUESTED fires");
878
+ console.log("[DEBUG-FLOW] \u25B6\uFE0F play() - Starting ad playback");
986
879
  if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
987
- console.warn(
988
- "[IMA] \u274C Cannot play ad: IMA SDK or ad container not available"
989
- );
990
880
  return Promise.reject(new Error("IMA SDK not available"));
991
881
  }
992
882
  if (!adsManager) {
993
- console.warn("[IMA] \u274C Cannot play ad: No ads manager available");
994
883
  return Promise.reject(new Error("No ads manager"));
995
884
  }
996
885
  try {
997
886
  const width = video.clientWidth || 640;
998
887
  const height = video.clientHeight || 360;
999
- console.log(`[IMA] \u{1F3AC} Initializing ads manager (${width}x${height})`);
1000
888
  adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);
1001
889
  adPlaying = true;
1002
890
  const adVolume = originalMutedState ? 0 : originalVolume;
@@ -1004,22 +892,18 @@ function createImaController(video, options) {
1004
892
  adVideoElement.volume = adVolume;
1005
893
  adVideoElement.muted = originalMutedState;
1006
894
  console.log(
1007
- `[IMA] \u{1F50A} Set dedicated ad video volume to ${adVolume}, muted: ${originalMutedState}`
895
+ `[DEBUG-AUDIO] \u{1F50A} Pre-start ad audio | volume=${adVolume}, muted=${originalMutedState}`
1008
896
  );
1009
897
  }
1010
898
  try {
1011
899
  adsManager.setVolume(adVolume);
1012
- console.log(`[IMA] Set IMA manager volume to ${adVolume}`);
1013
900
  } catch (error) {
1014
- console.warn("[IMA] Failed to set IMA manager volume:", error);
901
+ console.warn("[DEBUG-ERROR] Failed to set IMA manager volume:", error);
1015
902
  }
1016
- console.log("[IMA] \u{1F3AF} Calling adsManager.start()");
1017
- console.log("[IMA] If successful, IMA will fire CONTENT_PAUSE_REQUESTED");
1018
903
  adsManager.start();
1019
- console.log("[IMA] \u2705 play() completed successfully");
1020
904
  return Promise.resolve();
1021
905
  } catch (error) {
1022
- console.error("[IMA] \u274C Error starting ad playback:", error);
906
+ console.error("[DEBUG-ERROR] \u274C Error starting ad:", error);
1023
907
  adPlaying = false;
1024
908
  setAdPlayingFlag(false);
1025
909
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -1031,7 +915,7 @@ function createImaController(video, options) {
1031
915
  },
1032
916
  async stop() {
1033
917
  var _a;
1034
- console.log("[IMA] Stopping ad playback");
918
+ console.log("[DEBUG-FLOW] \u23F9\uFE0F stop() - Stopping ad playback");
1035
919
  adPlaying = false;
1036
920
  setAdPlayingFlag(false);
1037
921
  if (adContainerEl) {
@@ -1041,7 +925,7 @@ function createImaController(video, options) {
1041
925
  if (adContainerEl) {
1042
926
  adContainerEl.style.pointerEvents = "none";
1043
927
  adContainerEl.style.display = "none";
1044
- console.log("[IMA] Ad container hidden after stop");
928
+ console.log("[DEBUG-LAYER] \u26AB Ad container HIDDEN (stop)");
1045
929
  }
1046
930
  }, 300);
1047
931
  }
@@ -1112,7 +996,7 @@ function createImaController(video, options) {
1112
996
  updateOriginalMutedState(muted, volume) {
1113
997
  const nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
1114
998
  console.log(
1115
- `[IMA] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`
999
+ `[DEBUG-AUDIO] \u{1F4BE} Saved original state | muted: ${originalMutedState}->${muted}, volume: ${originalVolume}->${nextVolume}`
1116
1000
  );
1117
1001
  originalMutedState = muted;
1118
1002
  originalVolume = nextVolume;
@@ -1129,14 +1013,14 @@ function createImaController(video, options) {
1129
1013
  adVideoElement.volume = clampedVolume;
1130
1014
  adVideoElement.muted = clampedVolume === 0;
1131
1015
  console.log(
1132
- `[IMA] Set dedicated ad video volume to ${clampedVolume}, muted: ${clampedVolume === 0}`
1016
+ `[DEBUG-AUDIO] \u{1F50A} Ad volume changed | volume=${clampedVolume}, muted=${clampedVolume === 0}`
1133
1017
  );
1134
1018
  }
1135
1019
  if (adsManager && adPlaying) {
1136
1020
  try {
1137
1021
  adsManager.setVolume(clampedVolume);
1138
1022
  } catch (error) {
1139
- console.warn("[IMA] Failed to set IMA manager volume:", error);
1023
+ console.warn("[DEBUG-ERROR] Failed to set IMA manager volume:", error);
1140
1024
  }
1141
1025
  }
1142
1026
  },
@@ -2347,6 +2231,10 @@ var StormcloudVideoPlayer = class {
2347
2231
  this.vastToMediaUrlMap = /* @__PURE__ */ new Map();
2348
2232
  this.preloadedMediaUrls = /* @__PURE__ */ new Set();
2349
2233
  this.preloadingMediaUrls = /* @__PURE__ */ new Set();
2234
+ this.adRequestTokenCounter = 0;
2235
+ this.activeAdRequestToken = null;
2236
+ this.adRequestWatchdogToken = null;
2237
+ this.adFailsafeToken = null;
2350
2238
  initializePolyfills();
2351
2239
  const browserOverrides = getBrowserConfigOverrides();
2352
2240
  this.config = { ...config, ...browserOverrides };
@@ -2618,71 +2506,50 @@ var StormcloudVideoPlayer = class {
2618
2506
  }
2619
2507
  });
2620
2508
  this.ima.on("ad_error", () => {
2621
- if (this.config.debugAdTiming) {
2622
- console.log("[StormcloudVideoPlayer] IMA ad_error event received", {
2623
- showAds: this.showAds,
2624
- inAdBreak: this.inAdBreak,
2625
- remainingAds: this.adPodQueue.length
2626
- });
2627
- }
2509
+ const remaining = this.getRemainingAdMs();
2510
+ console.log(
2511
+ `[DEBUG-POD] \u274C ad_error event | inBreak=${this.inAdBreak}, queue=${this.adPodQueue.length}, remaining=${remaining}ms`
2512
+ );
2628
2513
  if (this.inAdBreak) {
2629
- const remaining = this.getRemainingAdMs();
2630
2514
  if (remaining > 500 && this.adPodQueue.length > 0) {
2631
2515
  const nextPreloaded = this.findNextPreloadedAd();
2632
2516
  if (nextPreloaded) {
2633
2517
  this.currentAdIndex++;
2634
- if (this.config.debugAdTiming) {
2635
- console.log(
2636
- `[StormcloudVideoPlayer] Skipping to next preloaded ad after error`
2637
- );
2638
- }
2518
+ console.log(
2519
+ `[DEBUG-POD] \u27A1\uFE0F Trying next ad after error (${this.currentAdIndex}/${this.totalAdsInBreak})`
2520
+ );
2639
2521
  this.playSingleAd(nextPreloaded).catch(() => {
2640
2522
  this.handleAdFailure();
2641
2523
  });
2642
2524
  } else {
2643
- if (this.config.debugAdTiming) {
2644
- console.log(
2645
- "[StormcloudVideoPlayer] No preloaded ads available, ending ad break"
2646
- );
2647
- }
2525
+ console.log("[DEBUG-POD] \u26A0\uFE0F No more preloaded ads - calling handleAdFailure");
2648
2526
  this.handleAdFailure();
2649
2527
  }
2650
2528
  } else {
2529
+ console.log("[DEBUG-POD] \u26A0\uFE0F No more ads or time - calling handleAdFailure");
2651
2530
  this.handleAdFailure();
2652
2531
  }
2653
2532
  } else {
2654
- if (this.config.debugAdTiming) {
2655
- console.log(
2656
- "[StormcloudVideoPlayer] Ad error before ad break established - cleaning up"
2657
- );
2658
- }
2533
+ console.log("[DEBUG-POD] \u26A0\uFE0F Error before ad break established");
2659
2534
  this.handleAdFailure();
2660
2535
  }
2661
2536
  });
2662
2537
  this.ima.on("content_pause", () => {
2663
- if (this.config.debugAdTiming) {
2664
- console.log("[StormcloudVideoPlayer] IMA content_pause event received");
2665
- }
2538
+ console.log(`[DEBUG-POD] \u{1F3AF} content_pause | ad ${this.currentAdIndex}/${this.totalAdsInBreak}, queue=${this.adPodQueue.length}`);
2666
2539
  this.clearAdFailsafeTimer();
2540
+ this.clearAdRequestWatchdog();
2541
+ this.activeAdRequestToken = null;
2542
+ this.showAds = true;
2667
2543
  this.enforceAdHoldState();
2668
2544
  });
2669
2545
  this.ima.on("content_resume", () => {
2670
- if (this.config.debugAdTiming) {
2671
- console.log(
2672
- "[StormcloudVideoPlayer] IMA content_resume event received",
2673
- {
2674
- inAdBreak: this.inAdBreak,
2675
- pendingAds: this.adPodQueue.length
2676
- }
2677
- );
2678
- }
2546
+ console.log(`[DEBUG-POD] \u23F8\uFE0F content_resume | ad ${this.currentAdIndex}/${this.totalAdsInBreak}, queue=${this.adPodQueue.length}, remaining=${this.getRemainingAdMs()}ms`);
2679
2547
  this.clearAdFailsafeTimer();
2548
+ this.clearAdRequestWatchdog();
2549
+ this.activeAdRequestToken = null;
2550
+ this.showAds = false;
2680
2551
  if (!this.inAdBreak) {
2681
- if (this.config.debugAdTiming) {
2682
- console.log(
2683
- "[StormcloudVideoPlayer] Not in ad break - this shouldn't happen during pod"
2684
- );
2685
- }
2552
+ console.warn("[DEBUG-POD] \u26A0\uFE0F Not in ad break - shouldn't happen");
2686
2553
  return;
2687
2554
  }
2688
2555
  const remaining = this.getRemainingAdMs();
@@ -2690,33 +2557,17 @@ var StormcloudVideoPlayer = class {
2690
2557
  const nextPreloaded = this.findNextPreloadedAd();
2691
2558
  if (nextPreloaded) {
2692
2559
  this.currentAdIndex++;
2693
- if (this.config.debugAdTiming) {
2694
- console.log(
2695
- `[StormcloudVideoPlayer] Playing next preloaded ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak}) - layer will stay visible if ad loads`
2696
- );
2697
- }
2560
+ console.log(`[DEBUG-POD] \u27A1\uFE0F Playing next ad ${this.currentAdIndex}/${this.totalAdsInBreak} (preloaded)`);
2698
2561
  this.playSingleAd(nextPreloaded).catch(() => {
2699
- if (this.config.debugAdTiming) {
2700
- console.error(
2701
- "[StormcloudVideoPlayer] Failed to play next ad in pod"
2702
- );
2703
- }
2562
+ console.error("[DEBUG-POD] \u274C Failed to play next ad");
2704
2563
  this.handleAdPodComplete();
2705
2564
  });
2706
2565
  } else {
2707
- if (this.config.debugAdTiming) {
2708
- console.log(
2709
- "[StormcloudVideoPlayer] No preloaded ads available - completing ad break"
2710
- );
2711
- }
2566
+ console.log("[DEBUG-POD] \u26A0\uFE0F No preloaded ads - ending pod");
2712
2567
  this.handleAdPodComplete();
2713
2568
  }
2714
2569
  } else {
2715
- if (this.config.debugAdTiming) {
2716
- console.log(
2717
- "[StormcloudVideoPlayer] No more ads in pod - completing ad break"
2718
- );
2719
- }
2570
+ console.log("[DEBUG-POD] \u2705 Pod complete (no more ads or time expired)");
2720
2571
  this.handleAdPodComplete();
2721
2572
  }
2722
2573
  });
@@ -3291,52 +3142,27 @@ var StormcloudVideoPlayer = class {
3291
3142
  let vastTagUrls = [];
3292
3143
  if (this.apiVastTagUrl) {
3293
3144
  vastTagUrls = [this.apiVastTagUrl];
3294
- if (this.config.debugAdTiming) {
3295
- console.log(
3296
- "[StormcloudVideoPlayer] Using VAST endpoint:",
3297
- this.apiVastTagUrl
3298
- );
3299
- }
3300
3145
  } else if (tags && tags.length > 0) {
3301
3146
  vastTagUrls = tags;
3302
- if (this.config.debugAdTiming) {
3303
- console.log(
3304
- "[StormcloudVideoPlayer] Using scheduled VAST tags (count: " + tags.length + "):",
3305
- tags
3306
- );
3307
- }
3308
3147
  } else {
3309
- if (this.config.debugAdTiming) {
3310
- console.log("[StormcloudVideoPlayer] No VAST tag available for ad");
3311
- }
3148
+ console.log("[DEBUG-POD] \u26A0\uFE0F No VAST tag available");
3312
3149
  return;
3313
3150
  }
3314
3151
  if (vastTagUrls.length > 0) {
3152
+ console.log(`[DEBUG-POD] \u{1F3AF} Starting ad break with ${vastTagUrls.length} ads`);
3315
3153
  this.adPodAllUrls = [...vastTagUrls];
3316
3154
  this.preloadingAdUrls.clear();
3317
3155
  this.vastToMediaUrlMap.clear();
3318
3156
  this.preloadedMediaUrls.clear();
3319
3157
  this.preloadingMediaUrls.clear();
3320
- this.logQueuedAdUrls(this.adPodAllUrls);
3321
- if (this.config.debugAdTiming) {
3322
- console.log(
3323
- `[StormcloudVideoPlayer] Capturing original audio state before ad break:`,
3324
- {
3325
- videoMuted: this.video.muted,
3326
- videoVolume: this.video.volume
3327
- }
3328
- );
3329
- }
3158
+ console.log(
3159
+ `[DEBUG-AUDIO] \u{1F4BE} Capturing original state | muted=${this.video.muted}, volume=${this.video.volume}`
3160
+ );
3330
3161
  this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
3331
3162
  this.inAdBreak = true;
3332
3163
  this.currentAdIndex = 0;
3333
3164
  this.totalAdsInBreak = vastTagUrls.length;
3334
3165
  this.adPodQueue = [...vastTagUrls];
3335
- if (this.config.debugAdTiming) {
3336
- console.log(
3337
- `[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads - preloading all ads in parallel (ad layer will show after ad loads)`
3338
- );
3339
- }
3340
3166
  this.preloadAllAdsInBackground().catch((error) => {
3341
3167
  if (this.config.debugAdTiming) {
3342
3168
  console.warn(
@@ -3348,12 +3174,7 @@ var StormcloudVideoPlayer = class {
3348
3174
  try {
3349
3175
  await this.playAdPod();
3350
3176
  } catch (error) {
3351
- if (this.config.debugAdTiming) {
3352
- console.error(
3353
- "[StormcloudVideoPlayer] Ad pod playback failed:",
3354
- error
3355
- );
3356
- }
3177
+ console.error("[DEBUG-POD] \u274C Pod playback failed:", error);
3357
3178
  this.handleAdFailure();
3358
3179
  }
3359
3180
  }
@@ -3365,19 +3186,13 @@ var StormcloudVideoPlayer = class {
3365
3186
  }
3366
3187
  async playAdPod() {
3367
3188
  if (this.adPodQueue.length === 0) {
3368
- if (this.config.debugAdTiming) {
3369
- console.log("[StormcloudVideoPlayer] No ads in pod to play");
3370
- }
3189
+ console.log("[DEBUG-POD] \u26A0\uFE0F No ads in pod");
3371
3190
  return;
3372
3191
  }
3373
3192
  await new Promise((resolve) => setTimeout(resolve, 500));
3374
3193
  const firstPreloaded = this.findNextPreloadedAd();
3375
3194
  if (!firstPreloaded) {
3376
- if (this.config.debugAdTiming) {
3377
- console.log(
3378
- "[StormcloudVideoPlayer] No preloaded ads available after waiting, trying first ad anyway"
3379
- );
3380
- }
3195
+ console.log("[DEBUG-POD] \u26A0\uFE0F No preloaded ads after wait, trying first ad");
3381
3196
  const firstAd = this.adPodQueue.shift();
3382
3197
  if (firstAd) {
3383
3198
  this.currentAdIndex++;
@@ -3386,11 +3201,7 @@ var StormcloudVideoPlayer = class {
3386
3201
  return;
3387
3202
  }
3388
3203
  this.currentAdIndex++;
3389
- if (this.config.debugAdTiming) {
3390
- console.log(
3391
- `[StormcloudVideoPlayer] Playing first preloaded ad ${this.currentAdIndex}/${this.totalAdsInBreak}`
3392
- );
3393
- }
3204
+ console.log(`[DEBUG-POD] \u{1F680} Starting pod with ad ${this.currentAdIndex}/${this.totalAdsInBreak}`);
3394
3205
  await this.playSingleAd(firstPreloaded);
3395
3206
  }
3396
3207
  findCurrentOrNextBreak(nowMs) {
@@ -3470,31 +3281,15 @@ var StormcloudVideoPlayer = class {
3470
3281
  const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);
3471
3282
  const shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;
3472
3283
  if (shouldExtendAdBreak) {
3473
- if (this.config.debugAdTiming) {
3474
- console.log(
3475
- "[StormcloudVideoPlayer] Extending ad break beyond scheduled duration",
3476
- {
3477
- adPlaying,
3478
- pendingAds,
3479
- showAds: this.showAds,
3480
- overrunMs,
3481
- checkIntervalMs,
3482
- maxExtensionMs
3483
- }
3484
- );
3485
- }
3284
+ console.log(
3285
+ `[DEBUG-POD] \u23F3 Extending ad break | elapsed=${elapsedSinceStartMs}ms, expected=${expectedDurationMs}ms, overrun=${overrunMs}ms`
3286
+ );
3486
3287
  this.scheduleAdStopCountdown(checkIntervalMs);
3487
3288
  return;
3488
3289
  }
3489
- if (this.config.debugAdTiming) {
3490
- console.log("[StormcloudVideoPlayer] Ending ad break via timer", {
3491
- adPlaying,
3492
- pendingAds,
3493
- showAds: this.showAds,
3494
- overrunMs,
3495
- maxExtensionMs
3496
- });
3497
- }
3290
+ console.log(
3291
+ `[DEBUG-POD] \u23F1\uFE0F Ad break duration expired | elapsed=${elapsedSinceStartMs}ms, expected=${expectedDurationMs}ms`
3292
+ );
3498
3293
  if (adPlaying) {
3499
3294
  this.ima.stop().catch(() => {
3500
3295
  });
@@ -3527,62 +3322,56 @@ var StormcloudVideoPlayer = class {
3527
3322
  this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;
3528
3323
  }
3529
3324
  async playSingleAd(vastTagUrl) {
3530
- if (this.config.debugAdTiming) {
3531
- console.log("[StormcloudVideoPlayer] Attempting to play ad:", vastTagUrl);
3532
- }
3325
+ console.log(`[DEBUG-POD] \u{1F3AC} playSingleAd | url=${vastTagUrl.substring(0, 60)}...`);
3533
3326
  if (this.ima.isAdPlaying()) {
3534
- if (this.config.debugAdTiming) {
3535
- console.warn(
3536
- "[StormcloudVideoPlayer] Ad already playing - skipping new ad request"
3537
- );
3538
- }
3327
+ console.warn("[DEBUG-POD] \u26A0\uFE0F Ad already playing - skipping request");
3539
3328
  return;
3540
3329
  }
3330
+ const requestToken = ++this.adRequestTokenCounter;
3541
3331
  const wasPreloaded = this.ima.hasPreloadedAd(vastTagUrl);
3542
- if (wasPreloaded && this.config.debugAdTiming) {
3543
- console.log(
3544
- `[StormcloudVideoPlayer] IMA SDK preloaded this ad already: ${vastTagUrl}`
3545
- );
3546
- }
3547
- this.startAdFailsafeTimer();
3332
+ this.activeAdRequestToken = requestToken;
3333
+ console.log(`[DEBUG-POD] \u{1F4DD} Request token=${requestToken}, preloaded=${wasPreloaded}`);
3334
+ this.startAdRequestWatchdog(requestToken);
3548
3335
  try {
3549
3336
  await this.ima.requestAds(vastTagUrl);
3337
+ this.clearAdRequestWatchdog();
3338
+ if (this.activeAdRequestToken !== requestToken) {
3339
+ console.warn(`[DEBUG-POD] \u26A0\uFE0F Token mismatch after requestAds (stale request)`);
3340
+ return;
3341
+ }
3550
3342
  try {
3551
- if (this.config.debugAdTiming) {
3552
- console.log(
3553
- "[StormcloudVideoPlayer] Ad request completed, attempting playback (ad layer will show when IMA triggers content pause)"
3554
- );
3555
- }
3343
+ this.startAdFailsafeTimer(requestToken);
3556
3344
  await this.ima.play();
3557
- this.showAds = true;
3558
- if (this.config.debugAdTiming) {
3559
- console.log(
3560
- "[StormcloudVideoPlayer] Ad playback started successfully, showAds = true"
3561
- );
3345
+ if (this.activeAdRequestToken === requestToken) {
3346
+ console.log(`[DEBUG-POD] \u2705 Ad play initiated (token=${requestToken})`);
3347
+ } else {
3348
+ console.warn(`[DEBUG-POD] \u26A0\uFE0F Token mismatch after play (stale request)`);
3562
3349
  }
3563
3350
  } catch (playError) {
3564
- if (this.config.debugAdTiming) {
3565
- console.log(
3566
- "[StormcloudVideoPlayer] No ads available, skipping playback"
3567
- );
3351
+ console.log("[DEBUG-POD] \u26A0\uFE0F No ads available from play()");
3352
+ this.clearAdFailsafeTimer();
3353
+ if (this.activeAdRequestToken === requestToken) {
3354
+ this.activeAdRequestToken = null;
3568
3355
  }
3569
3356
  this.handleAdFailure();
3570
3357
  return;
3571
3358
  }
3572
3359
  } catch (error) {
3573
- if (this.config.debugAdTiming) {
3574
- console.error("[StormcloudVideoPlayer] Ad playback failed:", error);
3360
+ console.error("[DEBUG-POD] \u274C Ad request failed:", error == null ? void 0 : error.message);
3361
+ this.clearAdRequestWatchdog();
3362
+ this.clearAdFailsafeTimer();
3363
+ if (this.activeAdRequestToken === requestToken) {
3364
+ this.activeAdRequestToken = null;
3575
3365
  }
3576
3366
  this.handleAdFailure();
3577
3367
  }
3578
3368
  }
3579
3369
  handleAdPodComplete() {
3580
3370
  var _a;
3581
- if (this.config.debugAdTiming) {
3582
- console.log(
3583
- "[StormcloudVideoPlayer] Handling ad pod completion - resuming content and hiding ad layer"
3584
- );
3585
- }
3371
+ console.log("[DEBUG-POD] \u{1F3C1} handleAdPodComplete - Ending ad break, restoring content");
3372
+ this.clearAdRequestWatchdog();
3373
+ this.clearAdFailsafeTimer();
3374
+ this.activeAdRequestToken = null;
3586
3375
  this.releaseAdHoldState();
3587
3376
  this.preloadingAdUrls.clear();
3588
3377
  this.vastToMediaUrlMap.clear();
@@ -3593,7 +3382,6 @@ var StormcloudVideoPlayer = class {
3593
3382
  this.currentAdBreakStartWallClockMs = void 0;
3594
3383
  this.clearAdStartTimer();
3595
3384
  this.clearAdStopTimer();
3596
- this.clearAdFailsafeTimer();
3597
3385
  this.adPodQueue = [];
3598
3386
  this.adPodAllUrls = [];
3599
3387
  this.showAds = false;
@@ -3605,70 +3393,95 @@ var StormcloudVideoPlayer = class {
3605
3393
  const originalVolume = typeof this.ima.getOriginalVolume === "function" ? this.ima.getOriginalVolume() : this.video.volume;
3606
3394
  this.video.muted = originalMutedState;
3607
3395
  this.video.volume = originalVolume;
3608
- if (this.config.debugAdTiming) {
3609
- console.log(
3610
- `[StormcloudVideoPlayer] Restored main video - muted: ${originalMutedState}, volume: ${this.video.volume}`
3611
- );
3612
- }
3396
+ console.log(
3397
+ `[DEBUG-AUDIO] \u{1F50A} Main video restored | muted=${originalMutedState}, volume=${originalVolume}`
3398
+ );
3613
3399
  if (!this.shouldContinueLiveStreamDuringAds() && this.video.paused) {
3614
- if (this.config.debugAdTiming) {
3615
- console.log("[StormcloudVideoPlayer] Resuming paused video");
3616
- }
3400
+ console.log("[DEBUG-FLOW] \u25B6\uFE0F Resuming main video playback");
3617
3401
  (_a = this.video.play()) == null ? void 0 : _a.catch((error) => {
3618
- if (this.config.debugAdTiming) {
3619
- console.error(
3620
- "[StormcloudVideoPlayer] Failed to resume video:",
3621
- error
3622
- );
3623
- }
3402
+ console.error("[DEBUG-ERROR] Failed to resume video:", error);
3624
3403
  });
3625
3404
  }
3626
3405
  }
3627
3406
  handleAdFailure() {
3628
- if (this.config.debugAdTiming) {
3407
+ const remaining = this.getRemainingAdMs();
3408
+ console.log(
3409
+ `[DEBUG-POD] \u274C handleAdFailure | inBreak=${this.inAdBreak}, showAds=${this.showAds}, remaining=${remaining}ms`
3410
+ );
3411
+ if (remaining > 500 && this.inAdBreak) {
3629
3412
  console.log(
3630
- "[StormcloudVideoPlayer] Handling ad failure - resuming content",
3631
- {
3632
- inAdBreak: this.inAdBreak,
3633
- showAds: this.showAds,
3634
- videoPaused: this.video.paused,
3635
- adPlaying: this.ima.isAdPlaying()
3636
- }
3413
+ `[DEBUG-POD] \u23F3 Ad failed but ${remaining}ms remaining - showing placeholder until duration expires`
3637
3414
  );
3415
+ this.showAds = true;
3416
+ this.ima.showPlaceholder();
3417
+ this.enforceAdHoldState();
3418
+ return;
3638
3419
  }
3420
+ console.log("[DEBUG-POD] \u23F9\uFE0F No remaining time - ending ad break now");
3639
3421
  this.handleAdPodComplete();
3640
3422
  }
3641
- startAdFailsafeTimer() {
3423
+ startAdRequestWatchdog(token) {
3424
+ var _a;
3425
+ this.clearAdRequestWatchdog();
3426
+ const timeoutMs = (_a = this.config.adFailsafeTimeoutMs) != null ? _a : 1e4;
3427
+ this.adRequestWatchdogToken = token;
3428
+ this.adRequestWatchdogId = window.setTimeout(() => {
3429
+ if (this.adRequestWatchdogToken !== token) {
3430
+ return;
3431
+ }
3432
+ this.adRequestWatchdogId = void 0;
3433
+ this.adRequestWatchdogToken = null;
3434
+ if (this.activeAdRequestToken === token) {
3435
+ this.activeAdRequestToken = null;
3436
+ }
3437
+ this.logAdState("ad_request_timeout", { token, timeoutMs });
3438
+ this.handleAdFailure();
3439
+ }, timeoutMs);
3440
+ this.logAdState("ad_request_watchdog_started", { token, timeoutMs });
3441
+ }
3442
+ clearAdRequestWatchdog() {
3443
+ if (this.adRequestWatchdogId != null) {
3444
+ clearTimeout(this.adRequestWatchdogId);
3445
+ this.adRequestWatchdogId = void 0;
3446
+ }
3447
+ if (this.adRequestWatchdogToken != null) {
3448
+ this.logAdState("ad_request_watchdog_cleared", {
3449
+ token: this.adRequestWatchdogToken
3450
+ });
3451
+ this.adRequestWatchdogToken = null;
3452
+ }
3453
+ }
3454
+ startAdFailsafeTimer(token) {
3642
3455
  var _a;
3643
3456
  this.clearAdFailsafeTimer();
3644
3457
  const failsafeMs = (_a = this.config.adFailsafeTimeoutMs) != null ? _a : 1e4;
3645
- if (this.config.debugAdTiming) {
3646
- console.log(
3647
- `[StormcloudVideoPlayer] Starting failsafe timer (${failsafeMs}ms)`
3648
- );
3649
- }
3458
+ this.adFailsafeToken = token;
3650
3459
  this.adFailsafeTimerId = window.setTimeout(() => {
3651
- const shouldTrigger = this.video.paused || this.showAds && !this.ima.isAdPlaying();
3652
- if (shouldTrigger) {
3653
- if (this.config.debugAdTiming) {
3654
- console.warn(
3655
- "[StormcloudVideoPlayer] Failsafe timer triggered - forcing video resume",
3656
- {
3657
- paused: this.video.paused,
3658
- showAds: this.showAds,
3659
- adPlaying: this.ima.isAdPlaying()
3660
- }
3661
- );
3662
- }
3663
- this.handleAdFailure();
3460
+ if (this.adFailsafeToken !== token) {
3461
+ return;
3664
3462
  }
3463
+ this.adFailsafeTimerId = void 0;
3464
+ this.adFailsafeToken = null;
3465
+ if (this.activeAdRequestToken === token) {
3466
+ this.activeAdRequestToken = null;
3467
+ }
3468
+ this.logAdState("ad_failsafe_triggered", {
3469
+ token,
3470
+ failsafeMs,
3471
+ videoPaused: this.video.paused,
3472
+ imaAdPlaying: this.ima.isAdPlaying()
3473
+ });
3474
+ this.handleAdFailure();
3665
3475
  }, failsafeMs);
3476
+ this.logAdState("ad_failsafe_started", { token, failsafeMs });
3666
3477
  }
3667
3478
  clearAdFailsafeTimer() {
3668
3479
  if (this.adFailsafeTimerId != null) {
3669
3480
  clearTimeout(this.adFailsafeTimerId);
3481
+ this.logAdState("ad_failsafe_cleared", { token: this.adFailsafeToken });
3670
3482
  this.adFailsafeTimerId = void 0;
3671
3483
  }
3484
+ this.adFailsafeToken = null;
3672
3485
  }
3673
3486
  selectVastTagsForBreak(b) {
3674
3487
  if (!b || !b.vastTagUrl) return void 0;
@@ -3683,16 +3496,32 @@ var StormcloudVideoPlayer = class {
3683
3496
  }
3684
3497
  console.log("[StormcloudVideoPlayer] ALL ad URLs queued:", urls);
3685
3498
  }
3499
+ logAdState(event, extra = {}) {
3500
+ if (!this.config.debugAdTiming) {
3501
+ return;
3502
+ }
3503
+ console.log("[StormcloudVideoPlayer][AdState]", {
3504
+ event,
3505
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3506
+ showAds: this.showAds,
3507
+ adPlaying: this.ima.isAdPlaying(),
3508
+ inAdBreak: this.inAdBreak,
3509
+ activeAdRequestToken: this.activeAdRequestToken,
3510
+ ...extra
3511
+ });
3512
+ }
3686
3513
  enforceAdHoldState() {
3687
3514
  this.video.dataset.stormcloudAdPlaying = "true";
3688
3515
  this.video.muted = true;
3689
3516
  this.video.volume = 0;
3517
+ console.log("[DEBUG-LAYER] \u{1F512} Enforced ad hold state (main video muted)");
3690
3518
  if (typeof this.ima.showPlaceholder === "function") {
3691
3519
  this.ima.showPlaceholder();
3692
3520
  }
3693
3521
  }
3694
3522
  releaseAdHoldState() {
3695
3523
  delete this.video.dataset.stormcloudAdPlaying;
3524
+ console.log("[DEBUG-LAYER] \u{1F513} Released ad hold state");
3696
3525
  if (typeof this.ima.hidePlaceholder === "function") {
3697
3526
  this.ima.hidePlaceholder();
3698
3527
  }