stormcloud-video-player 0.2.16 → 0.2.18
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 -56
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +6 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +387 -56
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +266 -23
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +5 -1
- package/lib/players/HlsPlayer.cjs +268 -23
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +268 -23
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +76 -12
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.d.cts +1 -1
- package/lib/sdk/ima.cjs +73 -2
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/sdk/ima.d.cts +1 -1
- package/lib/{types-mVgmKmzM.d.cts → types-J6-Dpcvw.d.cts} +1 -0
- package/lib/ui/StormcloudVideoPlayer.cjs +383 -56
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
- package/lib/utils/tracking.d.cts +1 -1
- package/package.json +1 -1
package/lib/index.cjs
CHANGED
|
@@ -267,6 +267,13 @@ function createImaController(video, options) {
|
|
|
267
267
|
let adPlaying = false;
|
|
268
268
|
let originalMutedState = false;
|
|
269
269
|
const listeners = /* @__PURE__ */ new Map();
|
|
270
|
+
function setAdPlayingFlag(isPlaying) {
|
|
271
|
+
if (isPlaying) {
|
|
272
|
+
video.dataset.stormcloudAdPlaying = "true";
|
|
273
|
+
} else {
|
|
274
|
+
delete video.dataset.stormcloudAdPlaying;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
270
277
|
function emit(event, payload) {
|
|
271
278
|
const set = listeners.get(event);
|
|
272
279
|
if (!set) return;
|
|
@@ -351,6 +358,14 @@ function createImaController(video, options) {
|
|
|
351
358
|
function makeAdsRequest(google, vastTagUrl) {
|
|
352
359
|
const adsRequest = new google.ima.AdsRequest();
|
|
353
360
|
adsRequest.adTagUrl = vastTagUrl;
|
|
361
|
+
const videoWidth = video.offsetWidth || video.clientWidth || 640;
|
|
362
|
+
const videoHeight = video.offsetHeight || video.clientHeight || 360;
|
|
363
|
+
adsRequest.linearAdSlotWidth = videoWidth;
|
|
364
|
+
adsRequest.linearAdSlotHeight = videoHeight;
|
|
365
|
+
adsRequest.nonLinearAdSlotWidth = videoWidth;
|
|
366
|
+
adsRequest.nonLinearAdSlotHeight = videoHeight;
|
|
367
|
+
adsRequest.vastLoadTimeout = 5e3;
|
|
368
|
+
console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
|
|
354
369
|
adsLoader.requestAds(adsRequest);
|
|
355
370
|
}
|
|
356
371
|
function destroyAdsManager() {
|
|
@@ -397,6 +412,18 @@ function createImaController(video, options) {
|
|
|
397
412
|
},
|
|
398
413
|
async requestAds(vastTagUrl) {
|
|
399
414
|
console.log("[IMA] Requesting ads:", vastTagUrl);
|
|
415
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
416
|
+
const error = new Error("VAST tag URL is empty or undefined");
|
|
417
|
+
console.warn("[IMA]", error.message);
|
|
418
|
+
return Promise.reject(error);
|
|
419
|
+
}
|
|
420
|
+
try {
|
|
421
|
+
new URL(vastTagUrl);
|
|
422
|
+
} catch (e) {
|
|
423
|
+
const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);
|
|
424
|
+
console.warn("[IMA]", error.message);
|
|
425
|
+
return Promise.reject(error);
|
|
426
|
+
}
|
|
400
427
|
if (adPlaying) {
|
|
401
428
|
console.warn(
|
|
402
429
|
"[IMA] Cannot request new ads while an ad is playing. Call stop() first."
|
|
@@ -458,6 +485,18 @@ function createImaController(video, options) {
|
|
|
458
485
|
);
|
|
459
486
|
}
|
|
460
487
|
}
|
|
488
|
+
const videoWidth = video.offsetWidth || video.clientWidth;
|
|
489
|
+
const videoHeight = video.offsetHeight || video.clientHeight;
|
|
490
|
+
if (!videoWidth || !videoHeight || videoWidth === 0 || videoHeight === 0) {
|
|
491
|
+
const error = new Error(
|
|
492
|
+
`Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`
|
|
493
|
+
);
|
|
494
|
+
console.warn("[IMA]", error.message);
|
|
495
|
+
currentReject == null ? void 0 : currentReject(error);
|
|
496
|
+
adsLoadedReject = void 0;
|
|
497
|
+
adsLoadedResolve = void 0;
|
|
498
|
+
return Promise.reject(error);
|
|
499
|
+
}
|
|
461
500
|
if (!adsLoader) {
|
|
462
501
|
console.log("[IMA] Creating ads loader");
|
|
463
502
|
const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);
|
|
@@ -477,7 +516,12 @@ function createImaController(video, options) {
|
|
|
477
516
|
console.error("[IMA] Ad error:", errorEvent.getError());
|
|
478
517
|
destroyAdsManager();
|
|
479
518
|
adPlaying = false;
|
|
519
|
+
const previousMutedState = video.muted;
|
|
480
520
|
video.muted = originalMutedState;
|
|
521
|
+
setAdPlayingFlag(false);
|
|
522
|
+
console.log(
|
|
523
|
+
`[IMA] Restored mute state after ad error: ${previousMutedState} -> ${originalMutedState}`
|
|
524
|
+
);
|
|
481
525
|
if (adContainerEl) {
|
|
482
526
|
adContainerEl.style.pointerEvents = "none";
|
|
483
527
|
adContainerEl.style.display = "none";
|
|
@@ -506,7 +550,9 @@ function createImaController(video, options) {
|
|
|
506
550
|
emit("ad_error");
|
|
507
551
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
508
552
|
if (video.paused) {
|
|
509
|
-
console.log(
|
|
553
|
+
console.log(
|
|
554
|
+
"[IMA] Resuming paused video after ad error"
|
|
555
|
+
);
|
|
510
556
|
(_a = video.play()) == null ? void 0 : _a.catch(() => {
|
|
511
557
|
});
|
|
512
558
|
}
|
|
@@ -528,11 +574,13 @@ function createImaController(video, options) {
|
|
|
528
574
|
}
|
|
529
575
|
video.muted = true;
|
|
530
576
|
adPlaying = true;
|
|
577
|
+
setAdPlayingFlag(true);
|
|
531
578
|
emit("content_pause");
|
|
532
579
|
}
|
|
533
580
|
);
|
|
534
581
|
adsManager.addEventListener(AdEvent.STARTED, () => {
|
|
535
582
|
console.log("[IMA] Ad started playing");
|
|
583
|
+
setAdPlayingFlag(true);
|
|
536
584
|
if (adContainerEl) {
|
|
537
585
|
adContainerEl.style.pointerEvents = "auto";
|
|
538
586
|
adContainerEl.style.display = "flex";
|
|
@@ -548,6 +596,7 @@ function createImaController(video, options) {
|
|
|
548
596
|
console.log("[IMA] Content resume requested");
|
|
549
597
|
adPlaying = false;
|
|
550
598
|
video.muted = originalMutedState;
|
|
599
|
+
setAdPlayingFlag(false);
|
|
551
600
|
if (adContainerEl) {
|
|
552
601
|
adContainerEl.style.pointerEvents = "none";
|
|
553
602
|
adContainerEl.style.display = "none";
|
|
@@ -571,6 +620,7 @@ function createImaController(video, options) {
|
|
|
571
620
|
console.log("[IMA] All ads completed");
|
|
572
621
|
adPlaying = false;
|
|
573
622
|
video.muted = originalMutedState;
|
|
623
|
+
setAdPlayingFlag(false);
|
|
574
624
|
if (adContainerEl) {
|
|
575
625
|
adContainerEl.style.pointerEvents = "none";
|
|
576
626
|
adContainerEl.style.display = "none";
|
|
@@ -601,6 +651,7 @@ function createImaController(video, options) {
|
|
|
601
651
|
console.error("[IMA] Error setting up ads manager:", e);
|
|
602
652
|
adPlaying = false;
|
|
603
653
|
video.muted = originalMutedState;
|
|
654
|
+
setAdPlayingFlag(false);
|
|
604
655
|
if (adContainerEl) {
|
|
605
656
|
adContainerEl.style.pointerEvents = "none";
|
|
606
657
|
adContainerEl.style.display = "none";
|
|
@@ -608,7 +659,9 @@ function createImaController(video, options) {
|
|
|
608
659
|
}
|
|
609
660
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
610
661
|
if (video.paused) {
|
|
611
|
-
console.log(
|
|
662
|
+
console.log(
|
|
663
|
+
"[IMA] Resuming paused video after setup error"
|
|
664
|
+
);
|
|
612
665
|
video.play().catch(() => {
|
|
613
666
|
});
|
|
614
667
|
}
|
|
@@ -628,7 +681,12 @@ function createImaController(video, options) {
|
|
|
628
681
|
(adErrorEvent) => {
|
|
629
682
|
console.error("[IMA] Ads loader error:", adErrorEvent.getError());
|
|
630
683
|
adPlaying = false;
|
|
684
|
+
const previousMutedState = video.muted;
|
|
631
685
|
video.muted = originalMutedState;
|
|
686
|
+
setAdPlayingFlag(false);
|
|
687
|
+
console.log(
|
|
688
|
+
`[IMA] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
689
|
+
);
|
|
632
690
|
if (adContainerEl) {
|
|
633
691
|
adContainerEl.style.pointerEvents = "none";
|
|
634
692
|
adContainerEl.style.display = "none";
|
|
@@ -680,12 +738,20 @@ function createImaController(video, options) {
|
|
|
680
738
|
console.log(`[IMA] Initializing ads manager (${width}x${height})`);
|
|
681
739
|
adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);
|
|
682
740
|
adPlaying = true;
|
|
741
|
+
const adVolume = originalMutedState ? 0 : video.volume;
|
|
742
|
+
try {
|
|
743
|
+
adsManager.setVolume(adVolume);
|
|
744
|
+
console.log(`[IMA] Set ad volume to ${adVolume}`);
|
|
745
|
+
} catch (error) {
|
|
746
|
+
console.warn("[IMA] Failed to set ad volume:", error);
|
|
747
|
+
}
|
|
683
748
|
console.log("[IMA] Starting ad playback");
|
|
684
749
|
adsManager.start();
|
|
685
750
|
return Promise.resolve();
|
|
686
751
|
} catch (error) {
|
|
687
752
|
console.error("[IMA] Error starting ad playback:", error);
|
|
688
753
|
adPlaying = false;
|
|
754
|
+
setAdPlayingFlag(false);
|
|
689
755
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
690
756
|
(_b = video.play()) == null ? void 0 : _b.catch(() => {
|
|
691
757
|
});
|
|
@@ -697,6 +763,7 @@ function createImaController(video, options) {
|
|
|
697
763
|
var _a;
|
|
698
764
|
adPlaying = false;
|
|
699
765
|
video.muted = originalMutedState;
|
|
766
|
+
setAdPlayingFlag(false);
|
|
700
767
|
if (adContainerEl) {
|
|
701
768
|
adContainerEl.style.pointerEvents = "none";
|
|
702
769
|
adContainerEl.style.display = "none";
|
|
@@ -720,6 +787,7 @@ function createImaController(video, options) {
|
|
|
720
787
|
destroyAdsManager();
|
|
721
788
|
adPlaying = false;
|
|
722
789
|
video.muted = originalMutedState;
|
|
790
|
+
setAdPlayingFlag(false);
|
|
723
791
|
if (adContainerEl) {
|
|
724
792
|
adContainerEl.style.pointerEvents = "none";
|
|
725
793
|
adContainerEl.style.display = "none";
|
|
@@ -762,6 +830,9 @@ function createImaController(video, options) {
|
|
|
762
830
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
763
831
|
},
|
|
764
832
|
updateOriginalMutedState(muted) {
|
|
833
|
+
console.log(
|
|
834
|
+
`[IMA] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
835
|
+
);
|
|
765
836
|
originalMutedState = muted;
|
|
766
837
|
},
|
|
767
838
|
getOriginalMutedState() {
|
|
@@ -818,7 +889,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
818
889
|
try {
|
|
819
890
|
fn(payload);
|
|
820
891
|
} catch (error) {
|
|
821
|
-
console.warn(
|
|
892
|
+
console.warn(
|
|
893
|
+
`[HlsAdPlayer] Error in event listener for ${event}:`,
|
|
894
|
+
error
|
|
895
|
+
);
|
|
822
896
|
}
|
|
823
897
|
}
|
|
824
898
|
}
|
|
@@ -881,7 +955,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
881
955
|
}
|
|
882
956
|
const mainQuality = getMainStreamQuality();
|
|
883
957
|
if (!mainQuality) {
|
|
884
|
-
console.log(
|
|
958
|
+
console.log(
|
|
959
|
+
"[HlsAdPlayer] No main stream quality info, using first media file"
|
|
960
|
+
);
|
|
885
961
|
return firstFile;
|
|
886
962
|
}
|
|
887
963
|
console.log("[HlsAdPlayer] Main stream quality:", mainQuality);
|
|
@@ -917,7 +993,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
917
993
|
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
|
|
918
994
|
const parserError = xmlDoc.querySelector("parsererror");
|
|
919
995
|
if (parserError) {
|
|
920
|
-
console.error(
|
|
996
|
+
console.error(
|
|
997
|
+
"[HlsAdPlayer] XML parsing error (malformed VAST XML):",
|
|
998
|
+
parserError.textContent
|
|
999
|
+
);
|
|
921
1000
|
return null;
|
|
922
1001
|
}
|
|
923
1002
|
const adElement = xmlDoc.querySelector("Ad");
|
|
@@ -933,17 +1012,23 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
933
1012
|
const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
|
|
934
1013
|
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
935
1014
|
const mediaFiles = [];
|
|
936
|
-
console.log(
|
|
1015
|
+
console.log(
|
|
1016
|
+
`[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`
|
|
1017
|
+
);
|
|
937
1018
|
mediaFileElements.forEach((mf, index) => {
|
|
938
1019
|
var _a2;
|
|
939
1020
|
const type = mf.getAttribute("type") || "";
|
|
940
1021
|
const url = ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "";
|
|
941
1022
|
const width = mf.getAttribute("width") || "";
|
|
942
1023
|
const height = mf.getAttribute("height") || "";
|
|
943
|
-
console.log(
|
|
1024
|
+
console.log(
|
|
1025
|
+
`[HlsAdPlayer] MediaFile ${index}: type="${type}", url="${url}", width="${width}", height="${height}"`
|
|
1026
|
+
);
|
|
944
1027
|
if (type === "application/x-mpegURL" || type.includes("m3u8")) {
|
|
945
1028
|
if (!url) {
|
|
946
|
-
console.warn(
|
|
1029
|
+
console.warn(
|
|
1030
|
+
`[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`
|
|
1031
|
+
);
|
|
947
1032
|
return;
|
|
948
1033
|
}
|
|
949
1034
|
const bitrateAttr = mf.getAttribute("bitrate");
|
|
@@ -957,12 +1042,16 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
957
1042
|
});
|
|
958
1043
|
console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);
|
|
959
1044
|
} else {
|
|
960
|
-
console.log(
|
|
1045
|
+
console.log(
|
|
1046
|
+
`[HlsAdPlayer] MediaFile ${index} ignored (type="${type}" is not HLS)`
|
|
1047
|
+
);
|
|
961
1048
|
}
|
|
962
1049
|
});
|
|
963
1050
|
if (mediaFiles.length === 0) {
|
|
964
1051
|
if (isNoAdAvailable) {
|
|
965
|
-
console.warn(
|
|
1052
|
+
console.warn(
|
|
1053
|
+
"[HlsAdPlayer] No ads available (VAST response indicates no ads)"
|
|
1054
|
+
);
|
|
966
1055
|
} else {
|
|
967
1056
|
console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
|
|
968
1057
|
}
|
|
@@ -1025,6 +1114,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1025
1114
|
video.style.backgroundColor = "#000";
|
|
1026
1115
|
video.playsInline = true;
|
|
1027
1116
|
video.muted = false;
|
|
1117
|
+
video.volume = 1;
|
|
1118
|
+
console.log(
|
|
1119
|
+
`[HlsAdPlayer] Created ad video element with volume ${video.volume}`
|
|
1120
|
+
);
|
|
1028
1121
|
return video;
|
|
1029
1122
|
}
|
|
1030
1123
|
function setupAdEventListeners() {
|
|
@@ -1084,10 +1177,22 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1084
1177
|
}
|
|
1085
1178
|
});
|
|
1086
1179
|
}
|
|
1180
|
+
function setAdPlayingFlag(isPlaying) {
|
|
1181
|
+
if (isPlaying) {
|
|
1182
|
+
contentVideo.dataset.stormcloudAdPlaying = "true";
|
|
1183
|
+
} else {
|
|
1184
|
+
delete contentVideo.dataset.stormcloudAdPlaying;
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1087
1187
|
function handleAdComplete() {
|
|
1088
1188
|
console.log("[HlsAdPlayer] Handling ad completion");
|
|
1089
1189
|
adPlaying = false;
|
|
1190
|
+
setAdPlayingFlag(false);
|
|
1191
|
+
const previousMutedState = contentVideo.muted;
|
|
1090
1192
|
contentVideo.muted = originalMutedState;
|
|
1193
|
+
console.log(
|
|
1194
|
+
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
1195
|
+
);
|
|
1091
1196
|
if (adContainerEl) {
|
|
1092
1197
|
adContainerEl.style.display = "none";
|
|
1093
1198
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -1105,7 +1210,12 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1105
1210
|
function handleAdError() {
|
|
1106
1211
|
console.log("[HlsAdPlayer] Handling ad error");
|
|
1107
1212
|
adPlaying = false;
|
|
1213
|
+
setAdPlayingFlag(false);
|
|
1214
|
+
const previousMutedState = contentVideo.muted;
|
|
1108
1215
|
contentVideo.muted = originalMutedState;
|
|
1216
|
+
console.log(
|
|
1217
|
+
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
1218
|
+
);
|
|
1109
1219
|
if (adContainerEl) {
|
|
1110
1220
|
adContainerEl.style.display = "none";
|
|
1111
1221
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -1142,7 +1252,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1142
1252
|
async requestAds(vastTagUrl) {
|
|
1143
1253
|
console.log("[HlsAdPlayer] Requesting ads:", vastTagUrl);
|
|
1144
1254
|
if (adPlaying) {
|
|
1145
|
-
console.warn(
|
|
1255
|
+
console.warn(
|
|
1256
|
+
"[HlsAdPlayer] Cannot request new ads while an ad is playing"
|
|
1257
|
+
);
|
|
1146
1258
|
return Promise.reject(new Error("Ad already playing"));
|
|
1147
1259
|
}
|
|
1148
1260
|
try {
|
|
@@ -1153,14 +1265,20 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1153
1265
|
}
|
|
1154
1266
|
const vastXml = await response.text();
|
|
1155
1267
|
console.log("[HlsAdPlayer] VAST XML received");
|
|
1156
|
-
console.log(
|
|
1268
|
+
console.log(
|
|
1269
|
+
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1270
|
+
vastXml.substring(0, 2e3)
|
|
1271
|
+
);
|
|
1157
1272
|
const ad = parseVastXml(vastXml);
|
|
1158
1273
|
if (!ad) {
|
|
1159
1274
|
console.warn("[HlsAdPlayer] No ads available from VAST response");
|
|
1275
|
+
emit("ad_error");
|
|
1160
1276
|
return Promise.resolve();
|
|
1161
1277
|
}
|
|
1162
1278
|
currentAd = ad;
|
|
1163
|
-
console.log(
|
|
1279
|
+
console.log(
|
|
1280
|
+
`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`
|
|
1281
|
+
);
|
|
1164
1282
|
fireTrackingPixels(ad.trackingUrls.impression);
|
|
1165
1283
|
trackingFired.impression = true;
|
|
1166
1284
|
return Promise.resolve();
|
|
@@ -1172,7 +1290,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1172
1290
|
},
|
|
1173
1291
|
async play() {
|
|
1174
1292
|
if (!currentAd) {
|
|
1175
|
-
console.warn(
|
|
1293
|
+
console.warn(
|
|
1294
|
+
"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)"
|
|
1295
|
+
);
|
|
1176
1296
|
return Promise.reject(new Error("No ad loaded"));
|
|
1177
1297
|
}
|
|
1178
1298
|
console.log("[HlsAdPlayer] Starting ad playback");
|
|
@@ -1190,6 +1310,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1190
1310
|
thirdQuartile: false,
|
|
1191
1311
|
complete: false
|
|
1192
1312
|
};
|
|
1313
|
+
const contentVolume = contentVideo.volume;
|
|
1193
1314
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1194
1315
|
contentVideo.pause();
|
|
1195
1316
|
console.log("[HlsAdPlayer] Content paused (VOD mode)");
|
|
@@ -1198,6 +1319,15 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1198
1319
|
}
|
|
1199
1320
|
contentVideo.muted = true;
|
|
1200
1321
|
adPlaying = true;
|
|
1322
|
+
setAdPlayingFlag(true);
|
|
1323
|
+
if (adVideoElement) {
|
|
1324
|
+
const adVolume = originalMutedState ? 0 : contentVolume;
|
|
1325
|
+
adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
|
|
1326
|
+
adVideoElement.muted = false;
|
|
1327
|
+
console.log(
|
|
1328
|
+
`[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`
|
|
1329
|
+
);
|
|
1330
|
+
}
|
|
1201
1331
|
if (adContainerEl) {
|
|
1202
1332
|
adContainerEl.style.display = "flex";
|
|
1203
1333
|
adContainerEl.style.pointerEvents = "auto";
|
|
@@ -1250,6 +1380,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1250
1380
|
async stop() {
|
|
1251
1381
|
console.log("[HlsAdPlayer] Stopping ad");
|
|
1252
1382
|
adPlaying = false;
|
|
1383
|
+
setAdPlayingFlag(false);
|
|
1253
1384
|
contentVideo.muted = originalMutedState;
|
|
1254
1385
|
if (adContainerEl) {
|
|
1255
1386
|
adContainerEl.style.display = "none";
|
|
@@ -1272,6 +1403,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1272
1403
|
destroy() {
|
|
1273
1404
|
console.log("[HlsAdPlayer] Destroying");
|
|
1274
1405
|
adPlaying = false;
|
|
1406
|
+
setAdPlayingFlag(false);
|
|
1275
1407
|
contentVideo.muted = originalMutedState;
|
|
1276
1408
|
if (adHls) {
|
|
1277
1409
|
adHls.destroy();
|
|
@@ -1313,6 +1445,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1313
1445
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
1314
1446
|
},
|
|
1315
1447
|
updateOriginalMutedState(muted) {
|
|
1448
|
+
console.log(
|
|
1449
|
+
`[HlsAdPlayer] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
1450
|
+
);
|
|
1316
1451
|
originalMutedState = muted;
|
|
1317
1452
|
},
|
|
1318
1453
|
getOriginalMutedState() {
|
|
@@ -1805,6 +1940,9 @@ var StormcloudVideoPlayer = class {
|
|
|
1805
1940
|
this.isLiveStream = false;
|
|
1806
1941
|
this.nativeHlsMode = false;
|
|
1807
1942
|
this.videoSrcProtection = null;
|
|
1943
|
+
this.bufferedSegmentsCount = 0;
|
|
1944
|
+
this.shouldAutoplayAfterBuffering = false;
|
|
1945
|
+
this.hasInitialBufferCompleted = false;
|
|
1808
1946
|
initializePolyfills();
|
|
1809
1947
|
const browserOverrides = getBrowserConfigOverrides();
|
|
1810
1948
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -1891,14 +2029,22 @@ var StormcloudVideoPlayer = class {
|
|
|
1891
2029
|
liveDurationInfinity: true,
|
|
1892
2030
|
lowLatencyMode: !!this.config.lowLatencyMode,
|
|
1893
2031
|
maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1,
|
|
1894
|
-
...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}
|
|
2032
|
+
...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {},
|
|
2033
|
+
maxBufferLength: 30,
|
|
2034
|
+
maxMaxBufferLength: 600,
|
|
2035
|
+
maxBufferSize: 60 * 1e3 * 1e3,
|
|
2036
|
+
maxBufferHole: 0.5,
|
|
2037
|
+
highBufferWatchdogPeriod: 2,
|
|
2038
|
+
nudgeOffset: 0.1,
|
|
2039
|
+
nudgeMaxRetry: 3,
|
|
2040
|
+
startPosition: -1
|
|
1895
2041
|
});
|
|
1896
2042
|
this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, () => {
|
|
1897
2043
|
var _a2;
|
|
1898
2044
|
(_a2 = this.hls) == null ? void 0 : _a2.loadSource(this.config.src);
|
|
1899
2045
|
});
|
|
1900
2046
|
this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, async (_, data) => {
|
|
1901
|
-
var _a2, _b2, _c, _d;
|
|
2047
|
+
var _a2, _b2, _c, _d, _e;
|
|
1902
2048
|
this.isLiveStream = (_c = (_b2 = (_a2 = this.hls) == null ? void 0 : _a2.levels) == null ? void 0 : _b2.some(
|
|
1903
2049
|
(level) => {
|
|
1904
2050
|
var _a3, _b3;
|
|
@@ -1916,9 +2062,51 @@ var StormcloudVideoPlayer = class {
|
|
|
1916
2062
|
this.ima.destroy();
|
|
1917
2063
|
this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());
|
|
1918
2064
|
this.ima.initialize();
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
2065
|
+
this.bufferedSegmentsCount = 0;
|
|
2066
|
+
this.hasInitialBufferCompleted = false;
|
|
2067
|
+
this.shouldAutoplayAfterBuffering = !!this.config.autoplay;
|
|
2068
|
+
const minSegments = (_d = this.config.minSegmentsBeforePlay) != null ? _d : 2;
|
|
2069
|
+
if (this.config.debugAdTiming) {
|
|
2070
|
+
console.log(
|
|
2071
|
+
"[StormcloudVideoPlayer] Waiting for",
|
|
2072
|
+
minSegments,
|
|
2073
|
+
"segments to buffer before playback"
|
|
2074
|
+
);
|
|
2075
|
+
}
|
|
2076
|
+
if (minSegments === 0 || !this.config.autoplay) {
|
|
2077
|
+
this.hasInitialBufferCompleted = true;
|
|
2078
|
+
if (this.config.autoplay) {
|
|
2079
|
+
await ((_e = this.video.play()) == null ? void 0 : _e.catch(() => {
|
|
2080
|
+
}));
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
});
|
|
2084
|
+
this.hls.on(import_hls2.default.Events.FRAG_BUFFERED, async (_evt, data) => {
|
|
2085
|
+
var _a2, _b2;
|
|
2086
|
+
if (this.hasInitialBufferCompleted) {
|
|
2087
|
+
return;
|
|
2088
|
+
}
|
|
2089
|
+
this.bufferedSegmentsCount++;
|
|
2090
|
+
const minSegments = (_a2 = this.config.minSegmentsBeforePlay) != null ? _a2 : 2;
|
|
2091
|
+
if (this.config.debugAdTiming) {
|
|
2092
|
+
console.log(
|
|
2093
|
+
`[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`
|
|
2094
|
+
);
|
|
2095
|
+
}
|
|
2096
|
+
if (this.bufferedSegmentsCount >= minSegments) {
|
|
2097
|
+
this.hasInitialBufferCompleted = true;
|
|
2098
|
+
if (this.shouldAutoplayAfterBuffering) {
|
|
2099
|
+
if (this.config.debugAdTiming) {
|
|
2100
|
+
console.log(
|
|
2101
|
+
`[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`
|
|
2102
|
+
);
|
|
2103
|
+
}
|
|
2104
|
+
await ((_b2 = this.video.play()) == null ? void 0 : _b2.catch((err) => {
|
|
2105
|
+
if (this.config.debugAdTiming) {
|
|
2106
|
+
console.warn("[StormcloudVideoPlayer] Autoplay failed:", err);
|
|
2107
|
+
}
|
|
2108
|
+
}));
|
|
2109
|
+
}
|
|
1922
2110
|
}
|
|
1923
2111
|
});
|
|
1924
2112
|
this.hls.on(import_hls2.default.Events.FRAG_PARSING_METADATA, (_evt, data) => {
|
|
@@ -2014,6 +2202,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2014
2202
|
this.video.autoplay = !!this.config.autoplay;
|
|
2015
2203
|
this.video.muted = !!this.config.muted;
|
|
2016
2204
|
this.ima.initialize();
|
|
2205
|
+
this.ima.updateOriginalMutedState(this.video.muted);
|
|
2017
2206
|
this.ima.on("all_ads_completed", () => {
|
|
2018
2207
|
if (this.config.debugAdTiming) {
|
|
2019
2208
|
console.log(
|
|
@@ -2798,7 +2987,23 @@ var StormcloudVideoPlayer = class {
|
|
|
2798
2987
|
}
|
|
2799
2988
|
return;
|
|
2800
2989
|
}
|
|
2801
|
-
|
|
2990
|
+
if (!this.showAds) {
|
|
2991
|
+
if (this.config.debugAdTiming) {
|
|
2992
|
+
console.log(
|
|
2993
|
+
`[StormcloudVideoPlayer] Capturing original state before ad request:`,
|
|
2994
|
+
{
|
|
2995
|
+
videoMuted: this.video.muted,
|
|
2996
|
+
videoVolume: this.video.volume,
|
|
2997
|
+
showAds: this.showAds
|
|
2998
|
+
}
|
|
2999
|
+
);
|
|
3000
|
+
}
|
|
3001
|
+
this.ima.updateOriginalMutedState(this.video.muted);
|
|
3002
|
+
} else if (this.config.debugAdTiming) {
|
|
3003
|
+
console.log(
|
|
3004
|
+
`[StormcloudVideoPlayer] Keeping existing original mute state (currently showing ads)`
|
|
3005
|
+
);
|
|
3006
|
+
}
|
|
2802
3007
|
this.startAdFailsafeTimer();
|
|
2803
3008
|
try {
|
|
2804
3009
|
await this.ima.requestAds(vastTagUrl);
|
|
@@ -2853,11 +3058,12 @@ var StormcloudVideoPlayer = class {
|
|
|
2853
3058
|
this.showAds = false;
|
|
2854
3059
|
this.currentAdIndex = 0;
|
|
2855
3060
|
this.totalAdsInBreak = 0;
|
|
3061
|
+
const currentMutedState = this.video.muted;
|
|
2856
3062
|
const originalMutedState = this.ima.getOriginalMutedState();
|
|
2857
3063
|
this.video.muted = originalMutedState;
|
|
2858
3064
|
if (this.config.debugAdTiming) {
|
|
2859
3065
|
console.log(
|
|
2860
|
-
`[StormcloudVideoPlayer] Restored mute state
|
|
3066
|
+
`[StormcloudVideoPlayer] Restored mute state: ${currentMutedState} -> ${originalMutedState}`
|
|
2861
3067
|
);
|
|
2862
3068
|
}
|
|
2863
3069
|
if (this.video.paused) {
|
|
@@ -2949,6 +3155,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2949
3155
|
}
|
|
2950
3156
|
} else {
|
|
2951
3157
|
this.video.muted = !this.video.muted;
|
|
3158
|
+
this.ima.updateOriginalMutedState(this.video.muted);
|
|
2952
3159
|
if (this.config.debugAdTiming) {
|
|
2953
3160
|
console.log("[StormcloudVideoPlayer] Muted:", this.video.muted);
|
|
2954
3161
|
}
|
|
@@ -2993,11 +3200,47 @@ var StormcloudVideoPlayer = class {
|
|
|
2993
3200
|
}
|
|
2994
3201
|
isMuted() {
|
|
2995
3202
|
if (this.ima.isAdPlaying()) {
|
|
2996
|
-
|
|
2997
|
-
|
|
3203
|
+
if (this.config.debugAdTiming) {
|
|
3204
|
+
console.log(
|
|
3205
|
+
"[StormcloudVideoPlayer] isMuted() override during ad playback -> false"
|
|
3206
|
+
);
|
|
3207
|
+
}
|
|
3208
|
+
return false;
|
|
3209
|
+
}
|
|
3210
|
+
if (this.config.debugAdTiming) {
|
|
3211
|
+
console.log(
|
|
3212
|
+
`[StormcloudVideoPlayer] isMuted() no ad playing: video.muted=${this.video.muted}`
|
|
3213
|
+
);
|
|
2998
3214
|
}
|
|
2999
3215
|
return this.video.muted;
|
|
3000
3216
|
}
|
|
3217
|
+
setMuted(muted) {
|
|
3218
|
+
const adPlaying = this.ima.isAdPlaying();
|
|
3219
|
+
if (adPlaying && muted === this.video.muted) {
|
|
3220
|
+
if (this.config.debugAdTiming) {
|
|
3221
|
+
console.log(
|
|
3222
|
+
"[StormcloudVideoPlayer] setMuted reflective update during ad ignored",
|
|
3223
|
+
{ muted }
|
|
3224
|
+
);
|
|
3225
|
+
}
|
|
3226
|
+
return;
|
|
3227
|
+
}
|
|
3228
|
+
this.video.muted = muted;
|
|
3229
|
+
if (adPlaying) {
|
|
3230
|
+
this.ima.updateOriginalMutedState(muted);
|
|
3231
|
+
this.ima.setAdVolume(muted ? 0 : 1);
|
|
3232
|
+
if (this.config.debugAdTiming) {
|
|
3233
|
+
console.log("[StormcloudVideoPlayer] setMuted applied during ad", {
|
|
3234
|
+
muted
|
|
3235
|
+
});
|
|
3236
|
+
}
|
|
3237
|
+
return;
|
|
3238
|
+
}
|
|
3239
|
+
this.ima.updateOriginalMutedState(muted);
|
|
3240
|
+
if (this.config.debugAdTiming) {
|
|
3241
|
+
console.log("[StormcloudVideoPlayer] setMuted called:", muted);
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3001
3244
|
isFullscreen() {
|
|
3002
3245
|
return !!document.fullscreenElement;
|
|
3003
3246
|
}
|
|
@@ -3076,10 +3319,12 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
|
|
|
3076
3319
|
vastMode,
|
|
3077
3320
|
vastTagUrl,
|
|
3078
3321
|
adPlayerType,
|
|
3322
|
+
minSegmentsBeforePlay,
|
|
3079
3323
|
...restVideoAttrs
|
|
3080
3324
|
} = props;
|
|
3081
3325
|
const videoRef = (0, import_react.useRef)(null);
|
|
3082
3326
|
const playerRef = (0, import_react.useRef)(null);
|
|
3327
|
+
const bufferingTimeoutRef = (0, import_react.useRef)(null);
|
|
3083
3328
|
const [adStatus, setAdStatus] = import_react.default.useState({ showAds: false, currentIndex: 0, totalAds: 0 });
|
|
3084
3329
|
const [shouldShowNativeControls, setShouldShowNativeControls] = import_react.default.useState(true);
|
|
3085
3330
|
const [isMuted, setIsMuted] = import_react.default.useState(false);
|
|
@@ -3201,6 +3446,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
|
|
|
3201
3446
|
return;
|
|
3202
3447
|
}
|
|
3203
3448
|
setShowLicenseWarning(false);
|
|
3449
|
+
if (debugAdTiming) {
|
|
3450
|
+
console.log("[StormcloudUI] Initializing player, isLoading=true");
|
|
3451
|
+
}
|
|
3204
3452
|
if (playerRef.current) {
|
|
3205
3453
|
try {
|
|
3206
3454
|
playerRef.current.destroy();
|
|
@@ -3231,17 +3479,25 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
|
|
|
3231
3479
|
if (vastMode !== void 0) cfg.vastMode = vastMode;
|
|
3232
3480
|
if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;
|
|
3233
3481
|
if (adPlayerType !== void 0) cfg.adPlayerType = adPlayerType;
|
|
3482
|
+
if (minSegmentsBeforePlay !== void 0)
|
|
3483
|
+
cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;
|
|
3234
3484
|
const player = new StormcloudVideoPlayer(cfg);
|
|
3235
3485
|
playerRef.current = player;
|
|
3236
3486
|
player.load().then(() => {
|
|
3237
3487
|
const showNative = player.shouldShowNativeControls();
|
|
3238
3488
|
setShouldShowNativeControls(showNative);
|
|
3489
|
+
if (debugAdTiming) {
|
|
3490
|
+
console.log(
|
|
3491
|
+
"[StormcloudUI] Player loaded successfully, waiting for video ready"
|
|
3492
|
+
);
|
|
3493
|
+
}
|
|
3239
3494
|
onReady == null ? void 0 : onReady(player);
|
|
3240
3495
|
}).catch((error) => {
|
|
3241
3496
|
console.error(
|
|
3242
3497
|
"StormcloudVideoPlayer: Failed to load player:",
|
|
3243
3498
|
error
|
|
3244
3499
|
);
|
|
3500
|
+
setIsLoading(false);
|
|
3245
3501
|
onReady == null ? void 0 : onReady(player);
|
|
3246
3502
|
});
|
|
3247
3503
|
return () => {
|
|
@@ -3258,8 +3514,8 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
|
|
|
3258
3514
|
if (autoplay !== void 0 && playerRef.current.videoElement) {
|
|
3259
3515
|
playerRef.current.videoElement.autoplay = autoplay;
|
|
3260
3516
|
}
|
|
3261
|
-
if (muted !== void 0
|
|
3262
|
-
playerRef.current.
|
|
3517
|
+
if (muted !== void 0) {
|
|
3518
|
+
playerRef.current.setMuted(muted);
|
|
3263
3519
|
}
|
|
3264
3520
|
} catch (error) {
|
|
3265
3521
|
console.warn("Failed to update player properties:", error);
|
|
@@ -3340,26 +3596,108 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
|
|
|
3340
3596
|
(0, import_react.useEffect)(() => {
|
|
3341
3597
|
if (!videoRef.current) return;
|
|
3342
3598
|
const handleLoadedMetadata = () => {
|
|
3599
|
+
var _a;
|
|
3343
3600
|
if (videoRef.current) {
|
|
3344
3601
|
const video2 = videoRef.current;
|
|
3345
3602
|
void video2.offsetHeight;
|
|
3346
3603
|
}
|
|
3604
|
+
if (debugAdTiming) {
|
|
3605
|
+
console.log(
|
|
3606
|
+
"[StormcloudUI] Video event: loadedmetadata, readyState:",
|
|
3607
|
+
(_a = videoRef.current) == null ? void 0 : _a.readyState
|
|
3608
|
+
);
|
|
3609
|
+
}
|
|
3610
|
+
};
|
|
3611
|
+
const handleLoadedData = () => {
|
|
3612
|
+
var _a;
|
|
3613
|
+
if (debugAdTiming) {
|
|
3614
|
+
console.log(
|
|
3615
|
+
"[StormcloudUI] Video event: loadeddata, readyState:",
|
|
3616
|
+
(_a = videoRef.current) == null ? void 0 : _a.readyState
|
|
3617
|
+
);
|
|
3618
|
+
}
|
|
3347
3619
|
};
|
|
3348
3620
|
const handleLoadStart = () => {
|
|
3349
|
-
|
|
3350
|
-
|
|
3621
|
+
var _a;
|
|
3622
|
+
if (debugAdTiming) {
|
|
3623
|
+
console.log(
|
|
3624
|
+
"[StormcloudUI] Video event: loadstart, readyState:",
|
|
3625
|
+
(_a = videoRef.current) == null ? void 0 : _a.readyState
|
|
3626
|
+
);
|
|
3627
|
+
}
|
|
3351
3628
|
};
|
|
3352
3629
|
const handleCanPlay = () => {
|
|
3630
|
+
var _a;
|
|
3631
|
+
setIsLoading(false);
|
|
3632
|
+
if (bufferingTimeoutRef.current) {
|
|
3633
|
+
clearTimeout(bufferingTimeoutRef.current);
|
|
3634
|
+
bufferingTimeoutRef.current = null;
|
|
3635
|
+
}
|
|
3636
|
+
setIsBuffering(false);
|
|
3637
|
+
if (debugAdTiming) {
|
|
3638
|
+
console.log(
|
|
3639
|
+
"[StormcloudUI] Video event: canplay, readyState:",
|
|
3640
|
+
(_a = videoRef.current) == null ? void 0 : _a.readyState,
|
|
3641
|
+
"- clearing loading state, isLoading=false"
|
|
3642
|
+
);
|
|
3643
|
+
}
|
|
3644
|
+
};
|
|
3645
|
+
const handleCanPlayThrough = () => {
|
|
3646
|
+
var _a;
|
|
3353
3647
|
setIsLoading(false);
|
|
3648
|
+
if (bufferingTimeoutRef.current) {
|
|
3649
|
+
clearTimeout(bufferingTimeoutRef.current);
|
|
3650
|
+
bufferingTimeoutRef.current = null;
|
|
3651
|
+
}
|
|
3354
3652
|
setIsBuffering(false);
|
|
3653
|
+
if (debugAdTiming) {
|
|
3654
|
+
console.log(
|
|
3655
|
+
"[StormcloudUI] Video event: canplaythrough, readyState:",
|
|
3656
|
+
(_a = videoRef.current) == null ? void 0 : _a.readyState,
|
|
3657
|
+
"- clearing loading state, isLoading=false"
|
|
3658
|
+
);
|
|
3659
|
+
}
|
|
3355
3660
|
};
|
|
3356
3661
|
const handleWaiting = () => {
|
|
3357
|
-
|
|
3662
|
+
var _a;
|
|
3663
|
+
if (bufferingTimeoutRef.current) {
|
|
3664
|
+
clearTimeout(bufferingTimeoutRef.current);
|
|
3665
|
+
}
|
|
3666
|
+
bufferingTimeoutRef.current = window.setTimeout(() => {
|
|
3667
|
+
var _a2;
|
|
3668
|
+
setIsBuffering(true);
|
|
3669
|
+
if (debugAdTiming) {
|
|
3670
|
+
console.log(
|
|
3671
|
+
"[StormcloudUI] Video buffering detected (after 300ms delay), readyState:",
|
|
3672
|
+
(_a2 = videoRef.current) == null ? void 0 : _a2.readyState,
|
|
3673
|
+
"- showing spinner, isBuffering=true"
|
|
3674
|
+
);
|
|
3675
|
+
}
|
|
3676
|
+
}, 300);
|
|
3677
|
+
if (debugAdTiming) {
|
|
3678
|
+
console.log(
|
|
3679
|
+
"[StormcloudUI] Video event: waiting, readyState:",
|
|
3680
|
+
(_a = videoRef.current) == null ? void 0 : _a.readyState,
|
|
3681
|
+
"- buffering delay started (300ms)"
|
|
3682
|
+
);
|
|
3683
|
+
}
|
|
3358
3684
|
};
|
|
3359
3685
|
const handlePlaying = () => {
|
|
3686
|
+
var _a;
|
|
3360
3687
|
setIsLoading(false);
|
|
3688
|
+
if (bufferingTimeoutRef.current) {
|
|
3689
|
+
clearTimeout(bufferingTimeoutRef.current);
|
|
3690
|
+
bufferingTimeoutRef.current = null;
|
|
3691
|
+
}
|
|
3361
3692
|
setIsBuffering(false);
|
|
3362
3693
|
setShowCenterPlay(false);
|
|
3694
|
+
if (debugAdTiming) {
|
|
3695
|
+
console.log(
|
|
3696
|
+
"[StormcloudUI] Video event: playing, readyState:",
|
|
3697
|
+
(_a = videoRef.current) == null ? void 0 : _a.readyState,
|
|
3698
|
+
"- playback started, isLoading=false, isBuffering=false"
|
|
3699
|
+
);
|
|
3700
|
+
}
|
|
3363
3701
|
};
|
|
3364
3702
|
const handlePause = () => {
|
|
3365
3703
|
if (playerRef.current && !playerRef.current.isShowingAds()) {
|
|
@@ -3374,8 +3712,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
|
|
|
3374
3712
|
const video = videoRef.current;
|
|
3375
3713
|
video.addEventListener("loadstart", handleLoadStart);
|
|
3376
3714
|
video.addEventListener("loadedmetadata", handleLoadedMetadata);
|
|
3377
|
-
video.addEventListener("loadeddata",
|
|
3715
|
+
video.addEventListener("loadeddata", handleLoadedData);
|
|
3378
3716
|
video.addEventListener("canplay", handleCanPlay);
|
|
3717
|
+
video.addEventListener("canplaythrough", handleCanPlayThrough);
|
|
3379
3718
|
video.addEventListener("waiting", handleWaiting);
|
|
3380
3719
|
video.addEventListener("playing", handlePlaying);
|
|
3381
3720
|
video.addEventListener("pause", handlePause);
|
|
@@ -3384,16 +3723,21 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
|
|
|
3384
3723
|
setShowCenterPlay(true);
|
|
3385
3724
|
}
|
|
3386
3725
|
return () => {
|
|
3726
|
+
if (bufferingTimeoutRef.current) {
|
|
3727
|
+
clearTimeout(bufferingTimeoutRef.current);
|
|
3728
|
+
bufferingTimeoutRef.current = null;
|
|
3729
|
+
}
|
|
3387
3730
|
video.removeEventListener("loadstart", handleLoadStart);
|
|
3388
3731
|
video.removeEventListener("loadedmetadata", handleLoadedMetadata);
|
|
3389
|
-
video.removeEventListener("loadeddata",
|
|
3732
|
+
video.removeEventListener("loadeddata", handleLoadedData);
|
|
3390
3733
|
video.removeEventListener("canplay", handleCanPlay);
|
|
3734
|
+
video.removeEventListener("canplaythrough", handleCanPlayThrough);
|
|
3391
3735
|
video.removeEventListener("waiting", handleWaiting);
|
|
3392
3736
|
video.removeEventListener("playing", handlePlaying);
|
|
3393
3737
|
video.removeEventListener("pause", handlePause);
|
|
3394
3738
|
video.removeEventListener("ended", handleEnded);
|
|
3395
3739
|
};
|
|
3396
|
-
}, []);
|
|
3740
|
+
}, [debugAdTiming]);
|
|
3397
3741
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
3398
3742
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
|
|
3399
3743
|
@keyframes spin {
|
|
@@ -3500,35 +3844,18 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
|
|
|
3500
3844
|
}
|
|
3501
3845
|
),
|
|
3502
3846
|
(isLoading || isBuffering) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
3503
|
-
|
|
3847
|
+
import_fa.FaSpinner,
|
|
3504
3848
|
{
|
|
3849
|
+
size: 42,
|
|
3850
|
+
color: "white",
|
|
3505
3851
|
style: {
|
|
3506
3852
|
position: "absolute",
|
|
3507
|
-
top: "50%",
|
|
3508
|
-
left: "50%",
|
|
3509
|
-
transform: "translate(-50%, -50%)",
|
|
3853
|
+
top: "calc(50% - 21px)",
|
|
3854
|
+
left: "calc(50% - 21px)",
|
|
3510
3855
|
zIndex: 20,
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
background: "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(20, 20, 20, 0.6) 100%)",
|
|
3515
|
-
width: "80px",
|
|
3516
|
-
height: "80px",
|
|
3517
|
-
borderRadius: "50%",
|
|
3518
|
-
backdropFilter: "blur(20px)",
|
|
3519
|
-
boxShadow: "0 12px 40px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 255, 255, 0.1)"
|
|
3520
|
-
},
|
|
3521
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
3522
|
-
import_fa.FaSpinner,
|
|
3523
|
-
{
|
|
3524
|
-
size: 28,
|
|
3525
|
-
color: "white",
|
|
3526
|
-
style: {
|
|
3527
|
-
animation: "spin 1s linear infinite",
|
|
3528
|
-
filter: "drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8))"
|
|
3529
|
-
}
|
|
3530
|
-
}
|
|
3531
|
-
)
|
|
3856
|
+
animation: "spin 1s linear infinite",
|
|
3857
|
+
filter: "drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8))"
|
|
3858
|
+
}
|
|
3532
3859
|
}
|
|
3533
3860
|
),
|
|
3534
3861
|
showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
@@ -4641,6 +4968,7 @@ var defaultProps = {
|
|
|
4641
4968
|
showCustomControls: false,
|
|
4642
4969
|
licenseKey: "",
|
|
4643
4970
|
adFailsafeTimeoutMs: 1e4,
|
|
4971
|
+
minSegmentsBeforePlay: 2,
|
|
4644
4972
|
onStart: noop,
|
|
4645
4973
|
onPlay: noop,
|
|
4646
4974
|
onPause: noop,
|
|
@@ -4814,6 +5142,8 @@ var HlsPlayer = class extends import_react3.Component {
|
|
|
4814
5142
|
config.licenseKey = this.props.licenseKey;
|
|
4815
5143
|
if (this.props.adFailsafeTimeoutMs !== void 0)
|
|
4816
5144
|
config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;
|
|
5145
|
+
if (this.props.minSegmentsBeforePlay !== void 0)
|
|
5146
|
+
config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;
|
|
4817
5147
|
this.player = new StormcloudVideoPlayer(config);
|
|
4818
5148
|
(_b = (_a = this.props).onMount) == null ? void 0 : _b.call(_a, this);
|
|
4819
5149
|
await this.player.load();
|
|
@@ -5420,6 +5750,7 @@ var SUPPORTED_PROPS = [
|
|
|
5420
5750
|
"showCustomControls",
|
|
5421
5751
|
"licenseKey",
|
|
5422
5752
|
"adFailsafeTimeoutMs",
|
|
5753
|
+
"minSegmentsBeforePlay",
|
|
5423
5754
|
"onReady",
|
|
5424
5755
|
"onStart",
|
|
5425
5756
|
"onPlay",
|