stormcloud-video-player 0.5.12 → 0.5.13

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.
@@ -28,13 +28,11 @@ declare class StormcloudVideoPlayer {
28
28
  private bufferedSegmentsCount;
29
29
  private shouldAutoplayAfterBuffering;
30
30
  private hasInitialBufferCompleted;
31
- private adRequestTokenCounter;
32
31
  private activeAdRequestToken;
33
32
  private adRequestWatchdogId;
34
33
  private adRequestWatchdogToken;
35
34
  private adFailsafeToken;
36
35
  private continuousFetchingActive;
37
- private adRequestQueue;
38
36
  private maxPlaceholderDurationMs;
39
37
  private isShowingPlaceholder;
40
38
  private timeUpdateHandler?;
@@ -43,7 +41,6 @@ declare class StormcloudVideoPlayer {
43
41
  private readonly maxTotalAdRequestsPerBreak;
44
42
  private pendingAdBreak;
45
43
  private prefetchTimerId;
46
- private prefetchAdPromise;
47
44
  private savedMutedStateBeforeScte;
48
45
  private consecutiveFailures;
49
46
  private readonly maxConsecutiveFailures;
@@ -51,6 +48,7 @@ declare class StormcloudVideoPlayer {
51
48
  private readonly minAdRequestIntervalMs;
52
49
  private readonly backoffBaseMs;
53
50
  private readonly maxBackoffMs;
51
+ private readonly adTransitionGapMs;
54
52
  private placeholderContainer;
55
53
  constructor(config: StormcloudVideoPlayerConfig);
56
54
  private adRequest;
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/players/FilePlayer.cjs"],"names":[],"mappings":"AAAA","sourcesContent":["\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/players/FilePlayer.tsx\nvar FilePlayer_exports = {};\n__export(FilePlayer_exports, {\n default: () => FilePlayer\n});\nmodule.exports = __toCommonJS(FilePlayer_exports);\nvar import_react = require(\"react\");\n\n// src/patterns.ts\nvar HLS_EXTENSIONS = /\\.(m3u8)($|\\?)/i;\nvar HLS_PATHS = /\\/hls\\//i;\nvar DASH_EXTENSIONS = /\\.(mpd)($|\\?)/i;\nvar VIDEO_EXTENSIONS = /\\.(mp4|webm|ogg|avi|mov|wmv|flv|mkv)($|\\?)/i;\nvar AUDIO_EXTENSIONS = /\\.(mp3|wav|ogg|aac|wma|flac|m4a)($|\\?)/i;\nvar canPlay = {\n hls: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return HLS_EXTENSIONS.test(url) || HLS_PATHS.test(url);\n },\n dash: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return DASH_EXTENSIONS.test(url);\n },\n video: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url);\n },\n audio: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return AUDIO_EXTENSIONS.test(url);\n },\n file: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url);\n }\n};\n\n// src/players/FilePlayer.tsx\nvar FilePlayer = class extends import_react.Component {\n constructor() {\n super(...arguments);\n this.mounted = false;\n this.ready = false;\n this.load = () => {\n if (!this.props.videoElement || !this.props.src) return;\n const video = this.props.videoElement;\n const handleLoadedMetadata = () => {\n if (this.mounted && !this.ready) {\n this.ready = true;\n this.props.onReady?.();\n }\n };\n const handlePlay = () => {\n if (this.mounted) {\n this.props.onPlay?.();\n }\n };\n const handlePause = () => {\n if (this.mounted) {\n this.props.onPause?.();\n }\n };\n const handleEnded = () => {\n if (this.mounted) {\n this.props.onEnded?.();\n }\n };\n const handleError = (error) => {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n };\n const handleLoadedData = () => {\n if (this.mounted) {\n this.props.onLoaded?.();\n }\n };\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"play\", handlePlay);\n video.addEventListener(\"pause\", handlePause);\n video.addEventListener(\"ended\", handleEnded);\n video.addEventListener(\"error\", handleError);\n video.addEventListener(\"loadeddata\", handleLoadedData);\n video.src = this.props.src;\n if (this.props.autoplay !== void 0) video.autoplay = this.props.autoplay;\n if (this.props.muted !== void 0) video.muted = this.props.muted;\n if (this.props.loop !== void 0) video.loop = this.props.loop;\n if (this.props.controls !== void 0) video.controls = this.props.controls;\n if (this.props.playsInline !== void 0)\n video.playsInline = this.props.playsInline;\n if (this.props.preload !== void 0)\n video.preload = this.props.preload;\n if (this.props.poster !== void 0) video.poster = this.props.poster;\n this.props.onMount?.(this);\n return () => {\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"play\", handlePlay);\n video.removeEventListener(\"pause\", handlePause);\n video.removeEventListener(\"ended\", handleEnded);\n video.removeEventListener(\"error\", handleError);\n video.removeEventListener(\"loadeddata\", handleLoadedData);\n };\n };\n this.play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource = video.src || video.currentSrc && video.currentSrc !== \"\" || video.readyState >= 1;\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[FilePlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n } else {\n console.warn(\"[FilePlayer] Cannot play: video has no valid source\");\n }\n }\n };\n this.pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n }\n };\n this.stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n this.seekTo = (seconds, keepPlaying) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n this.setVolume = (volume) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n this.mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n this.unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n this.setPlaybackRate = (rate) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n this.setLoop = (loop) => {\n if (this.props.videoElement) {\n this.props.videoElement.loop = loop;\n }\n };\n this.getDuration = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n this.getCurrentTime = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.currentTime)) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n this.getSecondsLoaded = () => {\n if (this.props.videoElement && this.props.videoElement.buffered.length > 0) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n this.getInternalPlayer = (key = \"player\") => {\n if (key === \"video\") return this.props.videoElement;\n return null;\n };\n this.enablePIP = async () => {\n if (this.props.videoElement && \"requestPictureInPicture\" in this.props.videoElement) {\n try {\n await this.props.videoElement.requestPictureInPicture();\n } catch (error) {\n console.warn(\"Picture-in-Picture failed:\", error);\n }\n }\n };\n this.disablePIP = async () => {\n if (document.pictureInPictureElement) {\n try {\n await document.exitPictureInPicture();\n } catch (error) {\n console.warn(\"Exit Picture-in-Picture failed:\", error);\n }\n }\n };\n }\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n componentWillUnmount() {\n this.mounted = false;\n }\n componentDidUpdate(prevProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n render() {\n return null;\n }\n};\nFilePlayer.displayName = \"FilePlayer\";\nFilePlayer.canPlay = canPlay.file;\n"]}
1
+ {"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/players/FilePlayer.cjs"],"names":["__defProp","Object","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__hasOwnProp","prototype","hasOwnProperty","name","all","target","enumerable","__copyProps","to","from","except","desc","key","call"],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YACIA,OAAAA,GAAYC,OAAOC,cAAc;QACjCC,mBAAmBF,OAAOG,wBAAwB;QAClDC,MAAAA,SAAAA,GAAAA,GAAoBJ,OAAOK,mBAAmB;;;;;;iCAC9CC,CAAAA,OAAAA,IAAeN,CAAAA,CAAAA,KAAOO,OAAAA,EAAS,CAACC,CAAAA,aAAc,gBAAA,OAAA,KAAA,CAAA,YAAA,GAA9CF;;;;;;;;;;;;4BAEG;;gCAAIG,IAAQC,GAAAA,GACfX,EAAAA,CAAAA,OAAUY,KAAAA,CAAAA,EAAQF,MAAM,eAAA;;;4BADrB,EAAIA;;;;;;4BAC4BA,KAAK;4BAAEG,QAAAA,EAAY,EAAA,CAAA,8BAAA;;;;;;;;;;;YAEtDC,cAAc,qBAACC,IAAIC,MAAMC,QAAQC;;QACnC,IAAIF,EAAAA,OAAQ,CAAA,EAAA,GAAA,EAAOA,qCAAP,SAAOA,KAAG,MAAM,YAAY,OAAOA,SAAS,YAAY;;oBAC7D;;;;0CAAA,uBAAA,IAAA,2BAAA;;;;;;;;;;;;;;;;;;;;;;;4BAAA,GAAIG,MAAJ;kCACH,EAAA,EAAI,CAACZ,CAAAA,CAAAA,WAAaa,IAAI,CAACL,IAAII,QAAQA,OAAAA,CAAQF,QACzCjB,UAAUe,IAAII,KAAK;;;;;;;;;;;;;;;;;;0CAA6F;;wBAFpH,CAAA,OAAK,YAAWd,kBAAkBW,0BAA7B,SAAA,6BAAA,QAAA,yBAAA;;;;;sCAAA;wBAAA,IAAA,GAAA;;;;;;iCAAA,KAAA,IAAA,CAAA,KAAA,CAAA,GAAA,EAAA,QAAA;kCAAA;;;;;mCAAA;;sCAAA;;;;;;;IAGP,OAAA,OAAA,GAAA,QAAA,IAAA","sourcesContent":["\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/players/FilePlayer.tsx\nvar FilePlayer_exports = {};\n__export(FilePlayer_exports, {\n default: () => FilePlayer\n});\nmodule.exports = __toCommonJS(FilePlayer_exports);\nvar import_react = require(\"react\");\n\n// src/patterns.ts\nvar HLS_EXTENSIONS = /\\.(m3u8)($|\\?)/i;\nvar HLS_PATHS = /\\/hls\\//i;\nvar DASH_EXTENSIONS = /\\.(mpd)($|\\?)/i;\nvar VIDEO_EXTENSIONS = /\\.(mp4|webm|ogg|avi|mov|wmv|flv|mkv)($|\\?)/i;\nvar AUDIO_EXTENSIONS = /\\.(mp3|wav|ogg|aac|wma|flac|m4a)($|\\?)/i;\nvar canPlay = {\n hls: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return HLS_EXTENSIONS.test(url) || HLS_PATHS.test(url);\n },\n dash: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return DASH_EXTENSIONS.test(url);\n },\n video: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url);\n },\n audio: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return AUDIO_EXTENSIONS.test(url);\n },\n file: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url);\n }\n};\n\n// src/players/FilePlayer.tsx\nvar FilePlayer = class extends import_react.Component {\n constructor() {\n super(...arguments);\n this.mounted = false;\n this.ready = false;\n this.load = () => {\n if (!this.props.videoElement || !this.props.src) return;\n const video = this.props.videoElement;\n const handleLoadedMetadata = () => {\n if (this.mounted && !this.ready) {\n this.ready = true;\n this.props.onReady?.();\n }\n };\n const handlePlay = () => {\n if (this.mounted) {\n this.props.onPlay?.();\n }\n };\n const handlePause = () => {\n if (this.mounted) {\n this.props.onPause?.();\n }\n };\n const handleEnded = () => {\n if (this.mounted) {\n this.props.onEnded?.();\n }\n };\n const handleError = (error) => {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n };\n const handleLoadedData = () => {\n if (this.mounted) {\n this.props.onLoaded?.();\n }\n };\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"play\", handlePlay);\n video.addEventListener(\"pause\", handlePause);\n video.addEventListener(\"ended\", handleEnded);\n video.addEventListener(\"error\", handleError);\n video.addEventListener(\"loadeddata\", handleLoadedData);\n video.src = this.props.src;\n if (this.props.autoplay !== void 0) video.autoplay = this.props.autoplay;\n if (this.props.muted !== void 0) video.muted = this.props.muted;\n if (this.props.loop !== void 0) video.loop = this.props.loop;\n if (this.props.controls !== void 0) video.controls = this.props.controls;\n if (this.props.playsInline !== void 0)\n video.playsInline = this.props.playsInline;\n if (this.props.preload !== void 0)\n video.preload = this.props.preload;\n if (this.props.poster !== void 0) video.poster = this.props.poster;\n this.props.onMount?.(this);\n return () => {\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"play\", handlePlay);\n video.removeEventListener(\"pause\", handlePause);\n video.removeEventListener(\"ended\", handleEnded);\n video.removeEventListener(\"error\", handleError);\n video.removeEventListener(\"loadeddata\", handleLoadedData);\n };\n };\n this.play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource = video.src || video.currentSrc && video.currentSrc !== \"\" || video.readyState >= 1;\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[FilePlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n } else {\n console.warn(\"[FilePlayer] Cannot play: video has no valid source\");\n }\n }\n };\n this.pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n }\n };\n this.stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n this.seekTo = (seconds, keepPlaying) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n this.setVolume = (volume) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n this.mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n this.unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n this.setPlaybackRate = (rate) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n this.setLoop = (loop) => {\n if (this.props.videoElement) {\n this.props.videoElement.loop = loop;\n }\n };\n this.getDuration = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n this.getCurrentTime = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.currentTime)) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n this.getSecondsLoaded = () => {\n if (this.props.videoElement && this.props.videoElement.buffered.length > 0) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n this.getInternalPlayer = (key = \"player\") => {\n if (key === \"video\") return this.props.videoElement;\n return null;\n };\n this.enablePIP = async () => {\n if (this.props.videoElement && \"requestPictureInPicture\" in this.props.videoElement) {\n try {\n await this.props.videoElement.requestPictureInPicture();\n } catch (error) {\n console.warn(\"Picture-in-Picture failed:\", error);\n }\n }\n };\n this.disablePIP = async () => {\n if (document.pictureInPictureElement) {\n try {\n await document.exitPictureInPicture();\n } catch (error) {\n console.warn(\"Exit Picture-in-Picture failed:\", error);\n }\n }\n };\n }\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n componentWillUnmount() {\n this.mounted = false;\n }\n componentDidUpdate(prevProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n render() {\n return null;\n }\n};\nFilePlayer.displayName = \"FilePlayer\";\nFilePlayer.canPlay = canPlay.file;\n"]}
@@ -2565,18 +2565,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2565
2565
  this.bufferedSegmentsCount = 0;
2566
2566
  this.shouldAutoplayAfterBuffering = false;
2567
2567
  this.hasInitialBufferCompleted = false;
2568
- this.adRequestTokenCounter = 0;
2569
2568
  this.activeAdRequestToken = null;
2570
2569
  this.adRequestWatchdogToken = null;
2571
2570
  this.adFailsafeToken = null;
2572
2571
  this.continuousFetchingActive = false;
2573
- this.adRequestQueue = [];
2574
2572
  this.maxPlaceholderDurationMs = 5e3;
2575
2573
  this.isShowingPlaceholder = false;
2576
2574
  this.totalAdRequestsInBreak = 0;
2577
2575
  this.maxTotalAdRequestsPerBreak = 20;
2578
2576
  this.pendingAdBreak = null;
2579
- this.prefetchAdPromise = null;
2580
2577
  this.savedMutedStateBeforeScte = null;
2581
2578
  this.consecutiveFailures = 0;
2582
2579
  this.maxConsecutiveFailures = 5;
@@ -2584,6 +2581,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2584
2581
  this.minAdRequestIntervalMs = 2500;
2585
2582
  this.backoffBaseMs = 1e3;
2586
2583
  this.maxBackoffMs = 15e3;
2584
+ this.adTransitionGapMs = 1500;
2587
2585
  initializePolyfills();
2588
2586
  var browserOverrides = getBrowserConfigOverrides();
2589
2587
  this.config = _object_spread({}, browserOverrides, config);
@@ -3110,7 +3108,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3110
3108
  if (_this.config.debugAdTiming) console.warn("[StormcloudVideoPlayer] playAd(pending) failed:", err);
3111
3109
  _this.handleAdFailure();
3112
3110
  });
3113
- }, 500);
3111
+ }, _this.adTransitionGapMs);
3114
3112
  return;
3115
3113
  }
3116
3114
  if (remaining <= 500 && _this.expectedAdBreakDurationMs != null) {
@@ -3890,7 +3888,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3890
3888
  isFetching: false,
3891
3889
  fetchStartTime: Date.now()
3892
3890
  });
3893
- this.prefetchAdPromise = this.adRequest().then(function() {}).catch(function() {
3891
+ void this.adRequest().then(function() {}).catch(function() {
3894
3892
  if (_this.config.debugAdTiming) {
3895
3893
  console.log("[PREFETCH] Prebid auction prefetch failed, will request at playback time");
3896
3894
  }
@@ -3907,7 +3905,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3907
3905
  clearTimeout(this.prefetchTimerId);
3908
3906
  this.prefetchTimerId = void 0;
3909
3907
  }
3910
- this.prefetchAdPromise = null;
3911
3908
  this.pendingAdBreak = null;
3912
3909
  }
3913
3910
  },
@@ -3935,6 +3932,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3935
3932
  2,
3936
3933
  "break"
3937
3934
  ];
3935
+ if (_this.totalAdRequestsInBreak >= _this.maxTotalAdRequestsPerBreak) return [
3936
+ 2,
3937
+ "break"
3938
+ ];
3938
3939
  delay = _this.lastAdRequestTime ? _this.minAdRequestIntervalMs + (_this.consecutiveFailures > 0 ? backoffMs() : 0) : 0;
3939
3940
  elapsed = Date.now() - _this.lastAdRequestTime;
3940
3941
  if (!(elapsed < delay && _this.lastAdRequestTime > 0)) return [
@@ -4128,14 +4129,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4128
4129
  this.expectedAdBreakDurationMs = adBreakDurationMs;
4129
4130
  }
4130
4131
  this.clearPendingAdBreak();
4131
- this.startContinuousFetchLoop();
4132
4132
  _state.label = 1;
4133
4133
  case 1:
4134
4134
  _state.trys.push([
4135
4135
  1,
4136
- 6,
4136
+ 7,
4137
4137
  ,
4138
- 7
4138
+ 9
4139
4139
  ]);
4140
4140
  this.lastAdRequestTime = Date.now();
4141
4141
  return [
@@ -4175,27 +4175,40 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4175
4175
  this.adLayer.setAdVolume(adVolume);
4176
4176
  return [
4177
4177
  3,
4178
- 5
4178
+ 6
4179
4179
  ];
4180
4180
  case 4:
4181
4181
  this.consecutiveFailures++;
4182
- _state.label = 5;
4182
+ return [
4183
+ 4,
4184
+ this.showPlaceholderAndWaitForAds()
4185
+ ];
4183
4186
  case 5:
4187
+ _state.sent();
4188
+ _state.label = 6;
4189
+ case 6:
4184
4190
  return [
4185
4191
  3,
4186
- 7
4192
+ 9
4187
4193
  ];
4188
- case 6:
4194
+ case 7:
4189
4195
  error = _state.sent();
4190
4196
  if (this.config.debugAdTiming) {
4191
4197
  console.warn("[CONTINUOUS-FETCH] \u26A0\uFE0F First ad request failed:", error);
4192
4198
  }
4193
4199
  this.consecutiveFailures++;
4200
+ return [
4201
+ 4,
4202
+ this.showPlaceholderAndWaitForAds()
4203
+ ];
4204
+ case 8:
4205
+ _state.sent();
4194
4206
  return [
4195
4207
  3,
4196
- 7
4208
+ 9
4197
4209
  ];
4198
- case 7:
4210
+ case 9:
4211
+ this.startContinuousFetchLoop();
4199
4212
  return [
4200
4213
  2
4201
4214
  ];
@@ -4271,6 +4284,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4271
4284
  return _ts_generator(this, function(_state) {
4272
4285
  switch(_state.label){
4273
4286
  case 0:
4287
+ if (this.totalAdRequestsInBreak >= this.maxTotalAdRequestsPerBreak) {
4288
+ if (this.config.debugAdTiming) {
4289
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Max ad requests per break (".concat(this.maxTotalAdRequestsPerBreak, ") reached"));
4290
+ }
4291
+ this.handleAdPodComplete();
4292
+ return [
4293
+ 2
4294
+ ];
4295
+ }
4274
4296
  remaining = this.getRemainingAdMs();
4275
4297
  if (remaining <= 500 && this.expectedAdBreakDurationMs != null) {
4276
4298
  if (this.config.debugAdTiming) {
@@ -4294,9 +4316,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4294
4316
  case 1:
4295
4317
  _state.trys.push([
4296
4318
  1,
4297
- 8,
4319
+ 9,
4298
4320
  ,
4299
- 9
4321
+ 11
4300
4322
  ]);
4301
4323
  this.lastAdRequestTime = Date.now();
4302
4324
  return [
@@ -4345,27 +4367,39 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4345
4367
  case 5:
4346
4368
  return [
4347
4369
  3,
4348
- 7
4370
+ 8
4349
4371
  ];
4350
4372
  case 6:
4351
4373
  this.consecutiveFailures++;
4352
- _state.label = 7;
4374
+ return [
4375
+ 4,
4376
+ this.showPlaceholderAndWaitForAds()
4377
+ ];
4353
4378
  case 7:
4379
+ _state.sent();
4380
+ _state.label = 8;
4381
+ case 8:
4354
4382
  return [
4355
4383
  3,
4356
- 9
4384
+ 11
4357
4385
  ];
4358
- case 8:
4386
+ case 9:
4359
4387
  error = _state.sent();
4360
4388
  this.consecutiveFailures++;
4361
4389
  if (this.config.debugAdTiming) {
4362
4390
  console.warn("[CONTINUOUS-FETCH] tryNextAvailableAd request failed:", error);
4363
4391
  }
4392
+ return [
4393
+ 4,
4394
+ this.showPlaceholderAndWaitForAds()
4395
+ ];
4396
+ case 10:
4397
+ _state.sent();
4364
4398
  return [
4365
4399
  3,
4366
- 9
4400
+ 11
4367
4401
  ];
4368
- case 9:
4402
+ case 11:
4369
4403
  return [
4370
4404
  2
4371
4405
  ];
@@ -4441,7 +4475,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4441
4475
  this.pendingNextAdBids = null;
4442
4476
  this.isShowingPlaceholder = false;
4443
4477
  this.adLayer.hidePlaceholder();
4444
- this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);
4445
4478
  this.currentAdIndex++;
4446
4479
  _state.label = 3;
4447
4480
  case 3:
@@ -4995,7 +5028,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4995
5028
  }
4996
5029
  (_this_hls = this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.destroy();
4997
5030
  (_this_adLayer = this.adLayer) === null || _this_adLayer === void 0 ? void 0 : _this_adLayer.destroy();
4998
- this.adRequestQueue = [];
4999
5031
  this.consecutiveFailures = 0;
5000
5032
  }
5001
5033
  }