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.
- package/dist/stormcloud-vp.min.js +2 -2
- package/lib/index.cjs +26 -191
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +26 -191
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +26 -191
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +1 -0
- package/lib/players/HlsPlayer.cjs +26 -191
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +26 -191
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/ima.cjs +6 -80
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +26 -191
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +1 -1
|
@@ -40,6 +40,7 @@ declare class StormcloudVideoPlayer {
|
|
|
40
40
|
private fetchedAdDurations;
|
|
41
41
|
private targetAdBreakDurationMs;
|
|
42
42
|
private isAdaptiveMode;
|
|
43
|
+
private failedVastUrls;
|
|
43
44
|
constructor(config: StormcloudVideoPlayerConfig);
|
|
44
45
|
private createAdPlayer;
|
|
45
46
|
load(): Promise<void>;
|
|
@@ -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
|
|
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((
|
|
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
|
-
|
|
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
|
|
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("[
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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("[
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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() {
|