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
package/lib/index.cjs
CHANGED
|
@@ -281,7 +281,11 @@ function createImaController(video, options) {
|
|
|
281
281
|
}
|
|
282
282
|
function hideContentVideo() {
|
|
283
283
|
if (!contentVideoHidden) {
|
|
284
|
-
video.style.
|
|
284
|
+
video.style.transition = "opacity 0.3s ease-in-out";
|
|
285
|
+
video.style.opacity = "0";
|
|
286
|
+
setTimeout(() => {
|
|
287
|
+
video.style.visibility = "hidden";
|
|
288
|
+
}, 300);
|
|
285
289
|
video.muted = true;
|
|
286
290
|
video.volume = 0;
|
|
287
291
|
contentVideoHidden = true;
|
|
@@ -291,6 +295,9 @@ function createImaController(video, options) {
|
|
|
291
295
|
function showContentVideo() {
|
|
292
296
|
if (contentVideoHidden) {
|
|
293
297
|
video.style.visibility = "visible";
|
|
298
|
+
video.style.transition = "opacity 0.3s ease-in-out";
|
|
299
|
+
video.offsetHeight;
|
|
300
|
+
video.style.opacity = "1";
|
|
294
301
|
video.muted = originalMutedState;
|
|
295
302
|
video.volume = originalVolume;
|
|
296
303
|
contentVideoHidden = false;
|
|
@@ -463,7 +470,9 @@ function createImaController(video, options) {
|
|
|
463
470
|
container.style.justifyContent = "center";
|
|
464
471
|
container.style.pointerEvents = "none";
|
|
465
472
|
container.style.zIndex = "10";
|
|
466
|
-
container.style.backgroundColor = "
|
|
473
|
+
container.style.backgroundColor = "transparent";
|
|
474
|
+
container.style.transition = "opacity 0.3s ease-in-out, background-color 0.3s ease-in-out";
|
|
475
|
+
container.style.opacity = "0";
|
|
467
476
|
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
468
477
|
adContainerEl = container;
|
|
469
478
|
}
|
|
@@ -573,7 +582,9 @@ function createImaController(video, options) {
|
|
|
573
582
|
container.style.justifyContent = "center";
|
|
574
583
|
container.style.pointerEvents = "none";
|
|
575
584
|
container.style.zIndex = "10";
|
|
576
|
-
container.style.backgroundColor = "
|
|
585
|
+
container.style.backgroundColor = "transparent";
|
|
586
|
+
container.style.transition = "opacity 0.3s ease-in-out, background-color 0.3s ease-in-out";
|
|
587
|
+
container.style.opacity = "0";
|
|
577
588
|
if (!video.parentElement) {
|
|
578
589
|
throw new Error("Video element has no parent for ad container");
|
|
579
590
|
}
|
|
@@ -637,13 +648,19 @@ function createImaController(video, options) {
|
|
|
637
648
|
console.error("[IMA] Ad error:", errorEvent.getError());
|
|
638
649
|
destroyAdsManager();
|
|
639
650
|
adPlaying = false;
|
|
640
|
-
showContentVideo();
|
|
641
651
|
setAdPlayingFlag(false);
|
|
642
652
|
if (adContainerEl) {
|
|
643
|
-
adContainerEl.style.
|
|
644
|
-
adContainerEl.style.
|
|
645
|
-
|
|
653
|
+
adContainerEl.style.opacity = "0";
|
|
654
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
655
|
+
setTimeout(() => {
|
|
656
|
+
if (adContainerEl) {
|
|
657
|
+
adContainerEl.style.pointerEvents = "none";
|
|
658
|
+
adContainerEl.style.display = "none";
|
|
659
|
+
console.log("[IMA] Ad container hidden after error");
|
|
660
|
+
}
|
|
661
|
+
}, 300);
|
|
646
662
|
}
|
|
663
|
+
showContentVideo();
|
|
647
664
|
if (adsLoadedReject) {
|
|
648
665
|
adsLoadedReject(new Error("Ad playback error"));
|
|
649
666
|
adsLoadedReject = void 0;
|
|
@@ -689,6 +706,15 @@ function createImaController(video, options) {
|
|
|
689
706
|
"[IMA] Content video continues in background (Live mode)"
|
|
690
707
|
);
|
|
691
708
|
}
|
|
709
|
+
hideContentVideo();
|
|
710
|
+
if (adContainerEl) {
|
|
711
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
712
|
+
adContainerEl.style.display = "flex";
|
|
713
|
+
adContainerEl.style.backgroundColor = "#000";
|
|
714
|
+
adContainerEl.offsetHeight;
|
|
715
|
+
adContainerEl.style.opacity = "1";
|
|
716
|
+
console.log("[IMA] Ad container shown on content pause");
|
|
717
|
+
}
|
|
692
718
|
adPlaying = true;
|
|
693
719
|
setAdPlayingFlag(true);
|
|
694
720
|
emit("content_pause");
|
|
@@ -708,6 +734,9 @@ function createImaController(video, options) {
|
|
|
708
734
|
if (adContainerEl) {
|
|
709
735
|
adContainerEl.style.pointerEvents = "auto";
|
|
710
736
|
adContainerEl.style.display = "flex";
|
|
737
|
+
adContainerEl.style.backgroundColor = "#000";
|
|
738
|
+
adContainerEl.offsetHeight;
|
|
739
|
+
adContainerEl.style.opacity = "1";
|
|
711
740
|
console.log("[IMA] Ad container now visible");
|
|
712
741
|
}
|
|
713
742
|
});
|
|
@@ -724,12 +753,18 @@ function createImaController(video, options) {
|
|
|
724
753
|
console.log("[IMA] All ads completed - restoring content");
|
|
725
754
|
adPlaying = false;
|
|
726
755
|
setAdPlayingFlag(false);
|
|
727
|
-
showContentVideo();
|
|
728
756
|
if (adContainerEl) {
|
|
729
|
-
adContainerEl.style.
|
|
730
|
-
adContainerEl.style.
|
|
731
|
-
|
|
757
|
+
adContainerEl.style.opacity = "0";
|
|
758
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
759
|
+
setTimeout(() => {
|
|
760
|
+
if (adContainerEl) {
|
|
761
|
+
adContainerEl.style.pointerEvents = "none";
|
|
762
|
+
adContainerEl.style.display = "none";
|
|
763
|
+
console.log("[IMA] Ad container hidden");
|
|
764
|
+
}
|
|
765
|
+
}, 300);
|
|
732
766
|
}
|
|
767
|
+
showContentVideo();
|
|
733
768
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds) && video.paused) {
|
|
734
769
|
console.log("[IMA] Resuming content video playback");
|
|
735
770
|
video.play().catch((e) => {
|
|
@@ -747,13 +782,21 @@ function createImaController(video, options) {
|
|
|
747
782
|
} catch (e) {
|
|
748
783
|
console.error("[IMA] Error setting up ads manager:", e);
|
|
749
784
|
adPlaying = false;
|
|
750
|
-
showContentVideo();
|
|
751
785
|
setAdPlayingFlag(false);
|
|
752
786
|
if (adContainerEl) {
|
|
753
|
-
adContainerEl.style.
|
|
754
|
-
adContainerEl.style.
|
|
755
|
-
|
|
787
|
+
adContainerEl.style.opacity = "0";
|
|
788
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
789
|
+
setTimeout(() => {
|
|
790
|
+
if (adContainerEl) {
|
|
791
|
+
adContainerEl.style.pointerEvents = "none";
|
|
792
|
+
adContainerEl.style.display = "none";
|
|
793
|
+
console.log(
|
|
794
|
+
"[IMA] Ad container hidden after setup error"
|
|
795
|
+
);
|
|
796
|
+
}
|
|
797
|
+
}, 300);
|
|
756
798
|
}
|
|
799
|
+
showContentVideo();
|
|
757
800
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
758
801
|
if (video.paused) {
|
|
759
802
|
console.log(
|
|
@@ -778,13 +821,19 @@ function createImaController(video, options) {
|
|
|
778
821
|
(adErrorEvent) => {
|
|
779
822
|
console.error("[IMA] Ads loader error:", adErrorEvent.getError());
|
|
780
823
|
adPlaying = false;
|
|
781
|
-
showContentVideo();
|
|
782
824
|
setAdPlayingFlag(false);
|
|
783
825
|
if (adContainerEl) {
|
|
784
|
-
adContainerEl.style.
|
|
785
|
-
adContainerEl.style.
|
|
786
|
-
|
|
826
|
+
adContainerEl.style.opacity = "0";
|
|
827
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
828
|
+
setTimeout(() => {
|
|
829
|
+
if (adContainerEl) {
|
|
830
|
+
adContainerEl.style.pointerEvents = "none";
|
|
831
|
+
adContainerEl.style.display = "none";
|
|
832
|
+
console.log("[IMA] Ad container hidden after loader error");
|
|
833
|
+
}
|
|
834
|
+
}, 300);
|
|
787
835
|
}
|
|
836
|
+
showContentVideo();
|
|
788
837
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
789
838
|
if (video.paused) {
|
|
790
839
|
console.log("[IMA] Resuming paused video after loader error");
|
|
@@ -890,12 +939,18 @@ function createImaController(video, options) {
|
|
|
890
939
|
console.log("[IMA] Stopping ad playback");
|
|
891
940
|
adPlaying = false;
|
|
892
941
|
setAdPlayingFlag(false);
|
|
893
|
-
showContentVideo();
|
|
894
942
|
if (adContainerEl) {
|
|
895
|
-
adContainerEl.style.
|
|
896
|
-
adContainerEl.style.
|
|
897
|
-
|
|
943
|
+
adContainerEl.style.opacity = "0";
|
|
944
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
945
|
+
setTimeout(() => {
|
|
946
|
+
if (adContainerEl) {
|
|
947
|
+
adContainerEl.style.pointerEvents = "none";
|
|
948
|
+
adContainerEl.style.display = "none";
|
|
949
|
+
console.log("[IMA] Ad container hidden after stop");
|
|
950
|
+
}
|
|
951
|
+
}, 300);
|
|
898
952
|
}
|
|
953
|
+
showContentVideo();
|
|
899
954
|
try {
|
|
900
955
|
(_a = adsManager == null ? void 0 : adsManager.stop) == null ? void 0 : _a.call(adsManager);
|
|
901
956
|
} catch {
|
|
@@ -906,23 +961,29 @@ function createImaController(video, options) {
|
|
|
906
961
|
var _a;
|
|
907
962
|
destroyAdsManager();
|
|
908
963
|
adPlaying = false;
|
|
909
|
-
showContentVideo();
|
|
910
964
|
setAdPlayingFlag(false);
|
|
911
965
|
if (adContainerEl) {
|
|
912
|
-
adContainerEl.style.
|
|
913
|
-
adContainerEl.style.
|
|
966
|
+
adContainerEl.style.opacity = "0";
|
|
967
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
968
|
+
setTimeout(() => {
|
|
969
|
+
if (adContainerEl) {
|
|
970
|
+
adContainerEl.style.pointerEvents = "none";
|
|
971
|
+
adContainerEl.style.display = "none";
|
|
972
|
+
if (adContainerEl.parentElement) {
|
|
973
|
+
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
974
|
+
}
|
|
975
|
+
adContainerEl = void 0;
|
|
976
|
+
adVideoElement = void 0;
|
|
977
|
+
}
|
|
978
|
+
}, 300);
|
|
914
979
|
}
|
|
980
|
+
showContentVideo();
|
|
915
981
|
try {
|
|
916
982
|
(_a = adsLoader == null ? void 0 : adsLoader.destroy) == null ? void 0 : _a.call(adsLoader);
|
|
917
983
|
} catch {
|
|
918
984
|
}
|
|
919
|
-
if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
|
|
920
|
-
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
921
|
-
}
|
|
922
|
-
adContainerEl = void 0;
|
|
923
985
|
adDisplayContainer = void 0;
|
|
924
986
|
adsLoader = void 0;
|
|
925
|
-
adVideoElement = void 0;
|
|
926
987
|
contentVideoHidden = false;
|
|
927
988
|
preloadedVast.clear();
|
|
928
989
|
preloadingVast.clear();
|
|
@@ -1002,13 +1063,22 @@ function createImaController(video, options) {
|
|
|
1002
1063
|
ensurePlaceholderContainer();
|
|
1003
1064
|
if (adContainerEl) {
|
|
1004
1065
|
adContainerEl.style.display = "flex";
|
|
1066
|
+
adContainerEl.style.backgroundColor = "#000";
|
|
1067
|
+
adContainerEl.offsetHeight;
|
|
1068
|
+
adContainerEl.style.opacity = "1";
|
|
1005
1069
|
adContainerEl.style.pointerEvents = "auto";
|
|
1006
1070
|
}
|
|
1007
1071
|
},
|
|
1008
1072
|
hidePlaceholder() {
|
|
1009
1073
|
if (adContainerEl) {
|
|
1010
|
-
adContainerEl.style.
|
|
1011
|
-
adContainerEl.style.
|
|
1074
|
+
adContainerEl.style.opacity = "0";
|
|
1075
|
+
adContainerEl.style.backgroundColor = "transparent";
|
|
1076
|
+
setTimeout(() => {
|
|
1077
|
+
if (adContainerEl) {
|
|
1078
|
+
adContainerEl.style.display = "none";
|
|
1079
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1080
|
+
}
|
|
1081
|
+
}, 300);
|
|
1012
1082
|
}
|
|
1013
1083
|
}
|
|
1014
1084
|
};
|
|
@@ -2179,6 +2249,9 @@ var StormcloudVideoPlayer = class {
|
|
|
2179
2249
|
this.hasInitialBufferCompleted = false;
|
|
2180
2250
|
this.adPodAllUrls = [];
|
|
2181
2251
|
this.preloadingAdUrls = /* @__PURE__ */ new Set();
|
|
2252
|
+
this.vastToMediaUrlMap = /* @__PURE__ */ new Map();
|
|
2253
|
+
this.preloadedMediaUrls = /* @__PURE__ */ new Set();
|
|
2254
|
+
this.preloadingMediaUrls = /* @__PURE__ */ new Set();
|
|
2182
2255
|
initializePolyfills();
|
|
2183
2256
|
const browserOverrides = getBrowserConfigOverrides();
|
|
2184
2257
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -2451,27 +2524,44 @@ var StormcloudVideoPlayer = class {
|
|
|
2451
2524
|
});
|
|
2452
2525
|
this.ima.on("ad_error", () => {
|
|
2453
2526
|
if (this.config.debugAdTiming) {
|
|
2454
|
-
console.log("[StormcloudVideoPlayer] IMA ad_error event received"
|
|
2527
|
+
console.log("[StormcloudVideoPlayer] IMA ad_error event received", {
|
|
2528
|
+
showAds: this.showAds,
|
|
2529
|
+
inAdBreak: this.inAdBreak,
|
|
2530
|
+
remainingAds: this.adPodQueue.length
|
|
2531
|
+
});
|
|
2455
2532
|
}
|
|
2456
|
-
if (this.
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2533
|
+
if (this.inAdBreak) {
|
|
2534
|
+
const remaining = this.getRemainingAdMs();
|
|
2535
|
+
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2536
|
+
const nextPreloaded = this.findNextPreloadedAd();
|
|
2537
|
+
if (nextPreloaded) {
|
|
2461
2538
|
this.currentAdIndex++;
|
|
2462
|
-
this.
|
|
2539
|
+
if (this.config.debugAdTiming) {
|
|
2540
|
+
console.log(
|
|
2541
|
+
`[StormcloudVideoPlayer] Skipping to next preloaded ad after error`
|
|
2542
|
+
);
|
|
2543
|
+
}
|
|
2544
|
+
this.playSingleAd(nextPreloaded).catch(() => {
|
|
2545
|
+
this.handleAdFailure();
|
|
2463
2546
|
});
|
|
2464
2547
|
} else {
|
|
2548
|
+
if (this.config.debugAdTiming) {
|
|
2549
|
+
console.log(
|
|
2550
|
+
"[StormcloudVideoPlayer] No preloaded ads available, ending ad break"
|
|
2551
|
+
);
|
|
2552
|
+
}
|
|
2465
2553
|
this.handleAdFailure();
|
|
2466
2554
|
}
|
|
2467
2555
|
} else {
|
|
2468
|
-
if (this.config.debugAdTiming) {
|
|
2469
|
-
console.log(
|
|
2470
|
-
"[StormcloudVideoPlayer] Ad error before ad break established - cleaning up"
|
|
2471
|
-
);
|
|
2472
|
-
}
|
|
2473
2556
|
this.handleAdFailure();
|
|
2474
2557
|
}
|
|
2558
|
+
} else {
|
|
2559
|
+
if (this.config.debugAdTiming) {
|
|
2560
|
+
console.log(
|
|
2561
|
+
"[StormcloudVideoPlayer] Ad error before ad break established - cleaning up"
|
|
2562
|
+
);
|
|
2563
|
+
}
|
|
2564
|
+
this.handleAdFailure();
|
|
2475
2565
|
}
|
|
2476
2566
|
});
|
|
2477
2567
|
this.ima.on("content_pause", () => {
|
|
@@ -2502,22 +2592,31 @@ var StormcloudVideoPlayer = class {
|
|
|
2502
2592
|
}
|
|
2503
2593
|
const remaining = this.getRemainingAdMs();
|
|
2504
2594
|
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2505
|
-
const
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
console.log(
|
|
2510
|
-
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak}) - IMMEDIATELY starting next ad`
|
|
2511
|
-
);
|
|
2512
|
-
}
|
|
2513
|
-
this.playSingleAd(next).catch(() => {
|
|
2595
|
+
const nextPreloaded = this.findNextPreloadedAd();
|
|
2596
|
+
if (nextPreloaded) {
|
|
2597
|
+
this.currentAdIndex++;
|
|
2598
|
+
this.enforceAdHoldState();
|
|
2514
2599
|
if (this.config.debugAdTiming) {
|
|
2515
|
-
console.
|
|
2516
|
-
|
|
2600
|
+
console.log(
|
|
2601
|
+
`[StormcloudVideoPlayer] Playing next preloaded ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak})`
|
|
2602
|
+
);
|
|
2603
|
+
}
|
|
2604
|
+
this.playSingleAd(nextPreloaded).catch(() => {
|
|
2605
|
+
if (this.config.debugAdTiming) {
|
|
2606
|
+
console.error(
|
|
2607
|
+
"[StormcloudVideoPlayer] Failed to play next ad in pod"
|
|
2608
|
+
);
|
|
2609
|
+
}
|
|
2610
|
+
this.handleAdPodComplete();
|
|
2611
|
+
});
|
|
2612
|
+
} else {
|
|
2613
|
+
if (this.config.debugAdTiming) {
|
|
2614
|
+
console.log(
|
|
2615
|
+
"[StormcloudVideoPlayer] No preloaded ads available - completing ad break"
|
|
2517
2616
|
);
|
|
2518
2617
|
}
|
|
2519
2618
|
this.handleAdPodComplete();
|
|
2520
|
-
}
|
|
2619
|
+
}
|
|
2521
2620
|
} else {
|
|
2522
2621
|
if (this.config.debugAdTiming) {
|
|
2523
2622
|
console.log(
|
|
@@ -2762,6 +2861,9 @@ var StormcloudVideoPlayer = class {
|
|
|
2762
2861
|
const first = tags[0];
|
|
2763
2862
|
const rest = tags.slice(1);
|
|
2764
2863
|
this.adPodQueue = rest;
|
|
2864
|
+
if (!this.showAds) {
|
|
2865
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
2866
|
+
}
|
|
2765
2867
|
this.playSingleAd(first).catch(() => {
|
|
2766
2868
|
});
|
|
2767
2869
|
}
|
|
@@ -3118,19 +3220,38 @@ var StormcloudVideoPlayer = class {
|
|
|
3118
3220
|
if (vastTagUrls.length > 0) {
|
|
3119
3221
|
this.adPodAllUrls = [...vastTagUrls];
|
|
3120
3222
|
this.preloadingAdUrls.clear();
|
|
3223
|
+
this.vastToMediaUrlMap.clear();
|
|
3224
|
+
this.preloadedMediaUrls.clear();
|
|
3225
|
+
this.preloadingMediaUrls.clear();
|
|
3121
3226
|
this.logQueuedAdUrls(this.adPodAllUrls);
|
|
3227
|
+
if (this.config.debugAdTiming) {
|
|
3228
|
+
console.log(
|
|
3229
|
+
`[StormcloudVideoPlayer] Capturing original audio state before ad break:`,
|
|
3230
|
+
{
|
|
3231
|
+
videoMuted: this.video.muted,
|
|
3232
|
+
videoVolume: this.video.volume
|
|
3233
|
+
}
|
|
3234
|
+
);
|
|
3235
|
+
}
|
|
3236
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3122
3237
|
this.inAdBreak = true;
|
|
3123
|
-
this.showAds = true;
|
|
3124
3238
|
this.currentAdIndex = 0;
|
|
3125
3239
|
this.totalAdsInBreak = vastTagUrls.length;
|
|
3126
3240
|
this.adPodQueue = [...vastTagUrls];
|
|
3127
3241
|
this.enforceAdHoldState();
|
|
3128
|
-
this.preloadUpcomingAds();
|
|
3129
3242
|
if (this.config.debugAdTiming) {
|
|
3130
3243
|
console.log(
|
|
3131
|
-
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads -
|
|
3244
|
+
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads - preloading all ads in parallel`
|
|
3132
3245
|
);
|
|
3133
3246
|
}
|
|
3247
|
+
this.preloadAllAdsInBackground().catch((error) => {
|
|
3248
|
+
if (this.config.debugAdTiming) {
|
|
3249
|
+
console.warn(
|
|
3250
|
+
"[StormcloudVideoPlayer] Error in background preloading:",
|
|
3251
|
+
error
|
|
3252
|
+
);
|
|
3253
|
+
}
|
|
3254
|
+
});
|
|
3134
3255
|
try {
|
|
3135
3256
|
await this.playAdPod();
|
|
3136
3257
|
} catch (error) {
|
|
@@ -3156,14 +3277,28 @@ var StormcloudVideoPlayer = class {
|
|
|
3156
3277
|
}
|
|
3157
3278
|
return;
|
|
3158
3279
|
}
|
|
3159
|
-
|
|
3280
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
3281
|
+
const firstPreloaded = this.findNextPreloadedAd();
|
|
3282
|
+
if (!firstPreloaded) {
|
|
3283
|
+
if (this.config.debugAdTiming) {
|
|
3284
|
+
console.log(
|
|
3285
|
+
"[StormcloudVideoPlayer] No preloaded ads available after waiting, trying first ad anyway"
|
|
3286
|
+
);
|
|
3287
|
+
}
|
|
3288
|
+
const firstAd = this.adPodQueue.shift();
|
|
3289
|
+
if (firstAd) {
|
|
3290
|
+
this.currentAdIndex++;
|
|
3291
|
+
await this.playSingleAd(firstAd);
|
|
3292
|
+
}
|
|
3293
|
+
return;
|
|
3294
|
+
}
|
|
3160
3295
|
this.currentAdIndex++;
|
|
3161
3296
|
if (this.config.debugAdTiming) {
|
|
3162
3297
|
console.log(
|
|
3163
|
-
`[StormcloudVideoPlayer] Playing ad ${this.currentAdIndex}/${this.totalAdsInBreak}`
|
|
3298
|
+
`[StormcloudVideoPlayer] Playing first preloaded ad ${this.currentAdIndex}/${this.totalAdsInBreak}`
|
|
3164
3299
|
);
|
|
3165
3300
|
}
|
|
3166
|
-
await this.playSingleAd(
|
|
3301
|
+
await this.playSingleAd(firstPreloaded);
|
|
3167
3302
|
}
|
|
3168
3303
|
findCurrentOrNextBreak(nowMs) {
|
|
3169
3304
|
var _a;
|
|
@@ -3196,6 +3331,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3196
3331
|
const first = tags[0];
|
|
3197
3332
|
const rest = tags.slice(1);
|
|
3198
3333
|
this.adPodQueue = rest;
|
|
3334
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3199
3335
|
this.enforceAdHoldState();
|
|
3200
3336
|
await this.playSingleAd(first);
|
|
3201
3337
|
this.inAdBreak = true;
|
|
@@ -3316,27 +3452,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3316
3452
|
`[StormcloudVideoPlayer] IMA SDK preloaded this ad already: ${vastTagUrl}`
|
|
3317
3453
|
);
|
|
3318
3454
|
}
|
|
3319
|
-
if (!this.showAds) {
|
|
3320
|
-
if (this.config.debugAdTiming) {
|
|
3321
|
-
console.log(
|
|
3322
|
-
`[StormcloudVideoPlayer] Capturing original state before ad request:`,
|
|
3323
|
-
{
|
|
3324
|
-
videoMuted: this.video.muted,
|
|
3325
|
-
videoVolume: this.video.volume,
|
|
3326
|
-
showAds: this.showAds
|
|
3327
|
-
}
|
|
3328
|
-
);
|
|
3329
|
-
}
|
|
3330
|
-
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3331
|
-
} else if (this.config.debugAdTiming) {
|
|
3332
|
-
console.log(
|
|
3333
|
-
`[StormcloudVideoPlayer] Keeping existing original mute state (currently showing ads)`
|
|
3334
|
-
);
|
|
3335
|
-
}
|
|
3336
3455
|
this.startAdFailsafeTimer();
|
|
3337
3456
|
try {
|
|
3338
3457
|
await this.ima.requestAds(vastTagUrl);
|
|
3339
|
-
this.preloadUpcomingAds();
|
|
3340
3458
|
try {
|
|
3341
3459
|
if (this.config.debugAdTiming) {
|
|
3342
3460
|
console.log(
|
|
@@ -3345,9 +3463,10 @@ var StormcloudVideoPlayer = class {
|
|
|
3345
3463
|
}
|
|
3346
3464
|
this.enforceAdHoldState();
|
|
3347
3465
|
await this.ima.play();
|
|
3466
|
+
this.showAds = true;
|
|
3348
3467
|
if (this.config.debugAdTiming) {
|
|
3349
3468
|
console.log(
|
|
3350
|
-
"[StormcloudVideoPlayer] Ad playback started successfully"
|
|
3469
|
+
"[StormcloudVideoPlayer] Ad playback started successfully, showAds = true"
|
|
3351
3470
|
);
|
|
3352
3471
|
}
|
|
3353
3472
|
} catch (playError) {
|
|
@@ -3375,6 +3494,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3375
3494
|
}
|
|
3376
3495
|
this.releaseAdHoldState();
|
|
3377
3496
|
this.preloadingAdUrls.clear();
|
|
3497
|
+
this.vastToMediaUrlMap.clear();
|
|
3498
|
+
this.preloadedMediaUrls.clear();
|
|
3499
|
+
this.preloadingMediaUrls.clear();
|
|
3378
3500
|
this.inAdBreak = false;
|
|
3379
3501
|
this.expectedAdBreakDurationMs = void 0;
|
|
3380
3502
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
@@ -3484,43 +3606,203 @@ var StormcloudVideoPlayer = class {
|
|
|
3484
3606
|
this.ima.hidePlaceholder();
|
|
3485
3607
|
}
|
|
3486
3608
|
}
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3609
|
+
async fetchAndParseVastXml(vastTagUrl) {
|
|
3610
|
+
try {
|
|
3611
|
+
const response = await fetch(vastTagUrl, { mode: "cors" });
|
|
3612
|
+
if (!response.ok) {
|
|
3613
|
+
throw new Error(`Failed to fetch VAST: ${response.status}`);
|
|
3614
|
+
}
|
|
3615
|
+
const xmlText = await response.text();
|
|
3616
|
+
return this.extractMediaUrlsFromVast(xmlText);
|
|
3617
|
+
} catch (error) {
|
|
3618
|
+
if (this.config.debugAdTiming) {
|
|
3619
|
+
console.warn(
|
|
3620
|
+
`[StormcloudVideoPlayer] Failed to fetch/parse VAST XML: ${vastTagUrl}`,
|
|
3621
|
+
error
|
|
3622
|
+
);
|
|
3623
|
+
}
|
|
3624
|
+
return [];
|
|
3490
3625
|
}
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3626
|
+
}
|
|
3627
|
+
extractMediaUrlsFromVast(xmlText) {
|
|
3628
|
+
var _a;
|
|
3629
|
+
const mediaUrls = [];
|
|
3630
|
+
try {
|
|
3631
|
+
const parser = new DOMParser();
|
|
3632
|
+
const xmlDoc = parser.parseFromString(xmlText, "text/xml");
|
|
3633
|
+
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
3634
|
+
for (const mediaFile of Array.from(mediaFileElements)) {
|
|
3635
|
+
const url = (_a = mediaFile.textContent) == null ? void 0 : _a.trim();
|
|
3636
|
+
if (url) {
|
|
3637
|
+
const lowerUrl = url.toLowerCase();
|
|
3638
|
+
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")) {
|
|
3639
|
+
mediaUrls.push(url);
|
|
3640
|
+
}
|
|
3641
|
+
}
|
|
3642
|
+
}
|
|
3643
|
+
if (this.config.debugAdTiming && mediaUrls.length > 0) {
|
|
3644
|
+
console.log(
|
|
3645
|
+
`[StormcloudVideoPlayer] Extracted ${mediaUrls.length} media URLs from VAST:`,
|
|
3646
|
+
mediaUrls
|
|
3647
|
+
);
|
|
3497
3648
|
}
|
|
3498
|
-
|
|
3499
|
-
|
|
3649
|
+
} catch (error) {
|
|
3650
|
+
if (this.config.debugAdTiming) {
|
|
3651
|
+
console.warn(
|
|
3652
|
+
"[StormcloudVideoPlayer] Failed to parse VAST XML:",
|
|
3653
|
+
error
|
|
3654
|
+
);
|
|
3500
3655
|
}
|
|
3656
|
+
}
|
|
3657
|
+
return mediaUrls;
|
|
3658
|
+
}
|
|
3659
|
+
async preloadMediaFile(mediaUrl) {
|
|
3660
|
+
if (this.preloadedMediaUrls.has(mediaUrl)) {
|
|
3661
|
+
return;
|
|
3662
|
+
}
|
|
3663
|
+
if (this.preloadingMediaUrls.has(mediaUrl)) {
|
|
3664
|
+
return;
|
|
3665
|
+
}
|
|
3666
|
+
this.preloadingMediaUrls.add(mediaUrl);
|
|
3667
|
+
try {
|
|
3501
3668
|
if (this.config.debugAdTiming) {
|
|
3502
3669
|
console.log(
|
|
3503
|
-
`[StormcloudVideoPlayer]
|
|
3670
|
+
`[StormcloudVideoPlayer] Preloading video file: ${mediaUrl}`
|
|
3504
3671
|
);
|
|
3505
3672
|
}
|
|
3506
|
-
|
|
3507
|
-
|
|
3673
|
+
const response = await fetch(mediaUrl, {
|
|
3674
|
+
mode: "cors",
|
|
3675
|
+
method: "GET",
|
|
3676
|
+
headers: {
|
|
3677
|
+
Range: "bytes=0-1048576"
|
|
3678
|
+
}
|
|
3679
|
+
});
|
|
3680
|
+
if (response.ok || response.status === 206) {
|
|
3681
|
+
this.preloadedMediaUrls.add(mediaUrl);
|
|
3508
3682
|
if (this.config.debugAdTiming) {
|
|
3509
3683
|
console.log(
|
|
3510
|
-
`[StormcloudVideoPlayer]
|
|
3684
|
+
`[StormcloudVideoPlayer] Successfully preloaded video file: ${mediaUrl}`
|
|
3511
3685
|
);
|
|
3512
3686
|
}
|
|
3513
|
-
}
|
|
3687
|
+
}
|
|
3688
|
+
} catch (error) {
|
|
3689
|
+
if (this.config.debugAdTiming) {
|
|
3690
|
+
console.warn(
|
|
3691
|
+
`[StormcloudVideoPlayer] Failed to preload video file: ${mediaUrl}`,
|
|
3692
|
+
error
|
|
3693
|
+
);
|
|
3694
|
+
}
|
|
3695
|
+
} finally {
|
|
3696
|
+
this.preloadingMediaUrls.delete(mediaUrl);
|
|
3697
|
+
}
|
|
3698
|
+
}
|
|
3699
|
+
async preloadAllAdsInBackground() {
|
|
3700
|
+
if (this.adPodAllUrls.length === 0) {
|
|
3701
|
+
return;
|
|
3702
|
+
}
|
|
3703
|
+
if (this.config.debugAdTiming) {
|
|
3704
|
+
console.log(
|
|
3705
|
+
`[StormcloudVideoPlayer] Starting parallel preload of ${this.adPodAllUrls.length} ads`
|
|
3706
|
+
);
|
|
3707
|
+
}
|
|
3708
|
+
const preloadPromises = this.adPodAllUrls.map(
|
|
3709
|
+
(vastTagUrl) => this.preloadSingleAd(vastTagUrl).catch((error) => {
|
|
3514
3710
|
if (this.config.debugAdTiming) {
|
|
3515
3711
|
console.warn(
|
|
3516
|
-
`[StormcloudVideoPlayer]
|
|
3712
|
+
`[StormcloudVideoPlayer] Preload failed for ${vastTagUrl}:`,
|
|
3517
3713
|
error
|
|
3518
3714
|
);
|
|
3519
3715
|
}
|
|
3520
|
-
})
|
|
3521
|
-
|
|
3522
|
-
|
|
3716
|
+
})
|
|
3717
|
+
);
|
|
3718
|
+
await Promise.all(preloadPromises);
|
|
3719
|
+
if (this.config.debugAdTiming) {
|
|
3720
|
+
console.log(
|
|
3721
|
+
`[StormcloudVideoPlayer] Background preloading completed for all ads`
|
|
3722
|
+
);
|
|
3723
|
+
}
|
|
3724
|
+
}
|
|
3725
|
+
async preloadSingleAd(vastTagUrl) {
|
|
3726
|
+
if (!vastTagUrl) return;
|
|
3727
|
+
try {
|
|
3728
|
+
if (this.ima.preloadAds && !this.ima.hasPreloadedAd(vastTagUrl)) {
|
|
3729
|
+
if (!this.preloadingAdUrls.has(vastTagUrl)) {
|
|
3730
|
+
if (this.config.debugAdTiming) {
|
|
3731
|
+
console.log(
|
|
3732
|
+
`[StormcloudVideoPlayer] Preloading VAST: ${vastTagUrl}`
|
|
3733
|
+
);
|
|
3734
|
+
}
|
|
3735
|
+
this.preloadingAdUrls.add(vastTagUrl);
|
|
3736
|
+
await this.ima.preloadAds(vastTagUrl).then(() => {
|
|
3737
|
+
if (this.config.debugAdTiming) {
|
|
3738
|
+
console.log(
|
|
3739
|
+
`[StormcloudVideoPlayer] IMA VAST preload complete: ${vastTagUrl}`
|
|
3740
|
+
);
|
|
3741
|
+
}
|
|
3742
|
+
}).catch((error) => {
|
|
3743
|
+
if (this.config.debugAdTiming) {
|
|
3744
|
+
console.warn(
|
|
3745
|
+
`[StormcloudVideoPlayer] IMA VAST preload failed: ${vastTagUrl}`,
|
|
3746
|
+
error
|
|
3747
|
+
);
|
|
3748
|
+
}
|
|
3749
|
+
}).finally(() => {
|
|
3750
|
+
this.preloadingAdUrls.delete(vastTagUrl);
|
|
3751
|
+
});
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3754
|
+
let mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);
|
|
3755
|
+
if (!mediaUrls) {
|
|
3756
|
+
if (this.config.debugAdTiming) {
|
|
3757
|
+
console.log(
|
|
3758
|
+
`[StormcloudVideoPlayer] Fetching and parsing VAST to extract media URLs: ${vastTagUrl}`
|
|
3759
|
+
);
|
|
3760
|
+
}
|
|
3761
|
+
mediaUrls = await this.fetchAndParseVastXml(vastTagUrl);
|
|
3762
|
+
if (mediaUrls.length > 0) {
|
|
3763
|
+
this.vastToMediaUrlMap.set(vastTagUrl, mediaUrls);
|
|
3764
|
+
}
|
|
3765
|
+
}
|
|
3766
|
+
if (mediaUrls && mediaUrls.length > 0) {
|
|
3767
|
+
const primaryMediaUrl = mediaUrls[0];
|
|
3768
|
+
if (primaryMediaUrl && !this.preloadedMediaUrls.has(primaryMediaUrl)) {
|
|
3769
|
+
await this.preloadMediaFile(primaryMediaUrl);
|
|
3770
|
+
}
|
|
3771
|
+
}
|
|
3772
|
+
} catch (error) {
|
|
3773
|
+
if (this.config.debugAdTiming) {
|
|
3774
|
+
console.warn(
|
|
3775
|
+
`[StormcloudVideoPlayer] Failed to preload ad: ${vastTagUrl}`,
|
|
3776
|
+
error
|
|
3777
|
+
);
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
3780
|
+
}
|
|
3781
|
+
findNextPreloadedAd() {
|
|
3782
|
+
var _a, _b, _c;
|
|
3783
|
+
for (let i = 0; i < this.adPodQueue.length; i++) {
|
|
3784
|
+
const vastTagUrl = this.adPodQueue[i];
|
|
3785
|
+
if (!vastTagUrl) continue;
|
|
3786
|
+
const hasImaPreload = (_c = (_b = (_a = this.ima).hasPreloadedAd) == null ? void 0 : _b.call(_a, vastTagUrl)) != null ? _c : false;
|
|
3787
|
+
const mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);
|
|
3788
|
+
const hasMediaPreload = mediaUrls && mediaUrls.length > 0 ? this.preloadedMediaUrls.has(mediaUrls[0]) : false;
|
|
3789
|
+
if (hasImaPreload || hasMediaPreload) {
|
|
3790
|
+
if (this.config.debugAdTiming) {
|
|
3791
|
+
console.log(
|
|
3792
|
+
`[StormcloudVideoPlayer] Found preloaded ad at index ${i}: ${vastTagUrl}`,
|
|
3793
|
+
{ hasImaPreload, hasMediaPreload }
|
|
3794
|
+
);
|
|
3795
|
+
}
|
|
3796
|
+
this.adPodQueue.splice(0, i + 1);
|
|
3797
|
+
return vastTagUrl;
|
|
3798
|
+
}
|
|
3523
3799
|
}
|
|
3800
|
+
if (this.config.debugAdTiming) {
|
|
3801
|
+
console.log(
|
|
3802
|
+
"[StormcloudVideoPlayer] No preloaded ads found in queue"
|
|
3803
|
+
);
|
|
3804
|
+
}
|
|
3805
|
+
return void 0;
|
|
3524
3806
|
}
|
|
3525
3807
|
getRemainingAdMs() {
|
|
3526
3808
|
if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)
|
|
@@ -3690,6 +3972,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3690
3972
|
(_b = this.ima) == null ? void 0 : _b.destroy();
|
|
3691
3973
|
this.releaseAdHoldState();
|
|
3692
3974
|
this.preloadingAdUrls.clear();
|
|
3975
|
+
this.vastToMediaUrlMap.clear();
|
|
3976
|
+
this.preloadedMediaUrls.clear();
|
|
3977
|
+
this.preloadingMediaUrls.clear();
|
|
3693
3978
|
this.adPodAllUrls = [];
|
|
3694
3979
|
}
|
|
3695
3980
|
};
|