stormcloud-video-player 0.2.31 → 0.2.32
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 +293 -69
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +9 -1
- package/lib/index.d.ts +9 -1
- package/lib/index.js +293 -69
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +293 -69
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +9 -1
- package/lib/players/HlsPlayer.cjs +293 -69
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +293 -69
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/ima.cjs +9 -0
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +293 -69
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +2 -2
package/lib/index.d.cts
CHANGED
|
@@ -129,6 +129,9 @@ declare class StormcloudVideoPlayer {
|
|
|
129
129
|
private hasInitialBufferCompleted;
|
|
130
130
|
private adPodAllUrls;
|
|
131
131
|
private preloadingAdUrls;
|
|
132
|
+
private vastToMediaUrlMap;
|
|
133
|
+
private preloadedMediaUrls;
|
|
134
|
+
private preloadingMediaUrls;
|
|
132
135
|
constructor(config: StormcloudVideoPlayerConfig);
|
|
133
136
|
private createAdPlayer;
|
|
134
137
|
load(): Promise<void>;
|
|
@@ -174,7 +177,12 @@ declare class StormcloudVideoPlayer {
|
|
|
174
177
|
private logQueuedAdUrls;
|
|
175
178
|
private enforceAdHoldState;
|
|
176
179
|
private releaseAdHoldState;
|
|
177
|
-
private
|
|
180
|
+
private fetchAndParseVastXml;
|
|
181
|
+
private extractMediaUrlsFromVast;
|
|
182
|
+
private preloadMediaFile;
|
|
183
|
+
private preloadAllAdsInBackground;
|
|
184
|
+
private preloadSingleAd;
|
|
185
|
+
private findNextPreloadedAd;
|
|
178
186
|
private getRemainingAdMs;
|
|
179
187
|
private findBreakForTime;
|
|
180
188
|
toggleMute(): void;
|
package/lib/index.d.ts
CHANGED
|
@@ -129,6 +129,9 @@ declare class StormcloudVideoPlayer {
|
|
|
129
129
|
private hasInitialBufferCompleted;
|
|
130
130
|
private adPodAllUrls;
|
|
131
131
|
private preloadingAdUrls;
|
|
132
|
+
private vastToMediaUrlMap;
|
|
133
|
+
private preloadedMediaUrls;
|
|
134
|
+
private preloadingMediaUrls;
|
|
132
135
|
constructor(config: StormcloudVideoPlayerConfig);
|
|
133
136
|
private createAdPlayer;
|
|
134
137
|
load(): Promise<void>;
|
|
@@ -174,7 +177,12 @@ declare class StormcloudVideoPlayer {
|
|
|
174
177
|
private logQueuedAdUrls;
|
|
175
178
|
private enforceAdHoldState;
|
|
176
179
|
private releaseAdHoldState;
|
|
177
|
-
private
|
|
180
|
+
private fetchAndParseVastXml;
|
|
181
|
+
private extractMediaUrlsFromVast;
|
|
182
|
+
private preloadMediaFile;
|
|
183
|
+
private preloadAllAdsInBackground;
|
|
184
|
+
private preloadSingleAd;
|
|
185
|
+
private findNextPreloadedAd;
|
|
178
186
|
private getRemainingAdMs;
|
|
179
187
|
private findBreakForTime;
|
|
180
188
|
toggleMute(): void;
|
package/lib/index.js
CHANGED
|
@@ -637,6 +637,15 @@ function createImaController(video, options) {
|
|
|
637
637
|
"[IMA] Content video continues in background (Live mode)"
|
|
638
638
|
);
|
|
639
639
|
}
|
|
640
|
+
hideContentVideo();
|
|
641
|
+
if (adContainerEl) {
|
|
642
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
643
|
+
adContainerEl.style.display = "flex";
|
|
644
|
+
adContainerEl.style.backgroundColor = "#000";
|
|
645
|
+
adContainerEl.offsetHeight;
|
|
646
|
+
adContainerEl.style.opacity = "1";
|
|
647
|
+
console.log("[IMA] Ad container shown on content pause");
|
|
648
|
+
}
|
|
640
649
|
adPlaying = true;
|
|
641
650
|
setAdPlayingFlag(true);
|
|
642
651
|
emit("content_pause");
|
|
@@ -2171,6 +2180,9 @@ var StormcloudVideoPlayer = class {
|
|
|
2171
2180
|
this.hasInitialBufferCompleted = false;
|
|
2172
2181
|
this.adPodAllUrls = [];
|
|
2173
2182
|
this.preloadingAdUrls = /* @__PURE__ */ new Set();
|
|
2183
|
+
this.vastToMediaUrlMap = /* @__PURE__ */ new Map();
|
|
2184
|
+
this.preloadedMediaUrls = /* @__PURE__ */ new Set();
|
|
2185
|
+
this.preloadingMediaUrls = /* @__PURE__ */ new Set();
|
|
2174
2186
|
initializePolyfills();
|
|
2175
2187
|
const browserOverrides = getBrowserConfigOverrides();
|
|
2176
2188
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -2443,27 +2455,44 @@ var StormcloudVideoPlayer = class {
|
|
|
2443
2455
|
});
|
|
2444
2456
|
this.ima.on("ad_error", () => {
|
|
2445
2457
|
if (this.config.debugAdTiming) {
|
|
2446
|
-
console.log("[StormcloudVideoPlayer] IMA ad_error event received"
|
|
2458
|
+
console.log("[StormcloudVideoPlayer] IMA ad_error event received", {
|
|
2459
|
+
showAds: this.showAds,
|
|
2460
|
+
inAdBreak: this.inAdBreak,
|
|
2461
|
+
remainingAds: this.adPodQueue.length
|
|
2462
|
+
});
|
|
2447
2463
|
}
|
|
2448
|
-
if (this.
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2464
|
+
if (this.inAdBreak) {
|
|
2465
|
+
const remaining = this.getRemainingAdMs();
|
|
2466
|
+
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2467
|
+
const nextPreloaded = this.findNextPreloadedAd();
|
|
2468
|
+
if (nextPreloaded) {
|
|
2453
2469
|
this.currentAdIndex++;
|
|
2454
|
-
this.
|
|
2470
|
+
if (this.config.debugAdTiming) {
|
|
2471
|
+
console.log(
|
|
2472
|
+
`[StormcloudVideoPlayer] Skipping to next preloaded ad after error`
|
|
2473
|
+
);
|
|
2474
|
+
}
|
|
2475
|
+
this.playSingleAd(nextPreloaded).catch(() => {
|
|
2476
|
+
this.handleAdFailure();
|
|
2455
2477
|
});
|
|
2456
2478
|
} else {
|
|
2479
|
+
if (this.config.debugAdTiming) {
|
|
2480
|
+
console.log(
|
|
2481
|
+
"[StormcloudVideoPlayer] No preloaded ads available, ending ad break"
|
|
2482
|
+
);
|
|
2483
|
+
}
|
|
2457
2484
|
this.handleAdFailure();
|
|
2458
2485
|
}
|
|
2459
2486
|
} else {
|
|
2460
|
-
if (this.config.debugAdTiming) {
|
|
2461
|
-
console.log(
|
|
2462
|
-
"[StormcloudVideoPlayer] Ad error before ad break established - cleaning up"
|
|
2463
|
-
);
|
|
2464
|
-
}
|
|
2465
2487
|
this.handleAdFailure();
|
|
2466
2488
|
}
|
|
2489
|
+
} else {
|
|
2490
|
+
if (this.config.debugAdTiming) {
|
|
2491
|
+
console.log(
|
|
2492
|
+
"[StormcloudVideoPlayer] Ad error before ad break established - cleaning up"
|
|
2493
|
+
);
|
|
2494
|
+
}
|
|
2495
|
+
this.handleAdFailure();
|
|
2467
2496
|
}
|
|
2468
2497
|
});
|
|
2469
2498
|
this.ima.on("content_pause", () => {
|
|
@@ -2494,22 +2523,31 @@ var StormcloudVideoPlayer = class {
|
|
|
2494
2523
|
}
|
|
2495
2524
|
const remaining = this.getRemainingAdMs();
|
|
2496
2525
|
if (remaining > 500 && this.adPodQueue.length > 0) {
|
|
2497
|
-
const
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
console.log(
|
|
2502
|
-
`[StormcloudVideoPlayer] Playing next ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak}) - IMMEDIATELY starting next ad`
|
|
2503
|
-
);
|
|
2504
|
-
}
|
|
2505
|
-
this.playSingleAd(next).catch(() => {
|
|
2526
|
+
const nextPreloaded = this.findNextPreloadedAd();
|
|
2527
|
+
if (nextPreloaded) {
|
|
2528
|
+
this.currentAdIndex++;
|
|
2529
|
+
this.enforceAdHoldState();
|
|
2506
2530
|
if (this.config.debugAdTiming) {
|
|
2507
|
-
console.
|
|
2508
|
-
|
|
2531
|
+
console.log(
|
|
2532
|
+
`[StormcloudVideoPlayer] Playing next preloaded ad in pod (${this.currentAdIndex}/${this.totalAdsInBreak})`
|
|
2533
|
+
);
|
|
2534
|
+
}
|
|
2535
|
+
this.playSingleAd(nextPreloaded).catch(() => {
|
|
2536
|
+
if (this.config.debugAdTiming) {
|
|
2537
|
+
console.error(
|
|
2538
|
+
"[StormcloudVideoPlayer] Failed to play next ad in pod"
|
|
2539
|
+
);
|
|
2540
|
+
}
|
|
2541
|
+
this.handleAdPodComplete();
|
|
2542
|
+
});
|
|
2543
|
+
} else {
|
|
2544
|
+
if (this.config.debugAdTiming) {
|
|
2545
|
+
console.log(
|
|
2546
|
+
"[StormcloudVideoPlayer] No preloaded ads available - completing ad break"
|
|
2509
2547
|
);
|
|
2510
2548
|
}
|
|
2511
2549
|
this.handleAdPodComplete();
|
|
2512
|
-
}
|
|
2550
|
+
}
|
|
2513
2551
|
} else {
|
|
2514
2552
|
if (this.config.debugAdTiming) {
|
|
2515
2553
|
console.log(
|
|
@@ -2754,6 +2792,9 @@ var StormcloudVideoPlayer = class {
|
|
|
2754
2792
|
const first = tags[0];
|
|
2755
2793
|
const rest = tags.slice(1);
|
|
2756
2794
|
this.adPodQueue = rest;
|
|
2795
|
+
if (!this.showAds) {
|
|
2796
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
2797
|
+
}
|
|
2757
2798
|
this.playSingleAd(first).catch(() => {
|
|
2758
2799
|
});
|
|
2759
2800
|
}
|
|
@@ -3110,19 +3151,38 @@ var StormcloudVideoPlayer = class {
|
|
|
3110
3151
|
if (vastTagUrls.length > 0) {
|
|
3111
3152
|
this.adPodAllUrls = [...vastTagUrls];
|
|
3112
3153
|
this.preloadingAdUrls.clear();
|
|
3154
|
+
this.vastToMediaUrlMap.clear();
|
|
3155
|
+
this.preloadedMediaUrls.clear();
|
|
3156
|
+
this.preloadingMediaUrls.clear();
|
|
3113
3157
|
this.logQueuedAdUrls(this.adPodAllUrls);
|
|
3158
|
+
if (this.config.debugAdTiming) {
|
|
3159
|
+
console.log(
|
|
3160
|
+
`[StormcloudVideoPlayer] Capturing original audio state before ad break:`,
|
|
3161
|
+
{
|
|
3162
|
+
videoMuted: this.video.muted,
|
|
3163
|
+
videoVolume: this.video.volume
|
|
3164
|
+
}
|
|
3165
|
+
);
|
|
3166
|
+
}
|
|
3167
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3114
3168
|
this.inAdBreak = true;
|
|
3115
|
-
this.showAds = true;
|
|
3116
3169
|
this.currentAdIndex = 0;
|
|
3117
3170
|
this.totalAdsInBreak = vastTagUrls.length;
|
|
3118
3171
|
this.adPodQueue = [...vastTagUrls];
|
|
3119
3172
|
this.enforceAdHoldState();
|
|
3120
|
-
this.preloadUpcomingAds();
|
|
3121
3173
|
if (this.config.debugAdTiming) {
|
|
3122
3174
|
console.log(
|
|
3123
|
-
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads -
|
|
3175
|
+
`[StormcloudVideoPlayer] Starting ad pod with ${vastTagUrls.length} ads - preloading all ads in parallel`
|
|
3124
3176
|
);
|
|
3125
3177
|
}
|
|
3178
|
+
this.preloadAllAdsInBackground().catch((error) => {
|
|
3179
|
+
if (this.config.debugAdTiming) {
|
|
3180
|
+
console.warn(
|
|
3181
|
+
"[StormcloudVideoPlayer] Error in background preloading:",
|
|
3182
|
+
error
|
|
3183
|
+
);
|
|
3184
|
+
}
|
|
3185
|
+
});
|
|
3126
3186
|
try {
|
|
3127
3187
|
await this.playAdPod();
|
|
3128
3188
|
} catch (error) {
|
|
@@ -3148,14 +3208,28 @@ var StormcloudVideoPlayer = class {
|
|
|
3148
3208
|
}
|
|
3149
3209
|
return;
|
|
3150
3210
|
}
|
|
3151
|
-
|
|
3211
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
3212
|
+
const firstPreloaded = this.findNextPreloadedAd();
|
|
3213
|
+
if (!firstPreloaded) {
|
|
3214
|
+
if (this.config.debugAdTiming) {
|
|
3215
|
+
console.log(
|
|
3216
|
+
"[StormcloudVideoPlayer] No preloaded ads available after waiting, trying first ad anyway"
|
|
3217
|
+
);
|
|
3218
|
+
}
|
|
3219
|
+
const firstAd = this.adPodQueue.shift();
|
|
3220
|
+
if (firstAd) {
|
|
3221
|
+
this.currentAdIndex++;
|
|
3222
|
+
await this.playSingleAd(firstAd);
|
|
3223
|
+
}
|
|
3224
|
+
return;
|
|
3225
|
+
}
|
|
3152
3226
|
this.currentAdIndex++;
|
|
3153
3227
|
if (this.config.debugAdTiming) {
|
|
3154
3228
|
console.log(
|
|
3155
|
-
`[StormcloudVideoPlayer] Playing ad ${this.currentAdIndex}/${this.totalAdsInBreak}`
|
|
3229
|
+
`[StormcloudVideoPlayer] Playing first preloaded ad ${this.currentAdIndex}/${this.totalAdsInBreak}`
|
|
3156
3230
|
);
|
|
3157
3231
|
}
|
|
3158
|
-
await this.playSingleAd(
|
|
3232
|
+
await this.playSingleAd(firstPreloaded);
|
|
3159
3233
|
}
|
|
3160
3234
|
findCurrentOrNextBreak(nowMs) {
|
|
3161
3235
|
var _a;
|
|
@@ -3188,6 +3262,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3188
3262
|
const first = tags[0];
|
|
3189
3263
|
const rest = tags.slice(1);
|
|
3190
3264
|
this.adPodQueue = rest;
|
|
3265
|
+
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3191
3266
|
this.enforceAdHoldState();
|
|
3192
3267
|
await this.playSingleAd(first);
|
|
3193
3268
|
this.inAdBreak = true;
|
|
@@ -3308,27 +3383,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3308
3383
|
`[StormcloudVideoPlayer] IMA SDK preloaded this ad already: ${vastTagUrl}`
|
|
3309
3384
|
);
|
|
3310
3385
|
}
|
|
3311
|
-
if (!this.showAds) {
|
|
3312
|
-
if (this.config.debugAdTiming) {
|
|
3313
|
-
console.log(
|
|
3314
|
-
`[StormcloudVideoPlayer] Capturing original state before ad request:`,
|
|
3315
|
-
{
|
|
3316
|
-
videoMuted: this.video.muted,
|
|
3317
|
-
videoVolume: this.video.volume,
|
|
3318
|
-
showAds: this.showAds
|
|
3319
|
-
}
|
|
3320
|
-
);
|
|
3321
|
-
}
|
|
3322
|
-
this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3323
|
-
} else if (this.config.debugAdTiming) {
|
|
3324
|
-
console.log(
|
|
3325
|
-
`[StormcloudVideoPlayer] Keeping existing original mute state (currently showing ads)`
|
|
3326
|
-
);
|
|
3327
|
-
}
|
|
3328
3386
|
this.startAdFailsafeTimer();
|
|
3329
3387
|
try {
|
|
3330
3388
|
await this.ima.requestAds(vastTagUrl);
|
|
3331
|
-
this.preloadUpcomingAds();
|
|
3332
3389
|
try {
|
|
3333
3390
|
if (this.config.debugAdTiming) {
|
|
3334
3391
|
console.log(
|
|
@@ -3337,9 +3394,10 @@ var StormcloudVideoPlayer = class {
|
|
|
3337
3394
|
}
|
|
3338
3395
|
this.enforceAdHoldState();
|
|
3339
3396
|
await this.ima.play();
|
|
3397
|
+
this.showAds = true;
|
|
3340
3398
|
if (this.config.debugAdTiming) {
|
|
3341
3399
|
console.log(
|
|
3342
|
-
"[StormcloudVideoPlayer] Ad playback started successfully"
|
|
3400
|
+
"[StormcloudVideoPlayer] Ad playback started successfully, showAds = true"
|
|
3343
3401
|
);
|
|
3344
3402
|
}
|
|
3345
3403
|
} catch (playError) {
|
|
@@ -3367,6 +3425,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3367
3425
|
}
|
|
3368
3426
|
this.releaseAdHoldState();
|
|
3369
3427
|
this.preloadingAdUrls.clear();
|
|
3428
|
+
this.vastToMediaUrlMap.clear();
|
|
3429
|
+
this.preloadedMediaUrls.clear();
|
|
3430
|
+
this.preloadingMediaUrls.clear();
|
|
3370
3431
|
this.inAdBreak = false;
|
|
3371
3432
|
this.expectedAdBreakDurationMs = void 0;
|
|
3372
3433
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
@@ -3476,44 +3537,204 @@ var StormcloudVideoPlayer = class {
|
|
|
3476
3537
|
this.ima.hidePlaceholder();
|
|
3477
3538
|
}
|
|
3478
3539
|
}
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3540
|
+
async fetchAndParseVastXml(vastTagUrl) {
|
|
3541
|
+
try {
|
|
3542
|
+
const response = await fetch(vastTagUrl, { mode: "cors" });
|
|
3543
|
+
if (!response.ok) {
|
|
3544
|
+
throw new Error(`Failed to fetch VAST: ${response.status}`);
|
|
3545
|
+
}
|
|
3546
|
+
const xmlText = await response.text();
|
|
3547
|
+
return this.extractMediaUrlsFromVast(xmlText);
|
|
3548
|
+
} catch (error) {
|
|
3549
|
+
if (this.config.debugAdTiming) {
|
|
3550
|
+
console.warn(
|
|
3551
|
+
`[StormcloudVideoPlayer] Failed to fetch/parse VAST XML: ${vastTagUrl}`,
|
|
3552
|
+
error
|
|
3553
|
+
);
|
|
3554
|
+
}
|
|
3555
|
+
return [];
|
|
3482
3556
|
}
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3557
|
+
}
|
|
3558
|
+
extractMediaUrlsFromVast(xmlText) {
|
|
3559
|
+
var _a;
|
|
3560
|
+
const mediaUrls = [];
|
|
3561
|
+
try {
|
|
3562
|
+
const parser = new DOMParser();
|
|
3563
|
+
const xmlDoc = parser.parseFromString(xmlText, "text/xml");
|
|
3564
|
+
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
3565
|
+
for (const mediaFile of Array.from(mediaFileElements)) {
|
|
3566
|
+
const url = (_a = mediaFile.textContent) == null ? void 0 : _a.trim();
|
|
3567
|
+
if (url) {
|
|
3568
|
+
const lowerUrl = url.toLowerCase();
|
|
3569
|
+
if (lowerUrl.endsWith(".mp4") || lowerUrl.endsWith(".webm") || lowerUrl.endsWith(".mov") || lowerUrl.endsWith(".avi") || lowerUrl.includes(".mp4?") || lowerUrl.includes(".webm?") || lowerUrl.includes("/mp4/") || lowerUrl.includes("type=video")) {
|
|
3570
|
+
mediaUrls.push(url);
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3489
3573
|
}
|
|
3490
|
-
if (this.
|
|
3491
|
-
|
|
3574
|
+
if (this.config.debugAdTiming && mediaUrls.length > 0) {
|
|
3575
|
+
console.log(
|
|
3576
|
+
`[StormcloudVideoPlayer] Extracted ${mediaUrls.length} media URLs from VAST:`,
|
|
3577
|
+
mediaUrls
|
|
3578
|
+
);
|
|
3579
|
+
}
|
|
3580
|
+
} catch (error) {
|
|
3581
|
+
if (this.config.debugAdTiming) {
|
|
3582
|
+
console.warn(
|
|
3583
|
+
"[StormcloudVideoPlayer] Failed to parse VAST XML:",
|
|
3584
|
+
error
|
|
3585
|
+
);
|
|
3492
3586
|
}
|
|
3587
|
+
}
|
|
3588
|
+
return mediaUrls;
|
|
3589
|
+
}
|
|
3590
|
+
async preloadMediaFile(mediaUrl) {
|
|
3591
|
+
if (this.preloadedMediaUrls.has(mediaUrl)) {
|
|
3592
|
+
return;
|
|
3593
|
+
}
|
|
3594
|
+
if (this.preloadingMediaUrls.has(mediaUrl)) {
|
|
3595
|
+
return;
|
|
3596
|
+
}
|
|
3597
|
+
this.preloadingMediaUrls.add(mediaUrl);
|
|
3598
|
+
try {
|
|
3493
3599
|
if (this.config.debugAdTiming) {
|
|
3494
3600
|
console.log(
|
|
3495
|
-
`[StormcloudVideoPlayer]
|
|
3601
|
+
`[StormcloudVideoPlayer] Preloading video file: ${mediaUrl}`
|
|
3496
3602
|
);
|
|
3497
3603
|
}
|
|
3498
|
-
|
|
3499
|
-
|
|
3604
|
+
const response = await fetch(mediaUrl, {
|
|
3605
|
+
mode: "cors",
|
|
3606
|
+
method: "GET",
|
|
3607
|
+
headers: {
|
|
3608
|
+
Range: "bytes=0-1048576"
|
|
3609
|
+
}
|
|
3610
|
+
});
|
|
3611
|
+
if (response.ok || response.status === 206) {
|
|
3612
|
+
this.preloadedMediaUrls.add(mediaUrl);
|
|
3500
3613
|
if (this.config.debugAdTiming) {
|
|
3501
3614
|
console.log(
|
|
3502
|
-
`[StormcloudVideoPlayer]
|
|
3615
|
+
`[StormcloudVideoPlayer] Successfully preloaded video file: ${mediaUrl}`
|
|
3503
3616
|
);
|
|
3504
3617
|
}
|
|
3505
|
-
}
|
|
3618
|
+
}
|
|
3619
|
+
} catch (error) {
|
|
3620
|
+
if (this.config.debugAdTiming) {
|
|
3621
|
+
console.warn(
|
|
3622
|
+
`[StormcloudVideoPlayer] Failed to preload video file: ${mediaUrl}`,
|
|
3623
|
+
error
|
|
3624
|
+
);
|
|
3625
|
+
}
|
|
3626
|
+
} finally {
|
|
3627
|
+
this.preloadingMediaUrls.delete(mediaUrl);
|
|
3628
|
+
}
|
|
3629
|
+
}
|
|
3630
|
+
async preloadAllAdsInBackground() {
|
|
3631
|
+
if (this.adPodAllUrls.length === 0) {
|
|
3632
|
+
return;
|
|
3633
|
+
}
|
|
3634
|
+
if (this.config.debugAdTiming) {
|
|
3635
|
+
console.log(
|
|
3636
|
+
`[StormcloudVideoPlayer] Starting parallel preload of ${this.adPodAllUrls.length} ads`
|
|
3637
|
+
);
|
|
3638
|
+
}
|
|
3639
|
+
const preloadPromises = this.adPodAllUrls.map(
|
|
3640
|
+
(vastTagUrl) => this.preloadSingleAd(vastTagUrl).catch((error) => {
|
|
3506
3641
|
if (this.config.debugAdTiming) {
|
|
3507
3642
|
console.warn(
|
|
3508
|
-
`[StormcloudVideoPlayer]
|
|
3643
|
+
`[StormcloudVideoPlayer] Preload failed for ${vastTagUrl}:`,
|
|
3509
3644
|
error
|
|
3510
3645
|
);
|
|
3511
3646
|
}
|
|
3512
|
-
})
|
|
3513
|
-
|
|
3514
|
-
|
|
3647
|
+
})
|
|
3648
|
+
);
|
|
3649
|
+
await Promise.all(preloadPromises);
|
|
3650
|
+
if (this.config.debugAdTiming) {
|
|
3651
|
+
console.log(
|
|
3652
|
+
`[StormcloudVideoPlayer] Background preloading completed for all ads`
|
|
3653
|
+
);
|
|
3515
3654
|
}
|
|
3516
3655
|
}
|
|
3656
|
+
async preloadSingleAd(vastTagUrl) {
|
|
3657
|
+
if (!vastTagUrl) return;
|
|
3658
|
+
try {
|
|
3659
|
+
if (this.ima.preloadAds && !this.ima.hasPreloadedAd(vastTagUrl)) {
|
|
3660
|
+
if (!this.preloadingAdUrls.has(vastTagUrl)) {
|
|
3661
|
+
if (this.config.debugAdTiming) {
|
|
3662
|
+
console.log(
|
|
3663
|
+
`[StormcloudVideoPlayer] Preloading VAST: ${vastTagUrl}`
|
|
3664
|
+
);
|
|
3665
|
+
}
|
|
3666
|
+
this.preloadingAdUrls.add(vastTagUrl);
|
|
3667
|
+
await this.ima.preloadAds(vastTagUrl).then(() => {
|
|
3668
|
+
if (this.config.debugAdTiming) {
|
|
3669
|
+
console.log(
|
|
3670
|
+
`[StormcloudVideoPlayer] IMA VAST preload complete: ${vastTagUrl}`
|
|
3671
|
+
);
|
|
3672
|
+
}
|
|
3673
|
+
}).catch((error) => {
|
|
3674
|
+
if (this.config.debugAdTiming) {
|
|
3675
|
+
console.warn(
|
|
3676
|
+
`[StormcloudVideoPlayer] IMA VAST preload failed: ${vastTagUrl}`,
|
|
3677
|
+
error
|
|
3678
|
+
);
|
|
3679
|
+
}
|
|
3680
|
+
}).finally(() => {
|
|
3681
|
+
this.preloadingAdUrls.delete(vastTagUrl);
|
|
3682
|
+
});
|
|
3683
|
+
}
|
|
3684
|
+
}
|
|
3685
|
+
let mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);
|
|
3686
|
+
if (!mediaUrls) {
|
|
3687
|
+
if (this.config.debugAdTiming) {
|
|
3688
|
+
console.log(
|
|
3689
|
+
`[StormcloudVideoPlayer] Fetching and parsing VAST to extract media URLs: ${vastTagUrl}`
|
|
3690
|
+
);
|
|
3691
|
+
}
|
|
3692
|
+
mediaUrls = await this.fetchAndParseVastXml(vastTagUrl);
|
|
3693
|
+
if (mediaUrls.length > 0) {
|
|
3694
|
+
this.vastToMediaUrlMap.set(vastTagUrl, mediaUrls);
|
|
3695
|
+
}
|
|
3696
|
+
}
|
|
3697
|
+
if (mediaUrls && mediaUrls.length > 0) {
|
|
3698
|
+
const primaryMediaUrl = mediaUrls[0];
|
|
3699
|
+
if (primaryMediaUrl && !this.preloadedMediaUrls.has(primaryMediaUrl)) {
|
|
3700
|
+
await this.preloadMediaFile(primaryMediaUrl);
|
|
3701
|
+
}
|
|
3702
|
+
}
|
|
3703
|
+
} catch (error) {
|
|
3704
|
+
if (this.config.debugAdTiming) {
|
|
3705
|
+
console.warn(
|
|
3706
|
+
`[StormcloudVideoPlayer] Failed to preload ad: ${vastTagUrl}`,
|
|
3707
|
+
error
|
|
3708
|
+
);
|
|
3709
|
+
}
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
3712
|
+
findNextPreloadedAd() {
|
|
3713
|
+
var _a, _b, _c;
|
|
3714
|
+
for (let i = 0; i < this.adPodQueue.length; i++) {
|
|
3715
|
+
const vastTagUrl = this.adPodQueue[i];
|
|
3716
|
+
if (!vastTagUrl) continue;
|
|
3717
|
+
const hasImaPreload = (_c = (_b = (_a = this.ima).hasPreloadedAd) == null ? void 0 : _b.call(_a, vastTagUrl)) != null ? _c : false;
|
|
3718
|
+
const mediaUrls = this.vastToMediaUrlMap.get(vastTagUrl);
|
|
3719
|
+
const hasMediaPreload = mediaUrls && mediaUrls.length > 0 ? this.preloadedMediaUrls.has(mediaUrls[0]) : false;
|
|
3720
|
+
if (hasImaPreload || hasMediaPreload) {
|
|
3721
|
+
if (this.config.debugAdTiming) {
|
|
3722
|
+
console.log(
|
|
3723
|
+
`[StormcloudVideoPlayer] Found preloaded ad at index ${i}: ${vastTagUrl}`,
|
|
3724
|
+
{ hasImaPreload, hasMediaPreload }
|
|
3725
|
+
);
|
|
3726
|
+
}
|
|
3727
|
+
this.adPodQueue.splice(0, i + 1);
|
|
3728
|
+
return vastTagUrl;
|
|
3729
|
+
}
|
|
3730
|
+
}
|
|
3731
|
+
if (this.config.debugAdTiming) {
|
|
3732
|
+
console.log(
|
|
3733
|
+
"[StormcloudVideoPlayer] No preloaded ads found in queue"
|
|
3734
|
+
);
|
|
3735
|
+
}
|
|
3736
|
+
return void 0;
|
|
3737
|
+
}
|
|
3517
3738
|
getRemainingAdMs() {
|
|
3518
3739
|
if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null)
|
|
3519
3740
|
return 0;
|
|
@@ -3682,6 +3903,9 @@ var StormcloudVideoPlayer = class {
|
|
|
3682
3903
|
(_b = this.ima) == null ? void 0 : _b.destroy();
|
|
3683
3904
|
this.releaseAdHoldState();
|
|
3684
3905
|
this.preloadingAdUrls.clear();
|
|
3906
|
+
this.vastToMediaUrlMap.clear();
|
|
3907
|
+
this.preloadedMediaUrls.clear();
|
|
3908
|
+
this.preloadingMediaUrls.clear();
|
|
3685
3909
|
this.adPodAllUrls = [];
|
|
3686
3910
|
}
|
|
3687
3911
|
};
|