stormcloud-video-player 0.2.5 → 0.2.6
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/README.md +15 -16
- package/dist/stormcloud-vp.min.js +1 -1
- package/lib/index.cjs +53 -363
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +0 -30
- package/lib/index.d.ts +0 -30
- package/lib/index.js +53 -363
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +0 -11
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +0 -1
- package/lib/players/HlsPlayer.cjs +0 -11
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +0 -11
- package/lib/players/index.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +0 -11
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +1 -1
- package/lib/types-DOcCdwQI.d.cts +0 -78
package/lib/index.cjs
CHANGED
|
@@ -127,8 +127,6 @@ function createImaController(video, options) {
|
|
|
127
127
|
let adsLoadedPromise;
|
|
128
128
|
let adsLoadedResolve;
|
|
129
129
|
let adsLoadedReject;
|
|
130
|
-
let currentAdDuration = 0;
|
|
131
|
-
let preloadedAds = [];
|
|
132
130
|
function makeAdsRequest(google, vastTagUrl) {
|
|
133
131
|
const adsRequest = new google.ima.AdsRequest();
|
|
134
132
|
adsRequest.adTagUrl = vastTagUrl;
|
|
@@ -235,7 +233,6 @@ function createImaController(video, options) {
|
|
|
235
233
|
} catch {
|
|
236
234
|
}
|
|
237
235
|
adPlaying = false;
|
|
238
|
-
currentAdDuration = 0;
|
|
239
236
|
video.muted = originalMutedState;
|
|
240
237
|
if (adContainerEl)
|
|
241
238
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -307,22 +304,9 @@ function createImaController(video, options) {
|
|
|
307
304
|
emit("content_resume");
|
|
308
305
|
}
|
|
309
306
|
);
|
|
310
|
-
adsManager.addEventListener(AdEvent.STARTED, (adEvent) => {
|
|
311
|
-
console.log("[IMA] Ad started");
|
|
312
|
-
try {
|
|
313
|
-
const ad = adEvent.getAd();
|
|
314
|
-
if (ad && ad.getDuration) {
|
|
315
|
-
currentAdDuration = ad.getDuration();
|
|
316
|
-
console.log(`[IMA] Ad duration: ${currentAdDuration}s`);
|
|
317
|
-
}
|
|
318
|
-
} catch (error) {
|
|
319
|
-
console.warn("[IMA] Could not get ad duration:", error);
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
307
|
adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {
|
|
323
308
|
console.log("[IMA] All ads completed");
|
|
324
309
|
adPlaying = false;
|
|
325
|
-
currentAdDuration = 0;
|
|
326
310
|
video.muted = originalMutedState;
|
|
327
311
|
if (adContainerEl) adContainerEl.style.pointerEvents = "none";
|
|
328
312
|
if (!options?.continueLiveStreamDuringAds) {
|
|
@@ -507,84 +491,6 @@ function createImaController(video, options) {
|
|
|
507
491
|
}
|
|
508
492
|
}
|
|
509
493
|
return 1;
|
|
510
|
-
},
|
|
511
|
-
getAdDuration() {
|
|
512
|
-
return currentAdDuration;
|
|
513
|
-
},
|
|
514
|
-
async preloadAds(vastTagUrls) {
|
|
515
|
-
console.log(`[IMA] Preloading ${vastTagUrls.length} ads`);
|
|
516
|
-
const adInfos = [];
|
|
517
|
-
for (const vastTagUrl of vastTagUrls) {
|
|
518
|
-
try {
|
|
519
|
-
await ensureImaLoaded();
|
|
520
|
-
const google = window.google;
|
|
521
|
-
const tempAdsLoader = new google.ima.AdsLoader(adDisplayContainer);
|
|
522
|
-
const adInfo = await new Promise((resolve, reject) => {
|
|
523
|
-
const timeout = setTimeout(() => {
|
|
524
|
-
reject(new Error("Preload timeout"));
|
|
525
|
-
}, 5e3);
|
|
526
|
-
tempAdsLoader.addEventListener(
|
|
527
|
-
google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
|
|
528
|
-
(evt) => {
|
|
529
|
-
clearTimeout(timeout);
|
|
530
|
-
try {
|
|
531
|
-
const tempAdsManager = evt.getAdsManager(video);
|
|
532
|
-
let duration = 30;
|
|
533
|
-
try {
|
|
534
|
-
const ads = tempAdsManager.getCuePoints?.() || [];
|
|
535
|
-
if (ads.length > 0) {
|
|
536
|
-
duration = 15;
|
|
537
|
-
}
|
|
538
|
-
} catch {
|
|
539
|
-
}
|
|
540
|
-
tempAdsManager.destroy();
|
|
541
|
-
resolve({
|
|
542
|
-
duration,
|
|
543
|
-
vastTagUrl,
|
|
544
|
-
isPreloaded: true
|
|
545
|
-
});
|
|
546
|
-
} catch (error) {
|
|
547
|
-
clearTimeout(timeout);
|
|
548
|
-
reject(error);
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
);
|
|
552
|
-
tempAdsLoader.addEventListener(
|
|
553
|
-
google.ima.AdErrorEvent.Type.AD_ERROR,
|
|
554
|
-
(errorEvent) => {
|
|
555
|
-
clearTimeout(timeout);
|
|
556
|
-
console.warn(
|
|
557
|
-
`[IMA] Preload error for ${vastTagUrl}:`,
|
|
558
|
-
errorEvent.getError()
|
|
559
|
-
);
|
|
560
|
-
resolve({
|
|
561
|
-
duration: 30,
|
|
562
|
-
vastTagUrl,
|
|
563
|
-
isPreloaded: false
|
|
564
|
-
});
|
|
565
|
-
}
|
|
566
|
-
);
|
|
567
|
-
const adsRequest = new google.ima.AdsRequest();
|
|
568
|
-
adsRequest.adTagUrl = vastTagUrl;
|
|
569
|
-
tempAdsLoader.requestAds(adsRequest);
|
|
570
|
-
});
|
|
571
|
-
adInfos.push(adInfo);
|
|
572
|
-
tempAdsLoader.destroy();
|
|
573
|
-
} catch (error) {
|
|
574
|
-
console.warn(`[IMA] Failed to preload ad ${vastTagUrl}:`, error);
|
|
575
|
-
adInfos.push({
|
|
576
|
-
duration: 30,
|
|
577
|
-
vastTagUrl,
|
|
578
|
-
isPreloaded: false
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
preloadedAds = adInfos;
|
|
583
|
-
console.log(
|
|
584
|
-
`[IMA] Preloaded ${adInfos.length} ads with total duration:`,
|
|
585
|
-
adInfos.reduce((sum, ad) => sum + ad.duration, 0)
|
|
586
|
-
);
|
|
587
|
-
return adInfos;
|
|
588
494
|
}
|
|
589
495
|
};
|
|
590
496
|
}
|
|
@@ -817,8 +723,6 @@ var StormcloudVideoPlayer = class {
|
|
|
817
723
|
this.totalAdsInBreak = 0;
|
|
818
724
|
this.showAds = false;
|
|
819
725
|
this.isLiveStream = false;
|
|
820
|
-
this.preloadedAdInfo = [];
|
|
821
|
-
this.cumulativeAdDurationMs = 0;
|
|
822
726
|
this.config = config;
|
|
823
727
|
this.video = config.videoElement;
|
|
824
728
|
this.ima = createImaController(this.video, {
|
|
@@ -990,28 +894,16 @@ var StormcloudVideoPlayer = class {
|
|
|
990
894
|
this.ima.initialize();
|
|
991
895
|
this.ima.on("all_ads_completed", () => {
|
|
992
896
|
if (!this.inAdBreak) return;
|
|
993
|
-
const actualAdDuration = this.ima.getAdDuration();
|
|
994
|
-
if (actualAdDuration > 0) {
|
|
995
|
-
this.cumulativeAdDurationMs += actualAdDuration * 1e3;
|
|
996
|
-
if (this.config.debugAdTiming) {
|
|
997
|
-
console.log(
|
|
998
|
-
`[StormcloudVideoPlayer] Ad completed. Duration: ${actualAdDuration}s, Cumulative: ${this.cumulativeAdDurationMs}ms`
|
|
999
|
-
);
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
897
|
const remaining = this.getRemainingAdMs();
|
|
1003
|
-
|
|
1004
|
-
if (shouldContinue && this.adPodQueue.length > 0) {
|
|
898
|
+
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
1005
899
|
const next = this.adPodQueue.shift();
|
|
1006
900
|
this.currentAdIndex++;
|
|
1007
901
|
this.playSingleAd(next).catch(() => {
|
|
1008
902
|
});
|
|
1009
|
-
} else if (shouldContinue && this.canRequestMoreAds()) {
|
|
1010
|
-
this.requestAdditionalAds().catch(() => {
|
|
1011
|
-
this.endAdBreak();
|
|
1012
|
-
});
|
|
1013
903
|
} else {
|
|
1014
|
-
this.
|
|
904
|
+
this.currentAdIndex = 0;
|
|
905
|
+
this.totalAdsInBreak = 0;
|
|
906
|
+
this.showAds = false;
|
|
1015
907
|
}
|
|
1016
908
|
});
|
|
1017
909
|
this.ima.on("ad_error", () => {
|
|
@@ -1020,16 +912,11 @@ var StormcloudVideoPlayer = class {
|
|
|
1020
912
|
}
|
|
1021
913
|
if (!this.inAdBreak) return;
|
|
1022
914
|
const remaining = this.getRemainingAdMs();
|
|
1023
|
-
|
|
1024
|
-
if (shouldContinue && this.adPodQueue.length > 0) {
|
|
915
|
+
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
1025
916
|
const next = this.adPodQueue.shift();
|
|
1026
917
|
this.currentAdIndex++;
|
|
1027
918
|
this.playSingleAd(next).catch(() => {
|
|
1028
919
|
});
|
|
1029
|
-
} else if (shouldContinue && this.canRequestMoreAds()) {
|
|
1030
|
-
this.requestAdditionalAds().catch(() => {
|
|
1031
|
-
this.handleAdFailure();
|
|
1032
|
-
});
|
|
1033
920
|
} else {
|
|
1034
921
|
this.handleAdFailure();
|
|
1035
922
|
}
|
|
@@ -1520,25 +1407,6 @@ var StormcloudVideoPlayer = class {
|
|
|
1520
1407
|
isShowingAds() {
|
|
1521
1408
|
return this.showAds;
|
|
1522
1409
|
}
|
|
1523
|
-
getAdBreakStats() {
|
|
1524
|
-
const remainingDurationMs = this.currentAdBreakTargetDurationMs != null ? Math.max(
|
|
1525
|
-
0,
|
|
1526
|
-
this.currentAdBreakTargetDurationMs - this.cumulativeAdDurationMs
|
|
1527
|
-
) : void 0;
|
|
1528
|
-
const estimatedFillRate = this.currentAdBreakTargetDurationMs != null && this.currentAdBreakTargetDurationMs > 0 ? this.cumulativeAdDurationMs / this.currentAdBreakTargetDurationMs * 100 : void 0;
|
|
1529
|
-
return {
|
|
1530
|
-
isInAdBreak: this.inAdBreak,
|
|
1531
|
-
currentAdIndex: this.currentAdIndex,
|
|
1532
|
-
totalAdsInBreak: this.totalAdsInBreak,
|
|
1533
|
-
targetDurationMs: this.currentAdBreakTargetDurationMs,
|
|
1534
|
-
cumulativeDurationMs: this.cumulativeAdDurationMs,
|
|
1535
|
-
estimatedFillRate,
|
|
1536
|
-
remainingDurationMs
|
|
1537
|
-
};
|
|
1538
|
-
}
|
|
1539
|
-
getPreloadedAdInfo() {
|
|
1540
|
-
return [...this.preloadedAdInfo];
|
|
1541
|
-
}
|
|
1542
1410
|
getStreamType() {
|
|
1543
1411
|
const url = this.config.src.toLowerCase();
|
|
1544
1412
|
if (url.includes(".m3u8") || url.includes("/hls/") || url.includes("application/vnd.apple.mpegurl")) {
|
|
@@ -1562,70 +1430,59 @@ var StormcloudVideoPlayer = class {
|
|
|
1562
1430
|
}
|
|
1563
1431
|
return true;
|
|
1564
1432
|
}
|
|
1565
|
-
async
|
|
1566
|
-
const usp = new URLSearchParams(params || {});
|
|
1567
|
-
const url = `${adstormApiUrl}?${usp.toString()}`;
|
|
1568
|
-
const res = await fetch(url);
|
|
1569
|
-
if (!res.ok) throw new Error(`Failed to fetch adstorm ads: ${res.status}`);
|
|
1570
|
-
const data = await res.json();
|
|
1571
|
-
const tag = data?.adTagUrl || data?.vastTagUrl || data?.tagUrl;
|
|
1572
|
-
if (typeof tag === "string" && tag.length > 0) {
|
|
1573
|
-
this.apiVastTagUrl = tag;
|
|
1574
|
-
}
|
|
1575
|
-
}
|
|
1576
|
-
async handleAdStart(marker) {
|
|
1433
|
+
async handleAdStart(_marker) {
|
|
1577
1434
|
const scheduled = this.findCurrentOrNextBreak(
|
|
1578
1435
|
this.video.currentTime * 1e3
|
|
1579
1436
|
);
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
"[StormcloudVideoPlayer] Starting ad break with target duration:",
|
|
1592
|
-
{
|
|
1593
|
-
targetDurationMs,
|
|
1594
|
-
scte35Duration: marker.durationSeconds,
|
|
1595
|
-
scheduledDuration: scheduled?.durationMs
|
|
1437
|
+
const tags = this.selectVastTagsForBreak(scheduled);
|
|
1438
|
+
let vastTagUrl;
|
|
1439
|
+
let adsNumber = 1;
|
|
1440
|
+
if (this.apiVastTagUrl) {
|
|
1441
|
+
vastTagUrl = this.apiVastTagUrl;
|
|
1442
|
+
if (this.vastConfig) {
|
|
1443
|
+
const isHls = this.config.src.includes(".m3u8") || this.config.src.includes("hls");
|
|
1444
|
+
if (isHls && this.vastConfig.cue_tones?.number_ads) {
|
|
1445
|
+
adsNumber = this.vastConfig.cue_tones.number_ads;
|
|
1446
|
+
} else if (!isHls && this.vastConfig.timer_vod?.number_ads) {
|
|
1447
|
+
adsNumber = this.vastConfig.timer_vod.number_ads;
|
|
1596
1448
|
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1449
|
+
}
|
|
1450
|
+
this.adPodQueue = new Array(adsNumber - 1).fill(vastTagUrl);
|
|
1451
|
+
this.currentAdIndex = 0;
|
|
1452
|
+
this.totalAdsInBreak = adsNumber;
|
|
1601
1453
|
if (this.config.debugAdTiming) {
|
|
1602
|
-
console.log(
|
|
1454
|
+
console.log(
|
|
1455
|
+
`[StormcloudVideoPlayer] Using API VAST tag with ${adsNumber} ads:`,
|
|
1456
|
+
vastTagUrl
|
|
1457
|
+
);
|
|
1458
|
+
}
|
|
1459
|
+
} else if (tags && tags.length > 0) {
|
|
1460
|
+
vastTagUrl = tags[0];
|
|
1461
|
+
const rest = tags.slice(1);
|
|
1462
|
+
this.adPodQueue = rest;
|
|
1463
|
+
this.currentAdIndex = 0;
|
|
1464
|
+
this.totalAdsInBreak = tags.length;
|
|
1465
|
+
if (this.config.debugAdTiming) {
|
|
1466
|
+
console.log(
|
|
1467
|
+
"[StormcloudVideoPlayer] Using scheduled VAST tag:",
|
|
1468
|
+
vastTagUrl
|
|
1469
|
+
);
|
|
1470
|
+
}
|
|
1471
|
+
} else {
|
|
1472
|
+
if (this.config.debugAdTiming) {
|
|
1473
|
+
console.log("[StormcloudVideoPlayer] No VAST tag available for ad");
|
|
1603
1474
|
}
|
|
1604
1475
|
return;
|
|
1605
1476
|
}
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
this.showAds = true;
|
|
1611
|
-
if (this.config.debugAdTiming) {
|
|
1612
|
-
const totalEstimatedDuration = this.preloadedAdInfo.reduce(
|
|
1613
|
-
(sum, ad) => sum + ad.duration,
|
|
1614
|
-
0
|
|
1615
|
-
);
|
|
1616
|
-
console.log("[StormcloudVideoPlayer] Ad queue built:", {
|
|
1617
|
-
totalAds: adQueue.length,
|
|
1618
|
-
estimatedTotalDuration: totalEstimatedDuration,
|
|
1619
|
-
targetDuration: targetDurationMs ? targetDurationMs / 1e3 : "unknown",
|
|
1620
|
-
fillRate: targetDurationMs ? totalEstimatedDuration * 1e3 / targetDurationMs : "unknown"
|
|
1621
|
-
});
|
|
1477
|
+
if (vastTagUrl) {
|
|
1478
|
+
this.showAds = true;
|
|
1479
|
+
this.currentAdIndex++;
|
|
1480
|
+
await this.playSingleAd(vastTagUrl);
|
|
1622
1481
|
}
|
|
1623
|
-
this.
|
|
1624
|
-
|
|
1625
|
-
if (targetDurationMs != null) {
|
|
1626
|
-
this.expectedAdBreakDurationMs = targetDurationMs;
|
|
1482
|
+
if (this.expectedAdBreakDurationMs == null && scheduled?.durationMs != null) {
|
|
1483
|
+
this.expectedAdBreakDurationMs = scheduled.durationMs;
|
|
1627
1484
|
this.currentAdBreakStartWallClockMs = this.currentAdBreakStartWallClockMs ?? Date.now();
|
|
1628
|
-
this.scheduleAdStopCountdown(
|
|
1485
|
+
this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
|
|
1629
1486
|
}
|
|
1630
1487
|
}
|
|
1631
1488
|
findCurrentOrNextBreak(nowMs) {
|
|
@@ -1742,89 +1599,25 @@ var StormcloudVideoPlayer = class {
|
|
|
1742
1599
|
"[StormcloudVideoPlayer] Handling ad failure - resuming content"
|
|
1743
1600
|
);
|
|
1744
1601
|
}
|
|
1745
|
-
this.endAdBreak();
|
|
1746
|
-
if (this.video.paused) {
|
|
1747
|
-
this.video.play().catch(() => {
|
|
1748
|
-
if (this.config.debugAdTiming) {
|
|
1749
|
-
console.error(
|
|
1750
|
-
"[StormcloudVideoPlayer] Failed to resume video after ad failure"
|
|
1751
|
-
);
|
|
1752
|
-
}
|
|
1753
|
-
});
|
|
1754
|
-
}
|
|
1755
|
-
}
|
|
1756
|
-
endAdBreak() {
|
|
1757
|
-
if (this.config.debugAdTiming) {
|
|
1758
|
-
const targetDuration = this.currentAdBreakTargetDurationMs ? this.currentAdBreakTargetDurationMs / 1e3 : "unknown";
|
|
1759
|
-
const actualDuration = this.cumulativeAdDurationMs / 1e3;
|
|
1760
|
-
const fillRate = this.currentAdBreakTargetDurationMs ? (this.cumulativeAdDurationMs / this.currentAdBreakTargetDurationMs * 100).toFixed(1) : "unknown";
|
|
1761
|
-
console.log("[StormcloudVideoPlayer] Ad break ended:", {
|
|
1762
|
-
targetDurationSeconds: targetDuration,
|
|
1763
|
-
actualDurationSeconds: actualDuration,
|
|
1764
|
-
fillRate: `${fillRate}%`,
|
|
1765
|
-
totalAdsPlayed: this.currentAdIndex
|
|
1766
|
-
});
|
|
1767
|
-
}
|
|
1768
1602
|
this.inAdBreak = false;
|
|
1769
1603
|
this.expectedAdBreakDurationMs = void 0;
|
|
1770
1604
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
1771
|
-
this.currentAdBreakTargetDurationMs = void 0;
|
|
1772
|
-
this.cumulativeAdDurationMs = 0;
|
|
1773
1605
|
this.clearAdStartTimer();
|
|
1774
1606
|
this.clearAdStopTimer();
|
|
1775
1607
|
this.clearAdFailsafeTimer();
|
|
1776
1608
|
this.adPodQueue = [];
|
|
1777
|
-
this.preloadedAdInfo = [];
|
|
1778
1609
|
this.showAds = false;
|
|
1779
1610
|
this.currentAdIndex = 0;
|
|
1780
1611
|
this.totalAdsInBreak = 0;
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
if (remainingMs > 500) {
|
|
1784
|
-
return true;
|
|
1785
|
-
}
|
|
1786
|
-
if (this.currentAdBreakTargetDurationMs) {
|
|
1787
|
-
const targetRemainingMs = this.currentAdBreakTargetDurationMs - this.cumulativeAdDurationMs;
|
|
1788
|
-
const minAdDuration = this.config.minAdDurationMs ?? 5e3;
|
|
1789
|
-
if (targetRemainingMs > minAdDuration) {
|
|
1612
|
+
if (this.video.paused) {
|
|
1613
|
+
this.video.play().catch(() => {
|
|
1790
1614
|
if (this.config.debugAdTiming) {
|
|
1791
|
-
console.
|
|
1792
|
-
|
|
1615
|
+
console.error(
|
|
1616
|
+
"[StormcloudVideoPlayer] Failed to resume video after ad failure"
|
|
1793
1617
|
);
|
|
1794
1618
|
}
|
|
1795
|
-
|
|
1796
|
-
}
|
|
1797
|
-
}
|
|
1798
|
-
return false;
|
|
1799
|
-
}
|
|
1800
|
-
canRequestMoreAds() {
|
|
1801
|
-
const maxAdsPerBreak = this.config.maxAdsPerBreak ?? 10;
|
|
1802
|
-
if (this.currentAdIndex >= maxAdsPerBreak) {
|
|
1803
|
-
return false;
|
|
1804
|
-
}
|
|
1805
|
-
return !!this.apiVastTagUrl;
|
|
1806
|
-
}
|
|
1807
|
-
async requestAdditionalAds() {
|
|
1808
|
-
if (!this.currentAdBreakTargetDurationMs || !this.apiVastTagUrl) {
|
|
1809
|
-
throw new Error(
|
|
1810
|
-
"Cannot request additional ads without target duration and VAST URL"
|
|
1811
|
-
);
|
|
1812
|
-
}
|
|
1813
|
-
const remainingDurationMs = this.currentAdBreakTargetDurationMs - this.cumulativeAdDurationMs;
|
|
1814
|
-
const estimatedAdDurationMs = this.getEstimatedAdDuration() * 1e3;
|
|
1815
|
-
if (remainingDurationMs < estimatedAdDurationMs * 0.5) {
|
|
1816
|
-
throw new Error("Not enough time remaining for additional ads");
|
|
1817
|
-
}
|
|
1818
|
-
if (this.config.debugAdTiming) {
|
|
1819
|
-
console.log(
|
|
1820
|
-
`[StormcloudVideoPlayer] Requesting additional ads for remaining ${remainingDurationMs}ms`
|
|
1821
|
-
);
|
|
1619
|
+
});
|
|
1822
1620
|
}
|
|
1823
|
-
this.adPodQueue.push(this.apiVastTagUrl);
|
|
1824
|
-
this.totalAdsInBreak++;
|
|
1825
|
-
const next = this.adPodQueue.shift();
|
|
1826
|
-
this.currentAdIndex++;
|
|
1827
|
-
await this.playSingleAd(next);
|
|
1828
1621
|
}
|
|
1829
1622
|
startAdFailsafeTimer() {
|
|
1830
1623
|
this.clearAdFailsafeTimer();
|
|
@@ -1858,109 +1651,6 @@ var StormcloudVideoPlayer = class {
|
|
|
1858
1651
|
}
|
|
1859
1652
|
return [b.vastTagUrl];
|
|
1860
1653
|
}
|
|
1861
|
-
async buildAdQueueForDuration(targetDurationMs) {
|
|
1862
|
-
const adQueue = [];
|
|
1863
|
-
let baseVastTagUrl = this.apiVastTagUrl;
|
|
1864
|
-
if (!baseVastTagUrl) {
|
|
1865
|
-
const scheduled = this.findCurrentOrNextBreak(
|
|
1866
|
-
this.video.currentTime * 1e3
|
|
1867
|
-
);
|
|
1868
|
-
const scheduledTags = this.selectVastTagsForBreak(scheduled);
|
|
1869
|
-
if (scheduledTags && scheduledTags.length > 0) {
|
|
1870
|
-
baseVastTagUrl = scheduledTags[0];
|
|
1871
|
-
}
|
|
1872
|
-
}
|
|
1873
|
-
if (!baseVastTagUrl) {
|
|
1874
|
-
return adQueue;
|
|
1875
|
-
}
|
|
1876
|
-
if (!targetDurationMs) {
|
|
1877
|
-
let adsNumber = 1;
|
|
1878
|
-
if (this.vastConfig) {
|
|
1879
|
-
const isHls = this.config.src.includes(".m3u8") || this.config.src.includes("hls");
|
|
1880
|
-
if (isHls && this.vastConfig.cue_tones?.number_ads) {
|
|
1881
|
-
adsNumber = this.vastConfig.cue_tones.number_ads;
|
|
1882
|
-
} else if (!isHls && this.vastConfig.timer_vod?.number_ads) {
|
|
1883
|
-
adsNumber = this.vastConfig.timer_vod.number_ads;
|
|
1884
|
-
}
|
|
1885
|
-
}
|
|
1886
|
-
return new Array(adsNumber).fill(baseVastTagUrl);
|
|
1887
|
-
}
|
|
1888
|
-
const targetDurationSeconds = targetDurationMs / 1e3;
|
|
1889
|
-
let cumulativeDurationSeconds = 0;
|
|
1890
|
-
const maxAdsToTry = 10;
|
|
1891
|
-
let adsAdded = 0;
|
|
1892
|
-
if (this.config.debugAdTiming) {
|
|
1893
|
-
console.log(
|
|
1894
|
-
`[StormcloudVideoPlayer] Attempting to fill ${targetDurationSeconds}s with ads`
|
|
1895
|
-
);
|
|
1896
|
-
}
|
|
1897
|
-
while (cumulativeDurationSeconds < targetDurationSeconds && adsAdded < maxAdsToTry) {
|
|
1898
|
-
adQueue.push(baseVastTagUrl);
|
|
1899
|
-
adsAdded++;
|
|
1900
|
-
const estimatedAdDuration = this.getEstimatedAdDuration();
|
|
1901
|
-
cumulativeDurationSeconds += estimatedAdDuration;
|
|
1902
|
-
if (this.config.debugAdTiming) {
|
|
1903
|
-
console.log(
|
|
1904
|
-
`[StormcloudVideoPlayer] Added ad ${adsAdded}, cumulative duration: ${cumulativeDurationSeconds}s`
|
|
1905
|
-
);
|
|
1906
|
-
}
|
|
1907
|
-
const remainingDuration = targetDurationSeconds - cumulativeDurationSeconds;
|
|
1908
|
-
const toleranceSeconds = (this.config.adBreakGapToleranceMs ?? 2e3) / 1e3;
|
|
1909
|
-
if (remainingDuration < estimatedAdDuration && remainingDuration >= -toleranceSeconds) {
|
|
1910
|
-
if (this.config.debugAdTiming) {
|
|
1911
|
-
console.log(
|
|
1912
|
-
`[StormcloudVideoPlayer] Within tolerance, adding final ad. Overage: ${-remainingDuration}s`
|
|
1913
|
-
);
|
|
1914
|
-
}
|
|
1915
|
-
break;
|
|
1916
|
-
}
|
|
1917
|
-
if (remainingDuration < estimatedAdDuration && remainingDuration < -toleranceSeconds) {
|
|
1918
|
-
if (this.config.debugAdTiming) {
|
|
1919
|
-
console.log(
|
|
1920
|
-
`[StormcloudVideoPlayer] Would exceed duration by too much, stopping at ${adsAdded} ads`
|
|
1921
|
-
);
|
|
1922
|
-
}
|
|
1923
|
-
break;
|
|
1924
|
-
}
|
|
1925
|
-
}
|
|
1926
|
-
return adQueue;
|
|
1927
|
-
}
|
|
1928
|
-
getEstimatedAdDuration() {
|
|
1929
|
-
if (this.vastConfig) {
|
|
1930
|
-
return 15;
|
|
1931
|
-
}
|
|
1932
|
-
return 30;
|
|
1933
|
-
}
|
|
1934
|
-
async getAdInfoForQueue(adQueue) {
|
|
1935
|
-
if (this.config.enableAdPreloading === false) {
|
|
1936
|
-
if (this.config.debugAdTiming) {
|
|
1937
|
-
console.log(
|
|
1938
|
-
"[StormcloudVideoPlayer] Ad preloading disabled, using estimates"
|
|
1939
|
-
);
|
|
1940
|
-
}
|
|
1941
|
-
return adQueue.map((vastTagUrl) => ({
|
|
1942
|
-
duration: this.getEstimatedAdDuration(),
|
|
1943
|
-
vastTagUrl,
|
|
1944
|
-
isPreloaded: false
|
|
1945
|
-
}));
|
|
1946
|
-
}
|
|
1947
|
-
try {
|
|
1948
|
-
const adInfos = await this.ima.preloadAds(adQueue);
|
|
1949
|
-
return adInfos;
|
|
1950
|
-
} catch (error) {
|
|
1951
|
-
if (this.config.debugAdTiming) {
|
|
1952
|
-
console.warn(
|
|
1953
|
-
"[StormcloudVideoPlayer] Failed to preload ads, using estimates:",
|
|
1954
|
-
error
|
|
1955
|
-
);
|
|
1956
|
-
}
|
|
1957
|
-
return adQueue.map((vastTagUrl) => ({
|
|
1958
|
-
duration: this.getEstimatedAdDuration(),
|
|
1959
|
-
vastTagUrl,
|
|
1960
|
-
isPreloaded: false
|
|
1961
|
-
}));
|
|
1962
|
-
}
|
|
1963
|
-
}
|
|
1964
1654
|
getRemainingAdMs() {
|
|
1965
1655
|
if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)
|
|
1966
1656
|
return 0;
|