stormcloud-video-player 0.3.9 → 0.3.11

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.
@@ -2124,6 +2124,12 @@ var StormcloudVideoPlayer = class {
2124
2124
  this.targetAdBreakDurationMs = null;
2125
2125
  this.isAdaptiveMode = false;
2126
2126
  this.failedVastUrls = /* @__PURE__ */ new Set();
2127
+ this.continuousFetchingActive = false;
2128
+ this.adRequestQueue = [];
2129
+ this.successfulAdRequests = [];
2130
+ this.maxPlaceholderDurationMs = 5e3;
2131
+ this.placeholderStartTimeMs = null;
2132
+ this.isShowingPlaceholder = false;
2127
2133
  initializePolyfills();
2128
2134
  const browserOverrides = getBrowserConfigOverrides();
2129
2135
  this.config = { ...config, ...browserOverrides };
@@ -2430,16 +2436,11 @@ var StormcloudVideoPlayer = class {
2430
2436
  return;
2431
2437
  }
2432
2438
  const remaining = this.getRemainingAdMs();
2433
- if (remaining > 500 && this.adPodQueue.length > 0) {
2434
- const nextPreloaded = this.findNextPreloadedAd();
2435
- if (nextPreloaded) {
2436
- this.currentAdIndex++;
2437
- this.playSingleAd(nextPreloaded).catch(() => {
2438
- this.handleAdPodComplete();
2439
- });
2440
- } else {
2441
- this.handleAdPodComplete();
2442
- }
2439
+ if (this.config.debugAdTiming) {
2440
+ console.log(`[CONTINUOUS-FETCH] content_resume event: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`);
2441
+ }
2442
+ if (remaining > 500) {
2443
+ this.tryNextAvailableAd();
2443
2444
  } else {
2444
2445
  this.handleAdPodComplete();
2445
2446
  }
@@ -3039,155 +3040,251 @@ var StormcloudVideoPlayer = class {
3039
3040
  return true;
3040
3041
  }
3041
3042
  async handleAdStart(_marker) {
3042
- var _a;
3043
3043
  const scheduled = this.findCurrentOrNextBreak(
3044
3044
  this.video.currentTime * 1e3
3045
3045
  );
3046
3046
  const tags = this.selectVastTagsForBreak(scheduled);
3047
- let vastTagUrls = [];
3047
+ let baseVastUrl;
3048
3048
  if (this.apiVastTagUrl) {
3049
- let numberOfAds = 1;
3050
- if (this.isLiveStream) {
3051
- const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : scheduled == null ? void 0 : scheduled.durationMs;
3052
- if (adBreakDurationMs != null && adBreakDurationMs > 0) {
3053
- this.isAdaptiveMode = true;
3054
- this.targetAdBreakDurationMs = adBreakDurationMs;
3055
- this.fetchedAdDurations.clear();
3056
- numberOfAds = 2;
3057
- if (this.config.debugAdTiming) {
3058
- console.log(
3059
- `[ADAPTIVE-POD] \u{1F4FA} LIVE MODE (ADAPTIVE): Target duration=${adBreakDurationMs}ms | Starting with ${numberOfAds} ads, will fetch actual durations and add more dynamically`
3060
- );
3061
- }
3062
- } else {
3063
- if (this.config.debugAdTiming) {
3064
- console.warn(
3065
- "[DEBUG-POD] \u26A0\uFE0F LIVE MODE: No duration available, defaulting to 1 ad"
3066
- );
3067
- }
3049
+ baseVastUrl = this.apiVastTagUrl;
3050
+ } else if (tags && tags.length > 0 && tags[0]) {
3051
+ baseVastUrl = tags[0];
3052
+ } else {
3053
+ return;
3054
+ }
3055
+ const adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : scheduled == null ? void 0 : scheduled.durationMs;
3056
+ if (this.isLiveStream && adBreakDurationMs != null && adBreakDurationMs > 0) {
3057
+ this.isAdaptiveMode = true;
3058
+ this.targetAdBreakDurationMs = adBreakDurationMs;
3059
+ this.fetchedAdDurations.clear();
3060
+ if (this.config.debugAdTiming) {
3061
+ console.log(
3062
+ `[CONTINUOUS-FETCH] \u{1F4FA} LIVE MODE: Target duration=${adBreakDurationMs}ms | Will continuously fetch ads during break`
3063
+ );
3064
+ }
3065
+ } else {
3066
+ this.isAdaptiveMode = false;
3067
+ this.targetAdBreakDurationMs = null;
3068
+ this.fetchedAdDurations.clear();
3069
+ if (this.config.debugAdTiming) {
3070
+ console.log(
3071
+ `[CONTINUOUS-FETCH] \u{1F3AC} VOD MODE: Using fixed ad strategy`
3072
+ );
3073
+ }
3074
+ }
3075
+ this.adPodAllUrls = [];
3076
+ this.preloadingAdUrls.clear();
3077
+ this.vastToMediaUrlMap.clear();
3078
+ this.preloadedMediaUrls.clear();
3079
+ this.preloadingMediaUrls.clear();
3080
+ this.failedVastUrls.clear();
3081
+ this.adRequestQueue = [];
3082
+ this.successfulAdRequests = [];
3083
+ this.continuousFetchingActive = true;
3084
+ this.isShowingPlaceholder = false;
3085
+ this.placeholderStartTimeMs = null;
3086
+ const currentMuted = this.video.muted;
3087
+ const currentVolume = this.video.volume;
3088
+ this.ima.updateOriginalMutedState(currentMuted, currentVolume);
3089
+ this.inAdBreak = true;
3090
+ this.currentAdIndex = 0;
3091
+ this.totalAdsInBreak = 1;
3092
+ this.adPodQueue = [];
3093
+ if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {
3094
+ this.expectedAdBreakDurationMs = adBreakDurationMs;
3095
+ this.currentAdBreakStartWallClockMs = Date.now();
3096
+ this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
3097
+ }
3098
+ if (this.config.debugAdTiming) {
3099
+ console.log("[CONTINUOUS-FETCH] \u{1F680} Immediately requesting first ad...");
3100
+ }
3101
+ const firstAdUrlArray = this.generateVastUrlsWithCorrelators(baseVastUrl, 1);
3102
+ const firstAdUrl = firstAdUrlArray[0];
3103
+ if (!firstAdUrl) {
3104
+ if (this.config.debugAdTiming) {
3105
+ console.warn("[CONTINUOUS-FETCH] \u26A0\uFE0F Failed to generate first ad URL");
3106
+ }
3107
+ this.handleAdPodComplete();
3108
+ return;
3109
+ }
3110
+ try {
3111
+ await this.ima.requestAds(firstAdUrl);
3112
+ if (this.config.debugAdTiming) {
3113
+ console.log("[CONTINUOUS-FETCH] \u2705 First ad request successful, starting playback");
3114
+ }
3115
+ this.successfulAdRequests.push(firstAdUrl);
3116
+ this.currentAdIndex++;
3117
+ this.startContinuousFetching(baseVastUrl);
3118
+ await this.ima.play();
3119
+ } catch (error) {
3120
+ if (this.config.debugAdTiming) {
3121
+ console.warn("[CONTINUOUS-FETCH] \u26A0\uFE0F First ad request failed:", error);
3122
+ }
3123
+ this.failedVastUrls.add(firstAdUrl);
3124
+ this.startContinuousFetching(baseVastUrl);
3125
+ this.tryNextAvailableAd();
3126
+ }
3127
+ }
3128
+ startContinuousFetching(baseVastUrl) {
3129
+ if (!this.continuousFetchingActive) {
3130
+ return;
3131
+ }
3132
+ if (this.config.debugAdTiming) {
3133
+ console.log("[CONTINUOUS-FETCH] \u{1F504} Starting continuous ad fetching loop");
3134
+ }
3135
+ this.continuousFetchLoop(baseVastUrl);
3136
+ }
3137
+ async continuousFetchLoop(baseVastUrl) {
3138
+ while (this.continuousFetchingActive && this.inAdBreak) {
3139
+ const remaining = this.getRemainingAdMs();
3140
+ if (remaining <= 0) {
3141
+ if (this.config.debugAdTiming) {
3142
+ console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F Ad break time expired, stopping fetch loop");
3068
3143
  }
3069
- } else {
3070
- this.isAdaptiveMode = false;
3071
- this.targetAdBreakDurationMs = null;
3072
- this.fetchedAdDurations.clear();
3073
- if (this.apiNumberAds && this.apiNumberAds > 1) {
3074
- numberOfAds = this.apiNumberAds;
3144
+ break;
3145
+ }
3146
+ const maxQueueSize = 3;
3147
+ if (this.adRequestQueue.length >= maxQueueSize) {
3148
+ if (this.config.debugAdTiming) {
3149
+ console.log(`[CONTINUOUS-FETCH] \u23F8\uFE0F Queue full (${this.adRequestQueue.length}), pausing fetching...`);
3150
+ }
3151
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
3152
+ continue;
3153
+ }
3154
+ const newAdUrl = this.generateVastUrlsWithCorrelators(baseVastUrl, 1)[0];
3155
+ if (!newAdUrl || this.failedVastUrls.has(newAdUrl)) {
3156
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
3157
+ continue;
3158
+ }
3159
+ if (this.config.debugAdTiming) {
3160
+ console.log(`[CONTINUOUS-FETCH] \u{1F4E1} Attempting to fetch ad (${this.successfulAdRequests.length + this.adRequestQueue.length + 1} total)...`);
3161
+ }
3162
+ try {
3163
+ const response = await fetch(newAdUrl, { mode: "cors" });
3164
+ if (!response.ok) {
3165
+ throw new Error(`Failed to fetch VAST: ${response.status}`);
3166
+ }
3167
+ const xmlText = await response.text();
3168
+ const parser = new DOMParser();
3169
+ const xmlDoc = parser.parseFromString(xmlText, "text/xml");
3170
+ const mediaFiles = xmlDoc.querySelectorAll("MediaFile");
3171
+ if (mediaFiles.length === 0) {
3075
3172
  if (this.config.debugAdTiming) {
3076
- console.log(
3077
- `[DEBUG-POD] \u{1F3AC} VOD MODE (FIXED): Using number_ads=${numberOfAds} from API`
3078
- );
3173
+ console.log("[CONTINUOUS-FETCH] \u26A0\uFE0F VAST response has no media files, skipping");
3079
3174
  }
3175
+ this.failedVastUrls.add(newAdUrl);
3176
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
3177
+ continue;
3080
3178
  }
3081
- }
3082
- if (numberOfAds > 1) {
3083
- vastTagUrls = this.generateVastUrlsWithCorrelators(
3084
- this.apiVastTagUrl,
3085
- numberOfAds
3086
- );
3087
3179
  if (this.config.debugAdTiming) {
3088
- console.log(
3089
- `[DEBUG-POD] \u{1F504} Generated ${vastTagUrls.length} initial VAST URLs with unique correlators`
3090
- );
3180
+ console.log(`[CONTINUOUS-FETCH] \u2705 Successfully fetched ad, adding to queue (queue size: ${this.adRequestQueue.length + 1})`);
3091
3181
  }
3092
- } else {
3093
- vastTagUrls = [this.apiVastTagUrl];
3182
+ this.adRequestQueue.push(newAdUrl);
3183
+ this.totalAdsInBreak++;
3184
+ await new Promise((resolve) => setTimeout(resolve, 500));
3185
+ } catch (error) {
3186
+ if (this.config.debugAdTiming) {
3187
+ console.log("[CONTINUOUS-FETCH] \u274C Ad fetch failed:", error.message);
3188
+ }
3189
+ this.failedVastUrls.add(newAdUrl);
3190
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
3094
3191
  }
3095
- } else if (tags && tags.length > 0) {
3096
- vastTagUrls = tags;
3097
- } else {
3192
+ }
3193
+ if (this.config.debugAdTiming) {
3194
+ console.log("[CONTINUOUS-FETCH] \u{1F6D1} Continuous fetch loop ended");
3195
+ }
3196
+ }
3197
+ stopContinuousFetching() {
3198
+ this.continuousFetchingActive = false;
3199
+ if (this.config.debugAdTiming) {
3200
+ console.log("[CONTINUOUS-FETCH] \u{1F6D1} Stopping continuous ad fetching");
3201
+ }
3202
+ }
3203
+ async tryNextAvailableAd(retryCount = 0) {
3204
+ const remaining = this.getRemainingAdMs();
3205
+ if (remaining <= 500) {
3206
+ if (this.config.debugAdTiming) {
3207
+ console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F No time remaining, ending ad break");
3208
+ }
3209
+ this.handleAdPodComplete();
3098
3210
  return;
3099
3211
  }
3100
- if (vastTagUrls.length > 0) {
3101
- this.adPodAllUrls = [...vastTagUrls];
3102
- this.preloadingAdUrls.clear();
3103
- this.vastToMediaUrlMap.clear();
3104
- this.preloadedMediaUrls.clear();
3105
- this.preloadingMediaUrls.clear();
3106
- this.failedVastUrls.clear();
3107
- const currentMuted = this.video.muted;
3108
- const currentVolume = this.video.volume;
3109
- this.ima.updateOriginalMutedState(currentMuted, currentVolume);
3110
- this.inAdBreak = true;
3111
- this.currentAdIndex = 0;
3112
- this.totalAdsInBreak = vastTagUrls.length;
3113
- this.adPodQueue = [...vastTagUrls];
3114
- if (this.isAdaptiveMode) {
3212
+ if (this.adRequestQueue.length > 0) {
3213
+ const nextAdUrl = this.adRequestQueue.shift();
3214
+ if (nextAdUrl) {
3115
3215
  if (this.config.debugAdTiming) {
3116
- console.log("[ADAPTIVE-POD] \u{1F680} Preloading first 2 ads before starting playback...");
3216
+ console.log(`[CONTINUOUS-FETCH] \u{1F3AC} Playing next queued ad (${this.currentAdIndex + 1}/${this.totalAdsInBreak}, ${this.adRequestQueue.length} remaining in queue)`);
3117
3217
  }
3118
- try {
3119
- const adsToPreloadBeforeStart = Math.min(2, this.adPodAllUrls.length);
3120
- for (let i = 0; i < adsToPreloadBeforeStart; i++) {
3121
- const url = this.adPodAllUrls[i];
3122
- if (url) {
3123
- await this.preloadSingleAd(url);
3124
- if (this.config.debugAdTiming) {
3125
- console.log(`[ADAPTIVE-POD] \u2705 Preloaded ad ${i + 1}/${adsToPreloadBeforeStart}`);
3126
- }
3127
- }
3128
- }
3129
- if (this.config.debugAdTiming) {
3130
- console.log("[ADAPTIVE-POD] \u{1F3AC} First ads preloaded, starting playback immediately");
3131
- }
3132
- } catch (error) {
3133
- if (this.config.debugAdTiming) {
3134
- console.warn(
3135
- "[ADAPTIVE-POD] \u26A0\uFE0F Error preloading initial ads:",
3136
- error
3137
- );
3138
- }
3139
- }
3140
- this.preloadAllAdsInBackground().catch((error) => {
3141
- if (this.config.debugAdTiming) {
3142
- console.warn(
3143
- "[ADAPTIVE-POD] Error in background preloading:",
3144
- error
3145
- );
3146
- }
3147
- });
3148
- await this.playAdPod();
3149
- } else {
3150
- this.preloadAllAdsInBackground().catch((error) => {
3151
- if (this.config.debugAdTiming) {
3152
- console.warn(
3153
- "[StormcloudVideoPlayer] Error in background preloading:",
3154
- error
3155
- );
3156
- }
3218
+ this.currentAdIndex++;
3219
+ this.successfulAdRequests.push(nextAdUrl);
3220
+ await this.playSingleAd(nextAdUrl).catch(() => {
3221
+ this.tryNextAvailableAd(0);
3157
3222
  });
3158
- await this.playAdPod();
3223
+ return;
3159
3224
  }
3160
3225
  }
3161
- if (this.expectedAdBreakDurationMs == null && (scheduled == null ? void 0 : scheduled.durationMs) != null) {
3162
- this.expectedAdBreakDurationMs = scheduled.durationMs;
3163
- this.currentAdBreakStartWallClockMs = (_a = this.currentAdBreakStartWallClockMs) != null ? _a : Date.now();
3164
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
3226
+ const maxRetries = 5;
3227
+ if (this.continuousFetchingActive && retryCount < maxRetries && remaining > 2e3) {
3228
+ if (this.config.debugAdTiming) {
3229
+ console.log(`[CONTINUOUS-FETCH] \u23F3 Queue empty but fetching active, waiting... (retry ${retryCount + 1}/${maxRetries})`);
3230
+ }
3231
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
3232
+ await this.tryNextAvailableAd(retryCount + 1);
3233
+ return;
3234
+ }
3235
+ if (!this.isShowingPlaceholder && remaining > 1e3) {
3236
+ this.showPlaceholderAndWaitForAds();
3237
+ } else {
3238
+ if (this.config.debugAdTiming) {
3239
+ console.log("[CONTINUOUS-FETCH] \u23F9\uFE0F No more ads available, ending ad break");
3240
+ }
3241
+ this.handleAdPodComplete();
3165
3242
  }
3166
3243
  }
3167
- async playAdPod() {
3168
- if (this.adPodQueue.length === 0) {
3244
+ async showPlaceholderAndWaitForAds() {
3245
+ const remaining = this.getRemainingAdMs();
3246
+ const waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);
3247
+ if (waitTime < 1e3) {
3248
+ this.handleAdPodComplete();
3169
3249
  return;
3170
3250
  }
3171
- const waitTime = this.isAdaptiveMode ? 50 : 500;
3172
- await new Promise((resolve) => setTimeout(resolve, waitTime));
3173
- const firstPreloaded = this.findNextPreloadedAd();
3174
- if (!firstPreloaded) {
3175
- const firstAd = this.adPodQueue.shift();
3176
- if (firstAd) {
3177
- this.currentAdIndex++;
3178
- try {
3179
- await this.playSingleAd(firstAd);
3180
- } catch (error) {
3181
- return;
3251
+ if (this.config.debugAdTiming) {
3252
+ console.log(`[CONTINUOUS-FETCH] \u2B1B Showing black placeholder for ${waitTime}ms while waiting for ads`);
3253
+ }
3254
+ this.isShowingPlaceholder = true;
3255
+ this.placeholderStartTimeMs = Date.now();
3256
+ this.ima.showPlaceholder();
3257
+ const checkInterval = 500;
3258
+ const maxChecks = Math.floor(waitTime / checkInterval);
3259
+ for (let i = 0; i < maxChecks; i++) {
3260
+ await new Promise((resolve) => setTimeout(resolve, checkInterval));
3261
+ if (!this.inAdBreak) {
3262
+ return;
3263
+ }
3264
+ if (this.adRequestQueue.length > 0) {
3265
+ if (this.config.debugAdTiming) {
3266
+ console.log("[CONTINUOUS-FETCH] \u2705 New ad became available during placeholder");
3267
+ }
3268
+ this.isShowingPlaceholder = false;
3269
+ this.placeholderStartTimeMs = null;
3270
+ this.ima.hidePlaceholder();
3271
+ const nextAdUrl = this.adRequestQueue.shift();
3272
+ if (nextAdUrl) {
3273
+ this.currentAdIndex++;
3274
+ await this.playSingleAd(nextAdUrl).catch(() => {
3275
+ this.tryNextAvailableAd();
3276
+ });
3182
3277
  }
3278
+ return;
3183
3279
  }
3184
- return;
3185
3280
  }
3186
- this.currentAdIndex++;
3187
- try {
3188
- await this.playSingleAd(firstPreloaded);
3189
- } catch (error) {
3281
+ if (this.config.debugAdTiming) {
3282
+ console.log("[CONTINUOUS-FETCH] \u23F0 Placeholder timeout reached, no ads fetched");
3190
3283
  }
3284
+ this.isShowingPlaceholder = false;
3285
+ this.placeholderStartTimeMs = null;
3286
+ this.ima.hidePlaceholder();
3287
+ this.handleAdPodComplete();
3191
3288
  }
3192
3289
  findCurrentOrNextBreak(nowMs) {
3193
3290
  var _a;
@@ -3347,10 +3444,18 @@ var StormcloudVideoPlayer = class {
3347
3444
  this.clearAdRequestWatchdog();
3348
3445
  this.clearAdFailsafeTimer();
3349
3446
  this.activeAdRequestToken = null;
3447
+ this.stopContinuousFetching();
3448
+ if (this.isShowingPlaceholder) {
3449
+ this.ima.hidePlaceholder();
3450
+ this.isShowingPlaceholder = false;
3451
+ this.placeholderStartTimeMs = null;
3452
+ }
3350
3453
  this.preloadingAdUrls.clear();
3351
3454
  this.vastToMediaUrlMap.clear();
3352
3455
  this.preloadedMediaUrls.clear();
3353
3456
  this.preloadingMediaUrls.clear();
3457
+ this.adRequestQueue = [];
3458
+ this.successfulAdRequests = [];
3354
3459
  this.inAdBreak = false;
3355
3460
  this.expectedAdBreakDurationMs = void 0;
3356
3461
  this.currentAdBreakStartWallClockMs = void 0;
@@ -3377,61 +3482,14 @@ var StormcloudVideoPlayer = class {
3377
3482
  }
3378
3483
  }
3379
3484
  handleAdFailure() {
3380
- const remaining = this.getRemainingAdMs();
3381
- const availableAds = this.adPodQueue.filter((url) => !this.failedVastUrls.has(url)).length;
3382
- if (remaining > 500 && availableAds > 0) {
3383
- if (this.isAdaptiveMode && this.currentAdIndex <= 1) {
3384
- console.log("[ADAPTIVE-POD] \u23F3 First ad failed, waiting for sequential preload to catch up...");
3385
- setTimeout(() => {
3386
- this.tryNextAdWithRetry(0);
3387
- }, 1500);
3388
- return;
3389
- }
3390
- const nextPreloaded = this.findNextPreloadedAd();
3391
- if (nextPreloaded) {
3392
- this.currentAdIndex++;
3393
- this.playSingleAd(nextPreloaded).catch(() => {
3394
- this.handleAdPodComplete();
3395
- });
3396
- return;
3397
- }
3398
- }
3399
- console.error("[AD-ERROR] All ads failed or time expired. Failed URLs:", this.failedVastUrls.size);
3400
- this.handleAdPodComplete();
3401
- }
3402
- tryNextAdWithRetry(retryCount) {
3403
- const maxRetries = 3;
3404
3485
  const remaining = this.getRemainingAdMs();
3405
3486
  if (this.config.debugAdTiming) {
3406
- console.log(
3407
- `[ADAPTIVE-POD] \u{1F50D} Retry attempt ${retryCount}: remaining=${remaining}ms, queue=${this.adPodQueue.length}, totalAds=${this.totalAdsInBreak}`
3408
- );
3409
- }
3410
- if (remaining <= 500 || this.adPodQueue.length === 0) {
3411
- console.log("[ADAPTIVE-POD] \u23F9\uFE0F No more time or ads available");
3412
- this.handleAdPodComplete();
3413
- return;
3487
+ console.log(`[CONTINUOUS-FETCH] Ad failure: remaining=${remaining}ms, queued ads=${this.adRequestQueue.length}`);
3414
3488
  }
3415
- const nextPreloaded = this.findNextPreloadedAd();
3416
- if (nextPreloaded) {
3417
- this.currentAdIndex++;
3418
- console.log(
3419
- `[ADAPTIVE-POD] \u2705 Found preloaded ad after retry ${retryCount}, playing (${this.currentAdIndex}/${this.totalAdsInBreak})`
3420
- );
3421
- this.playSingleAd(nextPreloaded).catch(() => {
3422
- this.handleAdPodComplete();
3423
- });
3424
- } else if (retryCount < maxRetries) {
3425
- console.log(
3426
- `[ADAPTIVE-POD] \u23F3 No preloaded ads yet (queue has ${this.adPodQueue.length} URLs), retry ${retryCount + 1}/${maxRetries} in 1s...`
3427
- );
3428
- setTimeout(() => {
3429
- this.tryNextAdWithRetry(retryCount + 1);
3430
- }, 1e3);
3489
+ if (remaining > 500) {
3490
+ this.tryNextAvailableAd();
3431
3491
  } else {
3432
- console.log(
3433
- `[ADAPTIVE-POD] \u274C Max retries reached, no preloaded ads available (queue=${this.adPodQueue.length} URLs)`
3434
- );
3492
+ console.error("[AD-ERROR] Ad failed and no time remaining. Failed URLs:", this.failedVastUrls.size);
3435
3493
  this.handleAdPodComplete();
3436
3494
  }
3437
3495
  }
@@ -4029,6 +4087,7 @@ var StormcloudVideoPlayer = class {
4029
4087
  }
4030
4088
  destroy() {
4031
4089
  var _a, _b;
4090
+ this.stopContinuousFetching();
4032
4091
  this.clearAdStartTimer();
4033
4092
  this.clearAdStopTimer();
4034
4093
  this.clearAdFailsafeTimer();
@@ -4043,6 +4102,8 @@ var StormcloudVideoPlayer = class {
4043
4102
  this.preloadedMediaUrls.clear();
4044
4103
  this.preloadingMediaUrls.clear();
4045
4104
  this.adPodAllUrls = [];
4105
+ this.adRequestQueue = [];
4106
+ this.successfulAdRequests = [];
4046
4107
  }
4047
4108
  };
4048
4109