stormcloud-video-player 0.2.13 → 0.2.15
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/README.md +92 -11
- package/dist/stormcloud-vp.min.js +2 -2
- package/lib/index.cjs +288 -133
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +2 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +288 -133
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +237 -106
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/players/FilePlayer.cjs +14 -7
- package/lib/players/FilePlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.cjs +245 -111
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +259 -118
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +115 -23
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.d.cts +2 -0
- package/lib/sdk/ima.cjs +34 -24
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +253 -113
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/utils/browserCompat.cjs +2 -1
- package/lib/utils/browserCompat.cjs.map +1 -1
- package/lib/utils/tracking.cjs +10 -9
- package/lib/utils/tracking.cjs.map +1 -1
- package/package.json +1 -1
package/lib/players/index.cjs
CHANGED
|
@@ -87,7 +87,8 @@ function getWebKitVersion(ua) {
|
|
|
87
87
|
return match && match[1] ? parseInt(match[1], 10) : 0;
|
|
88
88
|
}
|
|
89
89
|
function getPlatform() {
|
|
90
|
-
|
|
90
|
+
var _a;
|
|
91
|
+
if ("userAgentData" in navigator && ((_a = navigator.userAgentData) == null ? void 0 : _a.platform)) {
|
|
91
92
|
return navigator.userAgentData.platform;
|
|
92
93
|
}
|
|
93
94
|
const ua = navigator.userAgent;
|
|
@@ -252,6 +253,7 @@ function createImaController(video, options) {
|
|
|
252
253
|
}
|
|
253
254
|
}
|
|
254
255
|
function ensureImaLoaded() {
|
|
256
|
+
var _a, _b, _c;
|
|
255
257
|
if (!supportsGoogleIMA()) {
|
|
256
258
|
console.warn(
|
|
257
259
|
"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead."
|
|
@@ -262,7 +264,7 @@ function createImaController(video, options) {
|
|
|
262
264
|
}
|
|
263
265
|
try {
|
|
264
266
|
const frameEl = window.frameElement;
|
|
265
|
-
const sandboxAttr = frameEl
|
|
267
|
+
const sandboxAttr = ((_a = frameEl == null ? void 0 : frameEl.getAttribute) == null ? void 0 : _a.call(frameEl, "sandbox")) || "";
|
|
266
268
|
if (sandboxAttr) {
|
|
267
269
|
const tokens = new Set(
|
|
268
270
|
sandboxAttr.split(/\s+/).map((t) => t.trim()).filter((t) => t.length > 0)
|
|
@@ -276,13 +278,13 @@ function createImaController(video, options) {
|
|
|
276
278
|
}
|
|
277
279
|
} catch {
|
|
278
280
|
}
|
|
279
|
-
if (typeof window !== "undefined" && window.google
|
|
281
|
+
if (typeof window !== "undefined" && ((_b = window.google) == null ? void 0 : _b.ima))
|
|
280
282
|
return Promise.resolve();
|
|
281
283
|
const existing = document.querySelector(
|
|
282
284
|
'script[data-ima="true"]'
|
|
283
285
|
);
|
|
284
286
|
if (existing) {
|
|
285
|
-
if (window.google
|
|
287
|
+
if ((_c = window.google) == null ? void 0 : _c.ima) {
|
|
286
288
|
return Promise.resolve();
|
|
287
289
|
}
|
|
288
290
|
return new Promise((resolve, reject) => {
|
|
@@ -340,6 +342,7 @@ function createImaController(video, options) {
|
|
|
340
342
|
return {
|
|
341
343
|
initialize() {
|
|
342
344
|
ensureImaLoaded().then(() => {
|
|
345
|
+
var _a, _b;
|
|
343
346
|
const google = window.google;
|
|
344
347
|
if (!adDisplayContainer) {
|
|
345
348
|
const container = document.createElement("div");
|
|
@@ -353,14 +356,14 @@ function createImaController(video, options) {
|
|
|
353
356
|
container.style.justifyContent = "center";
|
|
354
357
|
container.style.pointerEvents = "none";
|
|
355
358
|
container.style.zIndex = "2";
|
|
356
|
-
video.parentElement
|
|
359
|
+
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
357
360
|
adContainerEl = container;
|
|
358
361
|
adDisplayContainer = new google.ima.AdDisplayContainer(
|
|
359
362
|
container,
|
|
360
363
|
video
|
|
361
364
|
);
|
|
362
365
|
try {
|
|
363
|
-
adDisplayContainer.initialize
|
|
366
|
+
(_b = adDisplayContainer.initialize) == null ? void 0 : _b.call(adDisplayContainer);
|
|
364
367
|
} catch {
|
|
365
368
|
}
|
|
366
369
|
}
|
|
@@ -445,6 +448,7 @@ function createImaController(video, options) {
|
|
|
445
448
|
adsManager.addEventListener(
|
|
446
449
|
AdErrorEvent.AD_ERROR,
|
|
447
450
|
(errorEvent) => {
|
|
451
|
+
var _a;
|
|
448
452
|
console.error("[IMA] Ad error:", errorEvent.getError());
|
|
449
453
|
destroyAdsManager();
|
|
450
454
|
adPlaying = false;
|
|
@@ -475,10 +479,10 @@ function createImaController(video, options) {
|
|
|
475
479
|
"[IMA] Max retries reached, emitting ad_error"
|
|
476
480
|
);
|
|
477
481
|
emit("ad_error");
|
|
478
|
-
if (!options
|
|
482
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
479
483
|
if (video.paused) {
|
|
480
484
|
console.log("[IMA] Resuming paused video after ad error");
|
|
481
|
-
video.play()
|
|
485
|
+
(_a = video.play()) == null ? void 0 : _a.catch(() => {
|
|
482
486
|
});
|
|
483
487
|
}
|
|
484
488
|
}
|
|
@@ -489,7 +493,7 @@ function createImaController(video, options) {
|
|
|
489
493
|
AdEvent.CONTENT_PAUSE_REQUESTED,
|
|
490
494
|
() => {
|
|
491
495
|
console.log("[IMA] Content pause requested");
|
|
492
|
-
if (!options
|
|
496
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
493
497
|
video.pause();
|
|
494
498
|
console.log("[IMA] Video paused (VOD mode)");
|
|
495
499
|
} else {
|
|
@@ -515,6 +519,7 @@ function createImaController(video, options) {
|
|
|
515
519
|
adsManager.addEventListener(
|
|
516
520
|
AdEvent.CONTENT_RESUME_REQUESTED,
|
|
517
521
|
() => {
|
|
522
|
+
var _a;
|
|
518
523
|
console.log("[IMA] Content resume requested");
|
|
519
524
|
adPlaying = false;
|
|
520
525
|
video.muted = originalMutedState;
|
|
@@ -525,8 +530,8 @@ function createImaController(video, options) {
|
|
|
525
530
|
"[IMA] Ad container hidden - pointer events disabled"
|
|
526
531
|
);
|
|
527
532
|
}
|
|
528
|
-
if (!options
|
|
529
|
-
video.play()
|
|
533
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
534
|
+
(_a = video.play()) == null ? void 0 : _a.catch(() => {
|
|
530
535
|
});
|
|
531
536
|
console.log("[IMA] Video resumed (VOD mode)");
|
|
532
537
|
} else {
|
|
@@ -548,7 +553,7 @@ function createImaController(video, options) {
|
|
|
548
553
|
"[IMA] Ad container hidden after all ads completed"
|
|
549
554
|
);
|
|
550
555
|
}
|
|
551
|
-
if (!options
|
|
556
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
552
557
|
video.play().catch(() => {
|
|
553
558
|
});
|
|
554
559
|
console.log(
|
|
@@ -576,7 +581,7 @@ function createImaController(video, options) {
|
|
|
576
581
|
adContainerEl.style.display = "none";
|
|
577
582
|
console.log("[IMA] Ad container hidden after setup error");
|
|
578
583
|
}
|
|
579
|
-
if (!options
|
|
584
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
580
585
|
if (video.paused) {
|
|
581
586
|
console.log("[IMA] Resuming paused video after setup error");
|
|
582
587
|
video.play().catch(() => {
|
|
@@ -604,7 +609,7 @@ function createImaController(video, options) {
|
|
|
604
609
|
adContainerEl.style.display = "none";
|
|
605
610
|
console.log("[IMA] Ad container hidden after loader error");
|
|
606
611
|
}
|
|
607
|
-
if (!options
|
|
612
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
608
613
|
if (video.paused) {
|
|
609
614
|
console.log("[IMA] Resuming paused video after loader error");
|
|
610
615
|
video.play().catch(() => {
|
|
@@ -626,14 +631,15 @@ function createImaController(video, options) {
|
|
|
626
631
|
return adsLoadedPromise;
|
|
627
632
|
} catch (error) {
|
|
628
633
|
console.error("[IMA] Failed to request ads:", error);
|
|
629
|
-
currentReject
|
|
634
|
+
currentReject == null ? void 0 : currentReject(error);
|
|
630
635
|
adsLoadedReject = void 0;
|
|
631
636
|
adsLoadedResolve = void 0;
|
|
632
637
|
return Promise.reject(error);
|
|
633
638
|
}
|
|
634
639
|
},
|
|
635
640
|
async play() {
|
|
636
|
-
|
|
641
|
+
var _a, _b;
|
|
642
|
+
if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
|
|
637
643
|
console.warn(
|
|
638
644
|
"[IMA] Cannot play ad: IMA SDK or ad container not available"
|
|
639
645
|
);
|
|
@@ -655,14 +661,15 @@ function createImaController(video, options) {
|
|
|
655
661
|
} catch (error) {
|
|
656
662
|
console.error("[IMA] Error starting ad playback:", error);
|
|
657
663
|
adPlaying = false;
|
|
658
|
-
if (!options
|
|
659
|
-
video.play()
|
|
664
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
665
|
+
(_b = video.play()) == null ? void 0 : _b.catch(() => {
|
|
660
666
|
});
|
|
661
667
|
}
|
|
662
668
|
return Promise.reject(error);
|
|
663
669
|
}
|
|
664
670
|
},
|
|
665
671
|
async stop() {
|
|
672
|
+
var _a;
|
|
666
673
|
adPlaying = false;
|
|
667
674
|
video.muted = originalMutedState;
|
|
668
675
|
if (adContainerEl) {
|
|
@@ -671,11 +678,11 @@ function createImaController(video, options) {
|
|
|
671
678
|
console.log("[IMA] Ad container hidden after stop");
|
|
672
679
|
}
|
|
673
680
|
try {
|
|
674
|
-
adsManager
|
|
681
|
+
(_a = adsManager == null ? void 0 : adsManager.stop) == null ? void 0 : _a.call(adsManager);
|
|
675
682
|
} catch {
|
|
676
683
|
}
|
|
677
684
|
destroyAdsManager();
|
|
678
|
-
if (!options
|
|
685
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
679
686
|
video.play().catch(() => {
|
|
680
687
|
});
|
|
681
688
|
console.log("[IMA] Video resumed after stop (VOD mode)");
|
|
@@ -684,6 +691,7 @@ function createImaController(video, options) {
|
|
|
684
691
|
}
|
|
685
692
|
},
|
|
686
693
|
destroy() {
|
|
694
|
+
var _a;
|
|
687
695
|
destroyAdsManager();
|
|
688
696
|
adPlaying = false;
|
|
689
697
|
video.muted = originalMutedState;
|
|
@@ -692,10 +700,10 @@ function createImaController(video, options) {
|
|
|
692
700
|
adContainerEl.style.display = "none";
|
|
693
701
|
}
|
|
694
702
|
try {
|
|
695
|
-
adsLoader
|
|
703
|
+
(_a = adsLoader == null ? void 0 : adsLoader.destroy) == null ? void 0 : _a.call(adsLoader);
|
|
696
704
|
} catch {
|
|
697
705
|
}
|
|
698
|
-
if (adContainerEl
|
|
706
|
+
if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
|
|
699
707
|
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
700
708
|
}
|
|
701
709
|
adContainerEl = void 0;
|
|
@@ -706,7 +714,8 @@ function createImaController(video, options) {
|
|
|
706
714
|
return adPlaying;
|
|
707
715
|
},
|
|
708
716
|
resize(width, height) {
|
|
709
|
-
|
|
717
|
+
var _a;
|
|
718
|
+
if (!adsManager || !((_a = window.google) == null ? void 0 : _a.ima)) {
|
|
710
719
|
console.warn(
|
|
711
720
|
"[IMA] Cannot resize: No ads manager or IMA SDK available"
|
|
712
721
|
);
|
|
@@ -724,7 +733,8 @@ function createImaController(video, options) {
|
|
|
724
733
|
listeners.get(event).add(listener);
|
|
725
734
|
},
|
|
726
735
|
off(event, listener) {
|
|
727
|
-
|
|
736
|
+
var _a;
|
|
737
|
+
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
728
738
|
},
|
|
729
739
|
updateOriginalMutedState(muted) {
|
|
730
740
|
originalMutedState = muted;
|
|
@@ -761,7 +771,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
761
771
|
let adPlaying = false;
|
|
762
772
|
let originalMutedState = false;
|
|
763
773
|
const listeners = /* @__PURE__ */ new Map();
|
|
764
|
-
const licenseKey = options
|
|
774
|
+
const licenseKey = options == null ? void 0 : options.licenseKey;
|
|
775
|
+
const mainHlsInstance = options == null ? void 0 : options.mainHlsInstance;
|
|
765
776
|
let adVideoElement;
|
|
766
777
|
let adHls;
|
|
767
778
|
let adContainerEl;
|
|
@@ -808,13 +819,80 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
808
819
|
}
|
|
809
820
|
});
|
|
810
821
|
}
|
|
822
|
+
function getMainStreamQuality() {
|
|
823
|
+
if (!mainHlsInstance || !mainHlsInstance.levels) {
|
|
824
|
+
return null;
|
|
825
|
+
}
|
|
826
|
+
const currentLevel = mainHlsInstance.currentLevel;
|
|
827
|
+
if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {
|
|
828
|
+
const autoLevel = mainHlsInstance.loadLevel;
|
|
829
|
+
if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {
|
|
830
|
+
const level2 = mainHlsInstance.levels[autoLevel];
|
|
831
|
+
return {
|
|
832
|
+
width: level2.width || 1920,
|
|
833
|
+
height: level2.height || 1080,
|
|
834
|
+
bitrate: level2.bitrate || 5e6
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
return null;
|
|
838
|
+
}
|
|
839
|
+
const level = mainHlsInstance.levels[currentLevel];
|
|
840
|
+
return {
|
|
841
|
+
width: level.width || 1920,
|
|
842
|
+
height: level.height || 1080,
|
|
843
|
+
bitrate: level.bitrate || 5e6
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
function selectBestMediaFile(mediaFiles) {
|
|
847
|
+
if (mediaFiles.length === 0) {
|
|
848
|
+
throw new Error("No media files available");
|
|
849
|
+
}
|
|
850
|
+
const firstFile = mediaFiles[0];
|
|
851
|
+
if (!firstFile) {
|
|
852
|
+
throw new Error("No media files available");
|
|
853
|
+
}
|
|
854
|
+
if (mediaFiles.length === 1) {
|
|
855
|
+
return firstFile;
|
|
856
|
+
}
|
|
857
|
+
const mainQuality = getMainStreamQuality();
|
|
858
|
+
if (!mainQuality) {
|
|
859
|
+
console.log("[HlsAdPlayer] No main stream quality info, using first media file");
|
|
860
|
+
return firstFile;
|
|
861
|
+
}
|
|
862
|
+
console.log("[HlsAdPlayer] Main stream quality:", mainQuality);
|
|
863
|
+
const scoredFiles = mediaFiles.map((file) => {
|
|
864
|
+
const widthDiff = Math.abs(file.width - mainQuality.width);
|
|
865
|
+
const heightDiff = Math.abs(file.height - mainQuality.height);
|
|
866
|
+
const resolutionDiff = widthDiff + heightDiff;
|
|
867
|
+
const fileBitrate = (file.bitrate || 5e3) * 1e3;
|
|
868
|
+
const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);
|
|
869
|
+
const score = resolutionDiff * 2 + bitrateDiff / 1e3;
|
|
870
|
+
return { file, score, resolutionDiff, bitrateDiff };
|
|
871
|
+
});
|
|
872
|
+
scoredFiles.sort((a, b) => a.score - b.score);
|
|
873
|
+
const bestMatch = scoredFiles[0];
|
|
874
|
+
if (!bestMatch) {
|
|
875
|
+
console.log("[HlsAdPlayer] No best match found, using first media file");
|
|
876
|
+
return firstFile;
|
|
877
|
+
}
|
|
878
|
+
console.log("[HlsAdPlayer] Selected media file:", {
|
|
879
|
+
url: bestMatch.file.url,
|
|
880
|
+
resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,
|
|
881
|
+
bitrate: bestMatch.file.bitrate,
|
|
882
|
+
score: bestMatch.score,
|
|
883
|
+
resolutionDiff: bestMatch.resolutionDiff,
|
|
884
|
+
bitrateDiff: bestMatch.bitrateDiff
|
|
885
|
+
});
|
|
886
|
+
return bestMatch.file;
|
|
887
|
+
}
|
|
811
888
|
function parseVastXml(xmlString) {
|
|
889
|
+
var _a, _b, _c, _d;
|
|
812
890
|
try {
|
|
813
891
|
const parser = new DOMParser();
|
|
814
892
|
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
|
|
815
893
|
const parserError = xmlDoc.querySelector("parsererror");
|
|
816
894
|
if (parserError) {
|
|
817
|
-
console.error("[HlsAdPlayer] XML parsing error:", parserError.textContent);
|
|
895
|
+
console.error("[HlsAdPlayer] XML parsing error (malformed VAST XML):", parserError.textContent);
|
|
818
896
|
return null;
|
|
819
897
|
}
|
|
820
898
|
const adElement = xmlDoc.querySelector("Ad");
|
|
@@ -823,28 +901,46 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
823
901
|
return null;
|
|
824
902
|
}
|
|
825
903
|
const adId = adElement.getAttribute("id") || "unknown";
|
|
826
|
-
const title = xmlDoc.querySelector("AdTitle")
|
|
827
|
-
const
|
|
904
|
+
const title = ((_a = xmlDoc.querySelector("AdTitle")) == null ? void 0 : _a.textContent) || "Ad";
|
|
905
|
+
const isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
|
|
906
|
+
const durationText = ((_b = xmlDoc.querySelector("Duration")) == null ? void 0 : _b.textContent) || "00:00:30";
|
|
828
907
|
const durationParts = durationText.split(":");
|
|
829
908
|
const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
|
|
830
909
|
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
831
910
|
const mediaFiles = [];
|
|
832
|
-
mediaFileElements.
|
|
911
|
+
console.log(`[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`);
|
|
912
|
+
mediaFileElements.forEach((mf, index) => {
|
|
913
|
+
var _a2;
|
|
833
914
|
const type = mf.getAttribute("type") || "";
|
|
915
|
+
const url = ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "";
|
|
916
|
+
const width = mf.getAttribute("width") || "";
|
|
917
|
+
const height = mf.getAttribute("height") || "";
|
|
918
|
+
console.log(`[HlsAdPlayer] MediaFile ${index}: type="${type}", url="${url}", width="${width}", height="${height}"`);
|
|
834
919
|
if (type === "application/x-mpegURL" || type.includes("m3u8")) {
|
|
920
|
+
if (!url) {
|
|
921
|
+
console.warn(`[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`);
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
835
924
|
const bitrateAttr = mf.getAttribute("bitrate");
|
|
836
925
|
const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
|
|
837
926
|
mediaFiles.push({
|
|
838
|
-
url
|
|
927
|
+
url,
|
|
839
928
|
type,
|
|
840
|
-
width: parseInt(
|
|
841
|
-
height: parseInt(
|
|
929
|
+
width: parseInt(width || "1920", 10),
|
|
930
|
+
height: parseInt(height || "1080", 10),
|
|
842
931
|
bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
|
|
843
932
|
});
|
|
933
|
+
console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);
|
|
934
|
+
} else {
|
|
935
|
+
console.log(`[HlsAdPlayer] MediaFile ${index} ignored (type="${type}" is not HLS)`);
|
|
844
936
|
}
|
|
845
937
|
});
|
|
846
938
|
if (mediaFiles.length === 0) {
|
|
847
|
-
|
|
939
|
+
if (isNoAdAvailable) {
|
|
940
|
+
console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
|
|
941
|
+
} else {
|
|
942
|
+
console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
|
|
943
|
+
}
|
|
848
944
|
return null;
|
|
849
945
|
}
|
|
850
946
|
const trackingUrls = {
|
|
@@ -864,12 +960,14 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
864
960
|
error: []
|
|
865
961
|
};
|
|
866
962
|
xmlDoc.querySelectorAll("Impression").forEach((el) => {
|
|
867
|
-
|
|
963
|
+
var _a2;
|
|
964
|
+
const url = (_a2 = el.textContent) == null ? void 0 : _a2.trim();
|
|
868
965
|
if (url) trackingUrls.impression.push(url);
|
|
869
966
|
});
|
|
870
967
|
xmlDoc.querySelectorAll("Tracking").forEach((el) => {
|
|
968
|
+
var _a2;
|
|
871
969
|
const event = el.getAttribute("event");
|
|
872
|
-
const url = el.textContent
|
|
970
|
+
const url = (_a2 = el.textContent) == null ? void 0 : _a2.trim();
|
|
873
971
|
if (event && url) {
|
|
874
972
|
const eventKey = event;
|
|
875
973
|
if (trackingUrls[eventKey]) {
|
|
@@ -877,7 +975,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
877
975
|
}
|
|
878
976
|
}
|
|
879
977
|
});
|
|
880
|
-
const clickThrough = xmlDoc.querySelector("ClickThrough")
|
|
978
|
+
const clickThrough = (_d = (_c = xmlDoc.querySelector("ClickThrough")) == null ? void 0 : _c.textContent) == null ? void 0 : _d.trim();
|
|
881
979
|
return {
|
|
882
980
|
id: adId,
|
|
883
981
|
title,
|
|
@@ -969,7 +1067,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
969
1067
|
adContainerEl.style.display = "none";
|
|
970
1068
|
adContainerEl.style.pointerEvents = "none";
|
|
971
1069
|
}
|
|
972
|
-
if (!options
|
|
1070
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
973
1071
|
contentVideo.play().catch(() => {
|
|
974
1072
|
});
|
|
975
1073
|
console.log("[HlsAdPlayer] Content resumed (VOD mode)");
|
|
@@ -987,7 +1085,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
987
1085
|
adContainerEl.style.display = "none";
|
|
988
1086
|
adContainerEl.style.pointerEvents = "none";
|
|
989
1087
|
}
|
|
990
|
-
if (!options
|
|
1088
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
991
1089
|
if (contentVideo.paused) {
|
|
992
1090
|
contentVideo.play().catch(() => {
|
|
993
1091
|
});
|
|
@@ -997,6 +1095,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
997
1095
|
}
|
|
998
1096
|
return {
|
|
999
1097
|
initialize() {
|
|
1098
|
+
var _a;
|
|
1000
1099
|
console.log("[HlsAdPlayer] Initializing");
|
|
1001
1100
|
if (!adContainerEl) {
|
|
1002
1101
|
const container = document.createElement("div");
|
|
@@ -1011,7 +1110,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1011
1110
|
container.style.pointerEvents = "none";
|
|
1012
1111
|
container.style.zIndex = "2";
|
|
1013
1112
|
container.style.backgroundColor = "#000";
|
|
1014
|
-
contentVideo.parentElement
|
|
1113
|
+
(_a = contentVideo.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
1015
1114
|
adContainerEl = container;
|
|
1016
1115
|
}
|
|
1017
1116
|
},
|
|
@@ -1029,9 +1128,11 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1029
1128
|
}
|
|
1030
1129
|
const vastXml = await response.text();
|
|
1031
1130
|
console.log("[HlsAdPlayer] VAST XML received");
|
|
1131
|
+
console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
|
|
1032
1132
|
const ad = parseVastXml(vastXml);
|
|
1033
1133
|
if (!ad) {
|
|
1034
|
-
|
|
1134
|
+
console.warn("[HlsAdPlayer] No ads available from VAST response");
|
|
1135
|
+
return Promise.resolve();
|
|
1035
1136
|
}
|
|
1036
1137
|
currentAd = ad;
|
|
1037
1138
|
console.log(`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`);
|
|
@@ -1046,14 +1147,14 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1046
1147
|
},
|
|
1047
1148
|
async play() {
|
|
1048
1149
|
if (!currentAd) {
|
|
1049
|
-
console.warn("[HlsAdPlayer] Cannot play: No ad loaded");
|
|
1150
|
+
console.warn("[HlsAdPlayer] Cannot play: No ad loaded (no ads available)");
|
|
1050
1151
|
return Promise.reject(new Error("No ad loaded"));
|
|
1051
1152
|
}
|
|
1052
1153
|
console.log("[HlsAdPlayer] Starting ad playback");
|
|
1053
1154
|
try {
|
|
1054
1155
|
if (!adVideoElement) {
|
|
1055
1156
|
adVideoElement = createAdVideoElement();
|
|
1056
|
-
adContainerEl
|
|
1157
|
+
adContainerEl == null ? void 0 : adContainerEl.appendChild(adVideoElement);
|
|
1057
1158
|
setupAdEventListeners();
|
|
1058
1159
|
}
|
|
1059
1160
|
trackingFired = {
|
|
@@ -1064,7 +1165,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1064
1165
|
thirdQuartile: false,
|
|
1065
1166
|
complete: false
|
|
1066
1167
|
};
|
|
1067
|
-
if (!options
|
|
1168
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1068
1169
|
contentVideo.pause();
|
|
1069
1170
|
console.log("[HlsAdPlayer] Content paused (VOD mode)");
|
|
1070
1171
|
} else {
|
|
@@ -1077,7 +1178,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1077
1178
|
adContainerEl.style.pointerEvents = "auto";
|
|
1078
1179
|
}
|
|
1079
1180
|
emit("content_pause");
|
|
1080
|
-
const mediaFile = currentAd.mediaFiles
|
|
1181
|
+
const mediaFile = selectBestMediaFile(currentAd.mediaFiles);
|
|
1081
1182
|
if (!mediaFile) {
|
|
1082
1183
|
throw new Error("No media file available for ad");
|
|
1083
1184
|
}
|
|
@@ -1137,7 +1238,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1137
1238
|
adVideoElement.pause();
|
|
1138
1239
|
adVideoElement.src = "";
|
|
1139
1240
|
}
|
|
1140
|
-
if (!options
|
|
1241
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1141
1242
|
contentVideo.play().catch(() => {
|
|
1142
1243
|
});
|
|
1143
1244
|
}
|
|
@@ -1157,7 +1258,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1157
1258
|
adVideoElement.remove();
|
|
1158
1259
|
adVideoElement = void 0;
|
|
1159
1260
|
}
|
|
1160
|
-
if (adContainerEl
|
|
1261
|
+
if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
|
|
1161
1262
|
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
1162
1263
|
}
|
|
1163
1264
|
adContainerEl = void 0;
|
|
@@ -1183,7 +1284,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1183
1284
|
listeners.get(event).add(listener);
|
|
1184
1285
|
},
|
|
1185
1286
|
off(event, listener) {
|
|
1186
|
-
|
|
1287
|
+
var _a;
|
|
1288
|
+
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
1187
1289
|
},
|
|
1188
1290
|
updateOriginalMutedState(muted) {
|
|
1189
1291
|
originalMutedState = muted;
|
|
@@ -1208,6 +1310,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1208
1310
|
// src/utils/tracking.ts
|
|
1209
1311
|
var cachedBrowserId = null;
|
|
1210
1312
|
function getClientInfo() {
|
|
1313
|
+
var _a, _b, _c, _d;
|
|
1211
1314
|
const ua = navigator.userAgent;
|
|
1212
1315
|
const platform = navigator.platform;
|
|
1213
1316
|
const vendor = navigator.vendor || "";
|
|
@@ -1215,12 +1318,12 @@ function getClientInfo() {
|
|
|
1215
1318
|
const memory = navigator.deviceMemory || null;
|
|
1216
1319
|
const hardwareConcurrency = navigator.hardwareConcurrency || 1;
|
|
1217
1320
|
const screenInfo = {
|
|
1218
|
-
width: screen
|
|
1219
|
-
height: screen
|
|
1220
|
-
availWidth: screen
|
|
1221
|
-
availHeight: screen
|
|
1222
|
-
orientation: screen
|
|
1223
|
-
pixelDepth: screen
|
|
1321
|
+
width: screen == null ? void 0 : screen.width,
|
|
1322
|
+
height: screen == null ? void 0 : screen.height,
|
|
1323
|
+
availWidth: screen == null ? void 0 : screen.availWidth,
|
|
1324
|
+
availHeight: screen == null ? void 0 : screen.availHeight,
|
|
1325
|
+
orientation: ((_a = screen == null ? void 0 : screen.orientation) == null ? void 0 : _a.type) || "",
|
|
1326
|
+
pixelDepth: screen == null ? void 0 : screen.pixelDepth
|
|
1224
1327
|
};
|
|
1225
1328
|
let deviceType = "desktop";
|
|
1226
1329
|
let brand = "Unknown";
|
|
@@ -1317,10 +1420,10 @@ function getClientInfo() {
|
|
|
1317
1420
|
if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
|
|
1318
1421
|
}
|
|
1319
1422
|
isWebView = /wv|WebView|Linux; U;/.test(ua);
|
|
1320
|
-
if (window
|
|
1423
|
+
if ((window == null ? void 0 : window.outerHeight) === 0 && (window == null ? void 0 : window.outerWidth) === 0) {
|
|
1321
1424
|
isWebView = true;
|
|
1322
1425
|
}
|
|
1323
|
-
isWebApp = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true || window.screen
|
|
1426
|
+
isWebApp = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true || ((_c = (_b = window.screen) == null ? void 0 : _b.orientation) == null ? void 0 : _c.angle) !== void 0;
|
|
1324
1427
|
return {
|
|
1325
1428
|
brand,
|
|
1326
1429
|
os,
|
|
@@ -1341,7 +1444,7 @@ function getClientInfo() {
|
|
|
1341
1444
|
deviceMemory: memory,
|
|
1342
1445
|
maxTouchPoints,
|
|
1343
1446
|
language: navigator.language,
|
|
1344
|
-
languages: navigator.languages
|
|
1447
|
+
languages: ((_d = navigator.languages) == null ? void 0 : _d.join(",")) || "",
|
|
1345
1448
|
cookieEnabled: navigator.cookieEnabled,
|
|
1346
1449
|
doNotTrack: navigator.doNotTrack || "",
|
|
1347
1450
|
referrer: document.referrer,
|
|
@@ -1699,7 +1802,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1699
1802
|
}
|
|
1700
1803
|
return createHlsAdPlayer(this.video, {
|
|
1701
1804
|
continueLiveStreamDuringAds,
|
|
1702
|
-
...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {}
|
|
1805
|
+
...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {},
|
|
1806
|
+
...this.hls ? { mainHlsInstance: this.hls } : {}
|
|
1703
1807
|
});
|
|
1704
1808
|
} else {
|
|
1705
1809
|
if (this.config.debugAdTiming) {
|
|
@@ -1711,6 +1815,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1711
1815
|
}
|
|
1712
1816
|
}
|
|
1713
1817
|
async load() {
|
|
1818
|
+
var _a, _b;
|
|
1714
1819
|
if (!this.attached) {
|
|
1715
1820
|
this.attach();
|
|
1716
1821
|
}
|
|
@@ -1727,7 +1832,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1727
1832
|
this.initializeTracking();
|
|
1728
1833
|
if (this.shouldUseNativeHls()) {
|
|
1729
1834
|
this.video.src = this.config.src;
|
|
1730
|
-
this.isLiveStream = this.config.lowLatencyMode
|
|
1835
|
+
this.isLiveStream = (_a = this.config.lowLatencyMode) != null ? _a : false;
|
|
1731
1836
|
if (this.config.debugAdTiming) {
|
|
1732
1837
|
console.log(
|
|
1733
1838
|
"[StormcloudVideoPlayer] allowNativeHls: true - VOD mode detected:",
|
|
@@ -1742,8 +1847,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1742
1847
|
this.ima = this.createAdPlayer(false);
|
|
1743
1848
|
this.ima.initialize();
|
|
1744
1849
|
if (this.config.autoplay) {
|
|
1745
|
-
await this.video.play()
|
|
1746
|
-
});
|
|
1850
|
+
await ((_b = this.video.play()) == null ? void 0 : _b.catch(() => {
|
|
1851
|
+
}));
|
|
1747
1852
|
}
|
|
1748
1853
|
return;
|
|
1749
1854
|
}
|
|
@@ -1756,12 +1861,17 @@ var StormcloudVideoPlayer = class {
|
|
|
1756
1861
|
...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}
|
|
1757
1862
|
});
|
|
1758
1863
|
this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, () => {
|
|
1759
|
-
|
|
1864
|
+
var _a2;
|
|
1865
|
+
(_a2 = this.hls) == null ? void 0 : _a2.loadSource(this.config.src);
|
|
1760
1866
|
});
|
|
1761
1867
|
this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, async (_, data) => {
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1868
|
+
var _a2, _b2, _c, _d;
|
|
1869
|
+
this.isLiveStream = (_c = (_b2 = (_a2 = this.hls) == null ? void 0 : _a2.levels) == null ? void 0 : _b2.some(
|
|
1870
|
+
(level) => {
|
|
1871
|
+
var _a3, _b3;
|
|
1872
|
+
return ((_a3 = level == null ? void 0 : level.details) == null ? void 0 : _a3.live) === true || ((_b3 = level == null ? void 0 : level.details) == null ? void 0 : _b3.type) === "LIVE";
|
|
1873
|
+
}
|
|
1874
|
+
)) != null ? _c : false;
|
|
1765
1875
|
if (this.config.debugAdTiming) {
|
|
1766
1876
|
const adBehavior = this.shouldContinueLiveStreamDuringAds() ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
|
|
1767
1877
|
console.log("[StormcloudVideoPlayer] Stream type detected:", {
|
|
@@ -1774,28 +1884,29 @@ var StormcloudVideoPlayer = class {
|
|
|
1774
1884
|
this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());
|
|
1775
1885
|
this.ima.initialize();
|
|
1776
1886
|
if (this.config.autoplay) {
|
|
1777
|
-
await this.video.play()
|
|
1778
|
-
});
|
|
1887
|
+
await ((_d = this.video.play()) == null ? void 0 : _d.catch(() => {
|
|
1888
|
+
}));
|
|
1779
1889
|
}
|
|
1780
1890
|
});
|
|
1781
1891
|
this.hls.on(import_hls2.default.Events.FRAG_PARSING_METADATA, (_evt, data) => {
|
|
1782
|
-
const id3Tags = (data
|
|
1892
|
+
const id3Tags = ((data == null ? void 0 : data.samples) || []).map((s) => ({
|
|
1783
1893
|
key: "ID3",
|
|
1784
|
-
value: s
|
|
1785
|
-
ptsSeconds: s
|
|
1894
|
+
value: s == null ? void 0 : s.data,
|
|
1895
|
+
ptsSeconds: s == null ? void 0 : s.pts
|
|
1786
1896
|
}));
|
|
1787
1897
|
id3Tags.forEach((tag) => this.onId3Tag(tag));
|
|
1788
1898
|
});
|
|
1789
1899
|
this.hls.on(import_hls2.default.Events.FRAG_CHANGED, (_evt, data) => {
|
|
1790
|
-
|
|
1791
|
-
const
|
|
1900
|
+
var _a2, _b2, _c;
|
|
1901
|
+
const frag = data == null ? void 0 : data.frag;
|
|
1902
|
+
const tagList = frag == null ? void 0 : frag.tagList;
|
|
1792
1903
|
if (!Array.isArray(tagList)) return;
|
|
1793
1904
|
for (const entry of tagList) {
|
|
1794
1905
|
let tag = "";
|
|
1795
1906
|
let value = "";
|
|
1796
1907
|
if (Array.isArray(entry)) {
|
|
1797
|
-
tag = String(entry[0]
|
|
1798
|
-
value = String(entry[1]
|
|
1908
|
+
tag = String((_a2 = entry[0]) != null ? _a2 : "");
|
|
1909
|
+
value = String((_b2 = entry[1]) != null ? _b2 : "");
|
|
1799
1910
|
} else if (typeof entry === "string") {
|
|
1800
1911
|
const idx = entry.indexOf(":");
|
|
1801
1912
|
if (idx >= 0) {
|
|
@@ -1819,8 +1930,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1819
1930
|
const prog = this.parseCueOutCont(value);
|
|
1820
1931
|
const marker = {
|
|
1821
1932
|
type: "progress",
|
|
1822
|
-
...prog
|
|
1823
|
-
...prog
|
|
1933
|
+
...(prog == null ? void 0 : prog.duration) !== void 0 ? { durationSeconds: prog.duration } : {},
|
|
1934
|
+
...(prog == null ? void 0 : prog.elapsed) !== void 0 ? { ptsSeconds: prog.elapsed } : {},
|
|
1824
1935
|
raw: { tag, value }
|
|
1825
1936
|
};
|
|
1826
1937
|
this.onScte35Marker(marker);
|
|
@@ -1830,7 +1941,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1830
1941
|
const attrs = this.parseAttributeList(value);
|
|
1831
1942
|
const hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
|
|
1832
1943
|
const hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
|
|
1833
|
-
const klass = String(attrs["CLASS"]
|
|
1944
|
+
const klass = String((_c = attrs["CLASS"]) != null ? _c : "");
|
|
1834
1945
|
const duration = this.toNumber(attrs["DURATION"]);
|
|
1835
1946
|
if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
|
|
1836
1947
|
const marker = {
|
|
@@ -1847,13 +1958,14 @@ var StormcloudVideoPlayer = class {
|
|
|
1847
1958
|
}
|
|
1848
1959
|
});
|
|
1849
1960
|
this.hls.on(import_hls2.default.Events.ERROR, (_evt, data) => {
|
|
1850
|
-
|
|
1961
|
+
var _a2, _b2;
|
|
1962
|
+
if (data == null ? void 0 : data.fatal) {
|
|
1851
1963
|
switch (data.type) {
|
|
1852
1964
|
case import_hls2.default.ErrorTypes.NETWORK_ERROR:
|
|
1853
|
-
this.hls
|
|
1965
|
+
(_a2 = this.hls) == null ? void 0 : _a2.startLoad();
|
|
1854
1966
|
break;
|
|
1855
1967
|
case import_hls2.default.ErrorTypes.MEDIA_ERROR:
|
|
1856
|
-
this.hls
|
|
1968
|
+
(_b2 = this.hls) == null ? void 0 : _b2.recoverMediaError();
|
|
1857
1969
|
break;
|
|
1858
1970
|
default:
|
|
1859
1971
|
this.destroy();
|
|
@@ -1955,11 +2067,12 @@ var StormcloudVideoPlayer = class {
|
|
|
1955
2067
|
}
|
|
1956
2068
|
}
|
|
1957
2069
|
parseScte35FromId3(tag) {
|
|
2070
|
+
var _a, _b, _c, _d;
|
|
1958
2071
|
const text = this.decodeId3ValueToText(tag.value);
|
|
1959
2072
|
if (!text) return void 0;
|
|
1960
2073
|
const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\r\n]*))?/i) || text.match(/CUE-OUT(?::([^\r\n]*))?/i);
|
|
1961
2074
|
if (cueOutMatch) {
|
|
1962
|
-
const arg = (cueOutMatch[1]
|
|
2075
|
+
const arg = ((_a = cueOutMatch[1]) != null ? _a : "").trim();
|
|
1963
2076
|
const dur = this.parseCueOutDuration(arg);
|
|
1964
2077
|
const marker = {
|
|
1965
2078
|
type: "start",
|
|
@@ -1971,12 +2084,12 @@ var StormcloudVideoPlayer = class {
|
|
|
1971
2084
|
}
|
|
1972
2085
|
const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\r\n]*)/i);
|
|
1973
2086
|
if (cueOutContMatch) {
|
|
1974
|
-
const arg = (cueOutContMatch[1]
|
|
2087
|
+
const arg = ((_b = cueOutContMatch[1]) != null ? _b : "").trim();
|
|
1975
2088
|
const cont = this.parseCueOutCont(arg);
|
|
1976
2089
|
const marker = {
|
|
1977
2090
|
type: "progress",
|
|
1978
2091
|
...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},
|
|
1979
|
-
...cont
|
|
2092
|
+
...(cont == null ? void 0 : cont.duration) !== void 0 ? { durationSeconds: cont.duration } : {},
|
|
1980
2093
|
raw: { id3: text }
|
|
1981
2094
|
};
|
|
1982
2095
|
return marker;
|
|
@@ -1992,10 +2105,10 @@ var StormcloudVideoPlayer = class {
|
|
|
1992
2105
|
}
|
|
1993
2106
|
const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\r\n]*)/i);
|
|
1994
2107
|
if (daterangeMatch) {
|
|
1995
|
-
const attrs = this.parseAttributeList(daterangeMatch[1]
|
|
2108
|
+
const attrs = this.parseAttributeList((_c = daterangeMatch[1]) != null ? _c : "");
|
|
1996
2109
|
const hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
|
|
1997
2110
|
const hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
|
|
1998
|
-
const klass = String(attrs["CLASS"]
|
|
2111
|
+
const klass = String((_d = attrs["CLASS"]) != null ? _d : "");
|
|
1999
2112
|
const duration = this.toNumber(attrs["DURATION"]);
|
|
2000
2113
|
if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
|
|
2001
2114
|
const marker = {
|
|
@@ -2052,6 +2165,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2052
2165
|
}
|
|
2053
2166
|
}
|
|
2054
2167
|
onScte35Marker(marker) {
|
|
2168
|
+
var _a, _b;
|
|
2055
2169
|
if (this.config.debugAdTiming) {
|
|
2056
2170
|
console.log("[StormcloudVideoPlayer] SCTE-35 marker detected:", {
|
|
2057
2171
|
type: marker.type,
|
|
@@ -2067,7 +2181,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2067
2181
|
this.expectedAdBreakDurationMs = durationMs;
|
|
2068
2182
|
this.currentAdBreakStartWallClockMs = Date.now();
|
|
2069
2183
|
const isManifestMarker = this.isManifestBasedMarker(marker);
|
|
2070
|
-
const forceImmediate = this.config.immediateManifestAds
|
|
2184
|
+
const forceImmediate = (_a = this.config.immediateManifestAds) != null ? _a : true;
|
|
2071
2185
|
if (this.config.debugAdTiming) {
|
|
2072
2186
|
console.log("[StormcloudVideoPlayer] Ad start decision:", {
|
|
2073
2187
|
isManifestMarker,
|
|
@@ -2084,7 +2198,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2084
2198
|
this.clearAdStartTimer();
|
|
2085
2199
|
this.handleAdStart(marker);
|
|
2086
2200
|
} else if (typeof marker.ptsSeconds === "number") {
|
|
2087
|
-
const tol = this.config.driftToleranceMs
|
|
2201
|
+
const tol = (_b = this.config.driftToleranceMs) != null ? _b : 1e3;
|
|
2088
2202
|
const nowMs = this.video.currentTime * 1e3;
|
|
2089
2203
|
const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
|
|
2090
2204
|
const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);
|
|
@@ -2194,12 +2308,13 @@ var StormcloudVideoPlayer = class {
|
|
|
2194
2308
|
return void 0;
|
|
2195
2309
|
}
|
|
2196
2310
|
parseAttributeList(value) {
|
|
2311
|
+
var _a, _b, _c;
|
|
2197
2312
|
const attrs = {};
|
|
2198
2313
|
const regex = /([A-Z0-9-]+)=(("[^"]*")|([^",]*))(?:,|$)/gi;
|
|
2199
2314
|
let match;
|
|
2200
2315
|
while ((match = regex.exec(value)) !== null) {
|
|
2201
|
-
const key = match[1]
|
|
2202
|
-
let rawVal = match[3]
|
|
2316
|
+
const key = (_a = match[1]) != null ? _a : "";
|
|
2317
|
+
let rawVal = (_c = (_b = match[3]) != null ? _b : match[4]) != null ? _c : "";
|
|
2203
2318
|
if (rawVal.startsWith('"') && rawVal.endsWith('"')) {
|
|
2204
2319
|
rawVal = rawVal.slice(1, -1);
|
|
2205
2320
|
}
|
|
@@ -2363,6 +2478,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2363
2478
|
}
|
|
2364
2479
|
}
|
|
2365
2480
|
async fetchAdConfiguration() {
|
|
2481
|
+
var _a, _b, _c;
|
|
2366
2482
|
const vastMode = this.config.vastMode || "default";
|
|
2367
2483
|
if (this.config.debugAdTiming) {
|
|
2368
2484
|
console.log(
|
|
@@ -2383,7 +2499,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2383
2499
|
this.apiVastTagUrl = vastEndpoint;
|
|
2384
2500
|
if (this.config.debugAdTiming) {
|
|
2385
2501
|
console.log(
|
|
2386
|
-
"[StormcloudVideoPlayer] Using AdStorm VAST endpoint:",
|
|
2502
|
+
"[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):",
|
|
2387
2503
|
vastEndpoint
|
|
2388
2504
|
);
|
|
2389
2505
|
}
|
|
@@ -2420,7 +2536,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2420
2536
|
return;
|
|
2421
2537
|
}
|
|
2422
2538
|
const data = await response.json();
|
|
2423
|
-
const imaPayload = data.response
|
|
2539
|
+
const imaPayload = (_c = (_b = (_a = data.response) == null ? void 0 : _a.ima) == null ? void 0 : _b["publisherdesk.ima"]) == null ? void 0 : _c.payload;
|
|
2424
2540
|
if (imaPayload) {
|
|
2425
2541
|
this.apiVastTagUrl = decodeURIComponent(imaPayload);
|
|
2426
2542
|
if (this.config.debugAdTiming) {
|
|
@@ -2457,11 +2573,12 @@ var StormcloudVideoPlayer = class {
|
|
|
2457
2573
|
return "other";
|
|
2458
2574
|
}
|
|
2459
2575
|
shouldShowNativeControls() {
|
|
2576
|
+
var _a, _b;
|
|
2460
2577
|
const streamType = this.getStreamType();
|
|
2461
2578
|
if (streamType === "other") {
|
|
2462
|
-
return !(this.config.showCustomControls
|
|
2579
|
+
return !((_a = this.config.showCustomControls) != null ? _a : false);
|
|
2463
2580
|
}
|
|
2464
|
-
return !!(this.config.allowNativeHls && !(this.config.showCustomControls
|
|
2581
|
+
return !!(this.config.allowNativeHls && !((_b = this.config.showCustomControls) != null ? _b : false));
|
|
2465
2582
|
}
|
|
2466
2583
|
shouldContinueLiveStreamDuringAds() {
|
|
2467
2584
|
if (this.config.allowNativeHls) {
|
|
@@ -2473,6 +2590,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2473
2590
|
return true;
|
|
2474
2591
|
}
|
|
2475
2592
|
async handleAdStart(_marker) {
|
|
2593
|
+
var _a;
|
|
2476
2594
|
const scheduled = this.findCurrentOrNextBreak(
|
|
2477
2595
|
this.video.currentTime * 1e3
|
|
2478
2596
|
);
|
|
@@ -2523,17 +2641,18 @@ var StormcloudVideoPlayer = class {
|
|
|
2523
2641
|
this.handleAdFailure();
|
|
2524
2642
|
}
|
|
2525
2643
|
}
|
|
2526
|
-
if (this.expectedAdBreakDurationMs == null && scheduled
|
|
2644
|
+
if (this.expectedAdBreakDurationMs == null && (scheduled == null ? void 0 : scheduled.durationMs) != null) {
|
|
2527
2645
|
this.expectedAdBreakDurationMs = scheduled.durationMs;
|
|
2528
|
-
this.currentAdBreakStartWallClockMs = this.currentAdBreakStartWallClockMs
|
|
2646
|
+
this.currentAdBreakStartWallClockMs = (_a = this.currentAdBreakStartWallClockMs) != null ? _a : Date.now();
|
|
2529
2647
|
this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
|
|
2530
2648
|
}
|
|
2531
2649
|
}
|
|
2532
2650
|
findCurrentOrNextBreak(nowMs) {
|
|
2651
|
+
var _a;
|
|
2533
2652
|
const schedule = [];
|
|
2534
2653
|
let candidate;
|
|
2535
2654
|
for (const b of schedule) {
|
|
2536
|
-
const tol = this.config.driftToleranceMs
|
|
2655
|
+
const tol = (_a = this.config.driftToleranceMs) != null ? _a : 1e3;
|
|
2537
2656
|
if (b.startTimeMs <= nowMs + tol && (candidate == null || b.startTimeMs > (candidate.startTimeMs || 0))) {
|
|
2538
2657
|
candidate = b;
|
|
2539
2658
|
}
|
|
@@ -2549,7 +2668,8 @@ var StormcloudVideoPlayer = class {
|
|
|
2549
2668
|
}
|
|
2550
2669
|
}
|
|
2551
2670
|
async handleMidAdJoin(adBreak, nowMs) {
|
|
2552
|
-
|
|
2671
|
+
var _a;
|
|
2672
|
+
const durationMs = (_a = adBreak.durationMs) != null ? _a : 0;
|
|
2553
2673
|
const endMs = adBreak.startTimeMs + durationMs;
|
|
2554
2674
|
if (durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs) {
|
|
2555
2675
|
const remainingMs = endMs - nowMs;
|
|
@@ -2635,12 +2755,20 @@ var StormcloudVideoPlayer = class {
|
|
|
2635
2755
|
this.startAdFailsafeTimer();
|
|
2636
2756
|
try {
|
|
2637
2757
|
await this.ima.requestAds(vastTagUrl);
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2758
|
+
try {
|
|
2759
|
+
if (this.config.debugAdTiming) {
|
|
2760
|
+
console.log("[StormcloudVideoPlayer] Ad request completed, attempting playback");
|
|
2761
|
+
}
|
|
2762
|
+
await this.ima.play();
|
|
2763
|
+
if (this.config.debugAdTiming) {
|
|
2764
|
+
console.log("[StormcloudVideoPlayer] Ad playback started successfully");
|
|
2765
|
+
}
|
|
2766
|
+
} catch (playError) {
|
|
2767
|
+
if (this.config.debugAdTiming) {
|
|
2768
|
+
console.log("[StormcloudVideoPlayer] No ads available, skipping playback");
|
|
2769
|
+
}
|
|
2770
|
+
this.handleAdFailure();
|
|
2771
|
+
return;
|
|
2644
2772
|
}
|
|
2645
2773
|
} catch (error) {
|
|
2646
2774
|
if (this.config.debugAdTiming) {
|
|
@@ -2650,6 +2778,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2650
2778
|
}
|
|
2651
2779
|
}
|
|
2652
2780
|
handleAdFailure() {
|
|
2781
|
+
var _a;
|
|
2653
2782
|
if (this.config.debugAdTiming) {
|
|
2654
2783
|
console.log(
|
|
2655
2784
|
"[StormcloudVideoPlayer] Handling ad failure - resuming content",
|
|
@@ -2682,7 +2811,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2682
2811
|
if (this.config.debugAdTiming) {
|
|
2683
2812
|
console.log("[StormcloudVideoPlayer] Resuming paused video");
|
|
2684
2813
|
}
|
|
2685
|
-
this.video.play()
|
|
2814
|
+
(_a = this.video.play()) == null ? void 0 : _a.catch((error) => {
|
|
2686
2815
|
if (this.config.debugAdTiming) {
|
|
2687
2816
|
console.error(
|
|
2688
2817
|
"[StormcloudVideoPlayer] Failed to resume video after ad failure:",
|
|
@@ -2697,8 +2826,9 @@ var StormcloudVideoPlayer = class {
|
|
|
2697
2826
|
}
|
|
2698
2827
|
}
|
|
2699
2828
|
startAdFailsafeTimer() {
|
|
2829
|
+
var _a;
|
|
2700
2830
|
this.clearAdFailsafeTimer();
|
|
2701
|
-
const failsafeMs = this.config.adFailsafeTimeoutMs
|
|
2831
|
+
const failsafeMs = (_a = this.config.adFailsafeTimeoutMs) != null ? _a : 1e4;
|
|
2702
2832
|
if (this.config.debugAdTiming) {
|
|
2703
2833
|
console.log(
|
|
2704
2834
|
`[StormcloudVideoPlayer] Starting failsafe timer (${failsafeMs}ms)`
|
|
@@ -2834,6 +2964,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2834
2964
|
}
|
|
2835
2965
|
}
|
|
2836
2966
|
destroy() {
|
|
2967
|
+
var _a, _b;
|
|
2837
2968
|
this.clearAdStartTimer();
|
|
2838
2969
|
this.clearAdStopTimer();
|
|
2839
2970
|
this.clearAdFailsafeTimer();
|
|
@@ -2841,8 +2972,8 @@ var StormcloudVideoPlayer = class {
|
|
|
2841
2972
|
clearInterval(this.heartbeatInterval);
|
|
2842
2973
|
this.heartbeatInterval = void 0;
|
|
2843
2974
|
}
|
|
2844
|
-
this.hls
|
|
2845
|
-
this.ima
|
|
2975
|
+
(_a = this.hls) == null ? void 0 : _a.destroy();
|
|
2976
|
+
(_b = this.ima) == null ? void 0 : _b.destroy();
|
|
2846
2977
|
}
|
|
2847
2978
|
};
|
|
2848
2979
|
|
|
@@ -2853,6 +2984,7 @@ var HlsPlayer = class extends import_react2.Component {
|
|
|
2853
2984
|
this.player = null;
|
|
2854
2985
|
this.mounted = false;
|
|
2855
2986
|
this.load = async () => {
|
|
2987
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2856
2988
|
if (!this.props.videoElement || !this.props.src) return;
|
|
2857
2989
|
try {
|
|
2858
2990
|
if (this.player) {
|
|
@@ -2889,27 +3021,29 @@ var HlsPlayer = class extends import_react2.Component {
|
|
|
2889
3021
|
if (this.props.adFailsafeTimeoutMs !== void 0)
|
|
2890
3022
|
config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;
|
|
2891
3023
|
this.player = new StormcloudVideoPlayer(config);
|
|
2892
|
-
this.props.onMount
|
|
3024
|
+
(_b = (_a = this.props).onMount) == null ? void 0 : _b.call(_a, this);
|
|
2893
3025
|
await this.player.load();
|
|
2894
3026
|
if (this.mounted) {
|
|
2895
|
-
this.props.onReady
|
|
3027
|
+
(_d = (_c = this.props).onReady) == null ? void 0 : _d.call(_c);
|
|
2896
3028
|
}
|
|
2897
3029
|
} catch (error) {
|
|
2898
3030
|
if (this.mounted) {
|
|
2899
|
-
this.props.onError
|
|
3031
|
+
(_f = (_e = this.props).onError) == null ? void 0 : _f.call(_e, error);
|
|
2900
3032
|
}
|
|
2901
3033
|
}
|
|
2902
3034
|
};
|
|
2903
3035
|
this.play = () => {
|
|
3036
|
+
var _a, _b;
|
|
2904
3037
|
if (this.props.videoElement) {
|
|
2905
3038
|
this.props.videoElement.play();
|
|
2906
|
-
this.props.onPlay
|
|
3039
|
+
(_b = (_a = this.props).onPlay) == null ? void 0 : _b.call(_a);
|
|
2907
3040
|
}
|
|
2908
3041
|
};
|
|
2909
3042
|
this.pause = () => {
|
|
3043
|
+
var _a, _b;
|
|
2910
3044
|
if (this.props.videoElement) {
|
|
2911
3045
|
this.props.videoElement.pause();
|
|
2912
|
-
this.props.onPause
|
|
3046
|
+
(_b = (_a = this.props).onPause) == null ? void 0 : _b.call(_a);
|
|
2913
3047
|
}
|
|
2914
3048
|
};
|
|
2915
3049
|
this.stop = () => {
|
|
@@ -3004,37 +3138,44 @@ var FilePlayer = class extends import_react3.Component {
|
|
|
3004
3138
|
this.mounted = false;
|
|
3005
3139
|
this.ready = false;
|
|
3006
3140
|
this.load = () => {
|
|
3141
|
+
var _a, _b;
|
|
3007
3142
|
if (!this.props.videoElement || !this.props.src) return;
|
|
3008
3143
|
const video = this.props.videoElement;
|
|
3009
3144
|
const handleLoadedMetadata = () => {
|
|
3145
|
+
var _a2, _b2;
|
|
3010
3146
|
if (this.mounted && !this.ready) {
|
|
3011
3147
|
this.ready = true;
|
|
3012
|
-
this.props.onReady
|
|
3148
|
+
(_b2 = (_a2 = this.props).onReady) == null ? void 0 : _b2.call(_a2);
|
|
3013
3149
|
}
|
|
3014
3150
|
};
|
|
3015
3151
|
const handlePlay = () => {
|
|
3152
|
+
var _a2, _b2;
|
|
3016
3153
|
if (this.mounted) {
|
|
3017
|
-
this.props.onPlay
|
|
3154
|
+
(_b2 = (_a2 = this.props).onPlay) == null ? void 0 : _b2.call(_a2);
|
|
3018
3155
|
}
|
|
3019
3156
|
};
|
|
3020
3157
|
const handlePause = () => {
|
|
3158
|
+
var _a2, _b2;
|
|
3021
3159
|
if (this.mounted) {
|
|
3022
|
-
this.props.onPause
|
|
3160
|
+
(_b2 = (_a2 = this.props).onPause) == null ? void 0 : _b2.call(_a2);
|
|
3023
3161
|
}
|
|
3024
3162
|
};
|
|
3025
3163
|
const handleEnded = () => {
|
|
3164
|
+
var _a2, _b2;
|
|
3026
3165
|
if (this.mounted) {
|
|
3027
|
-
this.props.onEnded
|
|
3166
|
+
(_b2 = (_a2 = this.props).onEnded) == null ? void 0 : _b2.call(_a2);
|
|
3028
3167
|
}
|
|
3029
3168
|
};
|
|
3030
3169
|
const handleError = (error) => {
|
|
3170
|
+
var _a2, _b2;
|
|
3031
3171
|
if (this.mounted) {
|
|
3032
|
-
this.props.onError
|
|
3172
|
+
(_b2 = (_a2 = this.props).onError) == null ? void 0 : _b2.call(_a2, error);
|
|
3033
3173
|
}
|
|
3034
3174
|
};
|
|
3035
3175
|
const handleLoadedData = () => {
|
|
3176
|
+
var _a2, _b2;
|
|
3036
3177
|
if (this.mounted) {
|
|
3037
|
-
this.props.onLoaded
|
|
3178
|
+
(_b2 = (_a2 = this.props).onLoaded) == null ? void 0 : _b2.call(_a2);
|
|
3038
3179
|
}
|
|
3039
3180
|
};
|
|
3040
3181
|
video.addEventListener("loadedmetadata", handleLoadedMetadata);
|
|
@@ -3053,7 +3194,7 @@ var FilePlayer = class extends import_react3.Component {
|
|
|
3053
3194
|
if (this.props.preload !== void 0)
|
|
3054
3195
|
video.preload = this.props.preload;
|
|
3055
3196
|
if (this.props.poster !== void 0) video.poster = this.props.poster;
|
|
3056
|
-
this.props.onMount
|
|
3197
|
+
(_b = (_a = this.props).onMount) == null ? void 0 : _b.call(_a, this);
|
|
3057
3198
|
return () => {
|
|
3058
3199
|
video.removeEventListener("loadedmetadata", handleLoadedMetadata);
|
|
3059
3200
|
video.removeEventListener("play", handlePlay);
|