stormcloud-video-player 0.2.30 → 0.2.32
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 +387 -102
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +9 -1
- package/lib/index.d.ts +9 -1
- package/lib/index.js +387 -102
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +387 -102
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +9 -1
- package/lib/players/HlsPlayer.cjs +387 -102
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +387 -102
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/ima.cjs +103 -33
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +387 -102
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +2 -2
|
@@ -217,7 +217,11 @@ function createImaController(video, options) {
|
|
|
217
217
|
}
|
|
218
218
|
function hideContentVideo() {
|
|
219
219
|
if (!contentVideoHidden) {
|
|
220
|
-
video.style.
|
|
220
|
+
video.style.transition = "opacity 0.3s ease-in-out";
|
|
221
|
+
video.style.opacity = "0";
|
|
222
|
+
setTimeout(() => {
|
|
223
|
+
video.style.visibility = "hidden";
|
|
224
|
+
}, 300);
|
|
221
225
|
video.muted = true;
|
|
222
226
|
video.volume = 0;
|
|
223
227
|
contentVideoHidden = true;
|
|
@@ -227,6 +231,9 @@ function createImaController(video, options) {
|
|
|
227
231
|
function showContentVideo() {
|
|
228
232
|
if (contentVideoHidden) {
|
|
229
233
|
video.style.visibility = "visible";
|
|
234
|
+
video.style.transition = "opacity 0.3s ease-in-out";
|
|
235
|
+
video.offsetHeight;
|
|
236
|
+
video.style.opacity = "1";
|
|
230
237
|
video.muted = originalMutedState;
|
|
231
238
|
video.volume = originalVolume;
|
|
232
239
|
contentVideoHidden = false;
|
|
@@ -399,7 +406,9 @@ function createImaController(video, options) {
|
|
|
399
406
|
container.style.justifyContent = "center";
|
|
400
407
|
container.style.pointerEvents = "none";
|
|
401
408
|
container.style.zIndex = "10";
|
|
402
|
-
container.style.backgroundColor = "
|
|
409
|
+
container.style.backgroundColor = "transparent";
|
|
410
|
+
container.style.transition = "opacity 0.3s ease-in-out, background-color 0.3s ease-in-out";
|
|
411
|
+
container.style.opacity = "0";
|
|
403
412
|
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
404
413
|
adContainerEl = container;
|
|
405
414
|
}
|
|
@@ -509,7 +518,9 @@ function createImaController(video, options) {
|
|
|
509
518
|
container.style.justifyContent = "center";
|
|
510
519
|
container.style.pointerEvents = "none";
|
|
511
520
|
container.style.zIndex = "10";
|
|
512
|
-
container.style.backgroundColor = "
|
|
521
|
+
container.style.backgroundColor = "transparent";
|
|
522
|
+
container.style.transition = "opacity 0.3s ease-in-out, background-color 0.3s ease-in-out";
|
|
523
|
+
container.style.opacity = "0";
|
|
513
524
|
if (!video.parentElement) {
|
|
514
525
|
throw new Error("Video element has no parent for ad container");
|
|
515
526
|
}
|
|
@@ -573,13 +584,19 @@ function createImaController(video, options) {
|
|
|
573
584
|
console.error("[IMA] Ad error:", errorEvent.getError());
|
|
574
585
|
destroyAdsManager();
|
|
575
586
|
adPlaying = false;
|
|
576
|
-
showContentVideo();
|
|
577
587
|
setAdPlayingFlag(false);
|
|
578
588
|
if (adContainerEl) {
|
|
579
|
-
adContainerEl.style.
|
|
580
|
-
adContainerEl.style.
|
|
581
|
-
|
|
589
|
+
adContainerEl.style.opacity = "0";
|
|
590
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
591
|
+
setTimeout(() => {
|
|
592
|
+
if (adContainerEl) {
|
|
593
|
+
adContainerEl.style.pointerEvents = "none";
|
|
594
|
+
adContainerEl.style.display = "none";
|
|
595
|
+
console.log("[IMA] Ad container hidden after error");
|
|
596
|
+
}
|
|
597
|
+
}, 300);
|
|
582
598
|
}
|
|
599
|
+
showContentVideo();
|
|
583
600
|
if (adsLoadedReject) {
|
|
584
601
|
adsLoadedReject(new Error("Ad playback error"));
|
|
585
602
|
adsLoadedReject = void 0;
|
|
@@ -625,6 +642,15 @@ function createImaController(video, options) {
|
|
|
625
642
|
"[IMA] Content video continues in background (Live mode)"
|
|
626
643
|
);
|
|
627
644
|
}
|
|
645
|
+
hideContentVideo();
|
|
646
|
+
if (adContainerEl) {
|
|
647
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
648
|
+
adContainerEl.style.display = "flex";
|
|
649
|
+
adContainerEl.style.backgroundColor = "#000";
|
|
650
|
+
adContainerEl.offsetHeight;
|
|
651
|
+
adContainerEl.style.opacity = "1";
|
|
652
|
+
console.log("[IMA] Ad container shown on content pause");
|
|
653
|
+
}
|
|
628
654
|
adPlaying = true;
|
|
629
655
|
setAdPlayingFlag(true);
|
|
630
656
|
emit("content_pause");
|
|
@@ -644,6 +670,9 @@ function createImaController(video, options) {
|
|
|
644
670
|
if (adContainerEl) {
|
|
645
671
|
adContainerEl.style.pointerEvents = "auto";
|
|
646
672
|
adContainerEl.style.display = "flex";
|
|
673
|
+
adContainerEl.style.backgroundColor = "#000";
|
|
674
|
+
adContainerEl.offsetHeight;
|
|
675
|
+
adContainerEl.style.opacity = "1";
|
|
647
676
|
console.log("[IMA] Ad container now visible");
|
|
648
677
|
}
|
|
649
678
|
});
|
|
@@ -660,12 +689,18 @@ function createImaController(video, options) {
|
|
|
660
689
|
console.log("[IMA] All ads completed - restoring content");
|
|
661
690
|
adPlaying = false;
|
|
662
691
|
setAdPlayingFlag(false);
|
|
663
|
-
showContentVideo();
|
|
664
692
|
if (adContainerEl) {
|
|
665
|
-
adContainerEl.style.
|
|
666
|
-
adContainerEl.style.
|
|
667
|
-
|
|
693
|
+
adContainerEl.style.opacity = "0";
|
|
694
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
695
|
+
setTimeout(() => {
|
|
696
|
+
if (adContainerEl) {
|
|
697
|
+
adContainerEl.style.pointerEvents = "none";
|
|
698
|
+
adContainerEl.style.display = "none";
|
|
699
|
+
console.log("[IMA] Ad container hidden");
|
|
700
|
+
}
|
|
701
|
+
}, 300);
|
|
668
702
|
}
|
|
703
|
+
showContentVideo();
|
|
669
704
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds) && video.paused) {
|
|
670
705
|
console.log("[IMA] Resuming content video playback");
|
|
671
706
|
video.play().catch((e) => {
|
|
@@ -683,13 +718,21 @@ function createImaController(video, options) {
|
|
|
683
718
|
} catch (e) {
|
|
684
719
|
console.error("[IMA] Error setting up ads manager:", e);
|
|
685
720
|
adPlaying = false;
|
|
686
|
-
showContentVideo();
|
|
687
721
|
setAdPlayingFlag(false);
|
|
688
722
|
if (adContainerEl) {
|
|
689
|
-
adContainerEl.style.
|
|
690
|
-
adContainerEl.style.
|
|
691
|
-
|
|
723
|
+
adContainerEl.style.opacity = "0";
|
|
724
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
725
|
+
setTimeout(() => {
|
|
726
|
+
if (adContainerEl) {
|
|
727
|
+
adContainerEl.style.pointerEvents = "none";
|
|
728
|
+
adContainerEl.style.display = "none";
|
|
729
|
+
console.log(
|
|
730
|
+
"[IMA] Ad container hidden after setup error"
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
}, 300);
|
|
692
734
|
}
|
|
735
|
+
showContentVideo();
|
|
693
736
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
694
737
|
if (video.paused) {
|
|
695
738
|
console.log(
|
|
@@ -714,13 +757,19 @@ function createImaController(video, options) {
|
|
|
714
757
|
(adErrorEvent) => {
|
|
715
758
|
console.error("[IMA] Ads loader error:", adErrorEvent.getError());
|
|
716
759
|
adPlaying = false;
|
|
717
|
-
showContentVideo();
|
|
718
760
|
setAdPlayingFlag(false);
|
|
719
761
|
if (adContainerEl) {
|
|
720
|
-
adContainerEl.style.
|
|
721
|
-
adContainerEl.style.
|
|
722
|
-
|
|
762
|
+
adContainerEl.style.opacity = "0";
|
|
763
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
764
|
+
setTimeout(() => {
|
|
765
|
+
if (adContainerEl) {
|
|
766
|
+
adContainerEl.style.pointerEvents = "none";
|
|
767
|
+
adContainerEl.style.display = "none";
|
|
768
|
+
console.log("[IMA] Ad container hidden after loader error");
|
|
769
|
+
}
|
|
770
|
+
}, 300);
|
|
723
771
|
}
|
|
772
|
+
showContentVideo();
|
|
724
773
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
725
774
|
if (video.paused) {
|
|
726
775
|
console.log("[IMA] Resuming paused video after loader error");
|
|
@@ -826,12 +875,18 @@ function createImaController(video, options) {
|
|
|
826
875
|
console.log("[IMA] Stopping ad playback");
|
|
827
876
|
adPlaying = false;
|
|
828
877
|
setAdPlayingFlag(false);
|
|
829
|
-
showContentVideo();
|
|
830
878
|
if (adContainerEl) {
|
|
831
|
-
adContainerEl.style.
|
|
832
|
-
adContainerEl.style.
|
|
833
|
-
|
|
879
|
+
adContainerEl.style.opacity = "0";
|
|
880
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
881
|
+
setTimeout(() => {
|
|
882
|
+
if (adContainerEl) {
|
|
883
|
+
adContainerEl.style.pointerEvents = "none";
|
|
884
|
+
adContainerEl.style.display = "none";
|
|
885
|
+
console.log("[IMA] Ad container hidden after stop");
|
|
886
|
+
}
|
|
887
|
+
}, 300);
|
|
834
888
|
}
|
|
889
|
+
showContentVideo();
|
|
835
890
|
try {
|
|
836
891
|
(_a = adsManager == null ? void 0 : adsManager.stop) == null ? void 0 : _a.call(adsManager);
|
|
837
892
|
} catch {
|
|
@@ -842,23 +897,29 @@ function createImaController(video, options) {
|
|
|
842
897
|
var _a;
|
|
843
898
|
destroyAdsManager();
|
|
844
899
|
adPlaying = false;
|
|
845
|
-
showContentVideo();
|
|
846
900
|
setAdPlayingFlag(false);
|
|
847
901
|
if (adContainerEl) {
|
|
848
|
-
adContainerEl.style.
|
|
849
|
-
adContainerEl.style.
|
|
902
|
+
adContainerEl.style.opacity = "0";
|
|
903
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
904
|
+
setTimeout(() => {
|
|
905
|
+
if (adContainerEl) {
|
|
906
|
+
adContainerEl.style.pointerEvents = "none";
|
|
907
|
+
adContainerEl.style.display = "none";
|
|
908
|
+
if (adContainerEl.parentElement) {
|
|
909
|
+
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
910
|
+
}
|
|
911
|
+
adContainerEl = void 0;
|
|
912
|
+
adVideoElement = void 0;
|
|
913
|
+
}
|
|
914
|
+
}, 300);
|
|
850
915
|
}
|
|
916
|
+
showContentVideo();
|
|
851
917
|
try {
|
|
852
918
|
(_a = adsLoader == null ? void 0 : adsLoader.destroy) == null ? void 0 : _a.call(adsLoader);
|
|
853
919
|
} catch {
|
|
854
920
|
}
|
|
855
|
-
if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
|
|
856
|
-
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
857
|
-
}
|
|
858
|
-
adContainerEl = void 0;
|
|
859
921
|
adDisplayContainer = void 0;
|
|
860
922
|
adsLoader = void 0;
|
|
861
|
-
adVideoElement = void 0;
|
|
862
923
|
contentVideoHidden = false;
|
|
863
924
|
preloadedVast.clear();
|
|
864
925
|
preloadingVast.clear();
|
|
@@ -938,13 +999,22 @@ function createImaController(video, options) {
|
|
|
938
999
|
ensurePlaceholderContainer();
|
|
939
1000
|
if (adContainerEl) {
|
|
940
1001
|
adContainerEl.style.display = "flex";
|
|
1002
|
+
adContainerEl.style.backgroundColor = "#000";
|
|
1003
|
+
adContainerEl.offsetHeight;
|
|
1004
|
+
adContainerEl.style.opacity = "1";
|
|
941
1005
|
adContainerEl.style.pointerEvents = "auto";
|
|
942
1006
|
}
|
|
943
1007
|
},
|
|
944
1008
|
hidePlaceholder() {
|
|
945
1009
|
if (adContainerEl) {
|
|
946
|
-
adContainerEl.style.
|
|
947
|
-
adContainerEl.style.
|
|
1010
|
+
adContainerEl.style.opacity = "0";
|
|
1011
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
1012
|
+
setTimeout(() => {
|
|
1013
|
+
if (adContainerEl) {
|
|
1014
|
+
adContainerEl.style.display = "none";
|
|
1015
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1016
|
+
}
|
|
1017
|
+
}, 300);
|
|
948
1018
|
}
|
|
949
1019
|
}
|
|
950
1020
|
};
|
|
@@ -2115,6 +2185,9 @@ var StormcloudVideoPlayer = class {
|
|
|
2115
2185
|
this.hasInitialBufferCompleted = false;
|
|
2116
2186
|
this.adPodAllUrls = [];
|
|
2117
2187
|
this.preloadingAdUrls = /* @__PURE__ */ new Set();
|
|
2188
|
+
this.vastToMediaUrlMap = /* @__PURE__ */ new Map();
|
|
2189
|
+
this.preloadedMediaUrls = /* @__PURE__ */ new Set();
|
|
2190
|
+
this.preloadingMediaUrls = /* @__PURE__ */ new Set();
|
|
2118
2191
|
initializePolyfills();
|
|
2119
2192
|
const browserOverrides = getBrowserConfigOverrides();
|
|
2120
2193
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -2387,27 +2460,44 @@ var StormcloudVideoPlayer = class {
|
|
|
2387
2460
|
});
|
|
2388
2461
|
this.ima.on("ad_error", () => {
|
|
2389
2462
|
if (this.config.debugAdTiming) {
|
|
2390
|
-
console.log("[StormcloudVideoPlayer] IMA ad_error event received"
|
|
2463
|
+
console.log("[StormcloudVideoPlayer] IMA ad_error event received", {
|
|
2464
|
+
showAds: this.showAds,
|
|
2465
|
+
inAdBreak: this.inAdBreak,
|
|
2466
|
+
remainingAds: this.adPodQueue.length
|
|
2467
|
+
});
|
|
2391
2468
|
}
|
|
2392
|
-
if (this.
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2469
|
+
if (this.inAdBreak) {
|
|
2470
|
+
const remaining = this.getRemainingAdMs();
|
|
2471
|
+
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2472
|
+
const nextPreloaded = this.findNextPreloadedAd();
|
|
2473
|
+
if (nextPreloaded) {
|
|
2397
2474
|
this.currentAdIndex++;
|
|
2398
|
-
this.
|
|
2475
|
+
if (this.config.debugAdTiming) {
|
|
2476
|
+
console.log(
|
|
2477
|
+
`[StormcloudVideoPlayer] Skipping to next preloaded ad after error`
|
|
2478
|
+
);
|
|
2479
|
+
}
|
|
2480
|
+
this.playSingleAd(nextPreloaded).catch(() => {
|
|
2481
|
+
this.handleAdFailure();
|
|
2399
2482
|
});
|
|
2400
2483
|
} else {
|
|
2484
|
+
if (this.config.debugAdTiming) {
|
|
2485
|
+
console.log(
|
|
2486
|
+
"[StormcloudVideoPlayer] No preloaded ads available, ending ad break"
|
|
2487
|
+
);
|
|
2488
|
+
}
|
|
2401
2489
|
this.handleAdFailure();
|
|
2402
2490
|
}
|
|
2403
2491
|
} else {
|
|
2404
|
-
if (this.config.debugAdTiming) {
|
|
2405
|
-
console.log(
|
|
2406
|
-
"[StormcloudVideoPlayer] Ad error before ad break established - cleaning up"
|
|
2407
|
-
);
|
|
2408
|
-
}
|
|
2409
2492
|
this.handleAdFailure();
|
|
2410
2493
|
}
|
|
2494
|
+
} else {
|
|
2495
|
+
if (this.config.debugAdTiming) {
|
|
2496
|
+
console.log(
|
|
2497
|
+
"[StormcloudVideoPlayer] Ad error before ad break established - cleaning up"
|
|
2498
|
+
);
|
|
2499
|
+
}
|
|
2500
|
+
this.handleAdFailure();
|
|
2411
2501
|
}
|
|
2412
2502
|
});
|
|
2413
2503
|
this.ima.on("content_pause", () => {
|
|
@@ -2438,22 +2528,31 @@ var StormcloudVideoPlayer = class {
|
|
|
2438
2528
|
}
|
|
2439
2529
|
const remaining = this.getRemainingAdMs();
|
|
2440
2530
|
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2441
|
-
const
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
console.log(
|
|
2446
|
-
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak}) - IMMEDIATELY starting next ad`
|
|
2447
|
-
);
|
|
2448
|
-
}
|
|
2449
|
-
this.playSingleAd(next).catch(() => {
|
|
2531
|
+
const nextPreloaded = this.findNextPreloadedAd();
|
|
2532
|
+
if (nextPreloaded) {
|
|
2533
|
+
this.currentAdIndex++;
|
|
2534
|
+
this.enforceAdHoldState();
|
|
2450
2535
|
if (this.config.debugAdTiming) {
|
|
2451
|
-
console.
|
|
2452
|
-
|
|
2536
|
+
console.log(
|
|
2537
|
+
`[StormcloudVideoPlayer] Playing next preloaded ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak})`
|
|
2538
|
+
);
|
|
2539
|
+
}
|
|
2540
|
+
this.playSingleAd(nextPreloaded).catch(() => {
|
|
2541
|
+
if (this.config.debugAdTiming) {
|
|
2542
|
+
console.error(
|
|
2543
|
+
"[StormcloudVideoPlayer] Failed to play next ad in pod"
|
|
2544
|
+
);
|
|
2545
|
+
}
|
|
2546
|
+
this.handleAdPodComplete();
|
|
2547
|
+
});
|
|
2548
|
+
} else {
|
|
2549
|
+
if (this.config.debugAdTiming) {
|
|
2550
|
+
console.log(
|
|
2551
|
+
"[StormcloudVideoPlayer] No preloaded ads available - completing ad break"
|
|
2453
2552
|
);
|
|
2454
2553
|
}
|
|
2455
2554
|
this.handleAdPodComplete();
|
|
2456
|
-
}
|
|
2555
|
+
}
|
|
2457
2556
|
} else {
|
|
2458
2557
|
if (this.config.debugAdTiming) {
|
|
2459
2558
|
console.log(
|
|
@@ -2698,6 +2797,9 @@ var StormcloudVideoPlayer = class {
|
|
|
2698
2797
|
const first = tags[0];
|
|
2699
2798
|
const rest = tags.slice(1);
|
|
2700
2799
|
this.adPodQueue = rest;
|
|
2800
|
+
if (!this.showAds) {
|
|
2801
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
2802
|
+
}
|
|
2701
2803
|
this.playSingleAd(first).catch(() => {
|
|
2702
2804
|
});
|
|
2703
2805
|
}
|
|
@@ -3054,19 +3156,38 @@ var StormcloudVideoPlayer = class {
|
|
|
3054
3156
|
if (vastTagUrls.length > 0) {
|
|
3055
3157
|
this.adPodAllUrls = [...vastTagUrls];
|
|
3056
3158
|
this.preloadingAdUrls.clear();
|
|
3159
|
+
this.vastToMediaUrlMap.clear();
|
|
3160
|
+
this.preloadedMediaUrls.clear();
|
|
3161
|
+
this.preloadingMediaUrls.clear();
|
|
3057
3162
|
this.logQueuedAdUrls(this.adPodAllUrls);
|
|
3163
|
+
if (this.config.debugAdTiming) {
|
|
3164
|
+
console.log(
|
|
3165
|
+
`[StormcloudVideoPlayer] Capturing original audio state before ad break:`,
|
|
3166
|
+
{
|
|
3167
|
+
videoMuted: this.video.muted,
|
|
3168
|
+
videoVolume: this.video.volume
|
|
3169
|
+
}
|
|
3170
|
+
);
|
|
3171
|
+
}
|
|
3172
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3058
3173
|
this.inAdBreak = true;
|
|
3059
|
-
this.showAds = true;
|
|
3060
3174
|
this.currentAdIndex = 0;
|
|
3061
3175
|
this.totalAdsInBreak = vastTagUrls.length;
|
|
3062
3176
|
this.adPodQueue = [...vastTagUrls];
|
|
3063
3177
|
this.enforceAdHoldState();
|
|
3064
|
-
this.preloadUpcomingAds();
|
|
3065
3178
|
if (this.config.debugAdTiming) {
|
|
3066
3179
|
console.log(
|
|
3067
|
-
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads -
|
|
3180
|
+
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads - preloading all ads in parallel`
|
|
3068
3181
|
);
|
|
3069
3182
|
}
|
|
3183
|
+
this.preloadAllAdsInBackground().catch((error) => {
|
|
3184
|
+
if (this.config.debugAdTiming) {
|
|
3185
|
+
console.warn(
|
|
3186
|
+
"[StormcloudVideoPlayer] Error in background preloading:",
|
|
3187
|
+
error
|
|
3188
|
+
);
|
|
3189
|
+
}
|
|
3190
|
+
});
|
|
3070
3191
|
try {
|
|
3071
3192
|
await this.playAdPod();
|
|
3072
3193
|
} catch (error) {
|
|
@@ -3092,14 +3213,28 @@ var StormcloudVideoPlayer = class {
|
|
|
3092
3213
|
}
|
|
3093
3214
|
return;
|
|
3094
3215
|
}
|
|
3095
|
-
|
|
3216
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
3217
|
+
const firstPreloaded = this.findNextPreloadedAd();
|
|
3218
|
+
if (!firstPreloaded) {
|
|
3219
|
+
if (this.config.debugAdTiming) {
|
|
3220
|
+
console.log(
|
|
3221
|
+
"[StormcloudVideoPlayer] No preloaded ads available after waiting, trying first ad anyway"
|
|
3222
|
+
);
|
|
3223
|
+
}
|
|
3224
|
+
const firstAd = this.adPodQueue.shift();
|
|
3225
|
+
if (firstAd) {
|
|
3226
|
+
this.currentAdIndex++;
|
|
3227
|
+
await this.playSingleAd(firstAd);
|
|
3228
|
+
}
|
|
3229
|
+
return;
|
|
3230
|
+
}
|
|
3096
3231
|
this.currentAdIndex++;
|
|
3097
3232
|
if (this.config.debugAdTiming) {
|
|
3098
3233
|
console.log(
|
|
3099
|
-
`[StormcloudVideoPlayer] Playing ad ${this.currentAdIndex}/${this.totalAdsInBreak}`
|
|
3234
|
+
`[StormcloudVideoPlayer] Playing first preloaded ad ${this.currentAdIndex}/${this.totalAdsInBreak}`
|
|
3100
3235
|
);
|
|
3101
3236
|
}
|
|
3102
|
-
await this.playSingleAd(
|
|
3237
|
+
await this.playSingleAd(firstPreloaded);
|
|
3103
3238
|
}
|
|
3104
3239
|
findCurrentOrNextBreak(nowMs) {
|
|
3105
3240
|
var _a;
|
|
@@ -3132,6 +3267,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3132
3267
|
const first = tags[0];
|
|
3133
3268
|
const rest = tags.slice(1);
|
|
3134
3269
|
this.adPodQueue = rest;
|
|
3270
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3135
3271
|
this.enforceAdHoldState();
|
|
3136
3272
|
await this.playSingleAd(first);
|
|
3137
3273
|
this.inAdBreak = true;
|
|
@@ -3252,27 +3388,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3252
3388
|
`[StormcloudVideoPlayer] IMA SDK preloaded this ad already: ${vastTagUrl}`
|
|
3253
3389
|
);
|
|
3254
3390
|
}
|
|
3255
|
-
if (!this.showAds) {
|
|
3256
|
-
if (this.config.debugAdTiming) {
|
|
3257
|
-
console.log(
|
|
3258
|
-
`[StormcloudVideoPlayer] Capturing original state before ad request:`,
|
|
3259
|
-
{
|
|
3260
|
-
videoMuted: this.video.muted,
|
|
3261
|
-
videoVolume: this.video.volume,
|
|
3262
|
-
showAds: this.showAds
|
|
3263
|
-
}
|
|
3264
|
-
);
|
|
3265
|
-
}
|
|
3266
|
-
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3267
|
-
} else if (this.config.debugAdTiming) {
|
|
3268
|
-
console.log(
|
|
3269
|
-
`[StormcloudVideoPlayer] Keeping existing original mute state (currently showing ads)`
|
|
3270
|
-
);
|
|
3271
|
-
}
|
|
3272
3391
|
this.startAdFailsafeTimer();
|
|
3273
3392
|
try {
|
|
3274
3393
|
await this.ima.requestAds(vastTagUrl);
|
|
3275
|
-
this.preloadUpcomingAds();
|
|
3276
3394
|
try {
|
|
3277
3395
|
if (this.config.debugAdTiming) {
|
|
3278
3396
|
console.log(
|
|
@@ -3281,9 +3399,10 @@ var StormcloudVideoPlayer = class {
|
|
|
3281
3399
|
}
|
|
3282
3400
|
this.enforceAdHoldState();
|
|
3283
3401
|
await this.ima.play();
|
|
3402
|
+
this.showAds = true;
|
|
3284
3403
|
if (this.config.debugAdTiming) {
|
|
3285
3404
|
console.log(
|
|
3286
|
-
"[StormcloudVideoPlayer] Ad playback started successfully"
|
|
3405
|
+
"[StormcloudVideoPlayer] Ad playback started successfully, showAds = true"
|
|
3287
3406
|
);
|
|
3288
3407
|
}
|
|
3289
3408
|
} catch (playError) {
|
|
@@ -3311,6 +3430,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3311
3430
|
}
|
|
3312
3431
|
this.releaseAdHoldState();
|
|
3313
3432
|
this.preloadingAdUrls.clear();
|
|
3433
|
+
this.vastToMediaUrlMap.clear();
|
|
3434
|
+
this.preloadedMediaUrls.clear();
|
|
3435
|
+
this.preloadingMediaUrls.clear();
|
|
3314
3436
|
this.inAdBreak = false;
|
|
3315
3437
|
this.expectedAdBreakDurationMs = void 0;
|
|
3316
3438
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
@@ -3420,43 +3542,203 @@ var StormcloudVideoPlayer = class {
|
|
|
3420
3542
|
this.ima.hidePlaceholder();
|
|
3421
3543
|
}
|
|
3422
3544
|
}
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3545
|
+
async fetchAndParseVastXml(vastTagUrl) {
|
|
3546
|
+
try {
|
|
3547
|
+
const response = await fetch(vastTagUrl, { mode: "cors" });
|
|
3548
|
+
if (!response.ok) {
|
|
3549
|
+
throw new Error(`Failed to fetch VAST: ${response.status}`);
|
|
3550
|
+
}
|
|
3551
|
+
const xmlText = await response.text();
|
|
3552
|
+
return this.extractMediaUrlsFromVast(xmlText);
|
|
3553
|
+
} catch (error) {
|
|
3554
|
+
if (this.config.debugAdTiming) {
|
|
3555
|
+
console.warn(
|
|
3556
|
+
`[StormcloudVideoPlayer] Failed to fetch/parse VAST XML: ${vastTagUrl}`,
|
|
3557
|
+
error
|
|
3558
|
+
);
|
|
3559
|
+
}
|
|
3560
|
+
return [];
|
|
3426
3561
|
}
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3562
|
+
}
|
|
3563
|
+
extractMediaUrlsFromVast(xmlText) {
|
|
3564
|
+
var _a;
|
|
3565
|
+
const mediaUrls = [];
|
|
3566
|
+
try {
|
|
3567
|
+
const parser = new DOMParser();
|
|
3568
|
+
const xmlDoc = parser.parseFromString(xmlText, "text/xml");
|
|
3569
|
+
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
3570
|
+
for (const mediaFile of Array.from(mediaFileElements)) {
|
|
3571
|
+
const url = (_a = mediaFile.textContent) == null ? void 0 : _a.trim();
|
|
3572
|
+
if (url) {
|
|
3573
|
+
const lowerUrl = url.toLowerCase();
|
|
3574
|
+
if (lowerUrl.endsWith(".mp4") || lowerUrl.endsWith(".webm") || lowerUrl.endsWith(".mov") || lowerUrl.endsWith(".avi") || lowerUrl.includes(".mp4?") || lowerUrl.includes(".webm?") || lowerUrl.includes("/mp4/") || lowerUrl.includes("type=video")) {
|
|
3575
|
+
mediaUrls.push(url);
|
|
3576
|
+
}
|
|
3577
|
+
}
|
|
3578
|
+
}
|
|
3579
|
+
if (this.config.debugAdTiming && mediaUrls.length > 0) {
|
|
3580
|
+
console.log(
|
|
3581
|
+
`[StormcloudVideoPlayer] Extracted ${mediaUrls.length} media URLs from VAST:`,
|
|
3582
|
+
mediaUrls
|
|
3583
|
+
);
|
|
3433
3584
|
}
|
|
3434
|
-
|
|
3435
|
-
|
|
3585
|
+
} catch (error) {
|
|
3586
|
+
if (this.config.debugAdTiming) {
|
|
3587
|
+
console.warn(
|
|
3588
|
+
"[StormcloudVideoPlayer] Failed to parse VAST XML:",
|
|
3589
|
+
error
|
|
3590
|
+
);
|
|
3436
3591
|
}
|
|
3592
|
+
}
|
|
3593
|
+
return mediaUrls;
|
|
3594
|
+
}
|
|
3595
|
+
async preloadMediaFile(mediaUrl) {
|
|
3596
|
+
if (this.preloadedMediaUrls.has(mediaUrl)) {
|
|
3597
|
+
return;
|
|
3598
|
+
}
|
|
3599
|
+
if (this.preloadingMediaUrls.has(mediaUrl)) {
|
|
3600
|
+
return;
|
|
3601
|
+
}
|
|
3602
|
+
this.preloadingMediaUrls.add(mediaUrl);
|
|
3603
|
+
try {
|
|
3437
3604
|
if (this.config.debugAdTiming) {
|
|
3438
3605
|
console.log(
|
|
3439
|
-
`[StormcloudVideoPlayer]
|
|
3606
|
+
`[StormcloudVideoPlayer] Preloading video file: ${mediaUrl}`
|
|
3440
3607
|
);
|
|
3441
3608
|
}
|
|
3442
|
-
|
|
3443
|
-
|
|
3609
|
+
const response = await fetch(mediaUrl, {
|
|
3610
|
+
mode: "cors",
|
|
3611
|
+
method: "GET",
|
|
3612
|
+
headers: {
|
|
3613
|
+
Range: "bytes=0-1048576"
|
|
3614
|
+
}
|
|
3615
|
+
});
|
|
3616
|
+
if (response.ok || response.status === 206) {
|
|
3617
|
+
this.preloadedMediaUrls.add(mediaUrl);
|
|
3444
3618
|
if (this.config.debugAdTiming) {
|
|
3445
3619
|
console.log(
|
|
3446
|
-
`[StormcloudVideoPlayer]
|
|
3620
|
+
`[StormcloudVideoPlayer] Successfully preloaded video file: ${mediaUrl}`
|
|
3447
3621
|
);
|
|
3448
3622
|
}
|
|
3449
|
-
}
|
|
3623
|
+
}
|
|
3624
|
+
} catch (error) {
|
|
3625
|
+
if (this.config.debugAdTiming) {
|
|
3626
|
+
console.warn(
|
|
3627
|
+
`[StormcloudVideoPlayer] Failed to preload video file: ${mediaUrl}`,
|
|
3628
|
+
error
|
|
3629
|
+
);
|
|
3630
|
+
}
|
|
3631
|
+
} finally {
|
|
3632
|
+
this.preloadingMediaUrls.delete(mediaUrl);
|
|
3633
|
+
}
|
|
3634
|
+
}
|
|
3635
|
+
async preloadAllAdsInBackground() {
|
|
3636
|
+
if (this.adPodAllUrls.length === 0) {
|
|
3637
|
+
return;
|
|
3638
|
+
}
|
|
3639
|
+
if (this.config.debugAdTiming) {
|
|
3640
|
+
console.log(
|
|
3641
|
+
`[StormcloudVideoPlayer] Starting parallel preload of ${this.adPodAllUrls.length} ads`
|
|
3642
|
+
);
|
|
3643
|
+
}
|
|
3644
|
+
const preloadPromises = this.adPodAllUrls.map(
|
|
3645
|
+
(vastTagUrl) => this.preloadSingleAd(vastTagUrl).catch((error) => {
|
|
3450
3646
|
if (this.config.debugAdTiming) {
|
|
3451
3647
|
console.warn(
|
|
3452
|
-
`[StormcloudVideoPlayer]
|
|
3648
|
+
`[StormcloudVideoPlayer] Preload failed for ${vastTagUrl}:`,
|
|
3453
3649
|
error
|
|
3454
3650
|
);
|
|
3455
3651
|
}
|
|
3456
|
-
})
|
|
3457
|
-
|
|
3458
|
-
|
|
3652
|
+
})
|
|
3653
|
+
);
|
|
3654
|
+
await Promise.all(preloadPromises);
|
|
3655
|
+
if (this.config.debugAdTiming) {
|
|
3656
|
+
console.log(
|
|
3657
|
+
`[StormcloudVideoPlayer] Background preloading completed for all ads`
|
|
3658
|
+
);
|
|
3659
|
+
}
|
|
3660
|
+
}
|
|
3661
|
+
async preloadSingleAd(vastTagUrl) {
|
|
3662
|
+
if (!vastTagUrl) return;
|
|
3663
|
+
try {
|
|
3664
|
+
if (this.ima.preloadAds && !this.ima.hasPreloadedAd(vastTagUrl)) {
|
|
3665
|
+
if (!this.preloadingAdUrls.has(vastTagUrl)) {
|
|
3666
|
+
if (this.config.debugAdTiming) {
|
|
3667
|
+
console.log(
|
|
3668
|
+
`[StormcloudVideoPlayer] Preloading VAST: ${vastTagUrl}`
|
|
3669
|
+
);
|
|
3670
|
+
}
|
|
3671
|
+
this.preloadingAdUrls.add(vastTagUrl);
|
|
3672
|
+
await this.ima.preloadAds(vastTagUrl).then(() => {
|
|
3673
|
+
if (this.config.debugAdTiming) {
|
|
3674
|
+
console.log(
|
|
3675
|
+
`[StormcloudVideoPlayer] IMA VAST preload complete: ${vastTagUrl}`
|
|
3676
|
+
);
|
|
3677
|
+
}
|
|
3678
|
+
}).catch((error) => {
|
|
3679
|
+
if (this.config.debugAdTiming) {
|
|
3680
|
+
console.warn(
|
|
3681
|
+
`[StormcloudVideoPlayer] IMA VAST preload failed: ${vastTagUrl}`,
|
|
3682
|
+
error
|
|
3683
|
+
);
|
|
3684
|
+
}
|
|
3685
|
+
}).finally(() => {
|
|
3686
|
+
this.preloadingAdUrls.delete(vastTagUrl);
|
|
3687
|
+
});
|
|
3688
|
+
}
|
|
3689
|
+
}
|
|
3690
|
+
let mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);
|
|
3691
|
+
if (!mediaUrls) {
|
|
3692
|
+
if (this.config.debugAdTiming) {
|
|
3693
|
+
console.log(
|
|
3694
|
+
`[StormcloudVideoPlayer] Fetching and parsing VAST to extract media URLs: ${vastTagUrl}`
|
|
3695
|
+
);
|
|
3696
|
+
}
|
|
3697
|
+
mediaUrls = await this.fetchAndParseVastXml(vastTagUrl);
|
|
3698
|
+
if (mediaUrls.length > 0) {
|
|
3699
|
+
this.vastToMediaUrlMap.set(vastTagUrl, mediaUrls);
|
|
3700
|
+
}
|
|
3701
|
+
}
|
|
3702
|
+
if (mediaUrls && mediaUrls.length > 0) {
|
|
3703
|
+
const primaryMediaUrl = mediaUrls[0];
|
|
3704
|
+
if (primaryMediaUrl && !this.preloadedMediaUrls.has(primaryMediaUrl)) {
|
|
3705
|
+
await this.preloadMediaFile(primaryMediaUrl);
|
|
3706
|
+
}
|
|
3707
|
+
}
|
|
3708
|
+
} catch (error) {
|
|
3709
|
+
if (this.config.debugAdTiming) {
|
|
3710
|
+
console.warn(
|
|
3711
|
+
`[StormcloudVideoPlayer] Failed to preload ad: ${vastTagUrl}`,
|
|
3712
|
+
error
|
|
3713
|
+
);
|
|
3714
|
+
}
|
|
3715
|
+
}
|
|
3716
|
+
}
|
|
3717
|
+
findNextPreloadedAd() {
|
|
3718
|
+
var _a, _b, _c;
|
|
3719
|
+
for (let i = 0; i < this.adPodQueue.length; i++) {
|
|
3720
|
+
const vastTagUrl = this.adPodQueue[i];
|
|
3721
|
+
if (!vastTagUrl) continue;
|
|
3722
|
+
const hasImaPreload = (_c = (_b = (_a = this.ima).hasPreloadedAd) == null ? void 0 : _b.call(_a, vastTagUrl)) != null ? _c : false;
|
|
3723
|
+
const mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);
|
|
3724
|
+
const hasMediaPreload = mediaUrls && mediaUrls.length > 0 ? this.preloadedMediaUrls.has(mediaUrls[0]) : false;
|
|
3725
|
+
if (hasImaPreload || hasMediaPreload) {
|
|
3726
|
+
if (this.config.debugAdTiming) {
|
|
3727
|
+
console.log(
|
|
3728
|
+
`[StormcloudVideoPlayer] Found preloaded ad at index ${i}: ${vastTagUrl}`,
|
|
3729
|
+
{ hasImaPreload, hasMediaPreload }
|
|
3730
|
+
);
|
|
3731
|
+
}
|
|
3732
|
+
this.adPodQueue.splice(0, i + 1);
|
|
3733
|
+
return vastTagUrl;
|
|
3734
|
+
}
|
|
3459
3735
|
}
|
|
3736
|
+
if (this.config.debugAdTiming) {
|
|
3737
|
+
console.log(
|
|
3738
|
+
"[StormcloudVideoPlayer] No preloaded ads found in queue"
|
|
3739
|
+
);
|
|
3740
|
+
}
|
|
3741
|
+
return void 0;
|
|
3460
3742
|
}
|
|
3461
3743
|
getRemainingAdMs() {
|
|
3462
3744
|
if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)
|
|
@@ -3626,6 +3908,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3626
3908
|
(_b = this.ima) == null ? void 0 : _b.destroy();
|
|
3627
3909
|
this.releaseAdHoldState();
|
|
3628
3910
|
this.preloadingAdUrls.clear();
|
|
3911
|
+
this.vastToMediaUrlMap.clear();
|
|
3912
|
+
this.preloadedMediaUrls.clear();
|
|
3913
|
+
this.preloadingMediaUrls.clear();
|
|
3629
3914
|
this.adPodAllUrls = [];
|
|
3630
3915
|
}
|
|
3631
3916
|
};
|