stormcloud-video-player 0.2.17 → 0.2.19
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 +403 -56
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +8 -0
- package/lib/index.d.ts +8 -0
- package/lib/index.js +403 -56
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +282 -23
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +5 -1
- package/lib/players/HlsPlayer.cjs +284 -23
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +284 -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 +35 -0
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/sdk/ima.d.cts +1 -1
- package/lib/{types-mVgmKmzM.d.cts → types-D1xfSdLP.d.cts} +3 -0
- package/lib/ui/StormcloudVideoPlayer.cjs +399 -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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Component } from 'react';
|
|
2
|
-
import { S as StormcloudVideoPlayerConfig } from '../types-
|
|
2
|
+
import { S as StormcloudVideoPlayerConfig } from '../types-D1xfSdLP.cjs';
|
|
3
3
|
|
|
4
4
|
interface HlsPlayerProps extends StormcloudVideoPlayerConfig {
|
|
5
5
|
onMount?: (player: any) => void;
|
package/lib/players/index.cjs
CHANGED
|
@@ -242,6 +242,13 @@ function createImaController(video, options) {
|
|
|
242
242
|
let adPlaying = false;
|
|
243
243
|
let originalMutedState = false;
|
|
244
244
|
const listeners = /* @__PURE__ */ new Map();
|
|
245
|
+
function setAdPlayingFlag(isPlaying) {
|
|
246
|
+
if (isPlaying) {
|
|
247
|
+
video.dataset.stormcloudAdPlaying = "true";
|
|
248
|
+
} else {
|
|
249
|
+
delete video.dataset.stormcloudAdPlaying;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
245
252
|
function emit(event, payload) {
|
|
246
253
|
const set = listeners.get(event);
|
|
247
254
|
if (!set) return;
|
|
@@ -484,7 +491,12 @@ function createImaController(video, options) {
|
|
|
484
491
|
console.error("[IMA] Ad error:", errorEvent.getError());
|
|
485
492
|
destroyAdsManager();
|
|
486
493
|
adPlaying = false;
|
|
494
|
+
const previousMutedState = video.muted;
|
|
487
495
|
video.muted = originalMutedState;
|
|
496
|
+
setAdPlayingFlag(false);
|
|
497
|
+
console.log(
|
|
498
|
+
`[IMA] Restored mute state after ad error: ${previousMutedState} -> ${originalMutedState}`
|
|
499
|
+
);
|
|
488
500
|
if (adContainerEl) {
|
|
489
501
|
adContainerEl.style.pointerEvents = "none";
|
|
490
502
|
adContainerEl.style.display = "none";
|
|
@@ -537,11 +549,13 @@ function createImaController(video, options) {
|
|
|
537
549
|
}
|
|
538
550
|
video.muted = true;
|
|
539
551
|
adPlaying = true;
|
|
552
|
+
setAdPlayingFlag(true);
|
|
540
553
|
emit("content_pause");
|
|
541
554
|
}
|
|
542
555
|
);
|
|
543
556
|
adsManager.addEventListener(AdEvent.STARTED, () => {
|
|
544
557
|
console.log("[IMA] Ad started playing");
|
|
558
|
+
setAdPlayingFlag(true);
|
|
545
559
|
if (adContainerEl) {
|
|
546
560
|
adContainerEl.style.pointerEvents = "auto";
|
|
547
561
|
adContainerEl.style.display = "flex";
|
|
@@ -557,6 +571,7 @@ function createImaController(video, options) {
|
|
|
557
571
|
console.log("[IMA] Content resume requested");
|
|
558
572
|
adPlaying = false;
|
|
559
573
|
video.muted = originalMutedState;
|
|
574
|
+
setAdPlayingFlag(false);
|
|
560
575
|
if (adContainerEl) {
|
|
561
576
|
adContainerEl.style.pointerEvents = "none";
|
|
562
577
|
adContainerEl.style.display = "none";
|
|
@@ -580,6 +595,7 @@ function createImaController(video, options) {
|
|
|
580
595
|
console.log("[IMA] All ads completed");
|
|
581
596
|
adPlaying = false;
|
|
582
597
|
video.muted = originalMutedState;
|
|
598
|
+
setAdPlayingFlag(false);
|
|
583
599
|
if (adContainerEl) {
|
|
584
600
|
adContainerEl.style.pointerEvents = "none";
|
|
585
601
|
adContainerEl.style.display = "none";
|
|
@@ -610,6 +626,7 @@ function createImaController(video, options) {
|
|
|
610
626
|
console.error("[IMA] Error setting up ads manager:", e);
|
|
611
627
|
adPlaying = false;
|
|
612
628
|
video.muted = originalMutedState;
|
|
629
|
+
setAdPlayingFlag(false);
|
|
613
630
|
if (adContainerEl) {
|
|
614
631
|
adContainerEl.style.pointerEvents = "none";
|
|
615
632
|
adContainerEl.style.display = "none";
|
|
@@ -639,7 +656,12 @@ function createImaController(video, options) {
|
|
|
639
656
|
(adErrorEvent) => {
|
|
640
657
|
console.error("[IMA] Ads loader error:", adErrorEvent.getError());
|
|
641
658
|
adPlaying = false;
|
|
659
|
+
const previousMutedState = video.muted;
|
|
642
660
|
video.muted = originalMutedState;
|
|
661
|
+
setAdPlayingFlag(false);
|
|
662
|
+
console.log(
|
|
663
|
+
`[IMA] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
664
|
+
);
|
|
643
665
|
if (adContainerEl) {
|
|
644
666
|
adContainerEl.style.pointerEvents = "none";
|
|
645
667
|
adContainerEl.style.display = "none";
|
|
@@ -691,12 +713,20 @@ function createImaController(video, options) {
|
|
|
691
713
|
console.log(`[IMA] Initializing ads manager (${width}x${height})`);
|
|
692
714
|
adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);
|
|
693
715
|
adPlaying = true;
|
|
716
|
+
const adVolume = originalMutedState ? 0 : video.volume;
|
|
717
|
+
try {
|
|
718
|
+
adsManager.setVolume(adVolume);
|
|
719
|
+
console.log(`[IMA] Set ad volume to ${adVolume}`);
|
|
720
|
+
} catch (error) {
|
|
721
|
+
console.warn("[IMA] Failed to set ad volume:", error);
|
|
722
|
+
}
|
|
694
723
|
console.log("[IMA] Starting ad playback");
|
|
695
724
|
adsManager.start();
|
|
696
725
|
return Promise.resolve();
|
|
697
726
|
} catch (error) {
|
|
698
727
|
console.error("[IMA] Error starting ad playback:", error);
|
|
699
728
|
adPlaying = false;
|
|
729
|
+
setAdPlayingFlag(false);
|
|
700
730
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
701
731
|
(_b = video.play()) == null ? void 0 : _b.catch(() => {
|
|
702
732
|
});
|
|
@@ -708,6 +738,7 @@ function createImaController(video, options) {
|
|
|
708
738
|
var _a;
|
|
709
739
|
adPlaying = false;
|
|
710
740
|
video.muted = originalMutedState;
|
|
741
|
+
setAdPlayingFlag(false);
|
|
711
742
|
if (adContainerEl) {
|
|
712
743
|
adContainerEl.style.pointerEvents = "none";
|
|
713
744
|
adContainerEl.style.display = "none";
|
|
@@ -731,6 +762,7 @@ function createImaController(video, options) {
|
|
|
731
762
|
destroyAdsManager();
|
|
732
763
|
adPlaying = false;
|
|
733
764
|
video.muted = originalMutedState;
|
|
765
|
+
setAdPlayingFlag(false);
|
|
734
766
|
if (adContainerEl) {
|
|
735
767
|
adContainerEl.style.pointerEvents = "none";
|
|
736
768
|
adContainerEl.style.display = "none";
|
|
@@ -773,6 +805,9 @@ function createImaController(video, options) {
|
|
|
773
805
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
774
806
|
},
|
|
775
807
|
updateOriginalMutedState(muted) {
|
|
808
|
+
console.log(
|
|
809
|
+
`[IMA] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
810
|
+
);
|
|
776
811
|
originalMutedState = muted;
|
|
777
812
|
},
|
|
778
813
|
getOriginalMutedState() {
|
|
@@ -829,7 +864,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
829
864
|
try {
|
|
830
865
|
fn(payload);
|
|
831
866
|
} catch (error) {
|
|
832
|
-
console.warn(
|
|
867
|
+
console.warn(
|
|
868
|
+
`[HlsAdPlayer] Error in event listener for ${event}:`,
|
|
869
|
+
error
|
|
870
|
+
);
|
|
833
871
|
}
|
|
834
872
|
}
|
|
835
873
|
}
|
|
@@ -892,7 +930,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
892
930
|
}
|
|
893
931
|
const mainQuality = getMainStreamQuality();
|
|
894
932
|
if (!mainQuality) {
|
|
895
|
-
console.log(
|
|
933
|
+
console.log(
|
|
934
|
+
"[HlsAdPlayer] No main stream quality info, using first media file"
|
|
935
|
+
);
|
|
896
936
|
return firstFile;
|
|
897
937
|
}
|
|
898
938
|
console.log("[HlsAdPlayer] Main stream quality:", mainQuality);
|
|
@@ -928,7 +968,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
928
968
|
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
|
|
929
969
|
const parserError = xmlDoc.querySelector("parsererror");
|
|
930
970
|
if (parserError) {
|
|
931
|
-
console.error(
|
|
971
|
+
console.error(
|
|
972
|
+
"[HlsAdPlayer] XML parsing error (malformed VAST XML):",
|
|
973
|
+
parserError.textContent
|
|
974
|
+
);
|
|
932
975
|
return null;
|
|
933
976
|
}
|
|
934
977
|
const adElement = xmlDoc.querySelector("Ad");
|
|
@@ -944,17 +987,23 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
944
987
|
const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
|
|
945
988
|
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
946
989
|
const mediaFiles = [];
|
|
947
|
-
console.log(
|
|
990
|
+
console.log(
|
|
991
|
+
`[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`
|
|
992
|
+
);
|
|
948
993
|
mediaFileElements.forEach((mf, index) => {
|
|
949
994
|
var _a2;
|
|
950
995
|
const type = mf.getAttribute("type") || "";
|
|
951
996
|
const url = ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "";
|
|
952
997
|
const width = mf.getAttribute("width") || "";
|
|
953
998
|
const height = mf.getAttribute("height") || "";
|
|
954
|
-
console.log(
|
|
999
|
+
console.log(
|
|
1000
|
+
`[HlsAdPlayer] MediaFile ${index}: type="${type}", url="${url}", width="${width}", height="${height}"`
|
|
1001
|
+
);
|
|
955
1002
|
if (type === "application/x-mpegURL" || type.includes("m3u8")) {
|
|
956
1003
|
if (!url) {
|
|
957
|
-
console.warn(
|
|
1004
|
+
console.warn(
|
|
1005
|
+
`[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`
|
|
1006
|
+
);
|
|
958
1007
|
return;
|
|
959
1008
|
}
|
|
960
1009
|
const bitrateAttr = mf.getAttribute("bitrate");
|
|
@@ -968,12 +1017,16 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
968
1017
|
});
|
|
969
1018
|
console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);
|
|
970
1019
|
} else {
|
|
971
|
-
console.log(
|
|
1020
|
+
console.log(
|
|
1021
|
+
`[HlsAdPlayer] MediaFile ${index} ignored (type="${type}" is not HLS)`
|
|
1022
|
+
);
|
|
972
1023
|
}
|
|
973
1024
|
});
|
|
974
1025
|
if (mediaFiles.length === 0) {
|
|
975
1026
|
if (isNoAdAvailable) {
|
|
976
|
-
console.warn(
|
|
1027
|
+
console.warn(
|
|
1028
|
+
"[HlsAdPlayer] No ads available (VAST response indicates no ads)"
|
|
1029
|
+
);
|
|
977
1030
|
} else {
|
|
978
1031
|
console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
|
|
979
1032
|
}
|
|
@@ -1036,6 +1089,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1036
1089
|
video.style.backgroundColor = "#000";
|
|
1037
1090
|
video.playsInline = true;
|
|
1038
1091
|
video.muted = false;
|
|
1092
|
+
video.volume = 1;
|
|
1093
|
+
console.log(
|
|
1094
|
+
`[HlsAdPlayer] Created ad video element with volume ${video.volume}`
|
|
1095
|
+
);
|
|
1039
1096
|
return video;
|
|
1040
1097
|
}
|
|
1041
1098
|
function setupAdEventListeners() {
|
|
@@ -1095,10 +1152,22 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1095
1152
|
}
|
|
1096
1153
|
});
|
|
1097
1154
|
}
|
|
1155
|
+
function setAdPlayingFlag(isPlaying) {
|
|
1156
|
+
if (isPlaying) {
|
|
1157
|
+
contentVideo.dataset.stormcloudAdPlaying = "true";
|
|
1158
|
+
} else {
|
|
1159
|
+
delete contentVideo.dataset.stormcloudAdPlaying;
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1098
1162
|
function handleAdComplete() {
|
|
1099
1163
|
console.log("[HlsAdPlayer] Handling ad completion");
|
|
1100
1164
|
adPlaying = false;
|
|
1165
|
+
setAdPlayingFlag(false);
|
|
1166
|
+
const previousMutedState = contentVideo.muted;
|
|
1101
1167
|
contentVideo.muted = originalMutedState;
|
|
1168
|
+
console.log(
|
|
1169
|
+
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
1170
|
+
);
|
|
1102
1171
|
if (adContainerEl) {
|
|
1103
1172
|
adContainerEl.style.display = "none";
|
|
1104
1173
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -1116,7 +1185,12 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1116
1185
|
function handleAdError() {
|
|
1117
1186
|
console.log("[HlsAdPlayer] Handling ad error");
|
|
1118
1187
|
adPlaying = false;
|
|
1188
|
+
setAdPlayingFlag(false);
|
|
1189
|
+
const previousMutedState = contentVideo.muted;
|
|
1119
1190
|
contentVideo.muted = originalMutedState;
|
|
1191
|
+
console.log(
|
|
1192
|
+
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
1193
|
+
);
|
|
1120
1194
|
if (adContainerEl) {
|
|
1121
1195
|
adContainerEl.style.display = "none";
|
|
1122
1196
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -1153,7 +1227,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1153
1227
|
async requestAds(vastTagUrl) {
|
|
1154
1228
|
console.log("[HlsAdPlayer] Requesting ads:", vastTagUrl);
|
|
1155
1229
|
if (adPlaying) {
|
|
1156
|
-
console.warn(
|
|
1230
|
+
console.warn(
|
|
1231
|
+
"[HlsAdPlayer] Cannot request new ads while an ad is playing"
|
|
1232
|
+
);
|
|
1157
1233
|
return Promise.reject(new Error("Ad already playing"));
|
|
1158
1234
|
}
|
|
1159
1235
|
try {
|
|
@@ -1164,14 +1240,20 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1164
1240
|
}
|
|
1165
1241
|
const vastXml = await response.text();
|
|
1166
1242
|
console.log("[HlsAdPlayer] VAST XML received");
|
|
1167
|
-
console.log(
|
|
1243
|
+
console.log(
|
|
1244
|
+
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1245
|
+
vastXml.substring(0, 2e3)
|
|
1246
|
+
);
|
|
1168
1247
|
const ad = parseVastXml(vastXml);
|
|
1169
1248
|
if (!ad) {
|
|
1170
1249
|
console.warn("[HlsAdPlayer] No ads available from VAST response");
|
|
1250
|
+
emit("ad_error");
|
|
1171
1251
|
return Promise.resolve();
|
|
1172
1252
|
}
|
|
1173
1253
|
currentAd = ad;
|
|
1174
|
-
console.log(
|
|
1254
|
+
console.log(
|
|
1255
|
+
`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`
|
|
1256
|
+
);
|
|
1175
1257
|
fireTrackingPixels(ad.trackingUrls.impression);
|
|
1176
1258
|
trackingFired.impression = true;
|
|
1177
1259
|
return Promise.resolve();
|
|
@@ -1183,7 +1265,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1183
1265
|
},
|
|
1184
1266
|
async play() {
|
|
1185
1267
|
if (!currentAd) {
|
|
1186
|
-
console.warn(
|
|
1268
|
+
console.warn(
|
|
1269
|
+
"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)"
|
|
1270
|
+
);
|
|
1187
1271
|
return Promise.reject(new Error("No ad loaded"));
|
|
1188
1272
|
}
|
|
1189
1273
|
console.log("[HlsAdPlayer] Starting ad playback");
|
|
@@ -1201,6 +1285,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1201
1285
|
thirdQuartile: false,
|
|
1202
1286
|
complete: false
|
|
1203
1287
|
};
|
|
1288
|
+
const contentVolume = contentVideo.volume;
|
|
1204
1289
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1205
1290
|
contentVideo.pause();
|
|
1206
1291
|
console.log("[HlsAdPlayer] Content paused (VOD mode)");
|
|
@@ -1209,6 +1294,15 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1209
1294
|
}
|
|
1210
1295
|
contentVideo.muted = true;
|
|
1211
1296
|
adPlaying = true;
|
|
1297
|
+
setAdPlayingFlag(true);
|
|
1298
|
+
if (adVideoElement) {
|
|
1299
|
+
const adVolume = originalMutedState ? 0 : contentVolume;
|
|
1300
|
+
adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
|
|
1301
|
+
adVideoElement.muted = false;
|
|
1302
|
+
console.log(
|
|
1303
|
+
`[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`
|
|
1304
|
+
);
|
|
1305
|
+
}
|
|
1212
1306
|
if (adContainerEl) {
|
|
1213
1307
|
adContainerEl.style.display = "flex";
|
|
1214
1308
|
adContainerEl.style.pointerEvents = "auto";
|
|
@@ -1261,6 +1355,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1261
1355
|
async stop() {
|
|
1262
1356
|
console.log("[HlsAdPlayer] Stopping ad");
|
|
1263
1357
|
adPlaying = false;
|
|
1358
|
+
setAdPlayingFlag(false);
|
|
1264
1359
|
contentVideo.muted = originalMutedState;
|
|
1265
1360
|
if (adContainerEl) {
|
|
1266
1361
|
adContainerEl.style.display = "none";
|
|
@@ -1283,6 +1378,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1283
1378
|
destroy() {
|
|
1284
1379
|
console.log("[HlsAdPlayer] Destroying");
|
|
1285
1380
|
adPlaying = false;
|
|
1381
|
+
setAdPlayingFlag(false);
|
|
1286
1382
|
contentVideo.muted = originalMutedState;
|
|
1287
1383
|
if (adHls) {
|
|
1288
1384
|
adHls.destroy();
|
|
@@ -1324,6 +1420,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1324
1420
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
1325
1421
|
},
|
|
1326
1422
|
updateOriginalMutedState(muted) {
|
|
1423
|
+
console.log(
|
|
1424
|
+
`[HlsAdPlayer] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
1425
|
+
);
|
|
1327
1426
|
originalMutedState = muted;
|
|
1328
1427
|
},
|
|
1329
1428
|
getOriginalMutedState() {
|
|
@@ -1816,6 +1915,9 @@ var StormcloudVideoPlayer = class {
|
|
|
1816
1915
|
this.isLiveStream = false;
|
|
1817
1916
|
this.nativeHlsMode = false;
|
|
1818
1917
|
this.videoSrcProtection = null;
|
|
1918
|
+
this.bufferedSegmentsCount = 0;
|
|
1919
|
+
this.shouldAutoplayAfterBuffering = false;
|
|
1920
|
+
this.hasInitialBufferCompleted = false;
|
|
1819
1921
|
initializePolyfills();
|
|
1820
1922
|
const browserOverrides = getBrowserConfigOverrides();
|
|
1821
1923
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -1902,14 +2004,22 @@ var StormcloudVideoPlayer = class {
|
|
|
1902
2004
|
liveDurationInfinity: true,
|
|
1903
2005
|
lowLatencyMode: !!this.config.lowLatencyMode,
|
|
1904
2006
|
maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1,
|
|
1905
|
-
...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}
|
|
2007
|
+
...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {},
|
|
2008
|
+
maxBufferLength: 30,
|
|
2009
|
+
maxMaxBufferLength: 600,
|
|
2010
|
+
maxBufferSize: 60 * 1e3 * 1e3,
|
|
2011
|
+
maxBufferHole: 0.5,
|
|
2012
|
+
highBufferWatchdogPeriod: 2,
|
|
2013
|
+
nudgeOffset: 0.1,
|
|
2014
|
+
nudgeMaxRetry: 3,
|
|
2015
|
+
startPosition: -1
|
|
1906
2016
|
});
|
|
1907
2017
|
this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, () => {
|
|
1908
2018
|
var _a2;
|
|
1909
2019
|
(_a2 = this.hls) == null ? void 0 : _a2.loadSource(this.config.src);
|
|
1910
2020
|
});
|
|
1911
2021
|
this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, async (_, data) => {
|
|
1912
|
-
var _a2, _b2, _c, _d;
|
|
2022
|
+
var _a2, _b2, _c, _d, _e;
|
|
1913
2023
|
this.isLiveStream = (_c = (_b2 = (_a2 = this.hls) == null ? void 0 : _a2.levels) == null ? void 0 : _b2.some(
|
|
1914
2024
|
(level) => {
|
|
1915
2025
|
var _a3, _b3;
|
|
@@ -1927,9 +2037,51 @@ var StormcloudVideoPlayer = class {
|
|
|
1927
2037
|
this.ima.destroy();
|
|
1928
2038
|
this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());
|
|
1929
2039
|
this.ima.initialize();
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
2040
|
+
this.bufferedSegmentsCount = 0;
|
|
2041
|
+
this.hasInitialBufferCompleted = false;
|
|
2042
|
+
this.shouldAutoplayAfterBuffering = !!this.config.autoplay;
|
|
2043
|
+
const minSegments = (_d = this.config.minSegmentsBeforePlay) != null ? _d : 2;
|
|
2044
|
+
if (this.config.debugAdTiming) {
|
|
2045
|
+
console.log(
|
|
2046
|
+
"[StormcloudVideoPlayer] Waiting for",
|
|
2047
|
+
minSegments,
|
|
2048
|
+
"segments to buffer before playback"
|
|
2049
|
+
);
|
|
2050
|
+
}
|
|
2051
|
+
if (minSegments === 0 || !this.config.autoplay) {
|
|
2052
|
+
this.hasInitialBufferCompleted = true;
|
|
2053
|
+
if (this.config.autoplay) {
|
|
2054
|
+
await ((_e = this.video.play()) == null ? void 0 : _e.catch(() => {
|
|
2055
|
+
}));
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
});
|
|
2059
|
+
this.hls.on(import_hls2.default.Events.FRAG_BUFFERED, async (_evt, data) => {
|
|
2060
|
+
var _a2, _b2;
|
|
2061
|
+
if (this.hasInitialBufferCompleted) {
|
|
2062
|
+
return;
|
|
2063
|
+
}
|
|
2064
|
+
this.bufferedSegmentsCount++;
|
|
2065
|
+
const minSegments = (_a2 = this.config.minSegmentsBeforePlay) != null ? _a2 : 2;
|
|
2066
|
+
if (this.config.debugAdTiming) {
|
|
2067
|
+
console.log(
|
|
2068
|
+
`[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`
|
|
2069
|
+
);
|
|
2070
|
+
}
|
|
2071
|
+
if (this.bufferedSegmentsCount >= minSegments) {
|
|
2072
|
+
this.hasInitialBufferCompleted = true;
|
|
2073
|
+
if (this.shouldAutoplayAfterBuffering) {
|
|
2074
|
+
if (this.config.debugAdTiming) {
|
|
2075
|
+
console.log(
|
|
2076
|
+
`[StormcloudVideoPlayer] Initial buffer complete (${this.bufferedSegmentsCount} segments). Starting playback.`
|
|
2077
|
+
);
|
|
2078
|
+
}
|
|
2079
|
+
await ((_b2 = this.video.play()) == null ? void 0 : _b2.catch((err) => {
|
|
2080
|
+
if (this.config.debugAdTiming) {
|
|
2081
|
+
console.warn("[StormcloudVideoPlayer] Autoplay failed:", err);
|
|
2082
|
+
}
|
|
2083
|
+
}));
|
|
2084
|
+
}
|
|
1933
2085
|
}
|
|
1934
2086
|
});
|
|
1935
2087
|
this.hls.on(import_hls2.default.Events.FRAG_PARSING_METADATA, (_evt, data) => {
|
|
@@ -2025,6 +2177,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2025
2177
|
this.video.autoplay = !!this.config.autoplay;
|
|
2026
2178
|
this.video.muted = !!this.config.muted;
|
|
2027
2179
|
this.ima.initialize();
|
|
2180
|
+
this.ima.updateOriginalMutedState(this.video.muted);
|
|
2028
2181
|
this.ima.on("all_ads_completed", () => {
|
|
2029
2182
|
if (this.config.debugAdTiming) {
|
|
2030
2183
|
console.log(
|
|
@@ -2762,14 +2915,66 @@ var StormcloudVideoPlayer = class {
|
|
|
2762
2915
|
}
|
|
2763
2916
|
}
|
|
2764
2917
|
ensureAdStoppedByTimer() {
|
|
2918
|
+
var _a, _b;
|
|
2765
2919
|
if (!this.inAdBreak) return;
|
|
2920
|
+
this.adStopTimerId = void 0;
|
|
2921
|
+
const adPlaying = this.ima.isAdPlaying();
|
|
2922
|
+
const pendingAds = this.adPodQueue.length > 0;
|
|
2923
|
+
const checkIntervalMs = Math.max(
|
|
2924
|
+
250,
|
|
2925
|
+
Math.floor((_a = this.config.adBreakCheckIntervalMs) != null ? _a : 1e3)
|
|
2926
|
+
);
|
|
2927
|
+
const maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;
|
|
2928
|
+
const maxExtensionMs = typeof maxExtensionMsConfig === "number" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 6e4;
|
|
2929
|
+
let elapsedSinceStartMs = 0;
|
|
2930
|
+
if (this.currentAdBreakStartWallClockMs != null) {
|
|
2931
|
+
elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;
|
|
2932
|
+
}
|
|
2933
|
+
const expectedDurationMs = (_b = this.expectedAdBreakDurationMs) != null ? _b : 0;
|
|
2934
|
+
const overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);
|
|
2935
|
+
const shouldExtendAdBreak = (adPlaying || pendingAds || this.showAds) && overrunMs < maxExtensionMs;
|
|
2936
|
+
if (shouldExtendAdBreak) {
|
|
2937
|
+
if (this.config.debugAdTiming) {
|
|
2938
|
+
console.log(
|
|
2939
|
+
"[StormcloudVideoPlayer] Extending ad break beyond scheduled duration",
|
|
2940
|
+
{
|
|
2941
|
+
adPlaying,
|
|
2942
|
+
pendingAds,
|
|
2943
|
+
showAds: this.showAds,
|
|
2944
|
+
overrunMs,
|
|
2945
|
+
checkIntervalMs,
|
|
2946
|
+
maxExtensionMs
|
|
2947
|
+
}
|
|
2948
|
+
);
|
|
2949
|
+
}
|
|
2950
|
+
this.scheduleAdStopCountdown(checkIntervalMs);
|
|
2951
|
+
return;
|
|
2952
|
+
}
|
|
2953
|
+
if (this.config.debugAdTiming) {
|
|
2954
|
+
console.log("[StormcloudVideoPlayer] Ending ad break via timer", {
|
|
2955
|
+
adPlaying,
|
|
2956
|
+
pendingAds,
|
|
2957
|
+
showAds: this.showAds,
|
|
2958
|
+
overrunMs,
|
|
2959
|
+
maxExtensionMs
|
|
2960
|
+
});
|
|
2961
|
+
}
|
|
2766
2962
|
this.inAdBreak = false;
|
|
2767
2963
|
this.expectedAdBreakDurationMs = void 0;
|
|
2768
2964
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
2769
|
-
this.
|
|
2770
|
-
|
|
2965
|
+
this.showAds = false;
|
|
2966
|
+
this.adPodQueue = [];
|
|
2967
|
+
this.currentAdIndex = 0;
|
|
2968
|
+
this.totalAdsInBreak = 0;
|
|
2969
|
+
this.clearAdFailsafeTimer();
|
|
2970
|
+
if (adPlaying) {
|
|
2771
2971
|
this.ima.stop().catch(() => {
|
|
2772
2972
|
});
|
|
2973
|
+
return;
|
|
2974
|
+
}
|
|
2975
|
+
const originalMutedState = this.ima.getOriginalMutedState();
|
|
2976
|
+
if (this.video.muted !== originalMutedState) {
|
|
2977
|
+
this.video.muted = originalMutedState;
|
|
2773
2978
|
}
|
|
2774
2979
|
}
|
|
2775
2980
|
scheduleAdStartIn(delayMs) {
|
|
@@ -2809,7 +3014,23 @@ var StormcloudVideoPlayer = class {
|
|
|
2809
3014
|
}
|
|
2810
3015
|
return;
|
|
2811
3016
|
}
|
|
2812
|
-
|
|
3017
|
+
if (!this.showAds) {
|
|
3018
|
+
if (this.config.debugAdTiming) {
|
|
3019
|
+
console.log(
|
|
3020
|
+
`[StormcloudVideoPlayer] Capturing original state before ad request:`,
|
|
3021
|
+
{
|
|
3022
|
+
videoMuted: this.video.muted,
|
|
3023
|
+
videoVolume: this.video.volume,
|
|
3024
|
+
showAds: this.showAds
|
|
3025
|
+
}
|
|
3026
|
+
);
|
|
3027
|
+
}
|
|
3028
|
+
this.ima.updateOriginalMutedState(this.video.muted);
|
|
3029
|
+
} else if (this.config.debugAdTiming) {
|
|
3030
|
+
console.log(
|
|
3031
|
+
`[StormcloudVideoPlayer] Keeping existing original mute state (currently showing ads)`
|
|
3032
|
+
);
|
|
3033
|
+
}
|
|
2813
3034
|
this.startAdFailsafeTimer();
|
|
2814
3035
|
try {
|
|
2815
3036
|
await this.ima.requestAds(vastTagUrl);
|
|
@@ -2864,11 +3085,12 @@ var StormcloudVideoPlayer = class {
|
|
|
2864
3085
|
this.showAds = false;
|
|
2865
3086
|
this.currentAdIndex = 0;
|
|
2866
3087
|
this.totalAdsInBreak = 0;
|
|
3088
|
+
const currentMutedState = this.video.muted;
|
|
2867
3089
|
const originalMutedState = this.ima.getOriginalMutedState();
|
|
2868
3090
|
this.video.muted = originalMutedState;
|
|
2869
3091
|
if (this.config.debugAdTiming) {
|
|
2870
3092
|
console.log(
|
|
2871
|
-
`[StormcloudVideoPlayer] Restored mute state
|
|
3093
|
+
`[StormcloudVideoPlayer] Restored mute state: ${currentMutedState} -> ${originalMutedState}`
|
|
2872
3094
|
);
|
|
2873
3095
|
}
|
|
2874
3096
|
if (this.video.paused) {
|
|
@@ -2960,6 +3182,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2960
3182
|
}
|
|
2961
3183
|
} else {
|
|
2962
3184
|
this.video.muted = !this.video.muted;
|
|
3185
|
+
this.ima.updateOriginalMutedState(this.video.muted);
|
|
2963
3186
|
if (this.config.debugAdTiming) {
|
|
2964
3187
|
console.log("[StormcloudVideoPlayer] Muted:", this.video.muted);
|
|
2965
3188
|
}
|
|
@@ -3004,11 +3227,47 @@ var StormcloudVideoPlayer = class {
|
|
|
3004
3227
|
}
|
|
3005
3228
|
isMuted() {
|
|
3006
3229
|
if (this.ima.isAdPlaying()) {
|
|
3007
|
-
|
|
3008
|
-
|
|
3230
|
+
if (this.config.debugAdTiming) {
|
|
3231
|
+
console.log(
|
|
3232
|
+
"[StormcloudVideoPlayer] isMuted() override during ad playback -> false"
|
|
3233
|
+
);
|
|
3234
|
+
}
|
|
3235
|
+
return false;
|
|
3236
|
+
}
|
|
3237
|
+
if (this.config.debugAdTiming) {
|
|
3238
|
+
console.log(
|
|
3239
|
+
`[StormcloudVideoPlayer] isMuted() no ad playing: video.muted=${this.video.muted}`
|
|
3240
|
+
);
|
|
3009
3241
|
}
|
|
3010
3242
|
return this.video.muted;
|
|
3011
3243
|
}
|
|
3244
|
+
setMuted(muted) {
|
|
3245
|
+
const adPlaying = this.ima.isAdPlaying();
|
|
3246
|
+
if (adPlaying && muted === this.video.muted) {
|
|
3247
|
+
if (this.config.debugAdTiming) {
|
|
3248
|
+
console.log(
|
|
3249
|
+
"[StormcloudVideoPlayer] setMuted reflective update during ad ignored",
|
|
3250
|
+
{ muted }
|
|
3251
|
+
);
|
|
3252
|
+
}
|
|
3253
|
+
return;
|
|
3254
|
+
}
|
|
3255
|
+
this.video.muted = muted;
|
|
3256
|
+
if (adPlaying) {
|
|
3257
|
+
this.ima.updateOriginalMutedState(muted);
|
|
3258
|
+
this.ima.setAdVolume(muted ? 0 : 1);
|
|
3259
|
+
if (this.config.debugAdTiming) {
|
|
3260
|
+
console.log("[StormcloudVideoPlayer] setMuted applied during ad", {
|
|
3261
|
+
muted
|
|
3262
|
+
});
|
|
3263
|
+
}
|
|
3264
|
+
return;
|
|
3265
|
+
}
|
|
3266
|
+
this.ima.updateOriginalMutedState(muted);
|
|
3267
|
+
if (this.config.debugAdTiming) {
|
|
3268
|
+
console.log("[StormcloudVideoPlayer] setMuted called:", muted);
|
|
3269
|
+
}
|
|
3270
|
+
}
|
|
3012
3271
|
isFullscreen() {
|
|
3013
3272
|
return !!document.fullscreenElement;
|
|
3014
3273
|
}
|
|
@@ -3090,6 +3349,8 @@ var HlsPlayer = class extends import_react2.Component {
|
|
|
3090
3349
|
config.licenseKey = this.props.licenseKey;
|
|
3091
3350
|
if (this.props.adFailsafeTimeoutMs !== void 0)
|
|
3092
3351
|
config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;
|
|
3352
|
+
if (this.props.minSegmentsBeforePlay !== void 0)
|
|
3353
|
+
config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;
|
|
3093
3354
|
this.player = new StormcloudVideoPlayer(config);
|
|
3094
3355
|
(_b = (_a = this.props).onMount) == null ? void 0 : _b.call(_a, this);
|
|
3095
3356
|
await this.player.load();
|