stormcloud-video-player 0.3.6 → 0.3.8

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.
@@ -225,7 +225,6 @@ function createImaController(video, options) {
225
225
  video.muted = true;
226
226
  video.volume = 0;
227
227
  contentVideoHidden = true;
228
- console.log("[DEBUG-LAYER] \u{1F534} Content video HIDDEN | muted=true, volume=0");
229
228
  }
230
229
  }
231
230
  function showContentVideo() {
@@ -237,9 +236,6 @@ function createImaController(video, options) {
237
236
  video.muted = originalMutedState;
238
237
  video.volume = originalVolume;
239
238
  contentVideoHidden = false;
240
- console.log(
241
- `[DEBUG-LAYER] \u{1F7E2} Content video RESTORED | muted=${originalMutedState}, volume=${originalVolume}`
242
- );
243
239
  }
244
240
  }
245
241
  function createAdVideoElement() {
@@ -260,13 +256,9 @@ function createImaController(video, options) {
260
256
  "canplay",
261
257
  () => {
262
258
  adVideo.style.opacity = "1";
263
- console.log("[DEBUG-LAYER] \u{1F4FA} Ad video element ready (canplay fired)");
264
259
  },
265
260
  { once: true }
266
261
  );
267
- console.log(
268
- `[DEBUG-AUDIO] \u{1F50A} Ad video created | volume=${adVideo.volume}, muted=${adVideo.muted}`
269
- );
270
262
  return adVideo;
271
263
  }
272
264
  function emit(event, payload) {
@@ -418,10 +410,8 @@ function createImaController(video, options) {
418
410
  function destroyAdsManager() {
419
411
  if (adsManager) {
420
412
  try {
421
- console.log("[IMA] Destroying existing ads manager");
422
413
  adsManager.destroy();
423
- } catch (error) {
424
- console.warn("[IMA] Error destroying ads manager:", error);
414
+ } catch {
425
415
  }
426
416
  adsManager = void 0;
427
417
  }
@@ -439,9 +429,6 @@ function createImaController(video, options) {
439
429
  if (!adVideoElement) {
440
430
  adVideoElement = createAdVideoElement();
441
431
  adContainerEl.appendChild(adVideoElement);
442
- console.log(
443
- "[IMA] Dedicated ad video element added to container"
444
- );
445
432
  }
446
433
  adDisplayContainer = new google.ima.AdDisplayContainer(
447
434
  adContainerEl,
@@ -449,9 +436,6 @@ function createImaController(video, options) {
449
436
  );
450
437
  try {
451
438
  (_a = adDisplayContainer.initialize) == null ? void 0 : _a.call(adDisplayContainer);
452
- console.log(
453
- "[IMA] AdDisplayContainer initialized with dedicated ad video"
454
- );
455
439
  } catch {
456
440
  }
457
441
  }
@@ -459,9 +443,6 @@ function createImaController(video, options) {
459
443
  });
460
444
  },
461
445
  async requestAds(vastTagUrl) {
462
- console.log("[IMA] \u{1F4E1} === requestAds() called ===");
463
- console.log("[IMA] VAST URL:", vastTagUrl);
464
- console.log("[IMA] This will fetch the ad from the server - no visual change yet");
465
446
  if (!vastTagUrl || vastTagUrl.trim() === "") {
466
447
  const error = new Error("VAST tag URL is empty or undefined");
467
448
  console.warn("[IMA] \u274C", error.message);
@@ -504,7 +485,6 @@ function createImaController(video, options) {
504
485
  lastAdTagUrl = vastTagUrl;
505
486
  retryAttempts = 0;
506
487
  if (!adDisplayContainer) {
507
- console.log("[IMA] Creating ad display container");
508
488
  const container = document.createElement("div");
509
489
  container.style.position = "absolute";
510
490
  container.style.left = "0";
@@ -527,25 +507,11 @@ function createImaController(video, options) {
527
507
  if (!adVideoElement) {
528
508
  adVideoElement = createAdVideoElement();
529
509
  adContainerEl.appendChild(adVideoElement);
530
- console.log(
531
- "[IMA] Dedicated ad video element created and added to container"
532
- );
533
510
  }
534
511
  adDisplayContainer = new google.ima.AdDisplayContainer(
535
512
  container,
536
513
  adVideoElement
537
514
  );
538
- try {
539
- adDisplayContainer.initialize();
540
- console.log(
541
- "[IMA] Ad display container initialized with dedicated ad video"
542
- );
543
- } catch (error) {
544
- console.warn(
545
- "[IMA] Failed to initialize ad display container:",
546
- error
547
- );
548
- }
549
515
  }
550
516
  const videoWidth = video.offsetWidth || video.clientWidth;
551
517
  const videoHeight = video.offsetHeight || video.clientHeight;
@@ -560,29 +526,17 @@ function createImaController(video, options) {
560
526
  return Promise.reject(error);
561
527
  }
562
528
  if (!adsLoader) {
563
- console.log("[IMA] Creating ads loader");
564
529
  const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);
565
530
  adsLoader = adsLoaderCls;
566
531
  adsLoader.addEventListener(
567
532
  google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
568
533
  (evt) => {
569
- console.log("[DEBUG-FLOW] \u2705 ADS_MANAGER_LOADED - Setting up manager");
570
534
  try {
571
535
  const adsRenderingSettings = new google.ima.AdsRenderingSettings();
572
536
  adsRenderingSettings.enablePreloading = true;
573
537
  adsManager = evt.getAdsManager(video, adsRenderingSettings);
574
538
  const AdEvent = google.ima.AdEvent.Type;
575
539
  const AdErrorEvent = google.ima.AdErrorEvent.Type;
576
- const keyEvents = ["STARTED", "COMPLETE", "CONTENT_PAUSE_REQUESTED", "CONTENT_RESUME_REQUESTED", "ALL_ADS_COMPLETED"];
577
- keyEvents.forEach((eventType) => {
578
- if (AdEvent[eventType]) {
579
- adsManager.addEventListener(AdEvent[eventType], (e) => {
580
- var _a, _b;
581
- const ad = (_a = e.getAd) == null ? void 0 : _a.call(e);
582
- console.log(`[DEBUG-FLOW] \u{1F3AC} ${eventType} | title=${((_b = ad == null ? void 0 : ad.getTitle) == null ? void 0 : _b.call(ad)) || "N/A"}`);
583
- });
584
- }
585
- });
586
540
  adsManager.addEventListener(
587
541
  AdErrorEvent.AD_ERROR,
588
542
  (errorEvent) => {
@@ -599,7 +553,6 @@ function createImaController(video, options) {
599
553
  if (adContainerEl) {
600
554
  adContainerEl.style.pointerEvents = "none";
601
555
  adContainerEl.style.display = "none";
602
- console.log("[DEBUG-LAYER] \u274C Ad container HIDDEN (error)");
603
556
  }
604
557
  }, 300);
605
558
  }
@@ -631,7 +584,6 @@ function createImaController(video, options) {
631
584
  adsManager.addEventListener(
632
585
  AdEvent.CONTENT_PAUSE_REQUESTED,
633
586
  () => {
634
- console.log("[DEBUG-FLOW] \u{1F3AF} CONTENT_PAUSE_REQUESTED - Ad request accepted");
635
587
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
636
588
  video.pause();
637
589
  }
@@ -641,15 +593,11 @@ function createImaController(video, options) {
641
593
  }
642
594
  );
643
595
  adsManager.addEventListener(AdEvent.STARTED, () => {
644
- console.log("[DEBUG-FLOW] \u25B6\uFE0F STARTED - Ad playing now");
645
596
  setAdPlayingFlag(true);
646
597
  hideContentVideo();
647
598
  if (adVideoElement) {
648
599
  adVideoElement.volume = originalMutedState ? 0 : originalVolume;
649
600
  adVideoElement.muted = originalMutedState;
650
- console.log(
651
- `[DEBUG-AUDIO] \u{1F50A} Ad audio set | volume=${adVideoElement.volume}, muted=${adVideoElement.muted}`
652
- );
653
601
  }
654
602
  if (adContainerEl) {
655
603
  adContainerEl.style.pointerEvents = "auto";
@@ -662,15 +610,12 @@ function createImaController(video, options) {
662
610
  adsManager.addEventListener(
663
611
  AdEvent.CONTENT_RESUME_REQUESTED,
664
612
  () => {
665
- console.log("[DEBUG-FLOW] \u23F8\uFE0F CONTENT_RESUME - Single ad done");
666
613
  adPlaying = false;
667
614
  setAdPlayingFlag(false);
668
- console.log("[DEBUG-LAYER] \u26A0\uFE0F Waiting for pod manager (more ads, placeholder, or done)");
669
615
  emit("content_resume");
670
616
  }
671
617
  );
672
618
  adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {
673
- console.log("[DEBUG-FLOW] \u{1F3C1} ALL_ADS_COMPLETED - Pod finished");
674
619
  adPlaying = false;
675
620
  setAdPlayingFlag(false);
676
621
  if (adContainerEl) {
@@ -680,19 +625,16 @@ function createImaController(video, options) {
680
625
  if (adContainerEl) {
681
626
  adContainerEl.style.pointerEvents = "none";
682
627
  adContainerEl.style.display = "none";
683
- console.log("[DEBUG-LAYER] \u26AB Ad container HIDDEN (pod done)");
684
628
  }
685
629
  }, 300);
686
630
  }
687
631
  showContentVideo();
688
632
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds) && video.paused) {
689
- video.play().catch((e) => {
690
- console.warn("[DEBUG-ERROR] Failed to resume video:", e);
633
+ video.play().catch(() => {
691
634
  });
692
635
  }
693
636
  emit("all_ads_completed");
694
637
  });
695
- console.log("[IMA] Ads manager event listeners attached");
696
638
  if (adsLoadedResolve) {
697
639
  adsLoadedResolve();
698
640
  adsLoadedResolve = void 0;
@@ -787,9 +729,7 @@ function createImaController(video, options) {
787
729
  }
788
730
  const preloadPromise = fetchVastDocument(vastTagUrl).then((xml) => {
789
731
  preloadedVast.set(vastTagUrl, xml);
790
- console.log("[IMA] Cached VAST response for preloading:", vastTagUrl);
791
- }).catch((error) => {
792
- console.warn("[IMA] Failed to preload VAST response:", error);
732
+ }).catch(() => {
793
733
  preloadedVast.delete(vastTagUrl);
794
734
  }).finally(() => {
795
735
  preloadingVast.delete(vastTagUrl);
@@ -802,7 +742,6 @@ function createImaController(video, options) {
802
742
  },
803
743
  async play() {
804
744
  var _a, _b;
805
- console.log("[DEBUG-FLOW] \u25B6\uFE0F play() - Starting ad playback");
806
745
  if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
807
746
  return Promise.reject(new Error("IMA SDK not available"));
808
747
  }
@@ -818,19 +757,15 @@ function createImaController(video, options) {
818
757
  if (adVideoElement) {
819
758
  adVideoElement.volume = adVolume;
820
759
  adVideoElement.muted = originalMutedState;
821
- console.log(
822
- `[DEBUG-AUDIO] \u{1F50A} Pre-start ad audio | volume=${adVolume}, muted=${originalMutedState}`
823
- );
824
760
  }
825
761
  try {
826
762
  adsManager.setVolume(adVolume);
827
- } catch (error) {
828
- console.warn("[DEBUG-ERROR] Failed to set IMA manager volume:", error);
763
+ } catch {
829
764
  }
830
765
  adsManager.start();
831
766
  return Promise.resolve();
832
767
  } catch (error) {
833
- console.error("[DEBUG-ERROR] \u274C Error starting ad:", error);
768
+ console.error("[IMA] \u274C Error starting ad:", error);
834
769
  adPlaying = false;
835
770
  setAdPlayingFlag(false);
836
771
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -842,7 +777,6 @@ function createImaController(video, options) {
842
777
  },
843
778
  async stop() {
844
779
  var _a;
845
- console.log("[DEBUG-FLOW] \u23F9\uFE0F stop() - Stopping ad playback");
846
780
  adPlaying = false;
847
781
  setAdPlayingFlag(false);
848
782
  if (adContainerEl) {
@@ -852,7 +786,6 @@ function createImaController(video, options) {
852
786
  if (adContainerEl) {
853
787
  adContainerEl.style.pointerEvents = "none";
854
788
  adContainerEl.style.display = "none";
855
- console.log("[DEBUG-LAYER] \u26AB Ad container HIDDEN (stop)");
856
789
  }
857
790
  }, 300);
858
791
  }
@@ -922,9 +855,6 @@ function createImaController(video, options) {
922
855
  },
923
856
  updateOriginalMutedState(muted, volume) {
924
857
  const nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
925
- console.log(
926
- `[DEBUG-AUDIO] \u{1F4BE} Saved original state | muted: ${originalMutedState}->${muted}, volume: ${originalVolume}->${nextVolume}`
927
- );
928
858
  originalMutedState = muted;
929
859
  originalVolume = nextVolume;
930
860
  },
@@ -939,15 +869,11 @@ function createImaController(video, options) {
939
869
  if (adVideoElement && adPlaying) {
940
870
  adVideoElement.volume = clampedVolume;
941
871
  adVideoElement.muted = clampedVolume === 0;
942
- console.log(
943
- `[DEBUG-AUDIO] \u{1F50A} Ad volume changed | volume=${clampedVolume}, muted=${clampedVolume === 0}`
944
- );
945
872
  }
946
873
  if (adsManager && adPlaying) {
947
874
  try {
948
875
  adsManager.setVolume(clampedVolume);
949
- } catch (error) {
950
- console.warn("[DEBUG-ERROR] Failed to set IMA manager volume:", error);
876
+ } catch {
951
877
  }
952
878
  }
953
879
  },
@@ -2165,6 +2091,7 @@ var StormcloudVideoPlayer = class {
2165
2091
  this.fetchedAdDurations = /* @__PURE__ */ new Map();
2166
2092
  this.targetAdBreakDurationMs = null;
2167
2093
  this.isAdaptiveMode = false;
2094
+ this.failedVastUrls = /* @__PURE__ */ new Set();
2168
2095
  initializePolyfills();
2169
2096
  const browserOverrides = getBrowserConfigOverrides();
2170
2097
  this.config = { ...config, ...browserOverrides };
@@ -2437,51 +2364,37 @@ var StormcloudVideoPlayer = class {
2437
2364
  });
2438
2365
  this.ima.on("ad_error", (errorPayload) => {
2439
2366
  const remaining = this.getRemainingAdMs();
2440
- console.error(
2441
- `[DEBUG-POD] \u274C ad_error event | inBreak=${this.inAdBreak}, queue=${this.adPodQueue.length}, remaining=${remaining}ms`,
2442
- errorPayload ? `
2443
- Error details: ${JSON.stringify(errorPayload)}` : ""
2444
- );
2367
+ console.error("[AD-ERROR] Ad playback failed", errorPayload || "");
2445
2368
  if (this.inAdBreak) {
2446
2369
  if (remaining > 500 && this.adPodQueue.length > 0) {
2447
2370
  const nextPreloaded = this.findNextPreloadedAd();
2448
2371
  if (nextPreloaded) {
2449
2372
  this.currentAdIndex++;
2450
- console.log(
2451
- `[DEBUG-POD] \u27A1\uFE0F Trying next ad after error (${this.currentAdIndex}/${this.totalAdsInBreak})`
2452
- );
2453
2373
  this.playSingleAd(nextPreloaded).catch(() => {
2454
2374
  this.handleAdFailure();
2455
2375
  });
2456
2376
  } else {
2457
- console.log("[DEBUG-POD] \u26A0\uFE0F No more preloaded ads - calling handleAdFailure");
2458
2377
  this.handleAdFailure();
2459
2378
  }
2460
2379
  } else {
2461
- console.log("[DEBUG-POD] \u26A0\uFE0F No more ads or time - calling handleAdFailure");
2462
2380
  this.handleAdFailure();
2463
2381
  }
2464
2382
  } else {
2465
- console.log("[DEBUG-POD] \u26A0\uFE0F Error before ad break established");
2466
2383
  this.handleAdFailure();
2467
2384
  }
2468
2385
  });
2469
2386
  this.ima.on("content_pause", () => {
2470
- console.log(`[DEBUG-POD] \u{1F3AF} content_pause (AD STARTING!) | ad ${this.currentAdIndex}/${this.totalAdsInBreak}, queue=${this.adPodQueue.length}`);
2471
2387
  this.clearAdFailsafeTimer();
2472
2388
  this.clearAdRequestWatchdog();
2473
2389
  this.activeAdRequestToken = null;
2474
2390
  this.showAds = true;
2475
- console.log("[DEBUG-LAYER] \u{1F3AC} Layers: Main=hidden, Ad=visible, Placeholder=no");
2476
2391
  });
2477
2392
  this.ima.on("content_resume", () => {
2478
- console.log(`[DEBUG-POD] \u23F8\uFE0F content_resume | ad ${this.currentAdIndex}/${this.totalAdsInBreak}, queue=${this.adPodQueue.length}, remaining=${this.getRemainingAdMs()}ms`);
2479
2393
  this.clearAdFailsafeTimer();
2480
2394
  this.clearAdRequestWatchdog();
2481
2395
  this.activeAdRequestToken = null;
2482
2396
  this.showAds = false;
2483
2397
  if (!this.inAdBreak) {
2484
- console.warn("[DEBUG-POD] \u26A0\uFE0F Not in ad break - shouldn't happen");
2485
2398
  return;
2486
2399
  }
2487
2400
  const remaining = this.getRemainingAdMs();
@@ -2489,17 +2402,13 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2489
2402
  const nextPreloaded = this.findNextPreloadedAd();
2490
2403
  if (nextPreloaded) {
2491
2404
  this.currentAdIndex++;
2492
- console.log(`[DEBUG-POD] \u27A1\uFE0F Playing next ad ${this.currentAdIndex}/${this.totalAdsInBreak} (preloaded)`);
2493
2405
  this.playSingleAd(nextPreloaded).catch(() => {
2494
- console.error("[DEBUG-POD] \u274C Failed to play next ad");
2495
2406
  this.handleAdPodComplete();
2496
2407
  });
2497
2408
  } else {
2498
- console.log("[DEBUG-POD] \u26A0\uFE0F No preloaded ads - ending pod");
2499
2409
  this.handleAdPodComplete();
2500
2410
  }
2501
2411
  } else {
2502
- console.log("[DEBUG-POD] \u2705 Pod complete (no more ads or time expired)");
2503
2412
  this.handleAdPodComplete();
2504
2413
  }
2505
2414
  });
@@ -2653,9 +2562,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2653
2562
  }
2654
2563
  if (marker.type === "start") {
2655
2564
  if (this.inAdBreak) {
2656
- console.log(
2657
- `[DEBUG-POD] \u26A0\uFE0F SCTE-35 start marker ignored - already in ad break (currentTime: ${this.video.currentTime})`
2658
- );
2659
2565
  return;
2660
2566
  }
2661
2567
  this.inAdBreak = true;
@@ -2724,9 +2630,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2724
2630
  return;
2725
2631
  }
2726
2632
  if (marker.type === "progress" && this.inAdBreak) {
2727
- console.log(
2728
- `[DEBUG-POD] \u{1F4CA} SCTE-35 progress marker (currentTime: ${this.video.currentTime})`
2729
- );
2730
2633
  if (marker.durationSeconds != null) {
2731
2634
  this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;
2732
2635
  }
@@ -2739,7 +2642,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2739
2642
  this.scheduleAdStopCountdown(remainingMs);
2740
2643
  }
2741
2644
  if (!this.ima.isAdPlaying() && this.activeAdRequestToken === null) {
2742
- console.log("[DEBUG-POD] \u{1F4CA} Progress marker: no ad playing, attempting to start");
2743
2645
  const scheduled = this.findCurrentOrNextBreak(
2744
2646
  this.video.currentTime * 1e3
2745
2647
  );
@@ -2751,24 +2653,16 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
2751
2653
  this.playSingleAd(first).catch(() => {
2752
2654
  });
2753
2655
  }
2754
- } else {
2755
- console.log(
2756
- `[DEBUG-POD] \u{1F4CA} Progress marker: ad playing or request active (playing=${this.ima.isAdPlaying()}, token=${this.activeAdRequestToken})`
2757
- );
2758
2656
  }
2759
2657
  return;
2760
2658
  }
2761
2659
  if (marker.type === "end") {
2762
- console.log(
2763
- `[DEBUG-POD] \u{1F3C1} SCTE-35 end marker received (currentTime: ${this.video.currentTime})`
2764
- );
2765
2660
  this.inAdBreak = false;
2766
2661
  this.expectedAdBreakDurationMs = void 0;
2767
2662
  this.currentAdBreakStartWallClockMs = void 0;
2768
2663
  this.clearAdStartTimer();
2769
2664
  this.clearAdStopTimer();
2770
2665
  if (this.ima.isAdPlaying()) {
2771
- console.log("[DEBUG-POD] \u{1F6D1} Stopping ad due to SCTE-35 end marker");
2772
2666
  this.ima.stop().catch(() => {
2773
2667
  });
2774
2668
  }
@@ -3169,21 +3063,17 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3169
3063
  } else if (tags && tags.length > 0) {
3170
3064
  vastTagUrls = tags;
3171
3065
  } else {
3172
- console.log("[DEBUG-POD] \u26A0\uFE0F No VAST tag available");
3173
3066
  return;
3174
3067
  }
3175
3068
  if (vastTagUrls.length > 0) {
3176
- console.log(`[DEBUG-POD] \u{1F3AF} Starting ad break with ${vastTagUrls.length} ads`);
3177
3069
  this.adPodAllUrls = [...vastTagUrls];
3178
3070
  this.preloadingAdUrls.clear();
3179
3071
  this.vastToMediaUrlMap.clear();
3180
3072
  this.preloadedMediaUrls.clear();
3181
3073
  this.preloadingMediaUrls.clear();
3074
+ this.failedVastUrls.clear();
3182
3075
  const currentMuted = this.video.muted;
3183
3076
  const currentVolume = this.video.volume;
3184
- console.log(
3185
- `[DEBUG-AUDIO] \u{1F4BE} Capturing ORIGINAL state (once) | muted=${currentMuted}, volume=${currentVolume}`
3186
- );
3187
3077
  this.ima.updateOriginalMutedState(currentMuted, currentVolume);
3188
3078
  this.inAdBreak = true;
3189
3079
  this.currentAdIndex = 0;
@@ -3244,40 +3134,27 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3244
3134
  }
3245
3135
  async playAdPod() {
3246
3136
  if (this.adPodQueue.length === 0) {
3247
- console.log("[DEBUG-POD] \u26A0\uFE0F No ads in pod");
3248
3137
  return;
3249
3138
  }
3250
3139
  const waitTime = this.isAdaptiveMode ? 50 : 500;
3251
3140
  await new Promise((resolve) => setTimeout(resolve, waitTime));
3252
- if (this.config.debugAdTiming) {
3253
- console.log(
3254
- `[DEBUG-POD] \u{1F50D} Looking for preloaded ad in queue of ${this.adPodQueue.length} URLs`
3255
- );
3256
- }
3257
3141
  const firstPreloaded = this.findNextPreloadedAd();
3258
3142
  if (!firstPreloaded) {
3259
- console.log("[DEBUG-POD] \u26A0\uFE0F No preloaded ads found, trying first ad from queue");
3260
3143
  const firstAd = this.adPodQueue.shift();
3261
3144
  if (firstAd) {
3262
3145
  this.currentAdIndex++;
3263
- console.log(`[DEBUG-POD] \u{1F3AC} Attempting to play first ad (not preloaded): ${firstAd.substring(0, 60)}...`);
3264
3146
  try {
3265
3147
  await this.playSingleAd(firstAd);
3266
3148
  } catch (error) {
3267
- console.log("[DEBUG-POD] \u26A0\uFE0F First ad failed, error handler will retry");
3268
3149
  return;
3269
3150
  }
3270
- } else {
3271
- console.log("[DEBUG-POD] \u274C No ads available in queue");
3272
3151
  }
3273
3152
  return;
3274
3153
  }
3275
3154
  this.currentAdIndex++;
3276
- console.log(`[DEBUG-POD] \u{1F680} Starting pod with ad ${this.currentAdIndex}/${this.totalAdsInBreak}`);
3277
3155
  try {
3278
3156
  await this.playSingleAd(firstPreloaded);
3279
3157
  } catch (error) {
3280
- console.log("[DEBUG-POD] \u26A0\uFE0F First ad failed, error handler will retry");
3281
3158
  }
3282
3159
  }
3283
3160
  findCurrentOrNextBreak(nowMs) {
@@ -3357,15 +3234,9 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3357
3234
  const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);
3358
3235
  const shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;
3359
3236
  if (shouldExtendAdBreak) {
3360
- console.log(
3361
- `[DEBUG-POD] \u23F3 Extending ad break | elapsed=${elapsedSinceStartMs}ms, expected=${expectedDurationMs}ms, overrun=${overrunMs}ms`
3362
- );
3363
3237
  this.scheduleAdStopCountdown(checkIntervalMs);
3364
3238
  return;
3365
3239
  }
3366
- console.log(
3367
- `[DEBUG-POD] \u23F1\uFE0F Ad break duration expired | elapsed=${elapsedSinceStartMs}ms, expected=${expectedDurationMs}ms`
3368
- );
3369
3240
  if (adPlaying) {
3370
3241
  this.ima.stop().catch(() => {
3371
3242
  });
@@ -3398,42 +3269,29 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3398
3269
  this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;
3399
3270
  }
3400
3271
  async playSingleAd(vastTagUrl) {
3401
- console.log(`[DEBUG-POD] \u{1F3AC} playSingleAd | url=${vastTagUrl.substring(0, 60)}...`);
3402
3272
  if (this.ima.isAdPlaying()) {
3403
- console.warn("[DEBUG-POD] \u26A0\uFE0F Ad already playing - skipping request");
3273
+ return;
3274
+ }
3275
+ if (this.failedVastUrls.has(vastTagUrl)) {
3276
+ console.warn("[AD-ERROR] Skipping already-failed VAST URL:", vastTagUrl.substring(0, 60));
3277
+ this.handleAdFailure();
3404
3278
  return;
3405
3279
  }
3406
3280
  const requestToken = ++this.adRequestTokenCounter;
3407
- const wasPreloaded = this.ima.hasPreloadedAd(vastTagUrl);
3408
3281
  this.activeAdRequestToken = requestToken;
3409
- console.log(`[DEBUG-POD] \u{1F4DD} Request token=${requestToken}, preloaded=${wasPreloaded}`);
3410
3282
  this.startAdRequestWatchdog(requestToken);
3411
3283
  try {
3412
- console.log(`[DEBUG-POD] \u{1F4E1} Calling ima.requestAds() for token=${requestToken}...`);
3413
3284
  await this.ima.requestAds(vastTagUrl);
3414
- console.log(`[DEBUG-POD] \u2705 ima.requestAds() completed successfully`);
3415
3285
  this.clearAdRequestWatchdog();
3416
3286
  if (this.activeAdRequestToken !== requestToken) {
3417
- console.warn(`[DEBUG-POD] \u26A0\uFE0F Token mismatch after requestAds (stale request)`);
3418
3287
  return;
3419
3288
  }
3420
- console.log(`[DEBUG-POD] \u{1F4FA} Calling ima.play() to start ad playback...`);
3421
- console.log(`[DEBUG-POD] \u{1F4CA} Video element state: paused=${this.video.paused}, muted=${this.video.muted}, readyState=${this.video.readyState}`);
3422
3289
  try {
3423
3290
  this.startAdFailsafeTimer(requestToken);
3424
3291
  await this.ima.play();
3425
- if (this.activeAdRequestToken === requestToken) {
3426
- console.log(`[DEBUG-POD] \u2705 Ad play initiated successfully (token=${requestToken})`);
3427
- } else {
3428
- console.warn(`[DEBUG-POD] \u26A0\uFE0F Token mismatch after play (stale request)`);
3429
- }
3430
3292
  } catch (playError) {
3431
- console.error(
3432
- "[DEBUG-POD] \u274C Failed to play ad:",
3433
- playError instanceof Error ? playError.message : playError,
3434
- "\nFull error:",
3435
- playError
3436
- );
3293
+ console.error("[AD-ERROR] Failed to play ad:", playError);
3294
+ this.failedVastUrls.add(vastTagUrl);
3437
3295
  this.clearAdFailsafeTimer();
3438
3296
  if (this.activeAdRequestToken === requestToken) {
3439
3297
  this.activeAdRequestToken = null;
@@ -3442,7 +3300,8 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3442
3300
  return;
3443
3301
  }
3444
3302
  } catch (error) {
3445
- console.error("[DEBUG-POD] \u274C Ad request failed:", error == null ? void 0 : error.message);
3303
+ console.error("[AD-ERROR] Ad request failed:", error == null ? void 0 : error.message);
3304
+ this.failedVastUrls.add(vastTagUrl);
3446
3305
  this.clearAdRequestWatchdog();
3447
3306
  this.clearAdFailsafeTimer();
3448
3307
  if (this.activeAdRequestToken === requestToken) {
@@ -3453,7 +3312,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3453
3312
  }
3454
3313
  handleAdPodComplete() {
3455
3314
  var _a;
3456
- console.log("[DEBUG-POD] \u{1F3C1} handleAdPodComplete - Ending ad break, restoring content");
3457
3315
  this.clearAdRequestWatchdog();
3458
3316
  this.clearAdFailsafeTimer();
3459
3317
  this.activeAdRequestToken = null;
@@ -3475,10 +3333,6 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3475
3333
  });
3476
3334
  const restoredMuted = this.ima.getOriginalMutedState();
3477
3335
  const restoredVolume = this.ima.getOriginalVolume();
3478
- console.log(
3479
- `[DEBUG-AUDIO] \u{1F50A} Audio restored by IMA | muted=${restoredMuted}, volume=${restoredVolume}`
3480
- );
3481
- console.log("[DEBUG-LAYER] \u{1F3AC} Layers: Main=visible, Ad=hidden, Placeholder=no");
3482
3336
  if (this.video.muted !== restoredMuted) {
3483
3337
  this.video.muted = restoredMuted;
3484
3338
  }
@@ -3486,16 +3340,14 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3486
3340
  this.video.volume = restoredVolume;
3487
3341
  }
3488
3342
  if (!this.shouldContinueLiveStreamDuringAds() && this.video.paused) {
3489
- console.log("[DEBUG-FLOW] \u25B6\uFE0F Resuming main video playback");
3490
- (_a = this.video.play()) == null ? void 0 : _a.catch((error) => {
3491
- console.error("[DEBUG-ERROR] Failed to resume video:", error);
3343
+ (_a = this.video.play()) == null ? void 0 : _a.catch(() => {
3492
3344
  });
3493
3345
  }
3494
3346
  }
3495
3347
  handleAdFailure() {
3496
- console.log("[DEBUG-POD] \u274C handleAdFailure - skipping to next ad or ending break");
3497
3348
  const remaining = this.getRemainingAdMs();
3498
- if (remaining > 500 && this.adPodQueue.length > 0) {
3349
+ const availableAds = this.adPodQueue.filter((url) => !this.failedVastUrls.has(url)).length;
3350
+ if (remaining > 500 && availableAds > 0) {
3499
3351
  if (this.isAdaptiveMode && this.currentAdIndex <= 1) {
3500
3352
  console.log("[ADAPTIVE-POD] \u23F3 First ad failed, waiting for sequential preload to catch up...");
3501
3353
  setTimeout(() => {
@@ -3506,14 +3358,13 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3506
3358
  const nextPreloaded = this.findNextPreloadedAd();
3507
3359
  if (nextPreloaded) {
3508
3360
  this.currentAdIndex++;
3509
- console.log(`[DEBUG-POD] \u27A1\uFE0F Trying next ad after failure (${this.currentAdIndex}/${this.totalAdsInBreak})`);
3510
3361
  this.playSingleAd(nextPreloaded).catch(() => {
3511
3362
  this.handleAdPodComplete();
3512
3363
  });
3513
3364
  return;
3514
3365
  }
3515
3366
  }
3516
- console.log("[DEBUG-POD] \u23F9\uFE0F Ending ad break after failure");
3367
+ console.error("[AD-ERROR] All ads failed or time expired. Failed URLs:", this.failedVastUrls.size);
3517
3368
  this.handleAdPodComplete();
3518
3369
  }
3519
3370
  tryNextAdWithRetry(retryCount) {
@@ -3966,37 +3817,21 @@ Error details: ${JSON.stringify(errorPayload)}` : ""
3966
3817
  }
3967
3818
  findNextPreloadedAd() {
3968
3819
  var _a, _b, _c;
3969
- if (this.config.debugAdTiming) {
3970
- console.log(
3971
- `[DEBUG-POD] \u{1F50E} Searching for preloaded ad in queue (${this.adPodQueue.length} URLs, ${this.preloadedMediaUrls.size} media preloaded, ${this.vastToMediaUrlMap.size} VAST mappings)`
3972
- );
3973
- }
3974
3820
  for (let i = 0; i < this.adPodQueue.length; i++) {
3975
3821
  const vastTagUrl = this.adPodQueue[i];
3976
3822
  if (!vastTagUrl) continue;
3823
+ if (this.failedVastUrls.has(vastTagUrl)) {
3824
+ console.warn("[AD-ERROR] Skipping failed URL in queue");
3825
+ continue;
3826
+ }
3977
3827
  const hasImaPreload = (_c = (_b = (_a = this.ima).hasPreloadedAd) == null ? void 0 : _b.call(_a, vastTagUrl)) != null ? _c : false;
3978
3828
  const mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);
3979
3829
  const hasMediaPreload = mediaUrls && mediaUrls.length > 0 ? this.preloadedMediaUrls.has(mediaUrls[0]) : false;
3980
- if (this.config.debugAdTiming) {
3981
- console.log(
3982
- `[DEBUG-POD] Ad ${i}: IMA=${hasImaPreload}, Media=${hasMediaPreload}, MediaURLs=${(mediaUrls == null ? void 0 : mediaUrls.length) || 0}, URL=${vastTagUrl.substring(0, 60)}...`
3983
- );
3984
- }
3985
3830
  if (hasImaPreload || hasMediaPreload) {
3986
- if (this.config.debugAdTiming) {
3987
- console.log(
3988
- `[DEBUG-POD] \u2705 Found preloaded ad at index ${i}`
3989
- );
3990
- }
3991
3831
  this.adPodQueue.splice(0, i + 1);
3992
3832
  return vastTagUrl;
3993
3833
  }
3994
3834
  }
3995
- if (this.config.debugAdTiming) {
3996
- console.log(
3997
- `[DEBUG-POD] \u274C No preloaded ads found in queue`
3998
- );
3999
- }
4000
3835
  return void 0;
4001
3836
  }
4002
3837
  getRemainingAdMs() {