stormcloud-video-player 0.2.24 → 0.2.26
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 +305 -45
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +12 -1
- package/lib/index.d.ts +12 -1
- package/lib/index.js +305 -45
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +305 -45
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +7 -1
- package/lib/players/HlsPlayer.cjs +305 -45
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +305 -45
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +102 -13
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.d.cts +1 -1
- package/lib/sdk/ima.cjs +113 -22
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/sdk/ima.d.cts +1 -1
- package/lib/{types-D1xfSdLP.d.cts → types-t9jEJXZy.d.cts} +6 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +305 -45
- 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
|
@@ -199,7 +199,10 @@ function getBrowserConfigOverrides() {
|
|
|
199
199
|
function createImaController(video, options) {
|
|
200
200
|
let adPlaying = false;
|
|
201
201
|
let originalMutedState = false;
|
|
202
|
+
let originalVolume = typeof video.volume === "number" && !Number.isNaN(video.volume) ? Math.max(0, Math.min(1, video.volume)) : 1;
|
|
202
203
|
const listeners = /* @__PURE__ */ new Map();
|
|
204
|
+
const preloadedVast = /* @__PURE__ */ new Map();
|
|
205
|
+
const preloadingVast = /* @__PURE__ */ new Map();
|
|
203
206
|
function setAdPlayingFlag(isPlaying) {
|
|
204
207
|
if (isPlaying) {
|
|
205
208
|
video.dataset.stormcloudAdPlaying = "true";
|
|
@@ -290,16 +293,70 @@ function createImaController(video, options) {
|
|
|
290
293
|
let adsLoadedReject;
|
|
291
294
|
function makeAdsRequest(google, vastTagUrl) {
|
|
292
295
|
const adsRequest = new google.ima.AdsRequest();
|
|
293
|
-
|
|
296
|
+
const preloadedResponse = preloadedVast.get(vastTagUrl);
|
|
297
|
+
if (preloadedResponse) {
|
|
298
|
+
adsRequest.adsResponse = preloadedResponse;
|
|
299
|
+
console.log(
|
|
300
|
+
"[IMA] Using preloaded VAST response for immediate ad request"
|
|
301
|
+
);
|
|
302
|
+
} else {
|
|
303
|
+
adsRequest.adTagUrl = vastTagUrl;
|
|
304
|
+
}
|
|
294
305
|
const videoWidth = video.offsetWidth || video.clientWidth || 640;
|
|
295
306
|
const videoHeight = video.offsetHeight || video.clientHeight || 360;
|
|
296
307
|
adsRequest.linearAdSlotWidth = videoWidth;
|
|
297
308
|
adsRequest.linearAdSlotHeight = videoHeight;
|
|
298
309
|
adsRequest.nonLinearAdSlotWidth = videoWidth;
|
|
299
310
|
adsRequest.nonLinearAdSlotHeight = videoHeight;
|
|
311
|
+
if (typeof adsRequest.setAdWillAutoPlay === "function") {
|
|
312
|
+
try {
|
|
313
|
+
const willAutoPlay = !video.paused || video.autoplay;
|
|
314
|
+
adsRequest.setAdWillAutoPlay(willAutoPlay);
|
|
315
|
+
} catch (error) {
|
|
316
|
+
console.warn("[IMA] Failed to call setAdWillAutoPlay:", error);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (typeof adsRequest.setAdWillPlayMuted === "function") {
|
|
320
|
+
try {
|
|
321
|
+
const willPlayMuted = video.muted || video.volume === 0;
|
|
322
|
+
adsRequest.setAdWillPlayMuted(willPlayMuted);
|
|
323
|
+
} catch (error) {
|
|
324
|
+
console.warn("[IMA] Failed to call setAdWillPlayMuted:", error);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
300
327
|
adsRequest.vastLoadTimeout = 5e3;
|
|
301
328
|
console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
|
|
302
329
|
adsLoader.requestAds(adsRequest);
|
|
330
|
+
if (preloadedResponse) {
|
|
331
|
+
preloadedVast.delete(vastTagUrl);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function ensurePlaceholderContainer() {
|
|
335
|
+
var _a;
|
|
336
|
+
if (adContainerEl) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
const container = document.createElement("div");
|
|
340
|
+
container.style.position = "absolute";
|
|
341
|
+
container.style.left = "0";
|
|
342
|
+
container.style.top = "0";
|
|
343
|
+
container.style.right = "0";
|
|
344
|
+
container.style.bottom = "0";
|
|
345
|
+
container.style.display = "none";
|
|
346
|
+
container.style.alignItems = "center";
|
|
347
|
+
container.style.justifyContent = "center";
|
|
348
|
+
container.style.pointerEvents = "none";
|
|
349
|
+
container.style.zIndex = "10";
|
|
350
|
+
container.style.backgroundColor = "#000";
|
|
351
|
+
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
352
|
+
adContainerEl = container;
|
|
353
|
+
}
|
|
354
|
+
async function fetchVastDocument(vastTagUrl) {
|
|
355
|
+
const response = await fetch(vastTagUrl, { mode: "cors" });
|
|
356
|
+
if (!response.ok) {
|
|
357
|
+
throw new Error(`Failed to preload VAST: ${response.status}`);
|
|
358
|
+
}
|
|
359
|
+
return response.text();
|
|
303
360
|
}
|
|
304
361
|
function destroyAdsManager() {
|
|
305
362
|
if (adsManager) {
|
|
@@ -315,29 +372,16 @@ function createImaController(video, options) {
|
|
|
315
372
|
return {
|
|
316
373
|
initialize() {
|
|
317
374
|
ensureImaLoaded().then(() => {
|
|
318
|
-
var _a
|
|
375
|
+
var _a;
|
|
319
376
|
const google = window.google;
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
container.style.position = "absolute";
|
|
323
|
-
container.style.left = "0";
|
|
324
|
-
container.style.top = "0";
|
|
325
|
-
container.style.right = "0";
|
|
326
|
-
container.style.bottom = "0";
|
|
327
|
-
container.style.display = "none";
|
|
328
|
-
container.style.alignItems = "center";
|
|
329
|
-
container.style.justifyContent = "center";
|
|
330
|
-
container.style.pointerEvents = "none";
|
|
331
|
-
container.style.zIndex = "10";
|
|
332
|
-
container.style.backgroundColor = "#000";
|
|
333
|
-
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
334
|
-
adContainerEl = container;
|
|
377
|
+
ensurePlaceholderContainer();
|
|
378
|
+
if (!adDisplayContainer && adContainerEl) {
|
|
335
379
|
adDisplayContainer = new google.ima.AdDisplayContainer(
|
|
336
|
-
|
|
380
|
+
adContainerEl,
|
|
337
381
|
video
|
|
338
382
|
);
|
|
339
383
|
try {
|
|
340
|
-
(
|
|
384
|
+
(_a = adDisplayContainer.initialize) == null ? void 0 : _a.call(adDisplayContainer);
|
|
341
385
|
} catch {
|
|
342
386
|
}
|
|
343
387
|
}
|
|
@@ -641,6 +685,32 @@ function createImaController(video, options) {
|
|
|
641
685
|
return Promise.reject(error);
|
|
642
686
|
}
|
|
643
687
|
},
|
|
688
|
+
async preloadAds(vastTagUrl) {
|
|
689
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
690
|
+
return Promise.resolve();
|
|
691
|
+
}
|
|
692
|
+
if (preloadedVast.has(vastTagUrl)) {
|
|
693
|
+
return Promise.resolve();
|
|
694
|
+
}
|
|
695
|
+
const inflight = preloadingVast.get(vastTagUrl);
|
|
696
|
+
if (inflight) {
|
|
697
|
+
return inflight;
|
|
698
|
+
}
|
|
699
|
+
const preloadPromise = fetchVastDocument(vastTagUrl).then((xml) => {
|
|
700
|
+
preloadedVast.set(vastTagUrl, xml);
|
|
701
|
+
console.log("[IMA] Cached VAST response for preloading:", vastTagUrl);
|
|
702
|
+
}).catch((error) => {
|
|
703
|
+
console.warn("[IMA] Failed to preload VAST response:", error);
|
|
704
|
+
preloadedVast.delete(vastTagUrl);
|
|
705
|
+
}).finally(() => {
|
|
706
|
+
preloadingVast.delete(vastTagUrl);
|
|
707
|
+
});
|
|
708
|
+
preloadingVast.set(vastTagUrl, preloadPromise);
|
|
709
|
+
return preloadPromise;
|
|
710
|
+
},
|
|
711
|
+
hasPreloadedAd(vastTagUrl) {
|
|
712
|
+
return preloadedVast.has(vastTagUrl);
|
|
713
|
+
},
|
|
644
714
|
async play() {
|
|
645
715
|
var _a, _b;
|
|
646
716
|
if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
|
|
@@ -659,7 +729,7 @@ function createImaController(video, options) {
|
|
|
659
729
|
console.log(`[IMA] Initializing ads manager (${width}x${height})`);
|
|
660
730
|
adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);
|
|
661
731
|
adPlaying = true;
|
|
662
|
-
const adVolume = originalMutedState ? 0 :
|
|
732
|
+
const adVolume = originalMutedState ? 0 : originalVolume;
|
|
663
733
|
try {
|
|
664
734
|
adsManager.setVolume(adVolume);
|
|
665
735
|
console.log(`[IMA] Set ad volume to ${adVolume}`);
|
|
@@ -701,6 +771,7 @@ function createImaController(video, options) {
|
|
|
701
771
|
destroyAdsManager();
|
|
702
772
|
adPlaying = false;
|
|
703
773
|
video.muted = originalMutedState;
|
|
774
|
+
video.volume = originalVolume;
|
|
704
775
|
setAdPlayingFlag(false);
|
|
705
776
|
if (adContainerEl) {
|
|
706
777
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -716,6 +787,8 @@ function createImaController(video, options) {
|
|
|
716
787
|
adContainerEl = void 0;
|
|
717
788
|
adDisplayContainer = void 0;
|
|
718
789
|
adsLoader = void 0;
|
|
790
|
+
preloadedVast.clear();
|
|
791
|
+
preloadingVast.clear();
|
|
719
792
|
},
|
|
720
793
|
isAdPlaying() {
|
|
721
794
|
return adPlaying;
|
|
@@ -743,15 +816,20 @@ function createImaController(video, options) {
|
|
|
743
816
|
var _a;
|
|
744
817
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
745
818
|
},
|
|
746
|
-
updateOriginalMutedState(muted) {
|
|
819
|
+
updateOriginalMutedState(muted, volume) {
|
|
820
|
+
const nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
|
|
747
821
|
console.log(
|
|
748
|
-
`[IMA] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
822
|
+
`[IMA] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`
|
|
749
823
|
);
|
|
750
824
|
originalMutedState = muted;
|
|
825
|
+
originalVolume = nextVolume;
|
|
751
826
|
},
|
|
752
827
|
getOriginalMutedState() {
|
|
753
828
|
return originalMutedState;
|
|
754
829
|
},
|
|
830
|
+
getOriginalVolume() {
|
|
831
|
+
return originalVolume;
|
|
832
|
+
},
|
|
755
833
|
setAdVolume(volume) {
|
|
756
834
|
if (adsManager && adPlaying) {
|
|
757
835
|
try {
|
|
@@ -771,6 +849,19 @@ function createImaController(video, options) {
|
|
|
771
849
|
}
|
|
772
850
|
}
|
|
773
851
|
return 1;
|
|
852
|
+
},
|
|
853
|
+
showPlaceholder() {
|
|
854
|
+
ensurePlaceholderContainer();
|
|
855
|
+
if (adContainerEl) {
|
|
856
|
+
adContainerEl.style.display = "flex";
|
|
857
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
858
|
+
}
|
|
859
|
+
},
|
|
860
|
+
hidePlaceholder() {
|
|
861
|
+
if (adContainerEl) {
|
|
862
|
+
adContainerEl.style.display = "none";
|
|
863
|
+
adContainerEl.style.pointerEvents = "none";
|
|
864
|
+
}
|
|
774
865
|
}
|
|
775
866
|
};
|
|
776
867
|
}
|
|
@@ -780,6 +871,7 @@ var import_hls = __toESM(require("hls.js"), 1);
|
|
|
780
871
|
function createHlsAdPlayer(contentVideo, options) {
|
|
781
872
|
let adPlaying = false;
|
|
782
873
|
let originalMutedState = false;
|
|
874
|
+
let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
|
|
783
875
|
const listeners = /* @__PURE__ */ new Map();
|
|
784
876
|
const licenseKey = options == null ? void 0 : options.licenseKey;
|
|
785
877
|
const mainHlsInstance = options == null ? void 0 : options.mainHlsInstance;
|
|
@@ -788,6 +880,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
788
880
|
let adContainerEl;
|
|
789
881
|
let currentAd;
|
|
790
882
|
let sessionId;
|
|
883
|
+
const preloadedAds = /* @__PURE__ */ new Map();
|
|
884
|
+
const preloadingAds = /* @__PURE__ */ new Map();
|
|
791
885
|
let trackingFired = {
|
|
792
886
|
impression: false,
|
|
793
887
|
start: false,
|
|
@@ -1017,6 +1111,19 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1017
1111
|
return null;
|
|
1018
1112
|
}
|
|
1019
1113
|
}
|
|
1114
|
+
async function fetchAndParseVastAd(vastTagUrl) {
|
|
1115
|
+
const response = await fetch(vastTagUrl);
|
|
1116
|
+
if (!response.ok) {
|
|
1117
|
+
throw new Error(`Failed to fetch VAST: ${response.statusText}`);
|
|
1118
|
+
}
|
|
1119
|
+
const vastXml = await response.text();
|
|
1120
|
+
console.log("[HlsAdPlayer] VAST XML received");
|
|
1121
|
+
console.log(
|
|
1122
|
+
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1123
|
+
vastXml.substring(0, 2e3)
|
|
1124
|
+
);
|
|
1125
|
+
return parseVastXml(vastXml);
|
|
1126
|
+
}
|
|
1020
1127
|
function createAdVideoElement() {
|
|
1021
1128
|
const video = document.createElement("video");
|
|
1022
1129
|
video.style.position = "absolute";
|
|
@@ -1122,6 +1229,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1122
1229
|
setAdPlayingFlag(false);
|
|
1123
1230
|
const previousMutedState = contentVideo.muted;
|
|
1124
1231
|
contentVideo.muted = originalMutedState;
|
|
1232
|
+
contentVideo.volume = originalMutedState ? 0 : originalVolume;
|
|
1125
1233
|
console.log(
|
|
1126
1234
|
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
1127
1235
|
);
|
|
@@ -1168,17 +1276,17 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1168
1276
|
}
|
|
1169
1277
|
try {
|
|
1170
1278
|
sessionId = generateSessionId();
|
|
1171
|
-
|
|
1172
|
-
if (
|
|
1173
|
-
|
|
1279
|
+
let ad;
|
|
1280
|
+
if (preloadedAds.has(vastTagUrl)) {
|
|
1281
|
+
ad = preloadedAds.get(vastTagUrl);
|
|
1282
|
+
preloadedAds.delete(vastTagUrl);
|
|
1283
|
+
console.log(
|
|
1284
|
+
"[HlsAdPlayer] Using preloaded VAST response:",
|
|
1285
|
+
vastTagUrl
|
|
1286
|
+
);
|
|
1287
|
+
} else {
|
|
1288
|
+
ad = await fetchAndParseVastAd(vastTagUrl);
|
|
1174
1289
|
}
|
|
1175
|
-
const vastXml = await response.text();
|
|
1176
|
-
console.log("[HlsAdPlayer] VAST XML received");
|
|
1177
|
-
console.log(
|
|
1178
|
-
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1179
|
-
vastXml.substring(0, 2e3)
|
|
1180
|
-
);
|
|
1181
|
-
const ad = parseVastXml(vastXml);
|
|
1182
1290
|
if (!ad) {
|
|
1183
1291
|
console.warn("[HlsAdPlayer] No ads available from VAST response");
|
|
1184
1292
|
emit("ad_error");
|
|
@@ -1197,6 +1305,37 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1197
1305
|
return Promise.reject(error);
|
|
1198
1306
|
}
|
|
1199
1307
|
},
|
|
1308
|
+
async preloadAds(vastTagUrl) {
|
|
1309
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
1310
|
+
return Promise.resolve();
|
|
1311
|
+
}
|
|
1312
|
+
if (preloadedAds.has(vastTagUrl)) {
|
|
1313
|
+
return Promise.resolve();
|
|
1314
|
+
}
|
|
1315
|
+
const inflight = preloadingAds.get(vastTagUrl);
|
|
1316
|
+
if (inflight) {
|
|
1317
|
+
return inflight;
|
|
1318
|
+
}
|
|
1319
|
+
const preloadPromise = fetchAndParseVastAd(vastTagUrl).then((ad) => {
|
|
1320
|
+
if (ad) {
|
|
1321
|
+
preloadedAds.set(vastTagUrl, ad);
|
|
1322
|
+
console.log(
|
|
1323
|
+
"[HlsAdPlayer] Cached VAST response for preloading:",
|
|
1324
|
+
vastTagUrl
|
|
1325
|
+
);
|
|
1326
|
+
}
|
|
1327
|
+
}).catch((error) => {
|
|
1328
|
+
console.warn("[HlsAdPlayer] Failed to preload VAST response:", error);
|
|
1329
|
+
preloadedAds.delete(vastTagUrl);
|
|
1330
|
+
}).finally(() => {
|
|
1331
|
+
preloadingAds.delete(vastTagUrl);
|
|
1332
|
+
});
|
|
1333
|
+
preloadingAds.set(vastTagUrl, preloadPromise);
|
|
1334
|
+
return preloadPromise;
|
|
1335
|
+
},
|
|
1336
|
+
hasPreloadedAd(vastTagUrl) {
|
|
1337
|
+
return preloadedAds.has(vastTagUrl);
|
|
1338
|
+
},
|
|
1200
1339
|
async play() {
|
|
1201
1340
|
if (!currentAd) {
|
|
1202
1341
|
console.warn(
|
|
@@ -1220,6 +1359,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1220
1359
|
complete: false
|
|
1221
1360
|
};
|
|
1222
1361
|
const contentVolume = contentVideo.volume;
|
|
1362
|
+
originalVolume = Math.max(
|
|
1363
|
+
0,
|
|
1364
|
+
Math.min(1, contentVolume || originalVolume)
|
|
1365
|
+
);
|
|
1223
1366
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1224
1367
|
contentVideo.pause();
|
|
1225
1368
|
console.log("[HlsAdPlayer] Content paused (VOD mode)");
|
|
@@ -1232,7 +1375,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1232
1375
|
adPlaying = true;
|
|
1233
1376
|
setAdPlayingFlag(true);
|
|
1234
1377
|
if (adVideoElement) {
|
|
1235
|
-
const adVolume = originalMutedState ? 0 :
|
|
1378
|
+
const adVolume = originalMutedState ? 0 : originalVolume;
|
|
1236
1379
|
adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
|
|
1237
1380
|
adVideoElement.muted = false;
|
|
1238
1381
|
console.log(
|
|
@@ -1311,6 +1454,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1311
1454
|
adPlaying = false;
|
|
1312
1455
|
setAdPlayingFlag(false);
|
|
1313
1456
|
contentVideo.muted = originalMutedState;
|
|
1457
|
+
contentVideo.volume = originalMutedState ? 0 : originalVolume;
|
|
1314
1458
|
if (adHls) {
|
|
1315
1459
|
adHls.destroy();
|
|
1316
1460
|
adHls = void 0;
|
|
@@ -1327,6 +1471,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1327
1471
|
adContainerEl = void 0;
|
|
1328
1472
|
currentAd = void 0;
|
|
1329
1473
|
listeners.clear();
|
|
1474
|
+
preloadedAds.clear();
|
|
1475
|
+
preloadingAds.clear();
|
|
1330
1476
|
},
|
|
1331
1477
|
isAdPlaying() {
|
|
1332
1478
|
return adPlaying;
|
|
@@ -1350,15 +1496,20 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1350
1496
|
var _a;
|
|
1351
1497
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
1352
1498
|
},
|
|
1353
|
-
updateOriginalMutedState(muted) {
|
|
1499
|
+
updateOriginalMutedState(muted, volume) {
|
|
1500
|
+
const nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
|
|
1354
1501
|
console.log(
|
|
1355
|
-
`[HlsAdPlayer] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
1502
|
+
`[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`
|
|
1356
1503
|
);
|
|
1357
1504
|
originalMutedState = muted;
|
|
1505
|
+
originalVolume = nextVolume;
|
|
1358
1506
|
},
|
|
1359
1507
|
getOriginalMutedState() {
|
|
1360
1508
|
return originalMutedState;
|
|
1361
1509
|
},
|
|
1510
|
+
getOriginalVolume() {
|
|
1511
|
+
return originalVolume;
|
|
1512
|
+
},
|
|
1362
1513
|
setAdVolume(volume) {
|
|
1363
1514
|
if (adVideoElement && adPlaying) {
|
|
1364
1515
|
adVideoElement.volume = Math.max(0, Math.min(1, volume));
|
|
@@ -1369,6 +1520,35 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1369
1520
|
return adVideoElement.volume;
|
|
1370
1521
|
}
|
|
1371
1522
|
return 1;
|
|
1523
|
+
},
|
|
1524
|
+
showPlaceholder() {
|
|
1525
|
+
var _a;
|
|
1526
|
+
if (!adContainerEl) {
|
|
1527
|
+
const container = document.createElement("div");
|
|
1528
|
+
container.style.position = "absolute";
|
|
1529
|
+
container.style.left = "0";
|
|
1530
|
+
container.style.top = "0";
|
|
1531
|
+
container.style.right = "0";
|
|
1532
|
+
container.style.bottom = "0";
|
|
1533
|
+
container.style.display = "none";
|
|
1534
|
+
container.style.alignItems = "center";
|
|
1535
|
+
container.style.justifyContent = "center";
|
|
1536
|
+
container.style.pointerEvents = "none";
|
|
1537
|
+
container.style.zIndex = "10";
|
|
1538
|
+
container.style.backgroundColor = "#000";
|
|
1539
|
+
(_a = contentVideo.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
1540
|
+
adContainerEl = container;
|
|
1541
|
+
}
|
|
1542
|
+
if (adContainerEl) {
|
|
1543
|
+
adContainerEl.style.display = "flex";
|
|
1544
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
1545
|
+
}
|
|
1546
|
+
},
|
|
1547
|
+
hidePlaceholder() {
|
|
1548
|
+
if (adContainerEl) {
|
|
1549
|
+
adContainerEl.style.display = "none";
|
|
1550
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1551
|
+
}
|
|
1372
1552
|
}
|
|
1373
1553
|
};
|
|
1374
1554
|
}
|
|
@@ -1849,6 +2029,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1849
2029
|
this.bufferedSegmentsCount = 0;
|
|
1850
2030
|
this.shouldAutoplayAfterBuffering = false;
|
|
1851
2031
|
this.hasInitialBufferCompleted = false;
|
|
2032
|
+
this.adPodAllUrls = [];
|
|
2033
|
+
this.preloadingAdUrls = /* @__PURE__ */ new Set();
|
|
1852
2034
|
initializePolyfills();
|
|
1853
2035
|
const browserOverrides = getBrowserConfigOverrides();
|
|
1854
2036
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -2108,7 +2290,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2108
2290
|
this.video.autoplay = !!this.config.autoplay;
|
|
2109
2291
|
this.video.muted = !!this.config.muted;
|
|
2110
2292
|
this.ima.initialize();
|
|
2111
|
-
this.ima.updateOriginalMutedState(this.video.muted);
|
|
2293
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
2112
2294
|
this.ima.on("all_ads_completed", () => {
|
|
2113
2295
|
if (this.config.debugAdTiming) {
|
|
2114
2296
|
console.log(
|
|
@@ -2149,6 +2331,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2149
2331
|
console.log("[StormcloudVideoPlayer] IMA content_pause event received");
|
|
2150
2332
|
}
|
|
2151
2333
|
this.clearAdFailsafeTimer();
|
|
2334
|
+
this.enforceAdHoldState();
|
|
2152
2335
|
});
|
|
2153
2336
|
this.ima.on("content_resume", () => {
|
|
2154
2337
|
if (this.config.debugAdTiming) {
|
|
@@ -2173,9 +2356,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2173
2356
|
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2174
2357
|
const next = this.adPodQueue.shift();
|
|
2175
2358
|
this.currentAdIndex++;
|
|
2176
|
-
this.
|
|
2177
|
-
this.video.muted = true;
|
|
2178
|
-
this.video.volume = 0;
|
|
2359
|
+
this.enforceAdHoldState();
|
|
2179
2360
|
if (this.config.debugAdTiming) {
|
|
2180
2361
|
console.log(
|
|
2181
2362
|
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak}) - IMMEDIATELY starting next ad`
|
|
@@ -2787,11 +2968,16 @@ var StormcloudVideoPlayer = class {
|
|
|
2787
2968
|
return;
|
|
2788
2969
|
}
|
|
2789
2970
|
if (vastTagUrls.length > 0) {
|
|
2971
|
+
this.adPodAllUrls = [...vastTagUrls];
|
|
2972
|
+
this.preloadingAdUrls.clear();
|
|
2973
|
+
this.logQueuedAdUrls(this.adPodAllUrls);
|
|
2790
2974
|
this.inAdBreak = true;
|
|
2791
2975
|
this.showAds = true;
|
|
2792
2976
|
this.currentAdIndex = 0;
|
|
2793
2977
|
this.totalAdsInBreak = vastTagUrls.length;
|
|
2794
2978
|
this.adPodQueue = [...vastTagUrls];
|
|
2979
|
+
this.enforceAdHoldState();
|
|
2980
|
+
this.preloadUpcomingAds();
|
|
2795
2981
|
if (this.config.debugAdTiming) {
|
|
2796
2982
|
console.log(
|
|
2797
2983
|
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads - will play continuously`
|
|
@@ -2862,6 +3048,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2862
3048
|
const first = tags[0];
|
|
2863
3049
|
const rest = tags.slice(1);
|
|
2864
3050
|
this.adPodQueue = rest;
|
|
3051
|
+
this.enforceAdHoldState();
|
|
2865
3052
|
await this.playSingleAd(first);
|
|
2866
3053
|
this.inAdBreak = true;
|
|
2867
3054
|
this.expectedAdBreakDurationMs = remainingMs;
|
|
@@ -2975,6 +3162,12 @@ var StormcloudVideoPlayer = class {
|
|
|
2975
3162
|
}
|
|
2976
3163
|
return;
|
|
2977
3164
|
}
|
|
3165
|
+
const wasPreloaded = this.ima.hasPreloadedAd(vastTagUrl);
|
|
3166
|
+
if (wasPreloaded && this.config.debugAdTiming) {
|
|
3167
|
+
console.log(
|
|
3168
|
+
`[StormcloudVideoPlayer] IMA SDK preloaded this ad already: ${vastTagUrl}`
|
|
3169
|
+
);
|
|
3170
|
+
}
|
|
2978
3171
|
if (!this.showAds) {
|
|
2979
3172
|
if (this.config.debugAdTiming) {
|
|
2980
3173
|
console.log(
|
|
@@ -2986,7 +3179,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2986
3179
|
}
|
|
2987
3180
|
);
|
|
2988
3181
|
}
|
|
2989
|
-
this.ima.updateOriginalMutedState(this.video.muted);
|
|
3182
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
2990
3183
|
} else if (this.config.debugAdTiming) {
|
|
2991
3184
|
console.log(
|
|
2992
3185
|
`[StormcloudVideoPlayer] Keeping existing original mute state (currently showing ads)`
|
|
@@ -2995,12 +3188,14 @@ var StormcloudVideoPlayer = class {
|
|
|
2995
3188
|
this.startAdFailsafeTimer();
|
|
2996
3189
|
try {
|
|
2997
3190
|
await this.ima.requestAds(vastTagUrl);
|
|
3191
|
+
this.preloadUpcomingAds();
|
|
2998
3192
|
try {
|
|
2999
3193
|
if (this.config.debugAdTiming) {
|
|
3000
3194
|
console.log(
|
|
3001
3195
|
"[StormcloudVideoPlayer] Ad request completed, attempting playback"
|
|
3002
3196
|
);
|
|
3003
3197
|
}
|
|
3198
|
+
this.enforceAdHoldState();
|
|
3004
3199
|
await this.ima.play();
|
|
3005
3200
|
if (this.config.debugAdTiming) {
|
|
3006
3201
|
console.log(
|
|
@@ -3030,6 +3225,8 @@ var StormcloudVideoPlayer = class {
|
|
|
3030
3225
|
"[StormcloudVideoPlayer] Handling ad pod completion - resuming content and hiding ad layer"
|
|
3031
3226
|
);
|
|
3032
3227
|
}
|
|
3228
|
+
this.releaseAdHoldState();
|
|
3229
|
+
this.preloadingAdUrls.clear();
|
|
3033
3230
|
this.inAdBreak = false;
|
|
3034
3231
|
this.expectedAdBreakDurationMs = void 0;
|
|
3035
3232
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
@@ -3037,14 +3234,16 @@ var StormcloudVideoPlayer = class {
|
|
|
3037
3234
|
this.clearAdStopTimer();
|
|
3038
3235
|
this.clearAdFailsafeTimer();
|
|
3039
3236
|
this.adPodQueue = [];
|
|
3237
|
+
this.adPodAllUrls = [];
|
|
3040
3238
|
this.showAds = false;
|
|
3041
3239
|
this.currentAdIndex = 0;
|
|
3042
3240
|
this.totalAdsInBreak = 0;
|
|
3043
3241
|
this.ima.stop().catch(() => {
|
|
3044
3242
|
});
|
|
3045
3243
|
const originalMutedState = this.ima.getOriginalMutedState();
|
|
3244
|
+
const originalVolume = typeof this.ima.getOriginalVolume === "function" ? this.ima.getOriginalVolume() : this.video.volume;
|
|
3046
3245
|
this.video.muted = originalMutedState;
|
|
3047
|
-
this.video.volume =
|
|
3246
|
+
this.video.volume = originalVolume;
|
|
3048
3247
|
if (this.config.debugAdTiming) {
|
|
3049
3248
|
console.log(
|
|
3050
3249
|
`[StormcloudVideoPlayer] Restored main video - muted: ${originalMutedState}, volume: ${this.video.volume}`
|
|
@@ -3117,6 +3316,64 @@ var StormcloudVideoPlayer = class {
|
|
|
3117
3316
|
}
|
|
3118
3317
|
return [b.vastTagUrl];
|
|
3119
3318
|
}
|
|
3319
|
+
logQueuedAdUrls(urls) {
|
|
3320
|
+
if (!this.config.debugAdTiming) {
|
|
3321
|
+
return;
|
|
3322
|
+
}
|
|
3323
|
+
console.log("[StormcloudVideoPlayer] ALL ad URLs queued:", urls);
|
|
3324
|
+
}
|
|
3325
|
+
enforceAdHoldState() {
|
|
3326
|
+
this.video.dataset.stormcloudAdPlaying = "true";
|
|
3327
|
+
this.video.muted = true;
|
|
3328
|
+
this.video.volume = 0;
|
|
3329
|
+
if (typeof this.ima.showPlaceholder === "function") {
|
|
3330
|
+
this.ima.showPlaceholder();
|
|
3331
|
+
}
|
|
3332
|
+
}
|
|
3333
|
+
releaseAdHoldState() {
|
|
3334
|
+
delete this.video.dataset.stormcloudAdPlaying;
|
|
3335
|
+
if (typeof this.ima.hidePlaceholder === "function") {
|
|
3336
|
+
this.ima.hidePlaceholder();
|
|
3337
|
+
}
|
|
3338
|
+
}
|
|
3339
|
+
preloadUpcomingAds() {
|
|
3340
|
+
if (!this.ima.preloadAds || this.adPodQueue.length === 0) {
|
|
3341
|
+
return;
|
|
3342
|
+
}
|
|
3343
|
+
const upcoming = this.adPodQueue.slice(0, 2);
|
|
3344
|
+
for (const url of upcoming) {
|
|
3345
|
+
if (!url) continue;
|
|
3346
|
+
if (this.ima.hasPreloadedAd(url)) {
|
|
3347
|
+
this.preloadingAdUrls.delete(url);
|
|
3348
|
+
continue;
|
|
3349
|
+
}
|
|
3350
|
+
if (this.preloadingAdUrls.has(url)) {
|
|
3351
|
+
continue;
|
|
3352
|
+
}
|
|
3353
|
+
if (this.config.debugAdTiming) {
|
|
3354
|
+
console.log(
|
|
3355
|
+
`[StormcloudVideoPlayer] Scheduling IMA preload for upcoming ad: ${url}`
|
|
3356
|
+
);
|
|
3357
|
+
}
|
|
3358
|
+
this.preloadingAdUrls.add(url);
|
|
3359
|
+
this.ima.preloadAds(url).then(() => {
|
|
3360
|
+
if (this.config.debugAdTiming) {
|
|
3361
|
+
console.log(
|
|
3362
|
+
`[StormcloudVideoPlayer] IMA preload complete for ad: ${url}`
|
|
3363
|
+
);
|
|
3364
|
+
}
|
|
3365
|
+
}).catch((error) => {
|
|
3366
|
+
if (this.config.debugAdTiming) {
|
|
3367
|
+
console.warn(
|
|
3368
|
+
`[StormcloudVideoPlayer] IMA preload failed for ad: ${url}`,
|
|
3369
|
+
error
|
|
3370
|
+
);
|
|
3371
|
+
}
|
|
3372
|
+
}).finally(() => {
|
|
3373
|
+
this.preloadingAdUrls.delete(url);
|
|
3374
|
+
});
|
|
3375
|
+
}
|
|
3376
|
+
}
|
|
3120
3377
|
getRemainingAdMs() {
|
|
3121
3378
|
if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)
|
|
3122
3379
|
return 0;
|
|
@@ -3137,7 +3394,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3137
3394
|
if (this.ima.isAdPlaying()) {
|
|
3138
3395
|
const currentPerceptualState = this.isMuted();
|
|
3139
3396
|
const newMutedState = !currentPerceptualState;
|
|
3140
|
-
this.ima.updateOriginalMutedState(newMutedState);
|
|
3397
|
+
this.ima.updateOriginalMutedState(newMutedState, this.video.volume);
|
|
3141
3398
|
this.ima.setAdVolume(newMutedState ? 0 : 1);
|
|
3142
3399
|
if (this.config.debugAdTiming) {
|
|
3143
3400
|
console.log(
|
|
@@ -3147,7 +3404,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3147
3404
|
}
|
|
3148
3405
|
} else {
|
|
3149
3406
|
this.video.muted = !this.video.muted;
|
|
3150
|
-
this.ima.updateOriginalMutedState(this.video.muted);
|
|
3407
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3151
3408
|
if (this.config.debugAdTiming) {
|
|
3152
3409
|
console.log("[StormcloudVideoPlayer] Muted:", this.video.muted);
|
|
3153
3410
|
}
|
|
@@ -3219,7 +3476,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3219
3476
|
}
|
|
3220
3477
|
this.video.muted = muted;
|
|
3221
3478
|
if (adPlaying) {
|
|
3222
|
-
this.ima.updateOriginalMutedState(muted);
|
|
3479
|
+
this.ima.updateOriginalMutedState(muted, this.video.volume);
|
|
3223
3480
|
this.ima.setAdVolume(muted ? 0 : 1);
|
|
3224
3481
|
if (this.config.debugAdTiming) {
|
|
3225
3482
|
console.log("[StormcloudVideoPlayer] setMuted applied during ad", {
|
|
@@ -3228,7 +3485,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3228
3485
|
}
|
|
3229
3486
|
return;
|
|
3230
3487
|
}
|
|
3231
|
-
this.ima.updateOriginalMutedState(muted);
|
|
3488
|
+
this.ima.updateOriginalMutedState(muted, this.video.volume);
|
|
3232
3489
|
if (this.config.debugAdTiming) {
|
|
3233
3490
|
console.log("[StormcloudVideoPlayer] setMuted called:", muted);
|
|
3234
3491
|
}
|
|
@@ -3268,6 +3525,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3268
3525
|
}
|
|
3269
3526
|
(_a = this.hls) == null ? void 0 : _a.destroy();
|
|
3270
3527
|
(_b = this.ima) == null ? void 0 : _b.destroy();
|
|
3528
|
+
this.releaseAdHoldState();
|
|
3529
|
+
this.preloadingAdUrls.clear();
|
|
3530
|
+
this.adPodAllUrls = [];
|
|
3271
3531
|
}
|
|
3272
3532
|
};
|
|
3273
3533
|
// Annotate the CommonJS export names for ESM import in node:
|