stormcloud-video-player 0.2.23 → 0.2.25
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 +299 -52
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +11 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.js +299 -52
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +299 -52
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +8 -1
- package/lib/players/HlsPlayer.cjs +299 -52
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +299 -52
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +87 -10
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.d.cts +1 -1
- package/lib/sdk/ima.cjs +93 -21
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/sdk/ima.d.cts +1 -1
- package/lib/{types-D1xfSdLP.d.cts → types-9_2sbHCg.d.cts} +4 -0
- package/lib/ui/StormcloudVideoPlayer.cjs +299 -52
- 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-9_2sbHCg.cjs';
|
|
3
3
|
|
|
4
4
|
interface HlsPlayerProps extends StormcloudVideoPlayerConfig {
|
|
5
5
|
onMount?: (player: any) => void;
|
package/lib/players/index.cjs
CHANGED
|
@@ -242,6 +242,8 @@ function createImaController(video, options) {
|
|
|
242
242
|
let adPlaying = false;
|
|
243
243
|
let originalMutedState = false;
|
|
244
244
|
const listeners = /* @__PURE__ */ new Map();
|
|
245
|
+
const preloadedVast = /* @__PURE__ */ new Map();
|
|
246
|
+
const preloadingVast = /* @__PURE__ */ new Map();
|
|
245
247
|
function setAdPlayingFlag(isPlaying) {
|
|
246
248
|
if (isPlaying) {
|
|
247
249
|
video.dataset.stormcloudAdPlaying = "true";
|
|
@@ -332,7 +334,15 @@ function createImaController(video, options) {
|
|
|
332
334
|
let adsLoadedReject;
|
|
333
335
|
function makeAdsRequest(google, vastTagUrl) {
|
|
334
336
|
const adsRequest = new google.ima.AdsRequest();
|
|
335
|
-
|
|
337
|
+
const preloadedResponse = preloadedVast.get(vastTagUrl);
|
|
338
|
+
if (preloadedResponse) {
|
|
339
|
+
adsRequest.adsResponse = preloadedResponse;
|
|
340
|
+
console.log(
|
|
341
|
+
"[IMA] Using preloaded VAST response for immediate ad request"
|
|
342
|
+
);
|
|
343
|
+
} else {
|
|
344
|
+
adsRequest.adTagUrl = vastTagUrl;
|
|
345
|
+
}
|
|
336
346
|
const videoWidth = video.offsetWidth || video.clientWidth || 640;
|
|
337
347
|
const videoHeight = video.offsetHeight || video.clientHeight || 360;
|
|
338
348
|
adsRequest.linearAdSlotWidth = videoWidth;
|
|
@@ -342,6 +352,36 @@ function createImaController(video, options) {
|
|
|
342
352
|
adsRequest.vastLoadTimeout = 5e3;
|
|
343
353
|
console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
|
|
344
354
|
adsLoader.requestAds(adsRequest);
|
|
355
|
+
if (preloadedResponse) {
|
|
356
|
+
preloadedVast.delete(vastTagUrl);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
function ensurePlaceholderContainer() {
|
|
360
|
+
var _a;
|
|
361
|
+
if (adContainerEl) {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
const container = document.createElement("div");
|
|
365
|
+
container.style.position = "absolute";
|
|
366
|
+
container.style.left = "0";
|
|
367
|
+
container.style.top = "0";
|
|
368
|
+
container.style.right = "0";
|
|
369
|
+
container.style.bottom = "0";
|
|
370
|
+
container.style.display = "none";
|
|
371
|
+
container.style.alignItems = "center";
|
|
372
|
+
container.style.justifyContent = "center";
|
|
373
|
+
container.style.pointerEvents = "none";
|
|
374
|
+
container.style.zIndex = "10";
|
|
375
|
+
container.style.backgroundColor = "#000";
|
|
376
|
+
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
377
|
+
adContainerEl = container;
|
|
378
|
+
}
|
|
379
|
+
async function fetchVastDocument(vastTagUrl) {
|
|
380
|
+
const response = await fetch(vastTagUrl, { mode: "cors" });
|
|
381
|
+
if (!response.ok) {
|
|
382
|
+
throw new Error(`Failed to preload VAST: ${response.status}`);
|
|
383
|
+
}
|
|
384
|
+
return response.text();
|
|
345
385
|
}
|
|
346
386
|
function destroyAdsManager() {
|
|
347
387
|
if (adsManager) {
|
|
@@ -357,29 +397,16 @@ function createImaController(video, options) {
|
|
|
357
397
|
return {
|
|
358
398
|
initialize() {
|
|
359
399
|
ensureImaLoaded().then(() => {
|
|
360
|
-
var _a
|
|
400
|
+
var _a;
|
|
361
401
|
const google = window.google;
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
container.style.position = "absolute";
|
|
365
|
-
container.style.left = "0";
|
|
366
|
-
container.style.top = "0";
|
|
367
|
-
container.style.right = "0";
|
|
368
|
-
container.style.bottom = "0";
|
|
369
|
-
container.style.display = "none";
|
|
370
|
-
container.style.alignItems = "center";
|
|
371
|
-
container.style.justifyContent = "center";
|
|
372
|
-
container.style.pointerEvents = "none";
|
|
373
|
-
container.style.zIndex = "10";
|
|
374
|
-
container.style.backgroundColor = "#000";
|
|
375
|
-
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
376
|
-
adContainerEl = container;
|
|
402
|
+
ensurePlaceholderContainer();
|
|
403
|
+
if (!adDisplayContainer && adContainerEl) {
|
|
377
404
|
adDisplayContainer = new google.ima.AdDisplayContainer(
|
|
378
|
-
|
|
405
|
+
adContainerEl,
|
|
379
406
|
video
|
|
380
407
|
);
|
|
381
408
|
try {
|
|
382
|
-
(
|
|
409
|
+
(_a = adDisplayContainer.initialize) == null ? void 0 : _a.call(adDisplayContainer);
|
|
383
410
|
} catch {
|
|
384
411
|
}
|
|
385
412
|
}
|
|
@@ -481,9 +508,13 @@ function createImaController(video, options) {
|
|
|
481
508
|
adsLoader.addEventListener(
|
|
482
509
|
google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
|
|
483
510
|
(evt) => {
|
|
484
|
-
console.log(
|
|
511
|
+
console.log(
|
|
512
|
+
"[IMA] Ads manager loaded - enabling preloading for continuous playback"
|
|
513
|
+
);
|
|
485
514
|
try {
|
|
486
|
-
|
|
515
|
+
const adsRenderingSettings = new google.ima.AdsRenderingSettings();
|
|
516
|
+
adsRenderingSettings.enablePreloading = true;
|
|
517
|
+
adsManager = evt.getAdsManager(video, adsRenderingSettings);
|
|
487
518
|
const AdEvent = google.ima.AdEvent.Type;
|
|
488
519
|
const AdErrorEvent = google.ima.AdErrorEvent.Type;
|
|
489
520
|
adsManager.addEventListener(
|
|
@@ -679,6 +710,32 @@ function createImaController(video, options) {
|
|
|
679
710
|
return Promise.reject(error);
|
|
680
711
|
}
|
|
681
712
|
},
|
|
713
|
+
async preloadAds(vastTagUrl) {
|
|
714
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
715
|
+
return Promise.resolve();
|
|
716
|
+
}
|
|
717
|
+
if (preloadedVast.has(vastTagUrl)) {
|
|
718
|
+
return Promise.resolve();
|
|
719
|
+
}
|
|
720
|
+
const inflight = preloadingVast.get(vastTagUrl);
|
|
721
|
+
if (inflight) {
|
|
722
|
+
return inflight;
|
|
723
|
+
}
|
|
724
|
+
const preloadPromise = fetchVastDocument(vastTagUrl).then((xml) => {
|
|
725
|
+
preloadedVast.set(vastTagUrl, xml);
|
|
726
|
+
console.log("[IMA] Cached VAST response for preloading:", vastTagUrl);
|
|
727
|
+
}).catch((error) => {
|
|
728
|
+
console.warn("[IMA] Failed to preload VAST response:", error);
|
|
729
|
+
preloadedVast.delete(vastTagUrl);
|
|
730
|
+
}).finally(() => {
|
|
731
|
+
preloadingVast.delete(vastTagUrl);
|
|
732
|
+
});
|
|
733
|
+
preloadingVast.set(vastTagUrl, preloadPromise);
|
|
734
|
+
return preloadPromise;
|
|
735
|
+
},
|
|
736
|
+
hasPreloadedAd(vastTagUrl) {
|
|
737
|
+
return preloadedVast.has(vastTagUrl);
|
|
738
|
+
},
|
|
682
739
|
async play() {
|
|
683
740
|
var _a, _b;
|
|
684
741
|
if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
|
|
@@ -754,6 +811,8 @@ function createImaController(video, options) {
|
|
|
754
811
|
adContainerEl = void 0;
|
|
755
812
|
adDisplayContainer = void 0;
|
|
756
813
|
adsLoader = void 0;
|
|
814
|
+
preloadedVast.clear();
|
|
815
|
+
preloadingVast.clear();
|
|
757
816
|
},
|
|
758
817
|
isAdPlaying() {
|
|
759
818
|
return adPlaying;
|
|
@@ -809,6 +868,19 @@ function createImaController(video, options) {
|
|
|
809
868
|
}
|
|
810
869
|
}
|
|
811
870
|
return 1;
|
|
871
|
+
},
|
|
872
|
+
showPlaceholder() {
|
|
873
|
+
ensurePlaceholderContainer();
|
|
874
|
+
if (adContainerEl) {
|
|
875
|
+
adContainerEl.style.display = "flex";
|
|
876
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
877
|
+
}
|
|
878
|
+
},
|
|
879
|
+
hidePlaceholder() {
|
|
880
|
+
if (adContainerEl) {
|
|
881
|
+
adContainerEl.style.display = "none";
|
|
882
|
+
adContainerEl.style.pointerEvents = "none";
|
|
883
|
+
}
|
|
812
884
|
}
|
|
813
885
|
};
|
|
814
886
|
}
|
|
@@ -826,6 +898,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
826
898
|
let adContainerEl;
|
|
827
899
|
let currentAd;
|
|
828
900
|
let sessionId;
|
|
901
|
+
const preloadedAds = /* @__PURE__ */ new Map();
|
|
902
|
+
const preloadingAds = /* @__PURE__ */ new Map();
|
|
829
903
|
let trackingFired = {
|
|
830
904
|
impression: false,
|
|
831
905
|
start: false,
|
|
@@ -1055,6 +1129,19 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1055
1129
|
return null;
|
|
1056
1130
|
}
|
|
1057
1131
|
}
|
|
1132
|
+
async function fetchAndParseVastAd(vastTagUrl) {
|
|
1133
|
+
const response = await fetch(vastTagUrl);
|
|
1134
|
+
if (!response.ok) {
|
|
1135
|
+
throw new Error(`Failed to fetch VAST: ${response.statusText}`);
|
|
1136
|
+
}
|
|
1137
|
+
const vastXml = await response.text();
|
|
1138
|
+
console.log("[HlsAdPlayer] VAST XML received");
|
|
1139
|
+
console.log(
|
|
1140
|
+
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1141
|
+
vastXml.substring(0, 2e3)
|
|
1142
|
+
);
|
|
1143
|
+
return parseVastXml(vastXml);
|
|
1144
|
+
}
|
|
1058
1145
|
function createAdVideoElement() {
|
|
1059
1146
|
const video = document.createElement("video");
|
|
1060
1147
|
video.style.position = "absolute";
|
|
@@ -1206,17 +1293,17 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1206
1293
|
}
|
|
1207
1294
|
try {
|
|
1208
1295
|
sessionId = generateSessionId();
|
|
1209
|
-
|
|
1210
|
-
if (
|
|
1211
|
-
|
|
1296
|
+
let ad;
|
|
1297
|
+
if (preloadedAds.has(vastTagUrl)) {
|
|
1298
|
+
ad = preloadedAds.get(vastTagUrl);
|
|
1299
|
+
preloadedAds.delete(vastTagUrl);
|
|
1300
|
+
console.log(
|
|
1301
|
+
"[HlsAdPlayer] Using preloaded VAST response:",
|
|
1302
|
+
vastTagUrl
|
|
1303
|
+
);
|
|
1304
|
+
} else {
|
|
1305
|
+
ad = await fetchAndParseVastAd(vastTagUrl);
|
|
1212
1306
|
}
|
|
1213
|
-
const vastXml = await response.text();
|
|
1214
|
-
console.log("[HlsAdPlayer] VAST XML received");
|
|
1215
|
-
console.log(
|
|
1216
|
-
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
1217
|
-
vastXml.substring(0, 2e3)
|
|
1218
|
-
);
|
|
1219
|
-
const ad = parseVastXml(vastXml);
|
|
1220
1307
|
if (!ad) {
|
|
1221
1308
|
console.warn("[HlsAdPlayer] No ads available from VAST response");
|
|
1222
1309
|
emit("ad_error");
|
|
@@ -1235,6 +1322,37 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1235
1322
|
return Promise.reject(error);
|
|
1236
1323
|
}
|
|
1237
1324
|
},
|
|
1325
|
+
async preloadAds(vastTagUrl) {
|
|
1326
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
1327
|
+
return Promise.resolve();
|
|
1328
|
+
}
|
|
1329
|
+
if (preloadedAds.has(vastTagUrl)) {
|
|
1330
|
+
return Promise.resolve();
|
|
1331
|
+
}
|
|
1332
|
+
const inflight = preloadingAds.get(vastTagUrl);
|
|
1333
|
+
if (inflight) {
|
|
1334
|
+
return inflight;
|
|
1335
|
+
}
|
|
1336
|
+
const preloadPromise = fetchAndParseVastAd(vastTagUrl).then((ad) => {
|
|
1337
|
+
if (ad) {
|
|
1338
|
+
preloadedAds.set(vastTagUrl, ad);
|
|
1339
|
+
console.log(
|
|
1340
|
+
"[HlsAdPlayer] Cached VAST response for preloading:",
|
|
1341
|
+
vastTagUrl
|
|
1342
|
+
);
|
|
1343
|
+
}
|
|
1344
|
+
}).catch((error) => {
|
|
1345
|
+
console.warn("[HlsAdPlayer] Failed to preload VAST response:", error);
|
|
1346
|
+
preloadedAds.delete(vastTagUrl);
|
|
1347
|
+
}).finally(() => {
|
|
1348
|
+
preloadingAds.delete(vastTagUrl);
|
|
1349
|
+
});
|
|
1350
|
+
preloadingAds.set(vastTagUrl, preloadPromise);
|
|
1351
|
+
return preloadPromise;
|
|
1352
|
+
},
|
|
1353
|
+
hasPreloadedAd(vastTagUrl) {
|
|
1354
|
+
return preloadedAds.has(vastTagUrl);
|
|
1355
|
+
},
|
|
1238
1356
|
async play() {
|
|
1239
1357
|
if (!currentAd) {
|
|
1240
1358
|
console.warn(
|
|
@@ -1365,6 +1483,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1365
1483
|
adContainerEl = void 0;
|
|
1366
1484
|
currentAd = void 0;
|
|
1367
1485
|
listeners.clear();
|
|
1486
|
+
preloadedAds.clear();
|
|
1487
|
+
preloadingAds.clear();
|
|
1368
1488
|
},
|
|
1369
1489
|
isAdPlaying() {
|
|
1370
1490
|
return adPlaying;
|
|
@@ -1407,6 +1527,35 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1407
1527
|
return adVideoElement.volume;
|
|
1408
1528
|
}
|
|
1409
1529
|
return 1;
|
|
1530
|
+
},
|
|
1531
|
+
showPlaceholder() {
|
|
1532
|
+
var _a;
|
|
1533
|
+
if (!adContainerEl) {
|
|
1534
|
+
const container = document.createElement("div");
|
|
1535
|
+
container.style.position = "absolute";
|
|
1536
|
+
container.style.left = "0";
|
|
1537
|
+
container.style.top = "0";
|
|
1538
|
+
container.style.right = "0";
|
|
1539
|
+
container.style.bottom = "0";
|
|
1540
|
+
container.style.display = "none";
|
|
1541
|
+
container.style.alignItems = "center";
|
|
1542
|
+
container.style.justifyContent = "center";
|
|
1543
|
+
container.style.pointerEvents = "none";
|
|
1544
|
+
container.style.zIndex = "10";
|
|
1545
|
+
container.style.backgroundColor = "#000";
|
|
1546
|
+
(_a = contentVideo.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
1547
|
+
adContainerEl = container;
|
|
1548
|
+
}
|
|
1549
|
+
if (adContainerEl) {
|
|
1550
|
+
adContainerEl.style.display = "flex";
|
|
1551
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
1552
|
+
}
|
|
1553
|
+
},
|
|
1554
|
+
hidePlaceholder() {
|
|
1555
|
+
if (adContainerEl) {
|
|
1556
|
+
adContainerEl.style.display = "none";
|
|
1557
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1558
|
+
}
|
|
1410
1559
|
}
|
|
1411
1560
|
};
|
|
1412
1561
|
}
|
|
@@ -1887,6 +2036,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1887
2036
|
this.bufferedSegmentsCount = 0;
|
|
1888
2037
|
this.shouldAutoplayAfterBuffering = false;
|
|
1889
2038
|
this.hasInitialBufferCompleted = false;
|
|
2039
|
+
this.adPodAllUrls = [];
|
|
2040
|
+
this.preloadingAdUrls = /* @__PURE__ */ new Set();
|
|
1890
2041
|
initializePolyfills();
|
|
1891
2042
|
const browserOverrides = getBrowserConfigOverrides();
|
|
1892
2043
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -2187,6 +2338,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2187
2338
|
console.log("[StormcloudVideoPlayer] IMA content_pause event received");
|
|
2188
2339
|
}
|
|
2189
2340
|
this.clearAdFailsafeTimer();
|
|
2341
|
+
this.enforceAdHoldState();
|
|
2190
2342
|
});
|
|
2191
2343
|
this.ima.on("content_resume", () => {
|
|
2192
2344
|
if (this.config.debugAdTiming) {
|
|
@@ -2211,12 +2363,10 @@ var StormcloudVideoPlayer = class {
|
|
|
2211
2363
|
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2212
2364
|
const next = this.adPodQueue.shift();
|
|
2213
2365
|
this.currentAdIndex++;
|
|
2214
|
-
this.
|
|
2215
|
-
this.video.muted = true;
|
|
2216
|
-
this.video.volume = 0;
|
|
2366
|
+
this.enforceAdHoldState();
|
|
2217
2367
|
if (this.config.debugAdTiming) {
|
|
2218
2368
|
console.log(
|
|
2219
|
-
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak}) -
|
|
2369
|
+
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak}) - IMMEDIATELY starting next ad`
|
|
2220
2370
|
);
|
|
2221
2371
|
}
|
|
2222
2372
|
this.playSingleAd(next).catch(() => {
|
|
@@ -2801,25 +2951,21 @@ var StormcloudVideoPlayer = class {
|
|
|
2801
2951
|
this.video.currentTime * 1e3
|
|
2802
2952
|
);
|
|
2803
2953
|
const tags = this.selectVastTagsForBreak(scheduled);
|
|
2804
|
-
let
|
|
2954
|
+
let vastTagUrls = [];
|
|
2805
2955
|
if (this.apiVastTagUrl) {
|
|
2806
|
-
|
|
2807
|
-
this.adPodQueue = [];
|
|
2808
|
-
this.currentAdIndex = 0;
|
|
2809
|
-
this.totalAdsInBreak = 1;
|
|
2956
|
+
vastTagUrls = [this.apiVastTagUrl];
|
|
2810
2957
|
if (this.config.debugAdTiming) {
|
|
2811
|
-
console.log(
|
|
2958
|
+
console.log(
|
|
2959
|
+
"[StormcloudVideoPlayer] Using VAST endpoint:",
|
|
2960
|
+
this.apiVastTagUrl
|
|
2961
|
+
);
|
|
2812
2962
|
}
|
|
2813
2963
|
} else if (tags && tags.length > 0) {
|
|
2814
|
-
|
|
2815
|
-
const rest = tags.slice(1);
|
|
2816
|
-
this.adPodQueue = rest;
|
|
2817
|
-
this.currentAdIndex = 0;
|
|
2818
|
-
this.totalAdsInBreak = tags.length;
|
|
2964
|
+
vastTagUrls = tags;
|
|
2819
2965
|
if (this.config.debugAdTiming) {
|
|
2820
2966
|
console.log(
|
|
2821
|
-
"[StormcloudVideoPlayer] Using scheduled VAST
|
|
2822
|
-
|
|
2967
|
+
"[StormcloudVideoPlayer] Using scheduled VAST tags (count: " + tags.length + "):",
|
|
2968
|
+
tags
|
|
2823
2969
|
);
|
|
2824
2970
|
}
|
|
2825
2971
|
} else {
|
|
@@ -2828,16 +2974,28 @@ var StormcloudVideoPlayer = class {
|
|
|
2828
2974
|
}
|
|
2829
2975
|
return;
|
|
2830
2976
|
}
|
|
2831
|
-
if (
|
|
2977
|
+
if (vastTagUrls.length > 0) {
|
|
2978
|
+
this.adPodAllUrls = [...vastTagUrls];
|
|
2979
|
+
this.preloadingAdUrls.clear();
|
|
2980
|
+
this.logQueuedAdUrls(this.adPodAllUrls);
|
|
2832
2981
|
this.inAdBreak = true;
|
|
2833
2982
|
this.showAds = true;
|
|
2834
|
-
this.currentAdIndex
|
|
2983
|
+
this.currentAdIndex = 0;
|
|
2984
|
+
this.totalAdsInBreak = vastTagUrls.length;
|
|
2985
|
+
this.adPodQueue = [...vastTagUrls];
|
|
2986
|
+
this.enforceAdHoldState();
|
|
2987
|
+
this.preloadUpcomingAds();
|
|
2988
|
+
if (this.config.debugAdTiming) {
|
|
2989
|
+
console.log(
|
|
2990
|
+
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads - will play continuously`
|
|
2991
|
+
);
|
|
2992
|
+
}
|
|
2835
2993
|
try {
|
|
2836
|
-
await this.
|
|
2994
|
+
await this.playAdPod();
|
|
2837
2995
|
} catch (error) {
|
|
2838
2996
|
if (this.config.debugAdTiming) {
|
|
2839
2997
|
console.error(
|
|
2840
|
-
"[StormcloudVideoPlayer] Ad playback failed
|
|
2998
|
+
"[StormcloudVideoPlayer] Ad pod playback failed:",
|
|
2841
2999
|
error
|
|
2842
3000
|
);
|
|
2843
3001
|
}
|
|
@@ -2850,6 +3008,22 @@ var StormcloudVideoPlayer = class {
|
|
|
2850
3008
|
this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
|
|
2851
3009
|
}
|
|
2852
3010
|
}
|
|
3011
|
+
async playAdPod() {
|
|
3012
|
+
if (this.adPodQueue.length === 0) {
|
|
3013
|
+
if (this.config.debugAdTiming) {
|
|
3014
|
+
console.log("[StormcloudVideoPlayer] No ads in pod to play");
|
|
3015
|
+
}
|
|
3016
|
+
return;
|
|
3017
|
+
}
|
|
3018
|
+
const firstAd = this.adPodQueue.shift();
|
|
3019
|
+
this.currentAdIndex++;
|
|
3020
|
+
if (this.config.debugAdTiming) {
|
|
3021
|
+
console.log(
|
|
3022
|
+
`[StormcloudVideoPlayer] Playing ad ${this.currentAdIndex}/${this.totalAdsInBreak}`
|
|
3023
|
+
);
|
|
3024
|
+
}
|
|
3025
|
+
await this.playSingleAd(firstAd);
|
|
3026
|
+
}
|
|
2853
3027
|
findCurrentOrNextBreak(nowMs) {
|
|
2854
3028
|
var _a;
|
|
2855
3029
|
const schedule = [];
|
|
@@ -2881,6 +3055,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2881
3055
|
const first = tags[0];
|
|
2882
3056
|
const rest = tags.slice(1);
|
|
2883
3057
|
this.adPodQueue = rest;
|
|
3058
|
+
this.enforceAdHoldState();
|
|
2884
3059
|
await this.playSingleAd(first);
|
|
2885
3060
|
this.inAdBreak = true;
|
|
2886
3061
|
this.expectedAdBreakDurationMs = remainingMs;
|
|
@@ -2994,6 +3169,12 @@ var StormcloudVideoPlayer = class {
|
|
|
2994
3169
|
}
|
|
2995
3170
|
return;
|
|
2996
3171
|
}
|
|
3172
|
+
const wasPreloaded = this.ima.hasPreloadedAd(vastTagUrl);
|
|
3173
|
+
if (wasPreloaded && this.config.debugAdTiming) {
|
|
3174
|
+
console.log(
|
|
3175
|
+
`[StormcloudVideoPlayer] IMA SDK preloaded this ad already: ${vastTagUrl}`
|
|
3176
|
+
);
|
|
3177
|
+
}
|
|
2997
3178
|
if (!this.showAds) {
|
|
2998
3179
|
if (this.config.debugAdTiming) {
|
|
2999
3180
|
console.log(
|
|
@@ -3014,12 +3195,14 @@ var StormcloudVideoPlayer = class {
|
|
|
3014
3195
|
this.startAdFailsafeTimer();
|
|
3015
3196
|
try {
|
|
3016
3197
|
await this.ima.requestAds(vastTagUrl);
|
|
3198
|
+
this.preloadUpcomingAds();
|
|
3017
3199
|
try {
|
|
3018
3200
|
if (this.config.debugAdTiming) {
|
|
3019
3201
|
console.log(
|
|
3020
3202
|
"[StormcloudVideoPlayer] Ad request completed, attempting playback"
|
|
3021
3203
|
);
|
|
3022
3204
|
}
|
|
3205
|
+
this.enforceAdHoldState();
|
|
3023
3206
|
await this.ima.play();
|
|
3024
3207
|
if (this.config.debugAdTiming) {
|
|
3025
3208
|
console.log(
|
|
@@ -3049,6 +3232,8 @@ var StormcloudVideoPlayer = class {
|
|
|
3049
3232
|
"[StormcloudVideoPlayer] Handling ad pod completion - resuming content and hiding ad layer"
|
|
3050
3233
|
);
|
|
3051
3234
|
}
|
|
3235
|
+
this.releaseAdHoldState();
|
|
3236
|
+
this.preloadingAdUrls.clear();
|
|
3052
3237
|
this.inAdBreak = false;
|
|
3053
3238
|
this.expectedAdBreakDurationMs = void 0;
|
|
3054
3239
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
@@ -3056,6 +3241,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3056
3241
|
this.clearAdStopTimer();
|
|
3057
3242
|
this.clearAdFailsafeTimer();
|
|
3058
3243
|
this.adPodQueue = [];
|
|
3244
|
+
this.adPodAllUrls = [];
|
|
3059
3245
|
this.showAds = false;
|
|
3060
3246
|
this.currentAdIndex = 0;
|
|
3061
3247
|
this.totalAdsInBreak = 0;
|
|
@@ -3136,6 +3322,64 @@ var StormcloudVideoPlayer = class {
|
|
|
3136
3322
|
}
|
|
3137
3323
|
return [b.vastTagUrl];
|
|
3138
3324
|
}
|
|
3325
|
+
logQueuedAdUrls(urls) {
|
|
3326
|
+
if (!this.config.debugAdTiming) {
|
|
3327
|
+
return;
|
|
3328
|
+
}
|
|
3329
|
+
console.log("[StormcloudVideoPlayer] ALL ad URLs queued:", urls);
|
|
3330
|
+
}
|
|
3331
|
+
enforceAdHoldState() {
|
|
3332
|
+
this.video.dataset.stormcloudAdPlaying = "true";
|
|
3333
|
+
this.video.muted = true;
|
|
3334
|
+
this.video.volume = 0;
|
|
3335
|
+
if (typeof this.ima.showPlaceholder === "function") {
|
|
3336
|
+
this.ima.showPlaceholder();
|
|
3337
|
+
}
|
|
3338
|
+
}
|
|
3339
|
+
releaseAdHoldState() {
|
|
3340
|
+
delete this.video.dataset.stormcloudAdPlaying;
|
|
3341
|
+
if (typeof this.ima.hidePlaceholder === "function") {
|
|
3342
|
+
this.ima.hidePlaceholder();
|
|
3343
|
+
}
|
|
3344
|
+
}
|
|
3345
|
+
preloadUpcomingAds() {
|
|
3346
|
+
if (!this.ima.preloadAds || this.adPodQueue.length === 0) {
|
|
3347
|
+
return;
|
|
3348
|
+
}
|
|
3349
|
+
const upcoming = this.adPodQueue.slice(0, 2);
|
|
3350
|
+
for (const url of upcoming) {
|
|
3351
|
+
if (!url) continue;
|
|
3352
|
+
if (this.ima.hasPreloadedAd(url)) {
|
|
3353
|
+
this.preloadingAdUrls.delete(url);
|
|
3354
|
+
continue;
|
|
3355
|
+
}
|
|
3356
|
+
if (this.preloadingAdUrls.has(url)) {
|
|
3357
|
+
continue;
|
|
3358
|
+
}
|
|
3359
|
+
if (this.config.debugAdTiming) {
|
|
3360
|
+
console.log(
|
|
3361
|
+
`[StormcloudVideoPlayer] Scheduling IMA preload for upcoming ad: ${url}`
|
|
3362
|
+
);
|
|
3363
|
+
}
|
|
3364
|
+
this.preloadingAdUrls.add(url);
|
|
3365
|
+
this.ima.preloadAds(url).then(() => {
|
|
3366
|
+
if (this.config.debugAdTiming) {
|
|
3367
|
+
console.log(
|
|
3368
|
+
`[StormcloudVideoPlayer] IMA preload complete for ad: ${url}`
|
|
3369
|
+
);
|
|
3370
|
+
}
|
|
3371
|
+
}).catch((error) => {
|
|
3372
|
+
if (this.config.debugAdTiming) {
|
|
3373
|
+
console.warn(
|
|
3374
|
+
`[StormcloudVideoPlayer] IMA preload failed for ad: ${url}`,
|
|
3375
|
+
error
|
|
3376
|
+
);
|
|
3377
|
+
}
|
|
3378
|
+
}).finally(() => {
|
|
3379
|
+
this.preloadingAdUrls.delete(url);
|
|
3380
|
+
});
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3139
3383
|
getRemainingAdMs() {
|
|
3140
3384
|
if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)
|
|
3141
3385
|
return 0;
|
|
@@ -3287,6 +3531,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3287
3531
|
}
|
|
3288
3532
|
(_a = this.hls) == null ? void 0 : _a.destroy();
|
|
3289
3533
|
(_b = this.ima) == null ? void 0 : _b.destroy();
|
|
3534
|
+
this.releaseAdHoldState();
|
|
3535
|
+
this.preloadingAdUrls.clear();
|
|
3536
|
+
this.adPodAllUrls = [];
|
|
3290
3537
|
}
|
|
3291
3538
|
};
|
|
3292
3539
|
|