stormcloud-video-player 0.3.9 → 0.3.10
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 +233 -183
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +11 -2
- package/lib/index.d.ts +11 -2
- package/lib/index.js +233 -183
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +233 -183
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +11 -2
- package/lib/players/HlsPlayer.cjs +233 -183
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +233 -183
- package/lib/players/index.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +233 -183
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +1 -1
|
@@ -2082,6 +2082,12 @@ var StormcloudVideoPlayer = class {
|
|
|
2082
2082
|
this.targetAdBreakDurationMs = null;
|
|
2083
2083
|
this.isAdaptiveMode = false;
|
|
2084
2084
|
this.failedVastUrls = /* @__PURE__ */ new Set();
|
|
2085
|
+
this.continuousFetchingActive = false;
|
|
2086
|
+
this.adRequestQueue = [];
|
|
2087
|
+
this.successfulAdRequests = [];
|
|
2088
|
+
this.maxPlaceholderDurationMs = 5e3;
|
|
2089
|
+
this.placeholderStartTimeMs = null;
|
|
2090
|
+
this.isShowingPlaceholder = false;
|
|
2085
2091
|
initializePolyfills();
|
|
2086
2092
|
const browserOverrides = getBrowserConfigOverrides();
|
|
2087
2093
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -2388,16 +2394,11 @@ var StormcloudVideoPlayer = class {
|
|
|
2388
2394
|
return;
|
|
2389
2395
|
}
|
|
2390
2396
|
const remaining = this.getRemainingAdMs();
|
|
2391
|
-
if (
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
this.handleAdPodComplete();
|
|
2397
|
-
});
|
|
2398
|
-
} else {
|
|
2399
|
-
this.handleAdPodComplete();
|
|
2400
|
-
}
|
|
2397
|
+
if (this.config.debugAdTiming) {
|
|
2398
|
+
console.log(`[CONTINUOUS-FETCH] content_resume event: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`);
|
|
2399
|
+
}
|
|
2400
|
+
if (remaining > 500) {
|
|
2401
|
+
this.tryNextAvailableAd();
|
|
2401
2402
|
} else {
|
|
2402
2403
|
this.handleAdPodComplete();
|
|
2403
2404
|
}
|
|
@@ -2997,155 +2998,240 @@ var StormcloudVideoPlayer = class {
|
|
|
2997
2998
|
return true;
|
|
2998
2999
|
}
|
|
2999
3000
|
async handleAdStart(_marker) {
|
|
3000
|
-
var _a;
|
|
3001
3001
|
const scheduled = this.findCurrentOrNextBreak(
|
|
3002
3002
|
this.video.currentTime * 1e3
|
|
3003
3003
|
);
|
|
3004
3004
|
const tags = this.selectVastTagsForBreak(scheduled);
|
|
3005
|
-
let
|
|
3005
|
+
let baseVastUrl;
|
|
3006
3006
|
if (this.apiVastTagUrl) {
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3007
|
+
baseVastUrl = this.apiVastTagUrl;
|
|
3008
|
+
} else if (tags && tags.length > 0 && tags[0]) {
|
|
3009
|
+
baseVastUrl = tags[0];
|
|
3010
|
+
} else {
|
|
3011
|
+
return;
|
|
3012
|
+
}
|
|
3013
|
+
const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : scheduled == null ? void 0 : scheduled.durationMs;
|
|
3014
|
+
if (this.isLiveStream && adBreakDurationMs != null && adBreakDurationMs > 0) {
|
|
3015
|
+
this.isAdaptiveMode = true;
|
|
3016
|
+
this.targetAdBreakDurationMs = adBreakDurationMs;
|
|
3017
|
+
this.fetchedAdDurations.clear();
|
|
3018
|
+
if (this.config.debugAdTiming) {
|
|
3019
|
+
console.log(
|
|
3020
|
+
`[CONTINUOUS-FETCH] \u{1F4FA} LIVE MODE: Target duration=${adBreakDurationMs}ms | Will continuously fetch ads during break`
|
|
3021
|
+
);
|
|
3022
|
+
}
|
|
3023
|
+
} else {
|
|
3024
|
+
this.isAdaptiveMode = false;
|
|
3025
|
+
this.targetAdBreakDurationMs = null;
|
|
3026
|
+
this.fetchedAdDurations.clear();
|
|
3027
|
+
if (this.config.debugAdTiming) {
|
|
3028
|
+
console.log(
|
|
3029
|
+
`[CONTINUOUS-FETCH] \u{1F3AC} VOD MODE: Using fixed ad strategy`
|
|
3030
|
+
);
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
3033
|
+
this.adPodAllUrls = [];
|
|
3034
|
+
this.preloadingAdUrls.clear();
|
|
3035
|
+
this.vastToMediaUrlMap.clear();
|
|
3036
|
+
this.preloadedMediaUrls.clear();
|
|
3037
|
+
this.preloadingMediaUrls.clear();
|
|
3038
|
+
this.failedVastUrls.clear();
|
|
3039
|
+
this.adRequestQueue = [];
|
|
3040
|
+
this.successfulAdRequests = [];
|
|
3041
|
+
this.continuousFetchingActive = true;
|
|
3042
|
+
this.isShowingPlaceholder = false;
|
|
3043
|
+
this.placeholderStartTimeMs = null;
|
|
3044
|
+
const currentMuted = this.video.muted;
|
|
3045
|
+
const currentVolume = this.video.volume;
|
|
3046
|
+
this.ima.updateOriginalMutedState(currentMuted, currentVolume);
|
|
3047
|
+
this.inAdBreak = true;
|
|
3048
|
+
this.currentAdIndex = 0;
|
|
3049
|
+
this.totalAdsInBreak = 1;
|
|
3050
|
+
this.adPodQueue = [];
|
|
3051
|
+
if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {
|
|
3052
|
+
this.expectedAdBreakDurationMs = adBreakDurationMs;
|
|
3053
|
+
this.currentAdBreakStartWallClockMs = Date.now();
|
|
3054
|
+
this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
|
|
3055
|
+
}
|
|
3056
|
+
if (this.config.debugAdTiming) {
|
|
3057
|
+
console.log("[CONTINUOUS-FETCH] \u{1F680} Immediately requesting first ad...");
|
|
3058
|
+
}
|
|
3059
|
+
const firstAdUrlArray = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);
|
|
3060
|
+
const firstAdUrl = firstAdUrlArray[0];
|
|
3061
|
+
if (!firstAdUrl) {
|
|
3062
|
+
if (this.config.debugAdTiming) {
|
|
3063
|
+
console.warn("[CONTINUOUS-FETCH] \u26A0\uFE0F Failed to generate first ad URL");
|
|
3064
|
+
}
|
|
3065
|
+
this.handleAdPodComplete();
|
|
3066
|
+
return;
|
|
3067
|
+
}
|
|
3068
|
+
try {
|
|
3069
|
+
await this.ima.requestAds(firstAdUrl);
|
|
3070
|
+
if (this.config.debugAdTiming) {
|
|
3071
|
+
console.log("[CONTINUOUS-FETCH] \u2705 First ad request successful, starting playback");
|
|
3072
|
+
}
|
|
3073
|
+
this.successfulAdRequests.push(firstAdUrl);
|
|
3074
|
+
this.currentAdIndex++;
|
|
3075
|
+
this.startContinuousFetching(baseVastUrl);
|
|
3076
|
+
await this.ima.play();
|
|
3077
|
+
} catch (error) {
|
|
3078
|
+
if (this.config.debugAdTiming) {
|
|
3079
|
+
console.warn("[CONTINUOUS-FETCH] \u26A0\uFE0F First ad request failed:", error);
|
|
3080
|
+
}
|
|
3081
|
+
this.failedVastUrls.add(firstAdUrl);
|
|
3082
|
+
this.startContinuousFetching(baseVastUrl);
|
|
3083
|
+
this.tryNextAvailableAd();
|
|
3084
|
+
}
|
|
3085
|
+
}
|
|
3086
|
+
startContinuousFetching(baseVastUrl) {
|
|
3087
|
+
if (!this.continuousFetchingActive) {
|
|
3088
|
+
return;
|
|
3089
|
+
}
|
|
3090
|
+
if (this.config.debugAdTiming) {
|
|
3091
|
+
console.log("[CONTINUOUS-FETCH] \u{1F504} Starting continuous ad fetching loop");
|
|
3092
|
+
}
|
|
3093
|
+
this.continuousFetchLoop(baseVastUrl);
|
|
3094
|
+
}
|
|
3095
|
+
async continuousFetchLoop(baseVastUrl) {
|
|
3096
|
+
while (this.continuousFetchingActive && this.inAdBreak) {
|
|
3097
|
+
const remaining = this.getRemainingAdMs();
|
|
3098
|
+
if (remaining <= 0) {
|
|
3099
|
+
if (this.config.debugAdTiming) {
|
|
3100
|
+
console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F Ad break time expired, stopping fetch loop");
|
|
3026
3101
|
}
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
this.
|
|
3031
|
-
|
|
3032
|
-
|
|
3102
|
+
break;
|
|
3103
|
+
}
|
|
3104
|
+
if (this.adRequestQueue.length > 0) {
|
|
3105
|
+
if (this.config.debugAdTiming) {
|
|
3106
|
+
console.log(`[CONTINUOUS-FETCH] \u23F3 Already have ${this.adRequestQueue.length} ads queued, waiting...`);
|
|
3107
|
+
}
|
|
3108
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
3109
|
+
continue;
|
|
3110
|
+
}
|
|
3111
|
+
const newAdUrl = this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];
|
|
3112
|
+
if (!newAdUrl || this.failedVastUrls.has(newAdUrl)) {
|
|
3113
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
3114
|
+
continue;
|
|
3115
|
+
}
|
|
3116
|
+
if (this.config.debugAdTiming) {
|
|
3117
|
+
console.log("[CONTINUOUS-FETCH] \u{1F4E1} Attempting to fetch additional ad...");
|
|
3118
|
+
}
|
|
3119
|
+
try {
|
|
3120
|
+
const response = await fetch(newAdUrl, { mode: "cors" });
|
|
3121
|
+
if (!response.ok) {
|
|
3122
|
+
throw new Error(`Failed to fetch VAST: ${response.status}`);
|
|
3123
|
+
}
|
|
3124
|
+
const xmlText = await response.text();
|
|
3125
|
+
const parser = new DOMParser();
|
|
3126
|
+
const xmlDoc = parser.parseFromString(xmlText, "text/xml");
|
|
3127
|
+
const mediaFiles = xmlDoc.querySelectorAll("MediaFile");
|
|
3128
|
+
if (mediaFiles.length === 0) {
|
|
3033
3129
|
if (this.config.debugAdTiming) {
|
|
3034
|
-
console.log(
|
|
3035
|
-
`[DEBUG-POD] \u{1F3AC} VOD MODE (FIXED): Using number_ads=${numberOfAds} from API`
|
|
3036
|
-
);
|
|
3130
|
+
console.log("[CONTINUOUS-FETCH] \u26A0\uFE0F VAST response has no media files, skipping");
|
|
3037
3131
|
}
|
|
3132
|
+
this.failedVastUrls.add(newAdUrl);
|
|
3133
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
3134
|
+
continue;
|
|
3038
3135
|
}
|
|
3039
|
-
}
|
|
3040
|
-
if (numberOfAds > 1) {
|
|
3041
|
-
vastTagUrls = this.generateVastUrlsWithCorrelators(
|
|
3042
|
-
this.apiVastTagUrl,
|
|
3043
|
-
numberOfAds
|
|
3044
|
-
);
|
|
3045
3136
|
if (this.config.debugAdTiming) {
|
|
3046
|
-
console.log(
|
|
3047
|
-
`[DEBUG-POD] \u{1F504} Generated ${vastTagUrls.length} initial VAST URLs with unique correlators`
|
|
3048
|
-
);
|
|
3137
|
+
console.log("[CONTINUOUS-FETCH] \u2705 Successfully fetched new ad, adding to queue");
|
|
3049
3138
|
}
|
|
3050
|
-
|
|
3051
|
-
|
|
3139
|
+
this.adRequestQueue.push(newAdUrl);
|
|
3140
|
+
this.totalAdsInBreak++;
|
|
3141
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
3142
|
+
} catch (error) {
|
|
3143
|
+
if (this.config.debugAdTiming) {
|
|
3144
|
+
console.log("[CONTINUOUS-FETCH] \u274C Ad fetch failed:", error.message);
|
|
3145
|
+
}
|
|
3146
|
+
this.failedVastUrls.add(newAdUrl);
|
|
3147
|
+
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
3052
3148
|
}
|
|
3053
|
-
}
|
|
3054
|
-
|
|
3055
|
-
|
|
3149
|
+
}
|
|
3150
|
+
if (this.config.debugAdTiming) {
|
|
3151
|
+
console.log("[CONTINUOUS-FETCH] \u{1F6D1} Continuous fetch loop ended");
|
|
3152
|
+
}
|
|
3153
|
+
}
|
|
3154
|
+
stopContinuousFetching() {
|
|
3155
|
+
this.continuousFetchingActive = false;
|
|
3156
|
+
if (this.config.debugAdTiming) {
|
|
3157
|
+
console.log("[CONTINUOUS-FETCH] \u{1F6D1} Stopping continuous ad fetching");
|
|
3158
|
+
}
|
|
3159
|
+
}
|
|
3160
|
+
async tryNextAvailableAd() {
|
|
3161
|
+
const remaining = this.getRemainingAdMs();
|
|
3162
|
+
if (remaining <= 500) {
|
|
3163
|
+
if (this.config.debugAdTiming) {
|
|
3164
|
+
console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F No time remaining, ending ad break");
|
|
3165
|
+
}
|
|
3166
|
+
this.handleAdPodComplete();
|
|
3056
3167
|
return;
|
|
3057
3168
|
}
|
|
3058
|
-
if (
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
this.vastToMediaUrlMap.clear();
|
|
3062
|
-
this.preloadedMediaUrls.clear();
|
|
3063
|
-
this.preloadingMediaUrls.clear();
|
|
3064
|
-
this.failedVastUrls.clear();
|
|
3065
|
-
const currentMuted = this.video.muted;
|
|
3066
|
-
const currentVolume = this.video.volume;
|
|
3067
|
-
this.ima.updateOriginalMutedState(currentMuted, currentVolume);
|
|
3068
|
-
this.inAdBreak = true;
|
|
3069
|
-
this.currentAdIndex = 0;
|
|
3070
|
-
this.totalAdsInBreak = vastTagUrls.length;
|
|
3071
|
-
this.adPodQueue = [...vastTagUrls];
|
|
3072
|
-
if (this.isAdaptiveMode) {
|
|
3169
|
+
if (this.adRequestQueue.length > 0) {
|
|
3170
|
+
const nextAdUrl = this.adRequestQueue.shift();
|
|
3171
|
+
if (nextAdUrl) {
|
|
3073
3172
|
if (this.config.debugAdTiming) {
|
|
3074
|
-
console.log("[
|
|
3075
|
-
}
|
|
3076
|
-
try {
|
|
3077
|
-
const adsToPreloadBeforeStart = Math.min(2, this.adPodAllUrls.length);
|
|
3078
|
-
for (let i = 0; i < adsToPreloadBeforeStart; i++) {
|
|
3079
|
-
const url = this.adPodAllUrls[i];
|
|
3080
|
-
if (url) {
|
|
3081
|
-
await this.preloadSingleAd(url);
|
|
3082
|
-
if (this.config.debugAdTiming) {
|
|
3083
|
-
console.log(`[ADAPTIVE-POD] \u2705 Preloaded ad ${i + 1}/${adsToPreloadBeforeStart}`);
|
|
3084
|
-
}
|
|
3085
|
-
}
|
|
3086
|
-
}
|
|
3087
|
-
if (this.config.debugAdTiming) {
|
|
3088
|
-
console.log("[ADAPTIVE-POD] \u{1F3AC} First ads preloaded, starting playback immediately");
|
|
3089
|
-
}
|
|
3090
|
-
} catch (error) {
|
|
3091
|
-
if (this.config.debugAdTiming) {
|
|
3092
|
-
console.warn(
|
|
3093
|
-
"[ADAPTIVE-POD] \u26A0\uFE0F Error preloading initial ads:",
|
|
3094
|
-
error
|
|
3095
|
-
);
|
|
3096
|
-
}
|
|
3173
|
+
console.log("[CONTINUOUS-FETCH] \u{1F3AC} Playing next queued ad");
|
|
3097
3174
|
}
|
|
3098
|
-
this.
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
"[ADAPTIVE-POD] Error in background preloading:",
|
|
3102
|
-
error
|
|
3103
|
-
);
|
|
3104
|
-
}
|
|
3105
|
-
});
|
|
3106
|
-
await this.playAdPod();
|
|
3107
|
-
} else {
|
|
3108
|
-
this.preloadAllAdsInBackground().catch((error) => {
|
|
3109
|
-
if (this.config.debugAdTiming) {
|
|
3110
|
-
console.warn(
|
|
3111
|
-
"[StormcloudVideoPlayer] Error in background preloading:",
|
|
3112
|
-
error
|
|
3113
|
-
);
|
|
3114
|
-
}
|
|
3175
|
+
this.currentAdIndex++;
|
|
3176
|
+
await this.playSingleAd(nextAdUrl).catch(() => {
|
|
3177
|
+
this.tryNextAvailableAd();
|
|
3115
3178
|
});
|
|
3116
|
-
|
|
3179
|
+
return;
|
|
3117
3180
|
}
|
|
3118
3181
|
}
|
|
3119
|
-
if (this.
|
|
3120
|
-
this.
|
|
3121
|
-
|
|
3122
|
-
|
|
3182
|
+
if (!this.isShowingPlaceholder && remaining > 1e3) {
|
|
3183
|
+
this.showPlaceholderAndWaitForAds();
|
|
3184
|
+
} else {
|
|
3185
|
+
if (this.config.debugAdTiming) {
|
|
3186
|
+
console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F No more ads available, ending ad break");
|
|
3187
|
+
}
|
|
3188
|
+
this.handleAdPodComplete();
|
|
3123
3189
|
}
|
|
3124
3190
|
}
|
|
3125
|
-
async
|
|
3126
|
-
|
|
3191
|
+
async showPlaceholderAndWaitForAds() {
|
|
3192
|
+
const remaining = this.getRemainingAdMs();
|
|
3193
|
+
const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);
|
|
3194
|
+
if (waitTime < 1e3) {
|
|
3195
|
+
this.handleAdPodComplete();
|
|
3127
3196
|
return;
|
|
3128
3197
|
}
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3198
|
+
if (this.config.debugAdTiming) {
|
|
3199
|
+
console.log(`[CONTINUOUS-FETCH] \u2B1B Showing black placeholder for ${waitTime}ms while waiting for ads`);
|
|
3200
|
+
}
|
|
3201
|
+
this.isShowingPlaceholder = true;
|
|
3202
|
+
this.placeholderStartTimeMs = Date.now();
|
|
3203
|
+
this.ima.showPlaceholder();
|
|
3204
|
+
const checkInterval = 500;
|
|
3205
|
+
const maxChecks = Math.floor(waitTime / checkInterval);
|
|
3206
|
+
for (let i = 0; i < maxChecks; i++) {
|
|
3207
|
+
await new Promise((resolve) => setTimeout(resolve, checkInterval));
|
|
3208
|
+
if (!this.inAdBreak) {
|
|
3209
|
+
return;
|
|
3210
|
+
}
|
|
3211
|
+
if (this.adRequestQueue.length > 0) {
|
|
3212
|
+
if (this.config.debugAdTiming) {
|
|
3213
|
+
console.log("[CONTINUOUS-FETCH] \u2705 New ad became available during placeholder");
|
|
3140
3214
|
}
|
|
3215
|
+
this.isShowingPlaceholder = false;
|
|
3216
|
+
this.placeholderStartTimeMs = null;
|
|
3217
|
+
this.ima.hidePlaceholder();
|
|
3218
|
+
const nextAdUrl = this.adRequestQueue.shift();
|
|
3219
|
+
if (nextAdUrl) {
|
|
3220
|
+
this.currentAdIndex++;
|
|
3221
|
+
await this.playSingleAd(nextAdUrl).catch(() => {
|
|
3222
|
+
this.tryNextAvailableAd();
|
|
3223
|
+
});
|
|
3224
|
+
}
|
|
3225
|
+
return;
|
|
3141
3226
|
}
|
|
3142
|
-
return;
|
|
3143
3227
|
}
|
|
3144
|
-
this.
|
|
3145
|
-
|
|
3146
|
-
await this.playSingleAd(firstPreloaded);
|
|
3147
|
-
} catch (error) {
|
|
3228
|
+
if (this.config.debugAdTiming) {
|
|
3229
|
+
console.log("[CONTINUOUS-FETCH] \u23F0 Placeholder timeout reached, no ads fetched");
|
|
3148
3230
|
}
|
|
3231
|
+
this.isShowingPlaceholder = false;
|
|
3232
|
+
this.placeholderStartTimeMs = null;
|
|
3233
|
+
this.ima.hidePlaceholder();
|
|
3234
|
+
this.handleAdPodComplete();
|
|
3149
3235
|
}
|
|
3150
3236
|
findCurrentOrNextBreak(nowMs) {
|
|
3151
3237
|
var _a;
|
|
@@ -3305,10 +3391,18 @@ var StormcloudVideoPlayer = class {
|
|
|
3305
3391
|
this.clearAdRequestWatchdog();
|
|
3306
3392
|
this.clearAdFailsafeTimer();
|
|
3307
3393
|
this.activeAdRequestToken = null;
|
|
3394
|
+
this.stopContinuousFetching();
|
|
3395
|
+
if (this.isShowingPlaceholder) {
|
|
3396
|
+
this.ima.hidePlaceholder();
|
|
3397
|
+
this.isShowingPlaceholder = false;
|
|
3398
|
+
this.placeholderStartTimeMs = null;
|
|
3399
|
+
}
|
|
3308
3400
|
this.preloadingAdUrls.clear();
|
|
3309
3401
|
this.vastToMediaUrlMap.clear();
|
|
3310
3402
|
this.preloadedMediaUrls.clear();
|
|
3311
3403
|
this.preloadingMediaUrls.clear();
|
|
3404
|
+
this.adRequestQueue = [];
|
|
3405
|
+
this.successfulAdRequests = [];
|
|
3312
3406
|
this.inAdBreak = false;
|
|
3313
3407
|
this.expectedAdBreakDurationMs = void 0;
|
|
3314
3408
|
this.currentAdBreakStartWallClockMs = void 0;
|
|
@@ -3335,61 +3429,14 @@ var StormcloudVideoPlayer = class {
|
|
|
3335
3429
|
}
|
|
3336
3430
|
}
|
|
3337
3431
|
handleAdFailure() {
|
|
3338
|
-
const remaining = this.getRemainingAdMs();
|
|
3339
|
-
const availableAds = this.adPodQueue.filter((url) => !this.failedVastUrls.has(url)).length;
|
|
3340
|
-
if (remaining > 500 && availableAds > 0) {
|
|
3341
|
-
if (this.isAdaptiveMode && this.currentAdIndex <= 1) {
|
|
3342
|
-
console.log("[ADAPTIVE-POD] \u23F3 First ad failed, waiting for sequential preload to catch up...");
|
|
3343
|
-
setTimeout(() => {
|
|
3344
|
-
this.tryNextAdWithRetry(0);
|
|
3345
|
-
}, 1500);
|
|
3346
|
-
return;
|
|
3347
|
-
}
|
|
3348
|
-
const nextPreloaded = this.findNextPreloadedAd();
|
|
3349
|
-
if (nextPreloaded) {
|
|
3350
|
-
this.currentAdIndex++;
|
|
3351
|
-
this.playSingleAd(nextPreloaded).catch(() => {
|
|
3352
|
-
this.handleAdPodComplete();
|
|
3353
|
-
});
|
|
3354
|
-
return;
|
|
3355
|
-
}
|
|
3356
|
-
}
|
|
3357
|
-
console.error("[AD-ERROR] All ads failed or time expired. Failed URLs:", this.failedVastUrls.size);
|
|
3358
|
-
this.handleAdPodComplete();
|
|
3359
|
-
}
|
|
3360
|
-
tryNextAdWithRetry(retryCount) {
|
|
3361
|
-
const maxRetries = 3;
|
|
3362
3432
|
const remaining = this.getRemainingAdMs();
|
|
3363
3433
|
if (this.config.debugAdTiming) {
|
|
3364
|
-
console.log(
|
|
3365
|
-
`[ADAPTIVE-POD] \u{1F50D} Retry attempt ${retryCount}: remaining=${remaining}ms, queue=${this.adPodQueue.length}, totalAds=${this.totalAdsInBreak}`
|
|
3366
|
-
);
|
|
3367
|
-
}
|
|
3368
|
-
if (remaining <= 500 || this.adPodQueue.length === 0) {
|
|
3369
|
-
console.log("[ADAPTIVE-POD] \u23F9\uFE0F No more time or ads available");
|
|
3370
|
-
this.handleAdPodComplete();
|
|
3371
|
-
return;
|
|
3434
|
+
console.log(`[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`);
|
|
3372
3435
|
}
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
this.currentAdIndex++;
|
|
3376
|
-
console.log(
|
|
3377
|
-
`[ADAPTIVE-POD] \u2705 Found preloaded ad after retry ${retryCount}, playing (${this.currentAdIndex}/${this.totalAdsInBreak})`
|
|
3378
|
-
);
|
|
3379
|
-
this.playSingleAd(nextPreloaded).catch(() => {
|
|
3380
|
-
this.handleAdPodComplete();
|
|
3381
|
-
});
|
|
3382
|
-
} else if (retryCount < maxRetries) {
|
|
3383
|
-
console.log(
|
|
3384
|
-
`[ADAPTIVE-POD] \u23F3 No preloaded ads yet (queue has ${this.adPodQueue.length} URLs), retry ${retryCount + 1}/${maxRetries} in 1s...`
|
|
3385
|
-
);
|
|
3386
|
-
setTimeout(() => {
|
|
3387
|
-
this.tryNextAdWithRetry(retryCount + 1);
|
|
3388
|
-
}, 1e3);
|
|
3436
|
+
if (remaining > 500) {
|
|
3437
|
+
this.tryNextAvailableAd();
|
|
3389
3438
|
} else {
|
|
3390
|
-
console.
|
|
3391
|
-
`[ADAPTIVE-POD] \u274C Max retries reached, no preloaded ads available (queue=${this.adPodQueue.length} URLs)`
|
|
3392
|
-
);
|
|
3439
|
+
console.error("[AD-ERROR] Ad failed and no time remaining. Failed URLs:", this.failedVastUrls.size);
|
|
3393
3440
|
this.handleAdPodComplete();
|
|
3394
3441
|
}
|
|
3395
3442
|
}
|
|
@@ -3987,6 +4034,7 @@ var StormcloudVideoPlayer = class {
|
|
|
3987
4034
|
}
|
|
3988
4035
|
destroy() {
|
|
3989
4036
|
var _a, _b;
|
|
4037
|
+
this.stopContinuousFetching();
|
|
3990
4038
|
this.clearAdStartTimer();
|
|
3991
4039
|
this.clearAdStopTimer();
|
|
3992
4040
|
this.clearAdFailsafeTimer();
|
|
@@ -4001,6 +4049,8 @@ var StormcloudVideoPlayer = class {
|
|
|
4001
4049
|
this.preloadedMediaUrls.clear();
|
|
4002
4050
|
this.preloadingMediaUrls.clear();
|
|
4003
4051
|
this.adPodAllUrls = [];
|
|
4052
|
+
this.adRequestQueue = [];
|
|
4053
|
+
this.successfulAdRequests = [];
|
|
4004
4054
|
}
|
|
4005
4055
|
};
|
|
4006
4056
|
// Annotate the CommonJS export names for ESM import in node:
|