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
package/lib/index.cjs
CHANGED
|
@@ -266,7 +266,10 @@ function supportsFeature(feature) {
|
|
|
266
266
|
function createImaController(video, options) {
|
|
267
267
|
let adPlaying = false;
|
|
268
268
|
let originalMutedState = false;
|
|
269
|
+
let originalVolume = typeof video.volume === "number" && !Number.isNaN(video.volume) ? Math.max(0, Math.min(1, video.volume)) : 1;
|
|
269
270
|
const listeners = /* @__PURE__ */ new Map();
|
|
271
|
+
const preloadedVast = /* @__PURE__ */ new Map();
|
|
272
|
+
const preloadingVast = /* @__PURE__ */ new Map();
|
|
270
273
|
function setAdPlayingFlag(isPlaying) {
|
|
271
274
|
if (isPlaying) {
|
|
272
275
|
video.dataset.stormcloudAdPlaying = "true";
|
|
@@ -357,16 +360,70 @@ function createImaController(video, options) {
|
|
|
357
360
|
let adsLoadedReject;
|
|
358
361
|
function makeAdsRequest(google, vastTagUrl) {
|
|
359
362
|
const adsRequest = new google.ima.AdsRequest();
|
|
360
|
-
|
|
363
|
+
const preloadedResponse = preloadedVast.get(vastTagUrl);
|
|
364
|
+
if (preloadedResponse) {
|
|
365
|
+
adsRequest.adsResponse = preloadedResponse;
|
|
366
|
+
console.log(
|
|
367
|
+
"[IMA] Using preloaded VAST response for immediate ad request"
|
|
368
|
+
);
|
|
369
|
+
} else {
|
|
370
|
+
adsRequest.adTagUrl = vastTagUrl;
|
|
371
|
+
}
|
|
361
372
|
const videoWidth = video.offsetWidth || video.clientWidth || 640;
|
|
362
373
|
const videoHeight = video.offsetHeight || video.clientHeight || 360;
|
|
363
374
|
adsRequest.linearAdSlotWidth = videoWidth;
|
|
364
375
|
adsRequest.linearAdSlotHeight = videoHeight;
|
|
365
376
|
adsRequest.nonLinearAdSlotWidth = videoWidth;
|
|
366
377
|
adsRequest.nonLinearAdSlotHeight = videoHeight;
|
|
378
|
+
if (typeof adsRequest.setAdWillAutoPlay === "function") {
|
|
379
|
+
try {
|
|
380
|
+
const willAutoPlay = !video.paused || video.autoplay;
|
|
381
|
+
adsRequest.setAdWillAutoPlay(willAutoPlay);
|
|
382
|
+
} catch (error) {
|
|
383
|
+
console.warn("[IMA] Failed to call setAdWillAutoPlay:", error);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
if (typeof adsRequest.setAdWillPlayMuted === "function") {
|
|
387
|
+
try {
|
|
388
|
+
const willPlayMuted = video.muted || video.volume === 0;
|
|
389
|
+
adsRequest.setAdWillPlayMuted(willPlayMuted);
|
|
390
|
+
} catch (error) {
|
|
391
|
+
console.warn("[IMA] Failed to call setAdWillPlayMuted:", error);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
367
394
|
adsRequest.vastLoadTimeout = 5e3;
|
|
368
395
|
console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
|
|
369
396
|
adsLoader.requestAds(adsRequest);
|
|
397
|
+
if (preloadedResponse) {
|
|
398
|
+
preloadedVast.delete(vastTagUrl);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
function ensurePlaceholderContainer() {
|
|
402
|
+
var _a;
|
|
403
|
+
if (adContainerEl) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
const container = document.createElement("div");
|
|
407
|
+
container.style.position = "absolute";
|
|
408
|
+
container.style.left = "0";
|
|
409
|
+
container.style.top = "0";
|
|
410
|
+
container.style.right = "0";
|
|
411
|
+
container.style.bottom = "0";
|
|
412
|
+
container.style.display = "none";
|
|
413
|
+
container.style.alignItems = "center";
|
|
414
|
+
container.style.justifyContent = "center";
|
|
415
|
+
container.style.pointerEvents = "none";
|
|
416
|
+
container.style.zIndex = "10";
|
|
417
|
+
container.style.backgroundColor = "#000";
|
|
418
|
+
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
419
|
+
adContainerEl = container;
|
|
420
|
+
}
|
|
421
|
+
async function fetchVastDocument(vastTagUrl) {
|
|
422
|
+
const response = await fetch(vastTagUrl, { mode: "cors" });
|
|
423
|
+
if (!response.ok) {
|
|
424
|
+
throw new Error(`Failed to preload VAST: ${response.status}`);
|
|
425
|
+
}
|
|
426
|
+
return response.text();
|
|
370
427
|
}
|
|
371
428
|
function destroyAdsManager() {
|
|
372
429
|
if (adsManager) {
|
|
@@ -382,29 +439,16 @@ function createImaController(video, options) {
|
|
|
382
439
|
return {
|
|
383
440
|
initialize() {
|
|
384
441
|
ensureImaLoaded().then(() => {
|
|
385
|
-
var _a
|
|
442
|
+
var _a;
|
|
386
443
|
const google = window.google;
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
container.style.position = "absolute";
|
|
390
|
-
container.style.left = "0";
|
|
391
|
-
container.style.top = "0";
|
|
392
|
-
container.style.right = "0";
|
|
393
|
-
container.style.bottom = "0";
|
|
394
|
-
container.style.display = "none";
|
|
395
|
-
container.style.alignItems = "center";
|
|
396
|
-
container.style.justifyContent = "center";
|
|
397
|
-
container.style.pointerEvents = "none";
|
|
398
|
-
container.style.zIndex = "10";
|
|
399
|
-
container.style.backgroundColor = "#000";
|
|
400
|
-
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
401
|
-
adContainerEl = container;
|
|
444
|
+
ensurePlaceholderContainer();
|
|
445
|
+
if (!adDisplayContainer && adContainerEl) {
|
|
402
446
|
adDisplayContainer = new google.ima.AdDisplayContainer(
|
|
403
|
-
|
|
447
|
+
adContainerEl,
|
|
404
448
|
video
|
|
405
449
|
);
|
|
406
450
|
try {
|
|
407
|
-
(
|
|
451
|
+
(_a = adDisplayContainer.initialize) == null ? void 0 : _a.call(adDisplayContainer);
|
|
408
452
|
} catch {
|
|
409
453
|
}
|
|
410
454
|
}
|
|
@@ -708,6 +752,32 @@ function createImaController(video, options) {
|
|
|
708
752
|
return Promise.reject(error);
|
|
709
753
|
}
|
|
710
754
|
},
|
|
755
|
+
async preloadAds(vastTagUrl) {
|
|
756
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
757
|
+
return Promise.resolve();
|
|
758
|
+
}
|
|
759
|
+
if (preloadedVast.has(vastTagUrl)) {
|
|
760
|
+
return Promise.resolve();
|
|
761
|
+
}
|
|
762
|
+
const inflight = preloadingVast.get(vastTagUrl);
|
|
763
|
+
if (inflight) {
|
|
764
|
+
return inflight;
|
|
765
|
+
}
|
|
766
|
+
const preloadPromise = fetchVastDocument(vastTagUrl).then((xml) => {
|
|
767
|
+
preloadedVast.set(vastTagUrl, xml);
|
|
768
|
+
console.log("[IMA] Cached VAST response for preloading:", vastTagUrl);
|
|
769
|
+
}).catch((error) => {
|
|
770
|
+
console.warn("[IMA] Failed to preload VAST response:", error);
|
|
771
|
+
preloadedVast.delete(vastTagUrl);
|
|
772
|
+
}).finally(() => {
|
|
773
|
+
preloadingVast.delete(vastTagUrl);
|
|
774
|
+
});
|
|
775
|
+
preloadingVast.set(vastTagUrl, preloadPromise);
|
|
776
|
+
return preloadPromise;
|
|
777
|
+
},
|
|
778
|
+
hasPreloadedAd(vastTagUrl) {
|
|
779
|
+
return preloadedVast.has(vastTagUrl);
|
|
780
|
+
},
|
|
711
781
|
async play() {
|
|
712
782
|
var _a, _b;
|
|
713
783
|
if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
|
|
@@ -726,7 +796,7 @@ function createImaController(video, options) {
|
|
|
726
796
|
console.log(`[IMA] Initializing ads manager (${width}x${height})`);
|
|
727
797
|
adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);
|
|
728
798
|
adPlaying = true;
|
|
729
|
-
const adVolume = originalMutedState ? 0 :
|
|
799
|
+
const adVolume = originalMutedState ? 0 : originalVolume;
|
|
730
800
|
try {
|
|
731
801
|
adsManager.setVolume(adVolume);
|
|
732
802
|
console.log(`[IMA] Set ad volume to ${adVolume}`);
|
|
@@ -768,6 +838,7 @@ function createImaController(video, options) {
|
|
|
768
838
|
destroyAdsManager();
|
|
769
839
|
adPlaying = false;
|
|
770
840
|
video.muted = originalMutedState;
|
|
841
|
+
video.volume = originalVolume;
|
|
771
842
|
setAdPlayingFlag(false);
|
|
772
843
|
if (adContainerEl) {
|
|
773
844
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -783,6 +854,8 @@ function createImaController(video, options) {
|
|
|
783
854
|
adContainerEl = void 0;
|
|
784
855
|
adDisplayContainer = void 0;
|
|
785
856
|
adsLoader = void 0;
|
|
857
|
+
preloadedVast.clear();
|
|
858
|
+
preloadingVast.clear();
|
|
786
859
|
},
|
|
787
860
|
isAdPlaying() {
|
|
788
861
|
return adPlaying;
|
|
@@ -810,15 +883,20 @@ function createImaController(video, options) {
|
|
|
810
883
|
var _a;
|
|
811
884
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
812
885
|
},
|
|
813
|
-
updateOriginalMutedState(muted) {
|
|
886
|
+
updateOriginalMutedState(muted, volume) {
|
|
887
|
+
const nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
|
|
814
888
|
console.log(
|
|
815
|
-
`[IMA] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
889
|
+
`[IMA] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`
|
|
816
890
|
);
|
|
817
891
|
originalMutedState = muted;
|
|
892
|
+
originalVolume = nextVolume;
|
|
818
893
|
},
|
|
819
894
|
getOriginalMutedState() {
|
|
820
895
|
return originalMutedState;
|
|
821
896
|
},
|
|
897
|
+
getOriginalVolume() {
|
|
898
|
+
return originalVolume;
|
|
899
|
+
},
|
|
822
900
|
setAdVolume(volume) {
|
|
823
901
|
if (adsManager && adPlaying) {
|
|
824
902
|
try {
|
|
@@ -838,6 +916,19 @@ function createImaController(video, options) {
|
|
|
838
916
|
}
|
|
839
917
|
}
|
|
840
918
|
return 1;
|
|
919
|
+
},
|
|
920
|
+
showPlaceholder() {
|
|
921
|
+
ensurePlaceholderContainer();
|
|
922
|
+
if (adContainerEl) {
|
|
923
|
+
adContainerEl.style.display = "flex";
|
|
924
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
925
|
+
}
|
|
926
|
+
},
|
|
927
|
+
hidePlaceholder() {
|
|
928
|
+
if (adContainerEl) {
|
|
929
|
+
adContainerEl.style.display = "none";
|
|
930
|
+
adContainerEl.style.pointerEvents = "none";
|
|
931
|
+
}
|
|
841
932
|
}
|
|
842
933
|
};
|
|
843
934
|
}
|
|
@@ -847,6 +938,7 @@ var import_hls = __toESM(require("hls.js"), 1);
|
|
|
847
938
|
function createHlsAdPlayer(contentVideo, options) {
|
|
848
939
|
let adPlaying = false;
|
|
849
940
|
let originalMutedState = false;
|
|
941
|
+
let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
|
|
850
942
|
const listeners = /* @__PURE__ */ new Map();
|
|
851
943
|
const licenseKey = options == null ? void 0 : options.licenseKey;
|
|
852
944
|
const mainHlsInstance = options == null ? void 0 : options.mainHlsInstance;
|
|
@@ -855,6 +947,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
855
947
|
let adContainerEl;
|
|
856
948
|
let currentAd;
|
|
857
949
|
let sessionId;
|
|
950
|
+
const preloadedAds = /* @__PURE__ */ new Map();
|
|
951
|
+
const preloadingAds = /* @__PURE__ */ new Map();
|
|
858
952
|
let trackingFired = {
|
|
859
953
|
impression: false,
|
|
860
954
|
start: false,
|
|
@@ -1084,6 +1178,19 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1084
1178
|
return null;
|
|
1085
1179
|
}
|
|
1086
1180
|
}
|
|
1181
|
+
async function fetchAndParseVastAd(vastTagUrl) {
|
|
1182
|
+
const response = await fetch(vastTagUrl);
|
|
1183
|
+
if (!response.ok) {
|
|
1184
|
+
throw new Error(`Failed to fetch VAST: ${response.statusText}`);
|
|
1185
|
+
}
|
|
1186
|
+
const vastXml = await response.text();
|
|
1187
|
+
console.log("[HlsAdPlayer] VAST XML received");
|
|
1188
|
+
console.log(
|
|
1189
|
+
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1190
|
+
vastXml.substring(0, 2e3)
|
|
1191
|
+
);
|
|
1192
|
+
return parseVastXml(vastXml);
|
|
1193
|
+
}
|
|
1087
1194
|
function createAdVideoElement() {
|
|
1088
1195
|
const video = document.createElement("video");
|
|
1089
1196
|
video.style.position = "absolute";
|
|
@@ -1189,6 +1296,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1189
1296
|
setAdPlayingFlag(false);
|
|
1190
1297
|
const previousMutedState = contentVideo.muted;
|
|
1191
1298
|
contentVideo.muted = originalMutedState;
|
|
1299
|
+
contentVideo.volume = originalMutedState ? 0 : originalVolume;
|
|
1192
1300
|
console.log(
|
|
1193
1301
|
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
1194
1302
|
);
|
|
@@ -1235,17 +1343,17 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1235
1343
|
}
|
|
1236
1344
|
try {
|
|
1237
1345
|
sessionId = generateSessionId();
|
|
1238
|
-
|
|
1239
|
-
if (
|
|
1240
|
-
|
|
1346
|
+
let ad;
|
|
1347
|
+
if (preloadedAds.has(vastTagUrl)) {
|
|
1348
|
+
ad = preloadedAds.get(vastTagUrl);
|
|
1349
|
+
preloadedAds.delete(vastTagUrl);
|
|
1350
|
+
console.log(
|
|
1351
|
+
"[HlsAdPlayer] Using preloaded VAST response:",
|
|
1352
|
+
vastTagUrl
|
|
1353
|
+
);
|
|
1354
|
+
} else {
|
|
1355
|
+
ad = await fetchAndParseVastAd(vastTagUrl);
|
|
1241
1356
|
}
|
|
1242
|
-
const vastXml = await response.text();
|
|
1243
|
-
console.log("[HlsAdPlayer] VAST XML received");
|
|
1244
|
-
console.log(
|
|
1245
|
-
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1246
|
-
vastXml.substring(0, 2e3)
|
|
1247
|
-
);
|
|
1248
|
-
const ad = parseVastXml(vastXml);
|
|
1249
1357
|
if (!ad) {
|
|
1250
1358
|
console.warn("[HlsAdPlayer] No ads available from VAST response");
|
|
1251
1359
|
emit("ad_error");
|
|
@@ -1264,6 +1372,37 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1264
1372
|
return Promise.reject(error);
|
|
1265
1373
|
}
|
|
1266
1374
|
},
|
|
1375
|
+
async preloadAds(vastTagUrl) {
|
|
1376
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
1377
|
+
return Promise.resolve();
|
|
1378
|
+
}
|
|
1379
|
+
if (preloadedAds.has(vastTagUrl)) {
|
|
1380
|
+
return Promise.resolve();
|
|
1381
|
+
}
|
|
1382
|
+
const inflight = preloadingAds.get(vastTagUrl);
|
|
1383
|
+
if (inflight) {
|
|
1384
|
+
return inflight;
|
|
1385
|
+
}
|
|
1386
|
+
const preloadPromise = fetchAndParseVastAd(vastTagUrl).then((ad) => {
|
|
1387
|
+
if (ad) {
|
|
1388
|
+
preloadedAds.set(vastTagUrl, ad);
|
|
1389
|
+
console.log(
|
|
1390
|
+
"[HlsAdPlayer] Cached VAST response for preloading:",
|
|
1391
|
+
vastTagUrl
|
|
1392
|
+
);
|
|
1393
|
+
}
|
|
1394
|
+
}).catch((error) => {
|
|
1395
|
+
console.warn("[HlsAdPlayer] Failed to preload VAST response:", error);
|
|
1396
|
+
preloadedAds.delete(vastTagUrl);
|
|
1397
|
+
}).finally(() => {
|
|
1398
|
+
preloadingAds.delete(vastTagUrl);
|
|
1399
|
+
});
|
|
1400
|
+
preloadingAds.set(vastTagUrl, preloadPromise);
|
|
1401
|
+
return preloadPromise;
|
|
1402
|
+
},
|
|
1403
|
+
hasPreloadedAd(vastTagUrl) {
|
|
1404
|
+
return preloadedAds.has(vastTagUrl);
|
|
1405
|
+
},
|
|
1267
1406
|
async play() {
|
|
1268
1407
|
if (!currentAd) {
|
|
1269
1408
|
console.warn(
|
|
@@ -1287,6 +1426,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1287
1426
|
complete: false
|
|
1288
1427
|
};
|
|
1289
1428
|
const contentVolume = contentVideo.volume;
|
|
1429
|
+
originalVolume = Math.max(
|
|
1430
|
+
0,
|
|
1431
|
+
Math.min(1, contentVolume || originalVolume)
|
|
1432
|
+
);
|
|
1290
1433
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1291
1434
|
contentVideo.pause();
|
|
1292
1435
|
console.log("[HlsAdPlayer] Content paused (VOD mode)");
|
|
@@ -1299,7 +1442,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1299
1442
|
adPlaying = true;
|
|
1300
1443
|
setAdPlayingFlag(true);
|
|
1301
1444
|
if (adVideoElement) {
|
|
1302
|
-
const adVolume = originalMutedState ? 0 :
|
|
1445
|
+
const adVolume = originalMutedState ? 0 : originalVolume;
|
|
1303
1446
|
adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
|
|
1304
1447
|
adVideoElement.muted = false;
|
|
1305
1448
|
console.log(
|
|
@@ -1378,6 +1521,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1378
1521
|
adPlaying = false;
|
|
1379
1522
|
setAdPlayingFlag(false);
|
|
1380
1523
|
contentVideo.muted = originalMutedState;
|
|
1524
|
+
contentVideo.volume = originalMutedState ? 0 : originalVolume;
|
|
1381
1525
|
if (adHls) {
|
|
1382
1526
|
adHls.destroy();
|
|
1383
1527
|
adHls = void 0;
|
|
@@ -1394,6 +1538,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1394
1538
|
adContainerEl = void 0;
|
|
1395
1539
|
currentAd = void 0;
|
|
1396
1540
|
listeners.clear();
|
|
1541
|
+
preloadedAds.clear();
|
|
1542
|
+
preloadingAds.clear();
|
|
1397
1543
|
},
|
|
1398
1544
|
isAdPlaying() {
|
|
1399
1545
|
return adPlaying;
|
|
@@ -1417,15 +1563,20 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1417
1563
|
var _a;
|
|
1418
1564
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
1419
1565
|
},
|
|
1420
|
-
updateOriginalMutedState(muted) {
|
|
1566
|
+
updateOriginalMutedState(muted, volume) {
|
|
1567
|
+
const nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
|
|
1421
1568
|
console.log(
|
|
1422
|
-
`[HlsAdPlayer] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
1569
|
+
`[HlsAdPlayer] updateOriginalMutedState called: { muted: ${originalMutedState} -> ${muted}, volume: ${originalVolume} -> ${nextVolume} }`
|
|
1423
1570
|
);
|
|
1424
1571
|
originalMutedState = muted;
|
|
1572
|
+
originalVolume = nextVolume;
|
|
1425
1573
|
},
|
|
1426
1574
|
getOriginalMutedState() {
|
|
1427
1575
|
return originalMutedState;
|
|
1428
1576
|
},
|
|
1577
|
+
getOriginalVolume() {
|
|
1578
|
+
return originalVolume;
|
|
1579
|
+
},
|
|
1429
1580
|
setAdVolume(volume) {
|
|
1430
1581
|
if (adVideoElement && adPlaying) {
|
|
1431
1582
|
adVideoElement.volume = Math.max(0, Math.min(1, volume));
|
|
@@ -1436,6 +1587,35 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1436
1587
|
return adVideoElement.volume;
|
|
1437
1588
|
}
|
|
1438
1589
|
return 1;
|
|
1590
|
+
},
|
|
1591
|
+
showPlaceholder() {
|
|
1592
|
+
var _a;
|
|
1593
|
+
if (!adContainerEl) {
|
|
1594
|
+
const container = document.createElement("div");
|
|
1595
|
+
container.style.position = "absolute";
|
|
1596
|
+
container.style.left = "0";
|
|
1597
|
+
container.style.top = "0";
|
|
1598
|
+
container.style.right = "0";
|
|
1599
|
+
container.style.bottom = "0";
|
|
1600
|
+
container.style.display = "none";
|
|
1601
|
+
container.style.alignItems = "center";
|
|
1602
|
+
container.style.justifyContent = "center";
|
|
1603
|
+
container.style.pointerEvents = "none";
|
|
1604
|
+
container.style.zIndex = "10";
|
|
1605
|
+
container.style.backgroundColor = "#000";
|
|
1606
|
+
(_a = contentVideo.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
1607
|
+
adContainerEl = container;
|
|
1608
|
+
}
|
|
1609
|
+
if (adContainerEl) {
|
|
1610
|
+
adContainerEl.style.display = "flex";
|
|
1611
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
1612
|
+
}
|
|
1613
|
+
},
|
|
1614
|
+
hidePlaceholder() {
|
|
1615
|
+
if (adContainerEl) {
|
|
1616
|
+
adContainerEl.style.display = "none";
|
|
1617
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1618
|
+
}
|
|
1439
1619
|
}
|
|
1440
1620
|
};
|
|
1441
1621
|
}
|
|
@@ -1916,6 +2096,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1916
2096
|
this.bufferedSegmentsCount = 0;
|
|
1917
2097
|
this.shouldAutoplayAfterBuffering = false;
|
|
1918
2098
|
this.hasInitialBufferCompleted = false;
|
|
2099
|
+
this.adPodAllUrls = [];
|
|
2100
|
+
this.preloadingAdUrls = /* @__PURE__ */ new Set();
|
|
1919
2101
|
initializePolyfills();
|
|
1920
2102
|
const browserOverrides = getBrowserConfigOverrides();
|
|
1921
2103
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -2175,7 +2357,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2175
2357
|
this.video.autoplay = !!this.config.autoplay;
|
|
2176
2358
|
this.video.muted = !!this.config.muted;
|
|
2177
2359
|
this.ima.initialize();
|
|
2178
|
-
this.ima.updateOriginalMutedState(this.video.muted);
|
|
2360
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
2179
2361
|
this.ima.on("all_ads_completed", () => {
|
|
2180
2362
|
if (this.config.debugAdTiming) {
|
|
2181
2363
|
console.log(
|
|
@@ -2216,6 +2398,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2216
2398
|
console.log("[StormcloudVideoPlayer] IMA content_pause event received");
|
|
2217
2399
|
}
|
|
2218
2400
|
this.clearAdFailsafeTimer();
|
|
2401
|
+
this.enforceAdHoldState();
|
|
2219
2402
|
});
|
|
2220
2403
|
this.ima.on("content_resume", () => {
|
|
2221
2404
|
if (this.config.debugAdTiming) {
|
|
@@ -2240,9 +2423,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2240
2423
|
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2241
2424
|
const next = this.adPodQueue.shift();
|
|
2242
2425
|
this.currentAdIndex++;
|
|
2243
|
-
this.
|
|
2244
|
-
this.video.muted = true;
|
|
2245
|
-
this.video.volume = 0;
|
|
2426
|
+
this.enforceAdHoldState();
|
|
2246
2427
|
if (this.config.debugAdTiming) {
|
|
2247
2428
|
console.log(
|
|
2248
2429
|
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak}) - IMMEDIATELY starting next ad`
|
|
@@ -2854,11 +3035,16 @@ var StormcloudVideoPlayer = class {
|
|
|
2854
3035
|
return;
|
|
2855
3036
|
}
|
|
2856
3037
|
if (vastTagUrls.length > 0) {
|
|
3038
|
+
this.adPodAllUrls = [...vastTagUrls];
|
|
3039
|
+
this.preloadingAdUrls.clear();
|
|
3040
|
+
this.logQueuedAdUrls(this.adPodAllUrls);
|
|
2857
3041
|
this.inAdBreak = true;
|
|
2858
3042
|
this.showAds = true;
|
|
2859
3043
|
this.currentAdIndex = 0;
|
|
2860
3044
|
this.totalAdsInBreak = vastTagUrls.length;
|
|
2861
3045
|
this.adPodQueue = [...vastTagUrls];
|
|
3046
|
+
this.enforceAdHoldState();
|
|
3047
|
+
this.preloadUpcomingAds();
|
|
2862
3048
|
if (this.config.debugAdTiming) {
|
|
2863
3049
|
console.log(
|
|
2864
3050
|
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads - will play continuously`
|
|
@@ -2929,6 +3115,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2929
3115
|
const first = tags[0];
|
|
2930
3116
|
const rest = tags.slice(1);
|
|
2931
3117
|
this.adPodQueue = rest;
|
|
3118
|
+
this.enforceAdHoldState();
|
|
2932
3119
|
await this.playSingleAd(first);
|
|
2933
3120
|
this.inAdBreak = true;
|
|
2934
3121
|
this.expectedAdBreakDurationMs = remainingMs;
|
|
@@ -3042,6 +3229,12 @@ var StormcloudVideoPlayer = class {
|
|
|
3042
3229
|
}
|
|
3043
3230
|
return;
|
|
3044
3231
|
}
|
|
3232
|
+
const wasPreloaded = this.ima.hasPreloadedAd(vastTagUrl);
|
|
3233
|
+
if (wasPreloaded && this.config.debugAdTiming) {
|
|
3234
|
+
console.log(
|
|
3235
|
+
`[StormcloudVideoPlayer] IMA SDK preloaded this ad already: ${vastTagUrl}`
|
|
3236
|
+
);
|
|
3237
|
+
}
|
|
3045
3238
|
if (!this.showAds) {
|
|
3046
3239
|
if (this.config.debugAdTiming) {
|
|
3047
3240
|
console.log(
|
|
@@ -3053,7 +3246,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3053
3246
|
}
|
|
3054
3247
|
);
|
|
3055
3248
|
}
|
|
3056
|
-
this.ima.updateOriginalMutedState(this.video.muted);
|
|
3249
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3057
3250
|
} else if (this.config.debugAdTiming) {
|
|
3058
3251
|
console.log(
|
|
3059
3252
|
`[StormcloudVideoPlayer] Keeping existing original mute state (currently showing ads)`
|
|
@@ -3062,12 +3255,14 @@ var StormcloudVideoPlayer = class {
|
|
|
3062
3255
|
this.startAdFailsafeTimer();
|
|
3063
3256
|
try {
|
|
3064
3257
|
await this.ima.requestAds(vastTagUrl);
|
|
3258
|
+
this.preloadUpcomingAds();
|
|
3065
3259
|
try {
|
|
3066
3260
|
if (this.config.debugAdTiming) {
|
|
3067
3261
|
console.log(
|
|
3068
3262
|
"[StormcloudVideoPlayer] Ad request completed, attempting playback"
|
|
3069
3263
|
);
|
|
3070
3264
|
}
|
|
3265
|
+
this.enforceAdHoldState();
|
|
3071
3266
|
await this.ima.play();
|
|
3072
3267
|
if (this.config.debugAdTiming) {
|
|
3073
3268
|
console.log(
|
|
@@ -3097,6 +3292,8 @@ var StormcloudVideoPlayer = class {
|
|
|
3097
3292
|
"[StormcloudVideoPlayer] Handling ad pod completion - resuming content and hiding ad layer"
|
|
3098
3293
|
);
|
|
3099
3294
|
}
|
|
3295
|
+
this.releaseAdHoldState();
|
|
3296
|
+
this.preloadingAdUrls.clear();
|
|
3100
3297
|
this.inAdBreak = false;
|
|
3101
3298
|
this.expectedAdBreakDurationMs = void 0;
|
|
3102
3299
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
@@ -3104,14 +3301,16 @@ var StormcloudVideoPlayer = class {
|
|
|
3104
3301
|
this.clearAdStopTimer();
|
|
3105
3302
|
this.clearAdFailsafeTimer();
|
|
3106
3303
|
this.adPodQueue = [];
|
|
3304
|
+
this.adPodAllUrls = [];
|
|
3107
3305
|
this.showAds = false;
|
|
3108
3306
|
this.currentAdIndex = 0;
|
|
3109
3307
|
this.totalAdsInBreak = 0;
|
|
3110
3308
|
this.ima.stop().catch(() => {
|
|
3111
3309
|
});
|
|
3112
3310
|
const originalMutedState = this.ima.getOriginalMutedState();
|
|
3311
|
+
const originalVolume = typeof this.ima.getOriginalVolume === "function" ? this.ima.getOriginalVolume() : this.video.volume;
|
|
3113
3312
|
this.video.muted = originalMutedState;
|
|
3114
|
-
this.video.volume =
|
|
3313
|
+
this.video.volume = originalVolume;
|
|
3115
3314
|
if (this.config.debugAdTiming) {
|
|
3116
3315
|
console.log(
|
|
3117
3316
|
`[StormcloudVideoPlayer] Restored main video - muted: ${originalMutedState}, volume: ${this.video.volume}`
|
|
@@ -3184,6 +3383,64 @@ var StormcloudVideoPlayer = class {
|
|
|
3184
3383
|
}
|
|
3185
3384
|
return [b.vastTagUrl];
|
|
3186
3385
|
}
|
|
3386
|
+
logQueuedAdUrls(urls) {
|
|
3387
|
+
if (!this.config.debugAdTiming) {
|
|
3388
|
+
return;
|
|
3389
|
+
}
|
|
3390
|
+
console.log("[StormcloudVideoPlayer] ALL ad URLs queued:", urls);
|
|
3391
|
+
}
|
|
3392
|
+
enforceAdHoldState() {
|
|
3393
|
+
this.video.dataset.stormcloudAdPlaying = "true";
|
|
3394
|
+
this.video.muted = true;
|
|
3395
|
+
this.video.volume = 0;
|
|
3396
|
+
if (typeof this.ima.showPlaceholder === "function") {
|
|
3397
|
+
this.ima.showPlaceholder();
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3400
|
+
releaseAdHoldState() {
|
|
3401
|
+
delete this.video.dataset.stormcloudAdPlaying;
|
|
3402
|
+
if (typeof this.ima.hidePlaceholder === "function") {
|
|
3403
|
+
this.ima.hidePlaceholder();
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
preloadUpcomingAds() {
|
|
3407
|
+
if (!this.ima.preloadAds || this.adPodQueue.length === 0) {
|
|
3408
|
+
return;
|
|
3409
|
+
}
|
|
3410
|
+
const upcoming = this.adPodQueue.slice(0, 2);
|
|
3411
|
+
for (const url of upcoming) {
|
|
3412
|
+
if (!url) continue;
|
|
3413
|
+
if (this.ima.hasPreloadedAd(url)) {
|
|
3414
|
+
this.preloadingAdUrls.delete(url);
|
|
3415
|
+
continue;
|
|
3416
|
+
}
|
|
3417
|
+
if (this.preloadingAdUrls.has(url)) {
|
|
3418
|
+
continue;
|
|
3419
|
+
}
|
|
3420
|
+
if (this.config.debugAdTiming) {
|
|
3421
|
+
console.log(
|
|
3422
|
+
`[StormcloudVideoPlayer] Scheduling IMA preload for upcoming ad: ${url}`
|
|
3423
|
+
);
|
|
3424
|
+
}
|
|
3425
|
+
this.preloadingAdUrls.add(url);
|
|
3426
|
+
this.ima.preloadAds(url).then(() => {
|
|
3427
|
+
if (this.config.debugAdTiming) {
|
|
3428
|
+
console.log(
|
|
3429
|
+
`[StormcloudVideoPlayer] IMA preload complete for ad: ${url}`
|
|
3430
|
+
);
|
|
3431
|
+
}
|
|
3432
|
+
}).catch((error) => {
|
|
3433
|
+
if (this.config.debugAdTiming) {
|
|
3434
|
+
console.warn(
|
|
3435
|
+
`[StormcloudVideoPlayer] IMA preload failed for ad: ${url}`,
|
|
3436
|
+
error
|
|
3437
|
+
);
|
|
3438
|
+
}
|
|
3439
|
+
}).finally(() => {
|
|
3440
|
+
this.preloadingAdUrls.delete(url);
|
|
3441
|
+
});
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3187
3444
|
getRemainingAdMs() {
|
|
3188
3445
|
if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)
|
|
3189
3446
|
return 0;
|
|
@@ -3204,7 +3461,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3204
3461
|
if (this.ima.isAdPlaying()) {
|
|
3205
3462
|
const currentPerceptualState = this.isMuted();
|
|
3206
3463
|
const newMutedState = !currentPerceptualState;
|
|
3207
|
-
this.ima.updateOriginalMutedState(newMutedState);
|
|
3464
|
+
this.ima.updateOriginalMutedState(newMutedState, this.video.volume);
|
|
3208
3465
|
this.ima.setAdVolume(newMutedState ? 0 : 1);
|
|
3209
3466
|
if (this.config.debugAdTiming) {
|
|
3210
3467
|
console.log(
|
|
@@ -3214,7 +3471,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3214
3471
|
}
|
|
3215
3472
|
} else {
|
|
3216
3473
|
this.video.muted = !this.video.muted;
|
|
3217
|
-
this.ima.updateOriginalMutedState(this.video.muted);
|
|
3474
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3218
3475
|
if (this.config.debugAdTiming) {
|
|
3219
3476
|
console.log("[StormcloudVideoPlayer] Muted:", this.video.muted);
|
|
3220
3477
|
}
|
|
@@ -3286,7 +3543,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3286
3543
|
}
|
|
3287
3544
|
this.video.muted = muted;
|
|
3288
3545
|
if (adPlaying) {
|
|
3289
|
-
this.ima.updateOriginalMutedState(muted);
|
|
3546
|
+
this.ima.updateOriginalMutedState(muted, this.video.volume);
|
|
3290
3547
|
this.ima.setAdVolume(muted ? 0 : 1);
|
|
3291
3548
|
if (this.config.debugAdTiming) {
|
|
3292
3549
|
console.log("[StormcloudVideoPlayer] setMuted applied during ad", {
|
|
@@ -3295,7 +3552,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3295
3552
|
}
|
|
3296
3553
|
return;
|
|
3297
3554
|
}
|
|
3298
|
-
this.ima.updateOriginalMutedState(muted);
|
|
3555
|
+
this.ima.updateOriginalMutedState(muted, this.video.volume);
|
|
3299
3556
|
if (this.config.debugAdTiming) {
|
|
3300
3557
|
console.log("[StormcloudVideoPlayer] setMuted called:", muted);
|
|
3301
3558
|
}
|
|
@@ -3335,6 +3592,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3335
3592
|
}
|
|
3336
3593
|
(_a = this.hls) == null ? void 0 : _a.destroy();
|
|
3337
3594
|
(_b = this.ima) == null ? void 0 : _b.destroy();
|
|
3595
|
+
this.releaseAdHoldState();
|
|
3596
|
+
this.preloadingAdUrls.clear();
|
|
3597
|
+
this.adPodAllUrls = [];
|
|
3338
3598
|
}
|
|
3339
3599
|
};
|
|
3340
3600
|
|