stormcloud-video-player 0.4.0 → 0.4.1

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/ubuntu24/Dev/stormcloud-vp/lib/players/HlsPlayer.cjs","../../src/sdk/adstormPlayer.ts","../../src/players/HlsPlayer.tsx","../../src/player/StormcloudVideoPlayer.ts","../../src/utils/polyfills.ts","../../src/utils/browserCompat.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","isNodeMode","__toESM","mod","__esModule","value","__toCommonJS","SUPPORTED_VIDEO_EXTENSIONS","HlsPlayer_exports","default","HlsPlayer","exports","import_react","require","import_hls","UNSUPPORTED_VIDEO_EXTENSIONS","getFileExtension","url","pathname","URL","lastDot","lastIndexOf","slice","toLowerCase","ext","split","isUnsupportedFormat","indexOf","replaceFlvExtension","replace","isSupportedFormat","mimeType","includes","createAdStormPlayer","contentVideo","options","licenseKey","debug","adPlaying","originalMutedState","originalVolume","Math","max","min","volume","listeners","Map","adVideoElement","adContainerEl","currentAd","destroyed","trackingFired","impression","start","firstQuartile","midpoint","thirdQuartile","complete","log","args","console","emit","event","payload","set","Array","fn","error","warn","fireTrackingPixels","urls","length","forEach","img","Image","src","buildVastUrl","durationSeconds","metadata","baseUrl","defaultMetadata","video","codec","width","videoWidth","height","videoHeight","fps","bitrate","profile","pix_fmt","has_b_frames","audio","sample_rate","finalMetadata","metadataStr","encodeURIComponent","JSON","stringify","ceil","parseVastXml","xmlString","ads","parser","DOMParser","xmlDoc","parseFromString","parserError","querySelector","textContent","adElements","querySelectorAll","adElement","adId","getAttribute","title","durationText","durationParts","duration","parseInt","parseFloat","mediaFileElements","mediaFiles","mf","type","trim","originalUrl","push","trackingUrls","el","eventKey","clickThrough","id","selectBestMediaFile","mp4Files","filter","candidates","targetWidth","targetHeight","sort","a","b","diffA","abs","diffB","createAdVideoElement","document","createElement","style","position","left","top","objectFit","backgroundColor","zIndex","playsInline","muted","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","setupAdEventListeners","ad","addEventListener","progress","currentTime","handleAdComplete","e","handleAdError","opacity","setTimeout","display","pointerEvents","visibility","fetchVast","vastUrl","response","xmlText","fetch","headers","ok","Error","status","statusText","text","initialize","container","right","bottom","alignItems","justifyContent","transition","parentElement","appendChild","requestAds","parsed","Promise","reject","isNaN","resolve","play","mediaFile","pause","offsetHeight","destroy","remove","removeChild","clear","isAdPlaying","resize","on","listener","has","Set","add","delete","nextVolume","getAdVolume","updateOriginalMutedState","Number","getOriginalMutedState","getOriginalVolume","setAdVolume","hidePlaceholder","polyfillURLSearchParams","URLSearchParams","URLSearchParamsPolyfill","init","params","parseQueryString","append","query","cleanQuery","startsWith","param","decodedKey","safeDecodeURIComponent","decodedValue","str","decodeURIComponent","values","String","getAll","callback","toString","parts","join","window","polyfillTextEncoder","TextEncoder","TextEncoderPolyfill","encoding","encode","i","charcode","charCodeAt","utf8","Uint8Array","polyfillPromiseFinally","finally","constructor","then","reason","polyfillObjectAssign","assign","sources","TypeError","nextSource","nextKey","polyfillArrayFrom","arrayLike","mapFn","thisArg","len","items","result","search","pos","substring","polyfillStringEndsWith","endsWith","polyfillStringIncludes","initializePolyfills","polyfillStringStartsWith","getChromeVersion","ua","match","getWebKitVersion","getPlatform","navigator","userAgentData","platform","userAgent","test","detectBrowser","version","majorVersion","isSmartTV","isLegacyTV","supportsModernJS","chromeVersion","webkitVersion","logBrowserInfo","browser","getBrowserConfigOverrides","overrides","allowNativeHls","StormcloudVideoPlayer","config","attached","inAdBreak","ptsDriftEmaMs","isLiveStream","nativeHlsMode","videoSrcProtection","bufferedSegmentsCount","shouldAutoplayAfterBuffering","hasInitialBufferCompleted","browserOverrides","videoElement","debugAdTiming","adPlayer","load","attach","shouldUseNativeHls","lowLatencyMode","isLive","autoplay","catch","hls","Hls","enableWorker","backBufferLength","liveDurationInfinity","maxLiveSyncPlaybackRate","maxBufferLength","maxMaxBufferLength","maxBufferSize","maxBufferHole","nudgeOffset","nudgeMaxRetry","startPosition","Events","MEDIA_ATTACHED","loadSource","MANIFEST_PARSED","minSegments","levels","some","level","details","live","minSegmentsBeforePlay","FRAG_BUFFERED","err","FRAG_PARSING_METADATA","_evt","data","id3Tags","samples","map","s","ptsSeconds","pts","tag","onId3Tag","FRAG_CHANGED","frag","tagList","entry","isArray","idx","parseCueOutDuration","onScte35Marker"],"mappings":"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","sourcesContent":["\"use strict\";\nvar __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/players/HlsPlayer.tsx\nvar HlsPlayer_exports = {};\n__export(HlsPlayer_exports, {\n default: () => HlsPlayer\n});\nmodule.exports = __toCommonJS(HlsPlayer_exports);\nvar import_react = require(\"react\");\n\n// src/player/StormcloudVideoPlayer.ts\nvar import_hls = __toESM(require(\"hls.js\"), 1);\n\n// src/sdk/adstormPlayer.ts\nvar SUPPORTED_VIDEO_EXTENSIONS = [\".mp4\", \".webm\", \".ogg\", \".m3u8\", \".ts\"];\nvar UNSUPPORTED_VIDEO_EXTENSIONS = [\".flv\", \".f4v\", \".swf\", \".wmv\", \".avi\", \".mov\", \".mkv\"];\nfunction getFileExtension(url) {\n try {\n const pathname = new URL(url, \"http://dummy\").pathname;\n const lastDot = pathname.lastIndexOf(\".\");\n if (lastDot === -1) return \"\";\n return pathname.slice(lastDot).toLowerCase();\n } catch {\n const lastDot = url.lastIndexOf(\".\");\n if (lastDot === -1) return \"\";\n const ext = url.slice(lastDot).split(/[?#]/)[0];\n return (ext || \"\").toLowerCase();\n }\n}\nfunction isUnsupportedFormat(url) {\n const ext = getFileExtension(url);\n return UNSUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1;\n}\nfunction replaceFlvExtension(url) {\n const ext = getFileExtension(url);\n if (ext === \".flv\") {\n return url.replace(/\\.flv(\\?|$)/i, \".mp4$1\");\n }\n return url;\n}\nfunction isSupportedFormat(url, mimeType) {\n if (isUnsupportedFormat(url)) {\n return false;\n }\n const ext = getFileExtension(url);\n if (SUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1) {\n return true;\n }\n if (ext === \"\" || ext === \".\") {\n return mimeType.includes(\"video/mp4\") || mimeType.includes(\"video/webm\") || mimeType.includes(\"m3u8\") || mimeType.includes(\"application/x-mpegurl\");\n }\n return false;\n}\nfunction createAdStormPlayer(contentVideo, options) {\n const { licenseKey, debug = false } = options;\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = /* @__PURE__ */ new Map();\n let adVideoElement;\n let adContainerEl;\n let currentAd;\n let destroyed = false;\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n function log(...args) {\n if (debug) {\n console.log(\"[AdStormPlayer]\", ...args);\n }\n }\n function emit(event, payload) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(`[AdStormPlayer] Error in event listener for ${event}:`, error);\n }\n }\n }\n function fireTrackingPixels(urls) {\n if (!urls || urls.length === 0) return;\n urls.forEach((url) => {\n try {\n const img = new Image(1, 1);\n img.src = url;\n log(\"Fired tracking pixel:\", url);\n } catch (error) {\n console.warn(\"[AdStormPlayer] Error firing tracking pixel:\", error);\n }\n });\n }\n function buildVastUrl(durationSeconds, metadata) {\n const baseUrl = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${licenseKey}/pod`;\n const defaultMetadata = {\n video: {\n codec: \"h264\",\n width: contentVideo.videoWidth || 1280,\n height: contentVideo.videoHeight || 720,\n fps: 29.97,\n bitrate: 5e3,\n profile: \"high\",\n pix_fmt: \"yuv420p\",\n has_b_frames: 0\n },\n audio: {\n codec: \"aac\",\n sample_rate: 48e3,\n bitrate: 128\n }\n };\n const finalMetadata = metadata || defaultMetadata;\n const metadataStr = encodeURIComponent(JSON.stringify(finalMetadata));\n return `${baseUrl}?duration=${Math.ceil(durationSeconds)}&metadata=${metadataStr}`;\n }\n function parseVastXml(xmlString) {\n const ads = [];\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\"[AdStormPlayer] XML parsing error:\", parserError.textContent);\n return [];\n }\n const adElements = xmlDoc.querySelectorAll(\"Ad\");\n adElements.forEach((adElement) => {\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = adElement.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n const durationText = adElement.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + parseFloat(durationParts[2] || \"0\");\n const mediaFileElements = adElement.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n mediaFileElements.forEach((mf) => {\n const type = mf.getAttribute(\"type\") || \"\";\n let url = mf.textContent?.trim() || \"\";\n const width = parseInt(mf.getAttribute(\"width\") || \"1920\", 10);\n const height = parseInt(mf.getAttribute(\"height\") || \"1080\", 10);\n const bitrate = mf.getAttribute(\"bitrate\") ? parseInt(mf.getAttribute(\"bitrate\"), 10) : void 0;\n if (!url) {\n log(`Skipping empty MediaFile URL`);\n return;\n }\n const originalUrl = url;\n url = replaceFlvExtension(url);\n if (url !== originalUrl) {\n log(`Converted FLV to MP4: ${originalUrl} -> ${url}`);\n }\n if (isUnsupportedFormat(url)) {\n const ext = getFileExtension(url);\n log(`Skipping unsupported format: ${url} (extension: ${ext}, declared type: ${type})`);\n return;\n }\n if (isSupportedFormat(url, type)) {\n mediaFiles.push({ url, type, width, height, bitrate });\n log(`Found media file: ${url} (${type}, ${width}x${height})`);\n } else {\n log(`Skipping incompatible media file: ${url} (type: ${type})`);\n }\n });\n if (mediaFiles.length === 0) {\n log(\"No valid media files found in ad:\", adId);\n return;\n }\n const trackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n error: []\n };\n adElement.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n adElement.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n const clickThrough = adElement.querySelector(\"ClickThrough\")?.textContent?.trim();\n ads.push({\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough\n });\n log(`Parsed ad: ${title}, duration: ${duration}s, media files: ${mediaFiles.length}`);\n });\n } catch (error) {\n console.error(\"[AdStormPlayer] Error parsing VAST XML:\", error);\n }\n return ads;\n }\n function selectBestMediaFile(mediaFiles) {\n if (mediaFiles.length === 0) return null;\n if (mediaFiles.length === 1) return mediaFiles[0];\n const mp4Files = mediaFiles.filter((mf) => mf.type.includes(\"video/mp4\"));\n const candidates = mp4Files.length > 0 ? mp4Files : mediaFiles;\n const targetWidth = contentVideo.videoWidth || 1280;\n const targetHeight = contentVideo.videoHeight || 720;\n candidates.sort((a, b) => {\n const diffA = Math.abs(a.width - targetWidth) + Math.abs(a.height - targetHeight);\n const diffB = Math.abs(b.width - targetWidth) + Math.abs(b.height - targetHeight);\n return diffA - diffB;\n });\n return candidates[0] || null;\n }\n function createAdVideoElement() {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.style.zIndex = \"15\";\n video.playsInline = true;\n video.muted = false;\n video.volume = originalMutedState ? 0 : originalVolume;\n return video;\n }\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n function setupAdEventListeners() {\n if (!adVideoElement || !currentAd) return;\n const ad = currentAd;\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!ad || !adVideoElement) return;\n const progress = adVideoElement.currentTime / ad.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(ad.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(ad.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(ad.trackingUrls.thirdQuartile);\n }\n });\n adVideoElement.addEventListener(\"playing\", () => {\n if (!ad || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(ad.trackingUrls.start);\n log(\"Ad started playing\");\n });\n adVideoElement.addEventListener(\"ended\", () => {\n if (!ad || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(ad.trackingUrls.complete);\n log(\"Ad completed\");\n handleAdComplete();\n });\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[AdStormPlayer] Ad video error:\", e);\n if (ad) {\n fireTrackingPixels(ad.trackingUrls.error);\n }\n handleAdError();\n });\n }\n function handleAdComplete() {\n log(\"Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n emit(\"content_resume\");\n emit(\"all_ads_completed\");\n }\n function handleAdError() {\n log(\"Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n emit(\"ad_error\");\n }\n async function fetchVast(durationSeconds) {\n const vastUrl = buildVastUrl(durationSeconds);\n log(\"Fetching VAST from:\", vastUrl);\n const response = await fetch(vastUrl, {\n headers: {\n \"Accept\": \"application/xml\"\n }\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.status} ${response.statusText}`);\n }\n const xmlText = await response.text();\n log(\"VAST response received, length:\", xmlText.length);\n return parseVastXml(xmlText);\n }\n return {\n initialize() {\n log(\"Initializing\");\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n async requestAds(duration) {\n log(\"Requesting ads for duration:\", duration);\n if (adPlaying) {\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n try {\n let durationSeconds = 30;\n const parsed = parseInt(duration, 10);\n if (!isNaN(parsed) && parsed > 0) {\n durationSeconds = parsed;\n }\n const ads = await fetchVast(durationSeconds);\n if (ads.length === 0) {\n log(\"No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.resolve();\n }\n currentAd = ads[0];\n log(`Ad loaded: ${currentAd.title}, duration: ${currentAd.duration}s`);\n fireTrackingPixels(currentAd.trackingUrls.impression);\n trackingFired.impression = true;\n return Promise.resolve();\n } catch (error) {\n console.error(\"[AdStormPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n async play() {\n if (!currentAd) {\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n log(\"Starting ad playback\");\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n contentVideo.style.transition = \"opacity 0.3s ease-in-out\";\n contentVideo.style.opacity = \"0\";\n setTimeout(() => {\n contentVideo.style.visibility = \"hidden\";\n }, 300);\n contentVideo.muted = true;\n contentVideo.volume = 0;\n contentVideo.pause();\n adPlaying = true;\n setAdPlayingFlag(true);\n if (adVideoElement) {\n adVideoElement.volume = originalMutedState ? 0 : originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n emit(\"content_pause\");\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available\");\n }\n log(\"Playing media file:\", mediaFile.url);\n adVideoElement.src = mediaFile.url;\n await adVideoElement.play();\n return Promise.resolve();\n } catch (error) {\n console.error(\"[AdStormPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n async stop() {\n log(\"Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n currentAd = void 0;\n },\n destroy() {\n log(\"Destroying\");\n destroyed = true;\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = void 0;\n }\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n currentAd = void 0;\n listeners.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n log(`Resizing to ${width}x${height}`);\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n log(`updateOriginalMutedState: muted=${muted}, volume=${nextVolume}`);\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n adVideoElement.muted = volume === 0;\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n }\n };\n}\n\n// src/utils/polyfills.ts\nfunction polyfillURLSearchParams() {\n if (typeof URLSearchParams !== \"undefined\") {\n return;\n }\n class URLSearchParamsPolyfill {\n constructor(init) {\n this.params = /* @__PURE__ */ new Map();\n if (typeof init === \"string\") {\n this.parseQueryString(init);\n } else if (init instanceof URLSearchParamsPolyfill) {\n init.forEach((value, key) => {\n this.append(key, value);\n });\n }\n }\n parseQueryString(query) {\n const cleanQuery = query.startsWith(\"?\") ? query.slice(1) : query;\n if (!cleanQuery) return;\n cleanQuery.split(\"&\").forEach((param) => {\n const [key, value] = param.split(\"=\");\n if (key) {\n const decodedKey = this.safeDecodeURIComponent(key);\n const decodedValue = value ? this.safeDecodeURIComponent(value) : \"\";\n this.append(decodedKey, decodedValue);\n }\n });\n }\n safeDecodeURIComponent(str) {\n try {\n return decodeURIComponent(str.replace(/\\+/g, \" \"));\n } catch (e) {\n return str;\n }\n }\n append(name, value) {\n const values = this.params.get(name) || [];\n values.push(String(value));\n this.params.set(name, values);\n }\n delete(name) {\n this.params.delete(name);\n }\n get(name) {\n const values = this.params.get(name);\n return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;\n }\n getAll(name) {\n return this.params.get(name) || [];\n }\n has(name) {\n return this.params.has(name);\n }\n set(name, value) {\n this.params.set(name, [String(value)]);\n }\n forEach(callback) {\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n callback(value, key, this);\n });\n });\n }\n toString() {\n const parts = [];\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n });\n });\n return parts.join(\"&\");\n }\n }\n window.URLSearchParams = URLSearchParamsPolyfill;\n}\nfunction polyfillTextEncoder() {\n if (typeof TextEncoder !== \"undefined\") {\n return;\n }\n class TextEncoderPolyfill {\n constructor() {\n this.encoding = \"utf-8\";\n }\n encode(str) {\n const utf8 = [];\n for (let i = 0; i < str.length; i++) {\n let charcode = str.charCodeAt(i);\n if (charcode < 128) {\n utf8.push(charcode);\n } else if (charcode < 2048) {\n utf8.push(192 | charcode >> 6, 128 | charcode & 63);\n } else if (charcode < 55296 || charcode >= 57344) {\n utf8.push(\n 224 | charcode >> 12,\n 128 | charcode >> 6 & 63,\n 128 | charcode & 63\n );\n } else {\n i++;\n charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);\n utf8.push(\n 240 | charcode >> 18,\n 128 | charcode >> 12 & 63,\n 128 | charcode >> 6 & 63,\n 128 | charcode & 63\n );\n }\n }\n return new Uint8Array(utf8);\n }\n }\n window.TextEncoder = TextEncoderPolyfill;\n}\nfunction polyfillPromiseFinally() {\n if (typeof Promise !== \"undefined\" && !Promise.prototype.finally) {\n Promise.prototype.finally = function(callback) {\n const constructor = this.constructor;\n return this.then(\n (value) => constructor.resolve(callback()).then(() => value),\n (reason) => constructor.resolve(callback()).then(() => {\n throw reason;\n })\n );\n };\n }\n}\nfunction polyfillObjectAssign() {\n if (typeof Object.assign !== \"function\") {\n Object.assign = function(target, ...sources) {\n if (target == null) {\n throw new TypeError(\"Cannot convert undefined or null to object\");\n }\n const to = Object(target);\n for (let i = 0; i < sources.length; i++) {\n const nextSource = sources[i];\n if (nextSource != null) {\n for (const nextKey in nextSource) {\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n }\n}\nfunction polyfillArrayFrom() {\n if (!Array.from) {\n Array.from = function(arrayLike, mapFn, thisArg) {\n const items = Object(arrayLike);\n if (arrayLike == null) {\n throw new TypeError(\"Array.from requires an array-like object\");\n }\n const len = items.length >>> 0;\n const result = new Array(len);\n for (let i = 0; i < len; i++) {\n if (mapFn) {\n result[i] = mapFn.call(thisArg, items[i], i);\n } else {\n result[i] = items[i];\n }\n }\n return result;\n };\n }\n}\nfunction polyfillStringStartsWith() {\n if (!String.prototype.startsWith) {\n String.prototype.startsWith = function(search, pos) {\n pos = !pos || pos < 0 ? 0 : +pos;\n return this.substring(pos, pos + search.length) === search;\n };\n }\n}\nfunction polyfillStringEndsWith() {\n if (!String.prototype.endsWith) {\n String.prototype.endsWith = function(search, length) {\n if (length === void 0 || length > this.length) {\n length = this.length;\n }\n return this.substring(length - search.length, length) === search;\n };\n }\n}\nfunction polyfillStringIncludes() {\n if (!String.prototype.includes) {\n String.prototype.includes = function(search, start) {\n if (typeof start !== \"number\") {\n start = 0;\n }\n if (start + search.length > this.length) {\n return false;\n }\n return this.indexOf(search, start) !== -1;\n };\n }\n}\nfunction initializePolyfills() {\n polyfillObjectAssign();\n polyfillArrayFrom();\n polyfillStringStartsWith();\n polyfillStringEndsWith();\n polyfillStringIncludes();\n polyfillURLSearchParams();\n polyfillTextEncoder();\n polyfillPromiseFinally();\n}\n\n// src/utils/browserCompat.ts\nfunction getChromeVersion(ua) {\n const match = ua.match(/Chrome\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getWebKitVersion(ua) {\n const match = ua.match(/AppleWebKit\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getPlatform() {\n if (\"userAgentData\" in navigator && navigator.userAgentData?.platform) {\n return navigator.userAgentData.platform;\n }\n const ua = navigator.userAgent;\n if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n return /iPhone|iPad|iPod/i.test(ua) ? \"iPhone\" : \"MacIntel\";\n }\n if (/Win/i.test(ua)) {\n return \"Win32\";\n }\n if (/Linux/i.test(ua)) {\n return /Android/i.test(ua) ? \"Linux armv8l\" : \"Linux x86_64\";\n }\n if (/CrOS/i.test(ua)) {\n return \"CrOS\";\n }\n return navigator.platform || \"Unknown\";\n}\nfunction detectBrowser() {\n const ua = navigator.userAgent;\n const platform = getPlatform();\n let name = \"Unknown\";\n let version = \"0\";\n let majorVersion = 0;\n let isSmartTV = false;\n let isLegacyTV = false;\n let supportsModernJS = true;\n if (/Web0S|webOS/i.test(ua)) {\n name = \"LG WebOS\";\n isSmartTV = true;\n const match = ua.match(/Web0S[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : \"Unknown\";\n if (version !== \"Unknown\") {\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/Tizen/i.test(ua)) {\n name = \"Samsung Tizen\";\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : \"Unknown\";\n if (version !== \"Unknown\") {\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = \"Smart TV\";\n isSmartTV = true;\n } else if (/NetCast/i.test(ua)) {\n name = \"LG NetCast\";\n isSmartTV = true;\n isLegacyTV = true;\n } else if (/BRAVIA/i.test(ua)) {\n name = \"Sony BRAVIA\";\n isSmartTV = true;\n }\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n if (chromeVersion > 0) {\n if (!isSmartTV) {\n name = \"Chrome\";\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n }\n if (chromeVersion < 50) {\n supportsModernJS = false;\n isLegacyTV = true;\n }\n }\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (isSmartTV) {\n isLegacyTV = true;\n }\n }\n if (typeof Promise === \"undefined\" || typeof Map === \"undefined\" || typeof Set === \"undefined\") {\n supportsModernJS = false;\n }\n if (typeof URLSearchParams === \"undefined\") {\n supportsModernJS = false;\n }\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsModernJS\n };\n}\nfunction logBrowserInfo(debug = false) {\n if (!debug) return;\n const browser = detectBrowser();\n console.log(\"[StormcloudVideoPlayer] Browser Compatibility Info:\", {\n browser: `${browser.name} ${browser.version}`,\n platform: browser.platform,\n isSmartTV: browser.isSmartTV,\n isLegacyTV: browser.isLegacyTV,\n supportsModernJS: browser.supportsModernJS,\n userAgent: navigator.userAgent\n });\n}\nfunction getBrowserConfigOverrides() {\n const browser = detectBrowser();\n const overrides = {};\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n return overrides;\n}\n\n// src/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer = class {\n constructor(config) {\n this.attached = false;\n this.inAdBreak = false;\n this.ptsDriftEmaMs = 0;\n this.isLiveStream = false;\n this.nativeHlsMode = false;\n this.videoSrcProtection = null;\n this.bufferedSegmentsCount = 0;\n this.shouldAutoplayAfterBuffering = false;\n this.hasInitialBufferCompleted = false;\n initializePolyfills();\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...config, ...browserOverrides };\n this.video = config.videoElement;\n logBrowserInfo(config.debugAdTiming);\n if (!this.config.licenseKey) {\n console.warn(\"[StormcloudVideoPlayer] No license key provided - ads will not work\");\n }\n this.adPlayer = createAdStormPlayer(this.video, {\n licenseKey: this.config.licenseKey || \"\",\n debug: this.config.debugAdTiming ?? false\n });\n }\n async load() {\n if (!this.attached) {\n this.attach();\n }\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Using native HLS playback:\", {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls\n });\n }\n this.adPlayer.initialize();\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n return;\n }\n this.hls = new import_hls.default({\n enableWorker: true,\n backBufferLength: 30,\n liveDurationInfinity: true,\n lowLatencyMode: !!this.config.lowLatencyMode,\n maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1,\n ...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {},\n maxBufferLength: 30,\n maxMaxBufferLength: 600,\n maxBufferSize: 60 * 1e3 * 1e3,\n maxBufferHole: 0.5,\n highBufferWatchdogPeriod: 2,\n nudgeOffset: 0.1,\n nudgeMaxRetry: 3,\n startPosition: -1\n });\n this.hls.on(import_hls.default.Events.MEDIA_ATTACHED, () => {\n this.hls?.loadSource(this.config.src);\n });\n this.hls.on(import_hls.default.Events.MANIFEST_PARSED, async () => {\n this.isLiveStream = this.hls?.levels?.some(\n (level) => level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n isLive: this.isLiveStream\n });\n }\n this.adPlayer.initialize();\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Waiting for\",\n minSegments,\n \"segments to buffer before playback\"\n );\n }\n if (minSegments === 0 || !this.config.autoplay) {\n this.hasInitialBufferCompleted = true;\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n }\n });\n this.hls.on(import_hls.default.Events.FRAG_BUFFERED, async () => {\n if (this.hasInitialBufferCompleted) {\n return;\n }\n this.bufferedSegmentsCount++;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n );\n }\n if (this.bufferedSegmentsCount >= minSegments) {\n this.hasInitialBufferCompleted = true;\n if (this.shouldAutoplayAfterBuffering) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete. Starting playback.`\n );\n }\n await this.video.play()?.catch((err) => {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n this.hls.on(import_hls.default.Events.FRAG_PARSING_METADATA, (_evt, data) => {\n const id3Tags = (data?.samples || []).map((s) => ({\n key: \"ID3\",\n value: s?.data,\n ptsSeconds: s?.pts\n }));\n id3Tags.forEach((tag) => this.onId3Tag(tag));\n });\n this.hls.on(import_hls.default.Events.FRAG_CHANGED, (_evt, data) => {\n const frag = data?.frag;\n const tagList = frag?.tagList;\n if (!Array.isArray(tagList)) return;\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n value = \"\";\n }\n }\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n this.onScte35Marker({\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value }\n });\n } else if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = this.parseCueOutCont(value);\n this.onScte35Marker({\n type: \"progress\",\n ...prog?.duration !== void 0 ? { durationSeconds: prog.duration } : {},\n ...prog?.elapsed !== void 0 ? { ptsSeconds: prog.elapsed } : {},\n raw: { tag, value }\n });\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut = \"SCTE35-OUT\" in attrs;\n const hasScteIn = \"SCTE35-IN\" in attrs;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]) ?? this.toNumber(attrs[\"PLANNED-DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n this.onScte35Marker({\n type: \"start\",\n ...duration !== void 0 ? { durationSeconds: duration } : {},\n raw: { tag, value, attrs }\n });\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\n });\n this.hls.on(import_hls.default.Events.ERROR, (_evt, data) => {\n if (data?.fatal) {\n switch (data.type) {\n case import_hls.default.ErrorTypes.NETWORK_ERROR:\n this.hls?.startLoad();\n break;\n case import_hls.default.ErrorTypes.MEDIA_ERROR:\n this.hls?.recoverMediaError();\n break;\n default:\n this.destroy();\n break;\n }\n }\n });\n this.hls.attachMedia(this.video);\n }\n attach() {\n if (this.attached) return;\n this.attached = true;\n this.video.autoplay = !!this.config.autoplay;\n this.video.muted = !!this.config.muted;\n this.adPlayer.initialize();\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.adPlayer.on(\"all_ads_completed\", () => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad completed - ending ad break\");\n }\n if (this.inAdBreak) {\n this.handleAdPodComplete();\n }\n });\n this.adPlayer.on(\"ad_error\", () => {\n console.error(\"[StormcloudVideoPlayer] Ad error occurred\");\n if (this.inAdBreak) {\n this.handleAdPodComplete();\n }\n });\n this.adPlayer.on(\"content_pause\", () => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content paused for ad\");\n }\n });\n this.adPlayer.on(\"content_resume\", () => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content resuming after ad\");\n }\n });\n this.timeUpdateHandler = () => {\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n this.emptiedHandler = () => {\n if (this.nativeHlsMode && this.videoSrcProtection && !this.adPlayer.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Video src was cleared, restoring\");\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {\n });\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n shouldUseNativeHls() {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return true;\n }\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n onId3Tag(tag) {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n parseScte35FromId3(tag) {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return void 0;\n const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) || text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n return {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...dur !== void 0 ? { durationSeconds: dur } : {},\n raw: { id3: text }\n };\n }\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n return {\n type: \"progress\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...cont?.duration !== void 0 ? { durationSeconds: cont.duration } : {},\n raw: { id3: text }\n };\n }\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n return {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n }\n return void 0;\n }\n decodeId3ValueToText(value) {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++) {\n out += String.fromCharCode(value[i]);\n }\n return out;\n } catch {\n return void 0;\n }\n }\n async onScte35Marker(marker) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime\n });\n }\n if (marker.type === \"start\") {\n if (this.inAdBreak) {\n return;\n }\n this.inAdBreak = true;\n const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : 3e4;\n this.expectedAdBreakDurationMs = durationMs;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break:\", {\n durationMs,\n durationSeconds: marker.durationSeconds\n });\n }\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n await this.handleAdStart(marker);\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;\n }\n return;\n }\n if (marker.type === \"end\") {\n if (!this.inAdBreak) return;\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.clearAdStopTimer();\n if (this.adPlayer.isAdPlaying()) {\n await this.adPlayer.stop();\n }\n this.handleAdPodComplete();\n return;\n }\n }\n async handleAdStart(marker) {\n const durationSeconds = marker.durationSeconds ?? 30;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Requesting ads for duration:\", durationSeconds);\n }\n try {\n await this.adPlayer.requestAds(String(durationSeconds));\n await this.adPlayer.play();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Ad request/play failed:\", error);\n }\n this.handleAdPodComplete();\n }\n }\n parseCueOutDuration(value) {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match = value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) || value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const d = parseFloat(match[1]);\n return Number.isNaN(d) ? void 0 : d;\n }\n return void 0;\n }\n parseCueOutCont(value) {\n const elapsedMatch = value.match(/Elapsed\\s*=\\s*([0-9.]+)/i);\n const durationMatch = value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n const res = {};\n if (elapsedMatch && elapsedMatch[1] != null) {\n const e = parseFloat(elapsedMatch[1]);\n if (!Number.isNaN(e)) res.elapsed = e;\n }\n if (durationMatch && durationMatch[1] != null) {\n const d = parseFloat(durationMatch[1]);\n if (!Number.isNaN(d)) res.duration = d;\n }\n if (\"elapsed\" in res || \"duration\" in res) return res;\n return void 0;\n }\n parseAttributeList(value) {\n const attrs = {};\n const regex = /([A-Z0-9-]+)=((\"[^\"]*\")|([^\",]*))(?:,|$)/gi;\n let match;\n while ((match = regex.exec(value)) !== null) {\n const key = match[1] ?? \"\";\n let rawVal = match[3] ?? match[4] ?? \"\";\n if (rawVal.startsWith('\"') && rawVal.endsWith('\"')) {\n rawVal = rawVal.slice(1, -1);\n }\n if (key) {\n attrs[key] = rawVal;\n }\n }\n return attrs;\n }\n toNumber(val) {\n if (val == null) return void 0;\n const n = typeof val === \"string\" ? parseFloat(val) : Number(val);\n return Number.isNaN(n) ? void 0 : n;\n }\n scheduleAdStopCountdown(remainingMs) {\n this.clearAdStopTimer();\n const ms = Math.max(0, Math.floor(remainingMs));\n if (ms === 0) {\n this.handleAdPodComplete();\n return;\n }\n this.adStopTimerId = window.setTimeout(() => {\n this.handleAdPodComplete();\n }, ms);\n }\n clearAdStopTimer() {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = void 0;\n }\n }\n updatePtsDrift(ptsSecondsSample) {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1e3;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 6e4) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n handleAdPodComplete() {\n this.clearAdStopTimer();\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.adPlayer.stop().catch(() => {\n });\n const restoredMuted = this.adPlayer.getOriginalMutedState();\n const restoredVolume = this.adPlayer.getOriginalVolume();\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n if (this.video.paused) {\n this.video.play()?.catch(() => {\n });\n }\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad break complete\");\n }\n }\n isAdPlaying() {\n return this.inAdBreak && this.adPlayer.isAdPlaying();\n }\n isShowingAds() {\n return this.adPlayer.isAdPlaying();\n }\n getStreamType() {\n const url = this.config.src.toLowerCase();\n if (url.includes(\".m3u8\") || url.includes(\"/hls/\") || url.includes(\"application/vnd.apple.mpegurl\")) {\n return \"hls\";\n }\n return \"other\";\n }\n shouldShowNativeControls() {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return !(this.config.showCustomControls ?? false);\n }\n return !!(this.config.allowNativeHls && !(this.config.showCustomControls ?? false));\n }\n toggleMute() {\n if (this.adPlayer.isAdPlaying()) {\n const currentMuted = this.video.muted;\n const newMutedState = !currentMuted;\n this.adPlayer.updateOriginalMutedState(newMutedState, this.video.volume);\n this.adPlayer.setAdVolume(newMutedState ? 0 : 1);\n } else {\n this.video.muted = !this.video.muted;\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n }\n }\n toggleFullscreen() {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container.requestFullscreen().then(() => resolve()).catch(reject);\n } else {\n document.exitFullscreen().then(() => resolve()).catch(reject);\n }\n });\n }\n isMuted() {\n return this.video.muted;\n }\n setMuted(muted) {\n this.video.muted = muted;\n this.adPlayer.updateOriginalMutedState(muted, this.video.volume);\n if (this.adPlayer.isAdPlaying()) {\n this.adPlayer.setAdVolume(muted ? 0 : 1);\n }\n }\n setVolume(volume) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n if (this.adPlayer.isAdPlaying()) {\n this.adPlayer.setAdVolume(clampedVolume);\n this.adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n }\n }\n isFullscreen() {\n return !!document.fullscreenElement;\n }\n isLive() {\n return this.isLiveStream;\n }\n get videoElement() {\n return this.video;\n }\n resize() {\n if (this.adPlayer && this.adPlayer.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 360;\n this.adPlayer.resize(width, height);\n }\n }\n destroy() {\n this.clearAdStopTimer();\n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n this.hls?.destroy();\n this.adPlayer?.destroy();\n }\n getCurrentAdIndex() {\n return 0;\n }\n getTotalAdsInBreak() {\n return 1;\n }\n};\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/HlsPlayer.tsx\nvar HlsPlayer = class extends import_react.Component {\n constructor() {\n super(...arguments);\n this.player = null;\n this.mounted = false;\n this.load = async () => {\n if (!this.props.videoElement || !this.props.src) return;\n try {\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n const config = {\n src: this.props.src,\n videoElement: this.props.videoElement\n };\n if (this.props.autoplay !== void 0)\n config.autoplay = this.props.autoplay;\n if (this.props.muted !== void 0) config.muted = this.props.muted;\n if (this.props.lowLatencyMode !== void 0)\n config.lowLatencyMode = this.props.lowLatencyMode;\n if (this.props.allowNativeHls !== void 0)\n config.allowNativeHls = this.props.allowNativeHls;\n if (this.props.driftToleranceMs !== void 0)\n config.driftToleranceMs = this.props.driftToleranceMs;\n if (this.props.immediateManifestAds !== void 0)\n config.immediateManifestAds = this.props.immediateManifestAds;\n if (this.props.debugAdTiming !== void 0)\n config.debugAdTiming = this.props.debugAdTiming;\n if (this.props.showCustomControls !== void 0)\n config.showCustomControls = this.props.showCustomControls;\n if (this.props.onVolumeToggle !== void 0)\n config.onVolumeToggle = this.props.onVolumeToggle;\n if (this.props.onFullscreenToggle !== void 0)\n config.onFullscreenToggle = this.props.onFullscreenToggle;\n if (this.props.onControlClick !== void 0)\n config.onControlClick = this.props.onControlClick;\n if (this.props.licenseKey !== void 0)\n config.licenseKey = this.props.licenseKey;\n if (this.props.adFailsafeTimeoutMs !== void 0)\n config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;\n if (this.props.minSegmentsBeforePlay !== void 0)\n config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;\n this.player = new StormcloudVideoPlayer(config);\n this.props.onMount?.(this);\n await this.player.load();\n if (this.mounted) {\n this.props.onReady?.();\n }\n } catch (error) {\n if (this.mounted) {\n this.props.onError?.(error);\n }\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(\"[HlsPlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n this.props.onPlay?.();\n } else {\n console.warn(\"[HlsPlayer] Cannot play: video has no valid source\");\n }\n }\n };\n this.pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n this.props.onPause?.();\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.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 === \"player\") return this.player;\n if (key === \"video\") return this.props.videoElement;\n if (key === \"hls\" && this.player) return this.player.hls;\n return null;\n };\n }\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n componentWillUnmount() {\n this.mounted = false;\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n }\n componentDidUpdate(prevProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n render() {\n return null;\n }\n};\nHlsPlayer.displayName = \"HlsPlayer\";\nHlsPlayer.canPlay = canPlay.hls;\n","import type { AdController } from \"../types\";\n\ninterface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\nconst SUPPORTED_VIDEO_EXTENSIONS = ['.mp4', '.webm', '.ogg', '.m3u8', '.ts'];\nconst UNSUPPORTED_VIDEO_EXTENSIONS = ['.flv', '.f4v', '.swf', '.wmv', '.avi', '.mov', '.mkv'];\n\nfunction getFileExtension(url: string): string {\n try {\n const pathname = new URL(url, 'http://dummy').pathname;\n const lastDot = pathname.lastIndexOf('.');\n if (lastDot === -1) return '';\n return pathname.slice(lastDot).toLowerCase();\n } catch {\n const lastDot = url.lastIndexOf('.');\n if (lastDot === -1) return '';\n const ext = url.slice(lastDot).split(/[?#]/)[0];\n return (ext || '').toLowerCase();\n }\n}\n\nfunction isUnsupportedFormat(url: string): boolean {\n const ext = getFileExtension(url);\n return UNSUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1;\n}\n\nfunction replaceFlvExtension(url: string): string {\n const ext = getFileExtension(url);\n if (ext === '.flv') {\n return url.replace(/\\.flv(\\?|$)/i, '.mp4$1');\n }\n return url;\n}\n\nfunction isSupportedFormat(url: string, mimeType: string): boolean {\n if (isUnsupportedFormat(url)) {\n return false;\n }\n \n const ext = getFileExtension(url);\n \n if (SUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1) {\n return true;\n }\n \n if (ext === '' || ext === '.') {\n return mimeType.includes('video/mp4') || \n mimeType.includes('video/webm') || \n mimeType.includes('m3u8') ||\n mimeType.includes('application/x-mpegurl');\n }\n \n return false;\n}\n\ninterface VastTrackingUrls {\n impression: string[];\n start: string[];\n firstQuartile: string[];\n midpoint: string[];\n thirdQuartile: string[];\n complete: string[];\n error: string[];\n}\n\ninterface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\ninterface AdStormMetadata {\n video?: {\n codec?: string;\n width?: number;\n height?: number;\n fps?: number;\n bitrate?: number;\n profile?: string;\n pix_fmt?: string;\n has_b_frames?: number;\n };\n audio?: {\n codec?: string;\n sample_rate?: number;\n bitrate?: number;\n };\n}\n\nexport interface AdStormPlayerOptions {\n licenseKey: string;\n debug?: boolean;\n}\n\nexport function createAdStormPlayer(\n contentVideo: HTMLVideoElement,\n options: AdStormPlayerOptions\n): AdController {\n const { licenseKey, debug = false } = options;\n \n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n \n let adVideoElement: HTMLVideoElement | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let currentAd: VastAd | undefined;\n let destroyed = false;\n \n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n function log(...args: any[]): void {\n if (debug) {\n console.log(\"[AdStormPlayer]\", ...args);\n }\n }\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(`[AdStormPlayer] Error in event listener for ${event}:`, error);\n }\n }\n }\n\n function fireTrackingPixels(urls: string[]): void {\n if (!urls || urls.length === 0) return;\n \n urls.forEach((url) => {\n try {\n const img = new Image(1, 1);\n img.src = url;\n log(\"Fired tracking pixel:\", url);\n } catch (error) {\n console.warn(\"[AdStormPlayer] Error firing tracking pixel:\", error);\n }\n });\n }\n\n function buildVastUrl(durationSeconds: number, metadata?: AdStormMetadata): string {\n const baseUrl = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${licenseKey}/pod`;\n \n const defaultMetadata: AdStormMetadata = {\n video: {\n codec: \"h264\",\n width: contentVideo.videoWidth || 1280,\n height: contentVideo.videoHeight || 720,\n fps: 29.97,\n bitrate: 5000,\n profile: \"high\",\n pix_fmt: \"yuv420p\",\n has_b_frames: 0,\n },\n audio: {\n codec: \"aac\",\n sample_rate: 48000,\n bitrate: 128,\n },\n };\n \n const finalMetadata = metadata || defaultMetadata;\n const metadataStr = encodeURIComponent(JSON.stringify(finalMetadata));\n \n return `${baseUrl}?duration=${Math.ceil(durationSeconds)}&metadata=${metadataStr}`;\n }\n\n function parseVastXml(xmlString: string): VastAd[] {\n const ads: VastAd[] = [];\n \n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n \n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\"[AdStormPlayer] XML parsing error:\", parserError.textContent);\n return [];\n }\n \n const adElements = xmlDoc.querySelectorAll(\"Ad\");\n \n adElements.forEach((adElement) => {\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = adElement.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n \n const durationText = adElement.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration =\n parseInt(durationParts[0] || \"0\", 10) * 3600 +\n parseInt(durationParts[1] || \"0\", 10) * 60 +\n parseFloat(durationParts[2] || \"0\");\n \n const mediaFileElements = adElement.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n \n mediaFileElements.forEach((mf) => {\n const type = mf.getAttribute(\"type\") || \"\";\n let url = mf.textContent?.trim() || \"\";\n const width = parseInt(mf.getAttribute(\"width\") || \"1920\", 10);\n const height = parseInt(mf.getAttribute(\"height\") || \"1080\", 10);\n const bitrate = mf.getAttribute(\"bitrate\") \n ? parseInt(mf.getAttribute(\"bitrate\")!, 10) \n : undefined;\n \n if (!url) {\n log(`Skipping empty MediaFile URL`);\n return;\n }\n \n const originalUrl = url;\n url = replaceFlvExtension(url);\n if (url !== originalUrl) {\n log(`Converted FLV to MP4: ${originalUrl} -> ${url}`);\n }\n \n if (isUnsupportedFormat(url)) {\n const ext = getFileExtension(url);\n log(`Skipping unsupported format: ${url} (extension: ${ext}, declared type: ${type})`);\n return;\n }\n \n if (isSupportedFormat(url, type)) {\n mediaFiles.push({ url, type, width, height, bitrate });\n log(`Found media file: ${url} (${type}, ${width}x${height})`);\n } else {\n log(`Skipping incompatible media file: ${url} (type: ${type})`);\n }\n });\n \n if (mediaFiles.length === 0) {\n log(\"No valid media files found in ad:\", adId);\n return;\n }\n \n const trackingUrls: VastTrackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n error: [],\n };\n \n adElement.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n \n adElement.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event as keyof VastTrackingUrls;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n \n const clickThrough = adElement.querySelector(\"ClickThrough\")?.textContent?.trim();\n \n ads.push({\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough,\n });\n \n log(`Parsed ad: ${title}, duration: ${duration}s, media files: ${mediaFiles.length}`);\n });\n \n } catch (error) {\n console.error(\"[AdStormPlayer] Error parsing VAST XML:\", error);\n }\n \n return ads;\n }\n\n function selectBestMediaFile(mediaFiles: VastMediaFile[]): VastMediaFile | null {\n if (mediaFiles.length === 0) return null;\n if (mediaFiles.length === 1) return mediaFiles[0]!;\n \n const mp4Files = mediaFiles.filter(mf => mf.type.includes(\"video/mp4\"));\n const candidates = mp4Files.length > 0 ? mp4Files : mediaFiles;\n \n const targetWidth = contentVideo.videoWidth || 1280;\n const targetHeight = contentVideo.videoHeight || 720;\n \n candidates.sort((a, b) => {\n const diffA = Math.abs(a.width - targetWidth) + Math.abs(a.height - targetHeight);\n const diffB = Math.abs(b.width - targetWidth) + Math.abs(b.height - targetHeight);\n return diffA - diffB;\n });\n \n return candidates[0] || null;\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.style.zIndex = \"15\";\n video.playsInline = true;\n video.muted = false;\n video.volume = originalMutedState ? 0 : originalVolume;\n \n return video;\n }\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement || !currentAd) return;\n \n const ad = currentAd;\n \n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!ad || !adVideoElement) return;\n \n const progress = adVideoElement.currentTime / ad.duration;\n \n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(ad.trackingUrls.firstQuartile);\n }\n \n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(ad.trackingUrls.midpoint);\n }\n \n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(ad.trackingUrls.thirdQuartile);\n }\n });\n \n adVideoElement.addEventListener(\"playing\", () => {\n if (!ad || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(ad.trackingUrls.start);\n log(\"Ad started playing\");\n });\n \n adVideoElement.addEventListener(\"ended\", () => {\n if (!ad || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(ad.trackingUrls.complete);\n log(\"Ad completed\");\n handleAdComplete();\n });\n \n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[AdStormPlayer] Ad video error:\", e);\n if (ad) {\n fireTrackingPixels(ad.trackingUrls.error);\n }\n handleAdError();\n });\n }\n\n function handleAdComplete(): void {\n log(\"Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n \n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n \n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n \n emit(\"content_resume\");\n emit(\"all_ads_completed\");\n }\n\n function handleAdError(): void {\n log(\"Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n \n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n \n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n \n emit(\"ad_error\");\n }\n\n async function fetchVast(durationSeconds: number): Promise<VastAd[]> {\n const vastUrl = buildVastUrl(durationSeconds);\n log(\"Fetching VAST from:\", vastUrl);\n \n const response = await fetch(vastUrl, {\n headers: {\n \"Accept\": \"application/xml\",\n },\n });\n \n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.status} ${response.statusText}`);\n }\n \n const xmlText = await response.text();\n log(\"VAST response received, length:\", xmlText.length);\n \n return parseVastXml(xmlText);\n }\n\n return {\n initialize() {\n log(\"Initializing\");\n \n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n \n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n\n async requestAds(duration: string) {\n log(\"Requesting ads for duration:\", duration);\n \n if (adPlaying) {\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n \n try {\n let durationSeconds = 30;\n const parsed = parseInt(duration, 10);\n if (!isNaN(parsed) && parsed > 0) {\n durationSeconds = parsed;\n }\n \n const ads = await fetchVast(durationSeconds);\n \n if (ads.length === 0) {\n log(\"No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.resolve();\n }\n \n currentAd = ads[0];\n log(`Ad loaded: ${currentAd!.title}, duration: ${currentAd!.duration}s`);\n \n fireTrackingPixels(currentAd!.trackingUrls.impression);\n trackingFired.impression = true;\n \n return Promise.resolve();\n } catch (error) {\n console.error(\"[AdStormPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n\n async play() {\n if (!currentAd) {\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n \n log(\"Starting ad playback\");\n \n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n \n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n \n contentVideo.style.transition = \"opacity 0.3s ease-in-out\";\n contentVideo.style.opacity = \"0\";\n setTimeout(() => {\n contentVideo.style.visibility = \"hidden\";\n }, 300);\n contentVideo.muted = true;\n contentVideo.volume = 0;\n contentVideo.pause();\n \n adPlaying = true;\n setAdPlayingFlag(true);\n \n if (adVideoElement) {\n adVideoElement.volume = originalMutedState ? 0 : originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n \n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n \n emit(\"content_pause\");\n \n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available\");\n }\n \n log(\"Playing media file:\", mediaFile.url);\n adVideoElement!.src = mediaFile.url;\n \n await adVideoElement!.play();\n \n return Promise.resolve();\n } catch (error) {\n console.error(\"[AdStormPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n\n async stop() {\n log(\"Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n \n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n \n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n \n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n \n currentAd = undefined;\n },\n\n destroy() {\n log(\"Destroying\");\n destroyed = true;\n adPlaying = false;\n setAdPlayingFlag(false);\n \n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n \n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n \n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n \n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\n log(`Resizing to ${width}x${height}`);\n \n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n \n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n log(`updateOriginalMutedState: muted=${muted}, volume=${nextVolume}`);\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n\n getOriginalVolume() {\n return originalVolume;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n adVideoElement.muted = volume === 0;\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n\n showPlaceholder() {\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n \n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n \n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n },\n };\n}\n\n","import { Component } from \"react\";\nimport { StormcloudVideoPlayer } from \"../player/StormcloudVideoPlayer\";\nimport type { StormcloudVideoPlayerConfig } from \"../types\";\nimport { canPlay } from \"../patterns\";\n\nexport interface HlsPlayerProps extends StormcloudVideoPlayerConfig {\n onMount?: (player: any) => void;\n onReady?: () => void;\n onPlay?: () => void;\n onPause?: () => void;\n onEnded?: () => void;\n onLoaded?: () => void;\n onError?: (error: any) => void;\n}\n\nexport default class HlsPlayer extends Component<HlsPlayerProps> {\n static displayName = \"HlsPlayer\";\n\n static canPlay = canPlay.hls;\n\n private player: StormcloudVideoPlayer | null = null;\n private mounted = false;\n\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n\n componentWillUnmount() {\n this.mounted = false;\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n }\n\n componentDidUpdate(prevProps: HlsPlayerProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n\n load = async () => {\n if (!this.props.videoElement || !this.props.src) return;\n\n try {\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n\n const config: StormcloudVideoPlayerConfig = {\n src: this.props.src,\n videoElement: this.props.videoElement,\n };\n\n if (this.props.autoplay !== undefined)\n config.autoplay = this.props.autoplay;\n if (this.props.muted !== undefined) config.muted = this.props.muted;\n if (this.props.lowLatencyMode !== undefined)\n config.lowLatencyMode = this.props.lowLatencyMode;\n if (this.props.allowNativeHls !== undefined)\n config.allowNativeHls = this.props.allowNativeHls;\n if (this.props.driftToleranceMs !== undefined)\n config.driftToleranceMs = this.props.driftToleranceMs;\n if (this.props.immediateManifestAds !== undefined)\n config.immediateManifestAds = this.props.immediateManifestAds;\n if (this.props.debugAdTiming !== undefined)\n config.debugAdTiming = this.props.debugAdTiming;\n if (this.props.showCustomControls !== undefined)\n config.showCustomControls = this.props.showCustomControls;\n if (this.props.onVolumeToggle !== undefined)\n config.onVolumeToggle = this.props.onVolumeToggle;\n if (this.props.onFullscreenToggle !== undefined)\n config.onFullscreenToggle = this.props.onFullscreenToggle;\n if (this.props.onControlClick !== undefined)\n config.onControlClick = this.props.onControlClick;\n if (this.props.licenseKey !== undefined)\n config.licenseKey = this.props.licenseKey;\n if (this.props.adFailsafeTimeoutMs !== undefined)\n config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;\n if (this.props.minSegmentsBeforePlay !== undefined)\n config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;\n\n this.player = new StormcloudVideoPlayer(config);\n\n this.props.onMount?.(this);\n\n await this.player.load();\n\n if (this.mounted) {\n this.props.onReady?.();\n }\n } catch (error) {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n }\n };\n\n play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource =\n video.src ||\n (video.currentSrc && video.currentSrc !== \"\") ||\n video.readyState >= 1;\n\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[HlsPlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n this.props.onPlay?.();\n } else {\n console.warn(\"[HlsPlayer] Cannot play: video has no valid source\");\n }\n }\n };\n\n pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n this.props.onPause?.();\n }\n };\n\n stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n\n seekTo = (seconds: number, keepPlaying?: boolean) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n\n setVolume = (volume: number) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n\n mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n\n unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n\n setPlaybackRate = (rate: number) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n\n getDuration = (): number | null => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n\n getCurrentTime = (): number | null => {\n if (\n this.props.videoElement &&\n isFinite(this.props.videoElement.currentTime)\n ) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n\n getSecondsLoaded = (): number | null => {\n if (\n this.props.videoElement &&\n this.props.videoElement.buffered.length > 0\n ) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n\n getInternalPlayer = (key = \"player\") => {\n if (key === \"player\") return this.player;\n if (key === \"video\") return this.props.videoElement;\n if (key === \"hls\" && this.player) return (this.player as any).hls;\n return null;\n };\n\n render() {\n return null;\n }\n}\n","import Hls from \"hls.js\";\nimport type {\n StormcloudVideoPlayerConfig,\n Scte35Marker,\n Id3TagInfo,\n AdController,\n} from \"../types\";\nimport { createAdStormPlayer } from \"../sdk/adstormPlayer\";\nimport { initializePolyfills } from \"../utils/polyfills\";\nimport { getBrowserConfigOverrides, logBrowserInfo } from \"../utils/browserCompat\";\n\nexport class StormcloudVideoPlayer {\n private readonly video: HTMLVideoElement;\n private readonly config: StormcloudVideoPlayerConfig;\n private hls?: Hls;\n private adPlayer: AdController;\n private attached = false;\n private inAdBreak = false;\n private expectedAdBreakDurationMs: number | undefined;\n private adStopTimerId: number | undefined;\n private ptsDriftEmaMs = 0;\n private isLiveStream: boolean = false;\n private nativeHlsMode: boolean = false;\n private videoSrcProtection: string | null = null;\n private bufferedSegmentsCount: number = 0;\n private shouldAutoplayAfterBuffering: boolean = false;\n private hasInitialBufferCompleted: boolean = false;\n private timeUpdateHandler?: (event: Event) => void;\n private emptiedHandler?: (event: Event) => void;\n\n constructor(config: StormcloudVideoPlayerConfig) {\n initializePolyfills();\n\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...config, ...browserOverrides };\n this.video = config.videoElement;\n\n logBrowserInfo(config.debugAdTiming);\n\n if (!this.config.licenseKey) {\n console.warn(\"[StormcloudVideoPlayer] No license key provided - ads will not work\");\n }\n\n this.adPlayer = createAdStormPlayer(this.video, {\n licenseKey: this.config.licenseKey || \"\",\n debug: this.config.debugAdTiming ?? false,\n });\n }\n\n async load(): Promise<void> {\n if (!this.attached) {\n this.attach();\n }\n\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Using native HLS playback:\", {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n });\n }\n\n this.adPlayer.initialize();\n\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n return;\n }\n\n this.hls = new Hls({\n enableWorker: true,\n backBufferLength: 30,\n liveDurationInfinity: true,\n lowLatencyMode: !!this.config.lowLatencyMode,\n maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1.0,\n ...(this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}),\n maxBufferLength: 30,\n maxMaxBufferLength: 600,\n maxBufferSize: 60 * 1000 * 1000,\n maxBufferHole: 0.5,\n highBufferWatchdogPeriod: 2,\n nudgeOffset: 0.1,\n nudgeMaxRetry: 3,\n startPosition: -1,\n });\n\n this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {\n this.hls?.loadSource(this.config.src);\n });\n\n this.hls.on(Hls.Events.MANIFEST_PARSED, async () => {\n this.isLiveStream =\n this.hls?.levels?.some(\n (level) =>\n level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n isLive: this.isLiveStream,\n });\n }\n\n this.adPlayer.initialize();\n\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Waiting for\",\n minSegments,\n \"segments to buffer before playback\"\n );\n }\n\n if (minSegments === 0 || !this.config.autoplay) {\n this.hasInitialBufferCompleted = true;\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n }\n });\n\n this.hls.on(Hls.Events.FRAG_BUFFERED, async () => {\n if (this.hasInitialBufferCompleted) {\n return;\n }\n\n this.bufferedSegmentsCount++;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n );\n }\n\n if (this.bufferedSegmentsCount >= minSegments) {\n this.hasInitialBufferCompleted = true;\n\n if (this.shouldAutoplayAfterBuffering) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete. Starting playback.`\n );\n }\n await this.video.play()?.catch((err) => {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n\n this.hls.on(Hls.Events.FRAG_PARSING_METADATA, (_evt, data: any) => {\n const id3Tags: Id3TagInfo[] = (data?.samples || []).map((s: any) => ({\n key: \"ID3\",\n value: s?.data,\n ptsSeconds: s?.pts,\n }));\n id3Tags.forEach((tag) => this.onId3Tag(tag));\n });\n\n this.hls.on(Hls.Events.FRAG_CHANGED, (_evt, data: any) => {\n const frag = data?.frag;\n const tagList: any[] | undefined = frag?.tagList;\n if (!Array.isArray(tagList)) return;\n\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n value = \"\";\n }\n }\n\n if (!tag) continue;\n \n if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n this.onScte35Marker({\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value },\n });\n } else if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = this.parseCueOutCont(value);\n this.onScte35Marker({\n type: \"progress\",\n ...(prog?.duration !== undefined ? { durationSeconds: prog.duration } : {}),\n ...(prog?.elapsed !== undefined ? { ptsSeconds: prog.elapsed } : {}),\n raw: { tag, value },\n });\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut = \"SCTE35-OUT\" in attrs;\n const hasScteIn = \"SCTE35-IN\" in attrs;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]) ?? this.toNumber(attrs[\"PLANNED-DURATION\"]);\n\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n this.onScte35Marker({\n type: \"start\",\n ...(duration !== undefined ? { durationSeconds: duration } : {}),\n raw: { tag, value, attrs },\n });\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\n });\n\n this.hls.on(Hls.Events.ERROR, (_evt, data) => {\n if (data?.fatal) {\n switch (data.type) {\n case Hls.ErrorTypes.NETWORK_ERROR:\n this.hls?.startLoad();\n break;\n case Hls.ErrorTypes.MEDIA_ERROR:\n this.hls?.recoverMediaError();\n break;\n default:\n this.destroy();\n break;\n }\n }\n });\n\n this.hls.attachMedia(this.video);\n }\n\n private attach(): void {\n if (this.attached) return;\n this.attached = true;\n this.video.autoplay = !!this.config.autoplay;\n this.video.muted = !!this.config.muted;\n\n this.adPlayer.initialize();\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n \n this.adPlayer.on(\"all_ads_completed\", () => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad completed - ending ad break\");\n }\n if (this.inAdBreak) {\n this.handleAdPodComplete();\n }\n });\n \n this.adPlayer.on(\"ad_error\", () => {\n console.error(\"[StormcloudVideoPlayer] Ad error occurred\");\n if (this.inAdBreak) {\n this.handleAdPodComplete();\n }\n });\n \n this.adPlayer.on(\"content_pause\", () => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content paused for ad\");\n }\n });\n \n this.adPlayer.on(\"content_resume\", () => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content resuming after ad\");\n }\n });\n\n this.timeUpdateHandler = () => {\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n\n this.emptiedHandler = () => {\n if (this.nativeHlsMode && this.videoSrcProtection && !this.adPlayer.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Video src was cleared, restoring\");\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {});\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n\n private shouldUseNativeHls(): boolean {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return true;\n }\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n\n private onId3Tag(tag: Id3TagInfo): void {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n\n private parseScte35FromId3(tag: Id3TagInfo): Scte35Marker | undefined {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return undefined;\n\n const cueOutMatch =\n text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) ||\n text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n return {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(dur !== undefined ? { durationSeconds: dur } : {}),\n raw: { id3: text },\n };\n }\n\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n return {\n type: \"progress\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(cont?.duration !== undefined ? { durationSeconds: cont.duration } : {}),\n raw: { id3: text },\n };\n }\n\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n return {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n };\n }\n\n return undefined;\n }\n\n private decodeId3ValueToText(value: string | Uint8Array): string | undefined {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++) {\n out += String.fromCharCode(value[i]!);\n }\n return out;\n } catch {\n return undefined;\n }\n }\n\n private async onScte35Marker(marker: Scte35Marker): Promise<void> {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime,\n });\n }\n\n if (marker.type === \"start\") {\n if (this.inAdBreak) {\n return;\n }\n\n this.inAdBreak = true;\n const durationMs = marker.durationSeconds != null\n ? marker.durationSeconds * 1000\n : 30000;\n \n this.expectedAdBreakDurationMs = durationMs;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break:\", {\n durationMs,\n durationSeconds: marker.durationSeconds,\n });\n }\n\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n\n await this.handleAdStart(marker);\n\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1000;\n }\n return;\n }\n\n if (marker.type === \"end\") {\n if (!this.inAdBreak) return;\n \n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = undefined;\n this.clearAdStopTimer();\n\n if (this.adPlayer.isAdPlaying()) {\n await this.adPlayer.stop();\n }\n\n this.handleAdPodComplete();\n return;\n }\n }\n\n private async handleAdStart(marker: Scte35Marker): Promise<void> {\n const durationSeconds = marker.durationSeconds ?? 30;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Requesting ads for duration:\", durationSeconds);\n }\n\n try {\n await this.adPlayer.requestAds(String(durationSeconds));\n \n await this.adPlayer.play();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Ad request/play failed:\", error);\n }\n this.handleAdPodComplete();\n }\n }\n\n private parseCueOutDuration(value: string): number | undefined {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match =\n value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) ||\n value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const d = parseFloat(match[1]);\n return Number.isNaN(d) ? undefined : d;\n }\n return undefined;\n }\n\n private parseCueOutCont(value: string): { elapsed?: number; duration?: number } | undefined {\n const elapsedMatch = value.match(/Elapsed\\s*=\\s*([0-9.]+)/i);\n const durationMatch = value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n const res: { elapsed?: number; duration?: number } = {};\n if (elapsedMatch && elapsedMatch[1] != null) {\n const e = parseFloat(elapsedMatch[1]);\n if (!Number.isNaN(e)) res.elapsed = e;\n }\n if (durationMatch && durationMatch[1] != null) {\n const d = parseFloat(durationMatch[1]);\n if (!Number.isNaN(d)) res.duration = d;\n }\n if (\"elapsed\" in res || \"duration\" in res) return res;\n return undefined;\n }\n\n private parseAttributeList(value: string): Record<string, string> {\n const attrs: Record<string, string> = {};\n const regex = /([A-Z0-9-]+)=((\"[^\"]*\")|([^\",]*))(?:,|$)/gi;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(value)) !== null) {\n const key: string = (match[1] ?? \"\") as string;\n let rawVal: string = (match[3] ?? match[4] ?? \"\") as string;\n if (rawVal.startsWith('\"') && rawVal.endsWith('\"')) {\n rawVal = rawVal.slice(1, -1);\n }\n if (key) {\n attrs[key] = rawVal;\n }\n }\n return attrs;\n }\n\n private toNumber(val: unknown): number | undefined {\n if (val == null) return undefined;\n const n = typeof val === \"string\" ? parseFloat(val) : Number(val);\n return Number.isNaN(n) ? undefined : n;\n }\n\n private scheduleAdStopCountdown(remainingMs: number): void {\n this.clearAdStopTimer();\n const ms = Math.max(0, Math.floor(remainingMs));\n if (ms === 0) {\n this.handleAdPodComplete();\n return;\n }\n this.adStopTimerId = window.setTimeout(() => {\n this.handleAdPodComplete();\n }, ms) as unknown as number;\n }\n\n private clearAdStopTimer(): void {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = undefined;\n }\n }\n\n private updatePtsDrift(ptsSecondsSample: number): void {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1000;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 60000) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n\n private handleAdPodComplete(): void {\n this.clearAdStopTimer();\n \n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = undefined;\n\n this.adPlayer.stop().catch(() => {});\n\n const restoredMuted = this.adPlayer.getOriginalMutedState();\n const restoredVolume = this.adPlayer.getOriginalVolume();\n\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n\n if (this.video.paused) {\n this.video.play()?.catch(() => {});\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad break complete\");\n }\n }\n\n isAdPlaying(): boolean {\n return this.inAdBreak && this.adPlayer.isAdPlaying();\n }\n\n isShowingAds(): boolean {\n return this.adPlayer.isAdPlaying();\n }\n\n getStreamType(): \"hls\" | \"other\" {\n const url = this.config.src.toLowerCase();\n if (\n url.includes(\".m3u8\") ||\n url.includes(\"/hls/\") ||\n url.includes(\"application/vnd.apple.mpegurl\")\n ) {\n return \"hls\";\n }\n return \"other\";\n }\n\n shouldShowNativeControls(): boolean {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return !(this.config.showCustomControls ?? false);\n }\n return !!(\n this.config.allowNativeHls && !(this.config.showCustomControls ?? false)\n );\n }\n\n toggleMute(): void {\n if (this.adPlayer.isAdPlaying()) {\n const currentMuted = this.video.muted;\n const newMutedState = !currentMuted;\n\n this.adPlayer.updateOriginalMutedState(newMutedState, this.video.volume);\n this.adPlayer.setAdVolume(newMutedState ? 0 : 1);\n } else {\n this.video.muted = !this.video.muted;\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n }\n }\n\n toggleFullscreen(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container\n .requestFullscreen()\n .then(() => resolve())\n .catch(reject);\n } else {\n document.exitFullscreen().then(() => resolve()).catch(reject);\n }\n });\n }\n\n isMuted(): boolean {\n return this.video.muted;\n }\n\n setMuted(muted: boolean): void {\n this.video.muted = muted;\n this.adPlayer.updateOriginalMutedState(muted, this.video.volume);\n\n if (this.adPlayer.isAdPlaying()) {\n this.adPlayer.setAdVolume(muted ? 0 : 1);\n }\n }\n\n setVolume(volume: number): void {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n\n if (this.adPlayer.isAdPlaying()) {\n this.adPlayer.setAdVolume(clampedVolume);\n this.adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n }\n }\n\n isFullscreen(): boolean {\n return !!document.fullscreenElement;\n }\n\n isLive(): boolean {\n return this.isLiveStream;\n }\n\n get videoElement(): HTMLVideoElement {\n return this.video;\n }\n\n resize(): void {\n if (this.adPlayer && this.adPlayer.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 360;\n this.adPlayer.resize(width, height);\n }\n }\n\n destroy(): void {\n this.clearAdStopTimer();\n\n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n\n this.hls?.destroy();\n this.adPlayer?.destroy();\n }\n\n getCurrentAdIndex(): number {\n return 0;\n }\n\n getTotalAdsInBreak(): number {\n return 1;\n }\n}\n","export function polyfillURLSearchParams(): void {\n if (typeof URLSearchParams !== 'undefined') {\n return;\n }\n\n class URLSearchParamsPolyfill {\n private params: Map<string, string[]>;\n\n constructor(init?: string | URLSearchParamsPolyfill) {\n this.params = new Map();\n\n if (typeof init === 'string') {\n this.parseQueryString(init);\n } else if (init instanceof URLSearchParamsPolyfill) {\n init.forEach((value, key) => {\n this.append(key, value);\n });\n }\n }\n\n private parseQueryString(query: string): void {\n const cleanQuery = query.startsWith('?') ? query.slice(1) : query;\n if (!cleanQuery) return;\n\n cleanQuery.split('&').forEach((param) => {\n const [key, value] = param.split('=');\n if (key) {\n const decodedKey = this.safeDecodeURIComponent(key);\n const decodedValue = value ? this.safeDecodeURIComponent(value) : '';\n this.append(decodedKey, decodedValue);\n }\n });\n }\n\n private safeDecodeURIComponent(str: string): string {\n try {\n return decodeURIComponent(str.replace(/\\+/g, ' '));\n } catch (e) {\n return str;\n }\n }\n\n append(name: string, value: string): void {\n const values = this.params.get(name) || [];\n values.push(String(value));\n this.params.set(name, values);\n }\n\n delete(name: string): void {\n this.params.delete(name);\n }\n\n get(name: string): string | null {\n const values = this.params.get(name);\n return values && values.length > 0 && values[0] !== undefined ? values[0] : null;\n }\n\n getAll(name: string): string[] {\n return this.params.get(name) || [];\n }\n\n has(name: string): boolean {\n return this.params.has(name);\n }\n\n set(name: string, value: string): void {\n this.params.set(name, [String(value)]);\n }\n\n forEach(callback: (value: string, key: string, parent: URLSearchParamsPolyfill) => void): void {\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n callback(value, key, this);\n });\n });\n }\n\n toString(): string {\n const parts: string[] = [];\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n });\n });\n return parts.join('&');\n }\n }\n\n // @ts-ignore\n window.URLSearchParams = URLSearchParamsPolyfill;\n}\n\nexport function polyfillTextEncoder(): void {\n if (typeof TextEncoder !== 'undefined') {\n return;\n }\n\n class TextEncoderPolyfill {\n encoding = 'utf-8';\n\n encode(str: string): Uint8Array {\n const utf8: number[] = [];\n for (let i = 0; i < str.length; i++) {\n let charcode = str.charCodeAt(i);\n if (charcode < 0x80) {\n utf8.push(charcode);\n } else if (charcode < 0x800) {\n utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f));\n } else if (charcode < 0xd800 || charcode >= 0xe000) {\n utf8.push(\n 0xe0 | (charcode >> 12),\n 0x80 | ((charcode >> 6) & 0x3f),\n 0x80 | (charcode & 0x3f)\n );\n } else {\n i++;\n charcode = 0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));\n utf8.push(\n 0xf0 | (charcode >> 18),\n 0x80 | ((charcode >> 12) & 0x3f),\n 0x80 | ((charcode >> 6) & 0x3f),\n 0x80 | (charcode & 0x3f)\n );\n }\n }\n return new Uint8Array(utf8);\n }\n }\n\n // @ts-ignore\n window.TextEncoder = TextEncoderPolyfill;\n}\n\nexport function polyfillPromiseFinally(): void {\n if (typeof Promise !== 'undefined' && !Promise.prototype.finally) {\n Promise.prototype.finally = function (callback: () => void) {\n const constructor = this.constructor as PromiseConstructor;\n return this.then(\n (value) => constructor.resolve(callback()).then(() => value),\n (reason) =>\n constructor.resolve(callback()).then(() => {\n throw reason;\n })\n );\n };\n }\n}\n\nexport function polyfillObjectAssign(): void {\n if (typeof Object.assign !== 'function') {\n Object.assign = function (target: any, ...sources: any[]) {\n if (target == null) {\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n const to = Object(target);\n\n for (let i = 0; i < sources.length; i++) {\n const nextSource = sources[i];\n\n if (nextSource != null) {\n for (const nextKey in nextSource) {\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n\n return to;\n };\n }\n}\n\nexport function polyfillArrayFrom(): void {\n if (!Array.from) {\n Array.from = function (arrayLike: any, mapFn?: any, thisArg?: any) {\n const items = Object(arrayLike);\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object');\n }\n\n const len = items.length >>> 0;\n const result = new Array(len);\n\n for (let i = 0; i < len; i++) {\n if (mapFn) {\n result[i] = mapFn.call(thisArg, items[i], i);\n } else {\n result[i] = items[i];\n }\n }\n\n return result;\n };\n }\n}\n\nexport function polyfillStringStartsWith(): void {\n if (!String.prototype.startsWith) {\n String.prototype.startsWith = function (search: string, pos?: number) {\n pos = !pos || pos < 0 ? 0 : +pos;\n return this.substring(pos, pos + search.length) === search;\n };\n }\n}\n\nexport function polyfillStringEndsWith(): void {\n if (!String.prototype.endsWith) {\n String.prototype.endsWith = function (search: string, length?: number) {\n if (length === undefined || length > this.length) {\n length = this.length;\n }\n return this.substring(length - search.length, length) === search;\n };\n }\n}\n\nexport function polyfillStringIncludes(): void {\n if (!String.prototype.includes) {\n String.prototype.includes = function (search: string, start?: number) {\n if (typeof start !== 'number') {\n start = 0;\n }\n if (start + search.length > this.length) {\n return false;\n }\n return this.indexOf(search, start) !== -1;\n };\n }\n}\n\nexport function initializePolyfills(): void {\n polyfillObjectAssign();\n polyfillArrayFrom();\n polyfillStringStartsWith();\n polyfillStringEndsWith();\n polyfillStringIncludes();\n polyfillURLSearchParams();\n polyfillTextEncoder();\n polyfillPromiseFinally();\n}\n\n","interface NavigatorUAData {\n platform?: string;\n brands?: Array<{ brand: string; version: string }>;\n mobile?: boolean;\n}\n\ndeclare global {\n interface Navigator {\n userAgentData?: NavigatorUAData;\n }\n}\n\nexport interface BrowserInfo {\n name: string;\n version: string;\n majorVersion: number;\n isSmartTV: boolean;\n isLegacyTV: boolean;\n platform: string;\n supportsModernJS: boolean;\n}\n\nfunction getChromeVersion(ua: string): number {\n const match = ua.match(/Chrome\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\n\nfunction getWebKitVersion(ua: string): number {\n const match = ua.match(/AppleWebKit\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\n\nfunction getPlatform(): string {\n if ('userAgentData' in navigator && navigator.userAgentData?.platform) {\n return navigator.userAgentData.platform;\n }\n\n const ua = navigator.userAgent;\n if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n return /iPhone|iPad|iPod/i.test(ua) ? 'iPhone' : 'MacIntel';\n }\n if (/Win/i.test(ua)) {\n return 'Win32';\n }\n if (/Linux/i.test(ua)) {\n return /Android/i.test(ua) ? 'Linux armv8l' : 'Linux x86_64';\n }\n if (/CrOS/i.test(ua)) {\n return 'CrOS';\n }\n\n // eslint-disable-next-line deprecation/deprecation\n return (navigator as any).platform || 'Unknown';\n}\n\nexport function detectBrowser(): BrowserInfo {\n const ua = navigator.userAgent;\n const platform = getPlatform();\n\n let name = 'Unknown';\n let version = '0';\n let majorVersion = 0;\n let isSmartTV = false;\n let isLegacyTV = false;\n let supportsModernJS = true;\n\n if (/Web0S|webOS/i.test(ua)) {\n name = 'LG WebOS';\n isSmartTV = true;\n const match = ua.match(/Web0S[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : 'Unknown';\n if (version !== 'Unknown') {\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/Tizen/i.test(ua)) {\n name = 'Samsung Tizen';\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : 'Unknown';\n if (version !== 'Unknown') {\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = 'Smart TV';\n isSmartTV = true;\n } else if (/NetCast/i.test(ua)) {\n name = 'LG NetCast';\n isSmartTV = true;\n isLegacyTV = true;\n } else if (/BRAVIA/i.test(ua)) {\n name = 'Sony BRAVIA';\n isSmartTV = true;\n }\n\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n\n if (chromeVersion > 0) {\n if (!isSmartTV) {\n name = 'Chrome';\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n }\n\n if (chromeVersion < 50) {\n supportsModernJS = false;\n isLegacyTV = true;\n }\n }\n\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (isSmartTV) {\n isLegacyTV = true;\n }\n }\n\n if (typeof Promise === 'undefined' ||\n typeof Map === 'undefined' ||\n typeof Set === 'undefined') {\n supportsModernJS = false;\n }\n\n if (typeof URLSearchParams === 'undefined') {\n supportsModernJS = false;\n }\n\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsModernJS,\n };\n}\n\nexport function supportsModernJS(): boolean {\n try {\n return (\n typeof Promise !== 'undefined' &&\n typeof Map !== 'undefined' &&\n typeof Set !== 'undefined' &&\n typeof Array.from !== 'undefined' &&\n typeof Object.assign !== 'undefined' &&\n typeof Array.prototype.forEach !== 'undefined' &&\n typeof String.prototype.includes !== 'undefined'\n );\n } catch (e) {\n return false;\n }\n}\n\nexport function logBrowserInfo(debug: boolean = false): void {\n if (!debug) return;\n\n const browser = detectBrowser();\n\n console.log('[StormcloudVideoPlayer] Browser Compatibility Info:', {\n browser: `${browser.name} ${browser.version}`,\n platform: browser.platform,\n isSmartTV: browser.isSmartTV,\n isLegacyTV: browser.isLegacyTV,\n supportsModernJS: browser.supportsModernJS,\n userAgent: navigator.userAgent,\n });\n}\n\nexport function getBrowserConfigOverrides(): {\n allowNativeHls?: boolean;\n} {\n const browser = detectBrowser();\n const overrides: { allowNativeHls?: boolean } = {};\n\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n\n return overrides;\n}\n\nexport function supportsFeature(feature: string): boolean {\n switch (feature) {\n case 'urlsearchparams':\n return typeof URLSearchParams !== 'undefined';\n case 'textencoder':\n return typeof TextEncoder !== 'undefined';\n case 'promises':\n return typeof Promise !== 'undefined';\n case 'fetch':\n return typeof fetch !== 'undefined';\n case 'crypto':\n return typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined';\n default:\n return false;\n }\n}\n"]}
1
+ {"version":3,"sources":["/home/ubuntu24/Dev/stormcloud-vp/lib/players/HlsPlayer.cjs","../../src/sdk/adstormPlayer.ts","../../src/players/HlsPlayer.tsx","../../src/player/StormcloudVideoPlayer.ts","../../src/utils/polyfills.ts","../../src/utils/browserCompat.ts"],"names":["__create","Object","create","__defProp","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","value","__toESM","mod","isNodeMode","__esModule","__toCommonJS","HlsPlayer_exports","default","HlsPlayer","exports","import_react","require","import_hls","SUPPORTED_VIDEO_EXTENSIONS","getFileExtension","UNSUPPORTED_VIDEO_EXTENSIONS","url","pathname","URL","lastDot","lastIndexOf","slice","toLowerCase","ext","split","isUnsupportedFormat","replaceFlvExtension","emit","event","payload","replace","isSupportedFormat","mimeType","indexOf","includes","createAdStormPlayer","contentVideo","options","licenseKey","debug","adPlaying","originalMutedState","originalVolume","Math","max","min","volume","listeners","Map","adVideoElement","adContainerEl","currentAd","destroyed","allowNativeHls","trackingFired","impression","start","firstQuartile","midpoint","thirdQuartile","complete","log","args","console","set","Array","fn","error","warn","fireTrackingPixels","urls","length","forEach","img","Image","src","buildVastUrl","durationSeconds","metadata","baseUrl","defaultMetadata","video","codec","width","videoWidth","height","videoHeight","fps","bitrate","profile","pix_fmt","has_b_frames","audio","sample_rate","finalMetadata","metadataStr","encodeURIComponent","JSON","stringify","ceil","parseVastXml","xmlString","ads","parser","DOMParser","xmlDoc","parseFromString","parserError","querySelector","textContent","adElements","querySelectorAll","adElement","adId","getAttribute","title","durationText","durationParts","duration","parseInt","parseFloat","mediaFileElements","mediaFiles","mf","type","trim","originalUrl","push","trackingUrls","el","eventKey","clickThrough","id","selectBestMediaFile","mp4Files","filter","candidates","targetWidth","targetHeight","sort","a","b","diffA","abs","diffB","createAdVideoElement","document","createElement","style","position","left","top","objectFit","backgroundColor","zIndex","playsInline","muted","setAdPlayingFlag","isPlaying","dataset","stormcloudAdPlaying","setupAdEventListeners","ad","addEventListener","progress","currentTime","handleAdComplete","e","handleAdError","setTimeout","display","pointerEvents","visibility","opacity","fetchVast","vastUrl","response","xmlText","fetch","headers","ok","Error","status","statusText","text","initialize","container","right","bottom","alignItems","justifyContent","transition","parentElement","appendChild","requestAds","parsed","isNaN","Promise","resolve","reject","play","mediaFile","pause","offsetHeight","stop","destroy","remove","removeChild","clear","updateOriginalMutedState","isAdPlaying","resize","on","listener","has","add","Set","off","delete","nextVolume","Number","showPlaceholder","getOriginalMutedState","getOriginalVolume","setAdVolume","getAdVolume","hidePlaceholder","setAllowNativeHls","polyfillURLSearchParams","URLSearchParamsPolyfill","init","params","parseQueryString","append","query","cleanQuery","startsWith","param","decodedKey","safeDecodeURIComponent","decodedValue","str","decodeURIComponent","values","String","getAll","callback","toString","parts","join","window","URLSearchParams","polyfillTextEncoder","TextEncoder","TextEncoderPolyfill","encoding","encode","utf8","i","charcode","charCodeAt","Uint8Array","polyfillPromiseFinally","finally","constructor","then","reason","polyfillObjectAssign","assign","sources","TypeError","nextSource","nextKey","polyfillArrayFrom","arrayLike","mapFn","thisArg","items","len","result","polyfillStringStartsWith","pos","substring","search","polyfillStringEndsWith","endsWith","polyfillStringIncludes","initializePolyfills","getChromeVersion","ua","match","getWebKitVersion","getPlatform","navigator","userAgentData","platform","userAgent","test","detectBrowser","version","majorVersion","isSmartTV","isLegacyTV","supportsModernJS","chromeVersion","webkitVersion","logBrowserInfo","browser","getBrowserConfigOverrides","overrides","StormcloudVideoPlayer","config","attached","inAdBreak","ptsDriftEmaMs","isLiveStream","nativeHlsMode","videoSrcProtection","bufferedSegmentsCount","shouldAutoplayAfterBuffering","hasInitialBufferCompleted","browserOverrides","videoElement","debugAdTiming","adPlayer","load","attach","shouldUseNativeHls","isLive","autoplay","catch","hls","Hls","enableWorker","backBufferLength","liveDurationInfinity","lowLatencyMode","maxBufferLength","maxMaxBufferLength","maxBufferSize","maxBufferHole","highBufferWatchdogPeriod","nudgeMaxRetry","startPosition","Events","MEDIA_ATTACHED","loadSource","MANIFEST_PARSED","minSegments","level","levels","some","details","live","minSegmentsBeforePlay","FRAG_BUFFERED","err","FRAG_PARSING_METADATA","_evt","data","id3Tags","samples","map","s","ptsSeconds","pts","tag","onId3Tag","FRAG_CHANGED","frag","tagList","entry","isArray","idx","parseCueOutDuration","onScte35Marker","liveSyncDuration"],"mappings":"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","sourcesContent":["\"use strict\";\nvar __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/players/HlsPlayer.tsx\nvar HlsPlayer_exports = {};\n__export(HlsPlayer_exports, {\n default: () => HlsPlayer\n});\nmodule.exports = __toCommonJS(HlsPlayer_exports);\nvar import_react = require(\"react\");\n\n// src/player/StormcloudVideoPlayer.ts\nvar import_hls = __toESM(require(\"hls.js\"), 1);\n\n// src/sdk/adstormPlayer.ts\nvar SUPPORTED_VIDEO_EXTENSIONS = [\".mp4\", \".webm\", \".ogg\", \".m3u8\", \".ts\"];\nvar UNSUPPORTED_VIDEO_EXTENSIONS = [\".flv\", \".f4v\", \".swf\", \".wmv\", \".avi\", \".mov\", \".mkv\"];\nfunction getFileExtension(url) {\n try {\n const pathname = new URL(url, \"http://dummy\").pathname;\n const lastDot = pathname.lastIndexOf(\".\");\n if (lastDot === -1) return \"\";\n return pathname.slice(lastDot).toLowerCase();\n } catch {\n const lastDot = url.lastIndexOf(\".\");\n if (lastDot === -1) return \"\";\n const ext = url.slice(lastDot).split(/[?#]/)[0];\n return (ext || \"\").toLowerCase();\n }\n}\nfunction isUnsupportedFormat(url) {\n const ext = getFileExtension(url);\n return UNSUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1;\n}\nfunction replaceFlvExtension(url) {\n const ext = getFileExtension(url);\n if (ext === \".flv\") {\n return url.replace(/\\.flv(\\?|$)/i, \".mp4$1\");\n }\n return url;\n}\nfunction isSupportedFormat(url, mimeType) {\n if (isUnsupportedFormat(url)) {\n return false;\n }\n const ext = getFileExtension(url);\n if (SUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1) {\n return true;\n }\n if (ext === \"\" || ext === \".\") {\n return mimeType.includes(\"video/mp4\") || mimeType.includes(\"video/webm\") || mimeType.includes(\"m3u8\") || mimeType.includes(\"application/x-mpegurl\");\n }\n return false;\n}\nfunction createAdStormPlayer(contentVideo, options) {\n const { licenseKey, debug = false } = options;\n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = /* @__PURE__ */ new Map();\n let adVideoElement;\n let adContainerEl;\n let currentAd;\n let destroyed = false;\n let allowNativeHls = false;\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n function log(...args) {\n if (debug) {\n console.log(\"[AdStormPlayer]\", ...args);\n }\n }\n function emit(event, payload) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(`[AdStormPlayer] Error in event listener for ${event}:`, error);\n }\n }\n }\n function fireTrackingPixels(urls) {\n if (!urls || urls.length === 0) return;\n urls.forEach((url) => {\n try {\n const img = new Image(1, 1);\n img.src = url;\n log(\"Fired tracking pixel:\", url);\n } catch (error) {\n console.warn(\"[AdStormPlayer] Error firing tracking pixel:\", error);\n }\n });\n }\n function buildVastUrl(durationSeconds, metadata) {\n const baseUrl = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${licenseKey}/pod`;\n const defaultMetadata = {\n video: {\n codec: \"h264\",\n width: contentVideo.videoWidth || 1280,\n height: contentVideo.videoHeight || 720,\n fps: 29.97,\n bitrate: 5e3,\n profile: \"high\",\n pix_fmt: \"yuv420p\",\n has_b_frames: 0\n },\n audio: {\n codec: \"aac\",\n sample_rate: 48e3,\n bitrate: 128\n }\n };\n const finalMetadata = metadata || defaultMetadata;\n const metadataStr = encodeURIComponent(JSON.stringify(finalMetadata));\n return `${baseUrl}?duration=${Math.ceil(durationSeconds)}&metadata=${metadataStr}`;\n }\n function parseVastXml(xmlString) {\n const ads = [];\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\"[AdStormPlayer] XML parsing error:\", parserError.textContent);\n return [];\n }\n const adElements = xmlDoc.querySelectorAll(\"Ad\");\n adElements.forEach((adElement) => {\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = adElement.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n const durationText = adElement.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + parseFloat(durationParts[2] || \"0\");\n const mediaFileElements = adElement.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n mediaFileElements.forEach((mf) => {\n const type = mf.getAttribute(\"type\") || \"\";\n let url = mf.textContent?.trim() || \"\";\n const width = parseInt(mf.getAttribute(\"width\") || \"1920\", 10);\n const height = parseInt(mf.getAttribute(\"height\") || \"1080\", 10);\n const bitrate = mf.getAttribute(\"bitrate\") ? parseInt(mf.getAttribute(\"bitrate\"), 10) : void 0;\n if (!url) {\n log(`Skipping empty MediaFile URL`);\n return;\n }\n const originalUrl = url;\n url = replaceFlvExtension(url);\n if (url !== originalUrl) {\n log(`Converted FLV to MP4: ${originalUrl} -> ${url}`);\n }\n if (isUnsupportedFormat(url)) {\n const ext = getFileExtension(url);\n log(`Skipping unsupported format: ${url} (extension: ${ext}, declared type: ${type})`);\n return;\n }\n if (isSupportedFormat(url, type)) {\n mediaFiles.push({ url, type, width, height, bitrate });\n log(`Found media file: ${url} (${type}, ${width}x${height})`);\n } else {\n log(`Skipping incompatible media file: ${url} (type: ${type})`);\n }\n });\n if (mediaFiles.length === 0) {\n log(\"No valid media files found in ad:\", adId);\n return;\n }\n const trackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n error: []\n };\n adElement.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n adElement.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n const clickThrough = adElement.querySelector(\"ClickThrough\")?.textContent?.trim();\n ads.push({\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough\n });\n log(`Parsed ad: ${title}, duration: ${duration}s, media files: ${mediaFiles.length}`);\n });\n } catch (error) {\n console.error(\"[AdStormPlayer] Error parsing VAST XML:\", error);\n }\n return ads;\n }\n function selectBestMediaFile(mediaFiles) {\n if (mediaFiles.length === 0) return null;\n if (mediaFiles.length === 1) return mediaFiles[0];\n const mp4Files = mediaFiles.filter((mf) => mf.type.includes(\"video/mp4\"));\n const candidates = mp4Files.length > 0 ? mp4Files : mediaFiles;\n const targetWidth = contentVideo.videoWidth || 1280;\n const targetHeight = contentVideo.videoHeight || 720;\n candidates.sort((a, b) => {\n const diffA = Math.abs(a.width - targetWidth) + Math.abs(a.height - targetHeight);\n const diffB = Math.abs(b.width - targetWidth) + Math.abs(b.height - targetHeight);\n return diffA - diffB;\n });\n return candidates[0] || null;\n }\n function createAdVideoElement() {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.style.zIndex = \"15\";\n video.playsInline = true;\n video.muted = false;\n video.volume = originalMutedState ? 0 : originalVolume;\n return video;\n }\n function setAdPlayingFlag(isPlaying) {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n function setupAdEventListeners() {\n if (!adVideoElement || !currentAd) return;\n const ad = currentAd;\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!ad || !adVideoElement) return;\n const progress = adVideoElement.currentTime / ad.duration;\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(ad.trackingUrls.firstQuartile);\n }\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(ad.trackingUrls.midpoint);\n }\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(ad.trackingUrls.thirdQuartile);\n }\n });\n adVideoElement.addEventListener(\"playing\", () => {\n if (!ad || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(ad.trackingUrls.start);\n log(\"Ad started playing\");\n });\n adVideoElement.addEventListener(\"ended\", () => {\n if (!ad || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(ad.trackingUrls.complete);\n log(\"Ad completed\");\n handleAdComplete();\n });\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[AdStormPlayer] Ad video error:\", e);\n if (ad) {\n fireTrackingPixels(ad.trackingUrls.error);\n }\n handleAdError();\n });\n }\n function handleAdComplete() {\n log(\"Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n emit(\"content_resume\");\n emit(\"all_ads_completed\");\n }\n function handleAdError() {\n log(\"Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n emit(\"ad_error\");\n }\n async function fetchVast(durationSeconds) {\n const vastUrl = buildVastUrl(durationSeconds);\n log(\"Fetching VAST from:\", vastUrl);\n const response = await fetch(vastUrl, {\n headers: {\n \"Accept\": \"application/xml\"\n }\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.status} ${response.statusText}`);\n }\n const xmlText = await response.text();\n log(\"VAST response received, length:\", xmlText.length);\n return parseVastXml(xmlText);\n }\n return {\n initialize() {\n log(\"Initializing\");\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n async requestAds(duration) {\n log(\"Requesting ads for duration:\", duration);\n if (adPlaying) {\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n try {\n let durationSeconds = 30;\n const parsed = parseInt(duration, 10);\n if (!isNaN(parsed) && parsed > 0) {\n durationSeconds = parsed;\n }\n const ads = await fetchVast(durationSeconds);\n if (ads.length === 0) {\n log(\"No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.resolve();\n }\n currentAd = ads[0];\n log(`Ad loaded: ${currentAd.title}, duration: ${currentAd.duration}s`);\n fireTrackingPixels(currentAd.trackingUrls.impression);\n trackingFired.impression = true;\n return Promise.resolve();\n } catch (error) {\n console.error(\"[AdStormPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n async play() {\n if (!currentAd) {\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n log(\"Starting ad playback\");\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n contentVideo.style.transition = \"opacity 0.3s ease-in-out\";\n contentVideo.style.opacity = \"0\";\n setTimeout(() => {\n contentVideo.style.visibility = \"hidden\";\n }, 300);\n contentVideo.muted = true;\n contentVideo.volume = 0;\n if (allowNativeHls) {\n contentVideo.pause();\n }\n adPlaying = true;\n setAdPlayingFlag(true);\n if (adVideoElement) {\n adVideoElement.volume = originalMutedState ? 0 : originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n emit(\"content_pause\");\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available\");\n }\n log(\"Playing media file:\", mediaFile.url);\n adVideoElement.src = mediaFile.url;\n await adVideoElement.play();\n return Promise.resolve();\n } catch (error) {\n console.error(\"[AdStormPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n async stop() {\n log(\"Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n currentAd = void 0;\n },\n destroy() {\n log(\"Destroying\");\n destroyed = true;\n adPlaying = false;\n setAdPlayingFlag(false);\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = void 0;\n }\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n adContainerEl = void 0;\n currentAd = void 0;\n listeners.clear();\n },\n isAdPlaying() {\n return adPlaying;\n },\n resize(width, height) {\n log(`Resizing to ${width}x${height}`);\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());\n listeners.get(event).add(listener);\n },\n off(event, listener) {\n listeners.get(event)?.delete(listener);\n },\n updateOriginalMutedState(muted, volume) {\n const nextVolume = typeof volume === \"number\" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;\n log(`updateOriginalMutedState: muted=${muted}, volume=${nextVolume}`);\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n getOriginalMutedState() {\n return originalMutedState;\n },\n getOriginalVolume() {\n return originalVolume;\n },\n setAdVolume(volume) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n adVideoElement.muted = volume === 0;\n }\n },\n getAdVolume() {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n showPlaceholder() {\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n },\n setAllowNativeHls(value) {\n allowNativeHls = value;\n log(`allowNativeHls set to: ${value}`);\n }\n };\n}\n\n// src/utils/polyfills.ts\nfunction polyfillURLSearchParams() {\n if (typeof URLSearchParams !== \"undefined\") {\n return;\n }\n class URLSearchParamsPolyfill {\n constructor(init) {\n this.params = /* @__PURE__ */ new Map();\n if (typeof init === \"string\") {\n this.parseQueryString(init);\n } else if (init instanceof URLSearchParamsPolyfill) {\n init.forEach((value, key) => {\n this.append(key, value);\n });\n }\n }\n parseQueryString(query) {\n const cleanQuery = query.startsWith(\"?\") ? query.slice(1) : query;\n if (!cleanQuery) return;\n cleanQuery.split(\"&\").forEach((param) => {\n const [key, value] = param.split(\"=\");\n if (key) {\n const decodedKey = this.safeDecodeURIComponent(key);\n const decodedValue = value ? this.safeDecodeURIComponent(value) : \"\";\n this.append(decodedKey, decodedValue);\n }\n });\n }\n safeDecodeURIComponent(str) {\n try {\n return decodeURIComponent(str.replace(/\\+/g, \" \"));\n } catch (e) {\n return str;\n }\n }\n append(name, value) {\n const values = this.params.get(name) || [];\n values.push(String(value));\n this.params.set(name, values);\n }\n delete(name) {\n this.params.delete(name);\n }\n get(name) {\n const values = this.params.get(name);\n return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;\n }\n getAll(name) {\n return this.params.get(name) || [];\n }\n has(name) {\n return this.params.has(name);\n }\n set(name, value) {\n this.params.set(name, [String(value)]);\n }\n forEach(callback) {\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n callback(value, key, this);\n });\n });\n }\n toString() {\n const parts = [];\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n });\n });\n return parts.join(\"&\");\n }\n }\n window.URLSearchParams = URLSearchParamsPolyfill;\n}\nfunction polyfillTextEncoder() {\n if (typeof TextEncoder !== \"undefined\") {\n return;\n }\n class TextEncoderPolyfill {\n constructor() {\n this.encoding = \"utf-8\";\n }\n encode(str) {\n const utf8 = [];\n for (let i = 0; i < str.length; i++) {\n let charcode = str.charCodeAt(i);\n if (charcode < 128) {\n utf8.push(charcode);\n } else if (charcode < 2048) {\n utf8.push(192 | charcode >> 6, 128 | charcode & 63);\n } else if (charcode < 55296 || charcode >= 57344) {\n utf8.push(\n 224 | charcode >> 12,\n 128 | charcode >> 6 & 63,\n 128 | charcode & 63\n );\n } else {\n i++;\n charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);\n utf8.push(\n 240 | charcode >> 18,\n 128 | charcode >> 12 & 63,\n 128 | charcode >> 6 & 63,\n 128 | charcode & 63\n );\n }\n }\n return new Uint8Array(utf8);\n }\n }\n window.TextEncoder = TextEncoderPolyfill;\n}\nfunction polyfillPromiseFinally() {\n if (typeof Promise !== \"undefined\" && !Promise.prototype.finally) {\n Promise.prototype.finally = function(callback) {\n const constructor = this.constructor;\n return this.then(\n (value) => constructor.resolve(callback()).then(() => value),\n (reason) => constructor.resolve(callback()).then(() => {\n throw reason;\n })\n );\n };\n }\n}\nfunction polyfillObjectAssign() {\n if (typeof Object.assign !== \"function\") {\n Object.assign = function(target, ...sources) {\n if (target == null) {\n throw new TypeError(\"Cannot convert undefined or null to object\");\n }\n const to = Object(target);\n for (let i = 0; i < sources.length; i++) {\n const nextSource = sources[i];\n if (nextSource != null) {\n for (const nextKey in nextSource) {\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n };\n }\n}\nfunction polyfillArrayFrom() {\n if (!Array.from) {\n Array.from = function(arrayLike, mapFn, thisArg) {\n const items = Object(arrayLike);\n if (arrayLike == null) {\n throw new TypeError(\"Array.from requires an array-like object\");\n }\n const len = items.length >>> 0;\n const result = new Array(len);\n for (let i = 0; i < len; i++) {\n if (mapFn) {\n result[i] = mapFn.call(thisArg, items[i], i);\n } else {\n result[i] = items[i];\n }\n }\n return result;\n };\n }\n}\nfunction polyfillStringStartsWith() {\n if (!String.prototype.startsWith) {\n String.prototype.startsWith = function(search, pos) {\n pos = !pos || pos < 0 ? 0 : +pos;\n return this.substring(pos, pos + search.length) === search;\n };\n }\n}\nfunction polyfillStringEndsWith() {\n if (!String.prototype.endsWith) {\n String.prototype.endsWith = function(search, length) {\n if (length === void 0 || length > this.length) {\n length = this.length;\n }\n return this.substring(length - search.length, length) === search;\n };\n }\n}\nfunction polyfillStringIncludes() {\n if (!String.prototype.includes) {\n String.prototype.includes = function(search, start) {\n if (typeof start !== \"number\") {\n start = 0;\n }\n if (start + search.length > this.length) {\n return false;\n }\n return this.indexOf(search, start) !== -1;\n };\n }\n}\nfunction initializePolyfills() {\n polyfillObjectAssign();\n polyfillArrayFrom();\n polyfillStringStartsWith();\n polyfillStringEndsWith();\n polyfillStringIncludes();\n polyfillURLSearchParams();\n polyfillTextEncoder();\n polyfillPromiseFinally();\n}\n\n// src/utils/browserCompat.ts\nfunction getChromeVersion(ua) {\n const match = ua.match(/Chrome\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getWebKitVersion(ua) {\n const match = ua.match(/AppleWebKit\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\nfunction getPlatform() {\n if (\"userAgentData\" in navigator && navigator.userAgentData?.platform) {\n return navigator.userAgentData.platform;\n }\n const ua = navigator.userAgent;\n if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n return /iPhone|iPad|iPod/i.test(ua) ? \"iPhone\" : \"MacIntel\";\n }\n if (/Win/i.test(ua)) {\n return \"Win32\";\n }\n if (/Linux/i.test(ua)) {\n return /Android/i.test(ua) ? \"Linux armv8l\" : \"Linux x86_64\";\n }\n if (/CrOS/i.test(ua)) {\n return \"CrOS\";\n }\n return navigator.platform || \"Unknown\";\n}\nfunction detectBrowser() {\n const ua = navigator.userAgent;\n const platform = getPlatform();\n let name = \"Unknown\";\n let version = \"0\";\n let majorVersion = 0;\n let isSmartTV = false;\n let isLegacyTV = false;\n let supportsModernJS = true;\n if (/Web0S|webOS/i.test(ua)) {\n name = \"LG WebOS\";\n isSmartTV = true;\n const match = ua.match(/Web0S[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : \"Unknown\";\n if (version !== \"Unknown\") {\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/Tizen/i.test(ua)) {\n name = \"Samsung Tizen\";\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : \"Unknown\";\n if (version !== \"Unknown\") {\n const parts = version.split(\".\");\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = \"Smart TV\";\n isSmartTV = true;\n } else if (/NetCast/i.test(ua)) {\n name = \"LG NetCast\";\n isSmartTV = true;\n isLegacyTV = true;\n } else if (/BRAVIA/i.test(ua)) {\n name = \"Sony BRAVIA\";\n isSmartTV = true;\n }\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n if (chromeVersion > 0) {\n if (!isSmartTV) {\n name = \"Chrome\";\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n }\n if (chromeVersion < 50) {\n supportsModernJS = false;\n isLegacyTV = true;\n }\n }\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (isSmartTV) {\n isLegacyTV = true;\n }\n }\n if (typeof Promise === \"undefined\" || typeof Map === \"undefined\" || typeof Set === \"undefined\") {\n supportsModernJS = false;\n }\n if (typeof URLSearchParams === \"undefined\") {\n supportsModernJS = false;\n }\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsModernJS\n };\n}\nfunction logBrowserInfo(debug = false) {\n if (!debug) return;\n const browser = detectBrowser();\n console.log(\"[StormcloudVideoPlayer] Browser Compatibility Info:\", {\n browser: `${browser.name} ${browser.version}`,\n platform: browser.platform,\n isSmartTV: browser.isSmartTV,\n isLegacyTV: browser.isLegacyTV,\n supportsModernJS: browser.supportsModernJS,\n userAgent: navigator.userAgent\n });\n}\nfunction getBrowserConfigOverrides() {\n const browser = detectBrowser();\n const overrides = {};\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n return overrides;\n}\n\n// src/player/StormcloudVideoPlayer.ts\nvar StormcloudVideoPlayer = class {\n constructor(config) {\n this.attached = false;\n this.inAdBreak = false;\n this.ptsDriftEmaMs = 0;\n this.isLiveStream = false;\n this.nativeHlsMode = false;\n this.videoSrcProtection = null;\n this.bufferedSegmentsCount = 0;\n this.shouldAutoplayAfterBuffering = false;\n this.hasInitialBufferCompleted = false;\n initializePolyfills();\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...config, ...browserOverrides };\n this.video = config.videoElement;\n logBrowserInfo(config.debugAdTiming);\n if (!this.config.licenseKey) {\n console.warn(\"[StormcloudVideoPlayer] No license key provided - ads will not work\");\n }\n this.adPlayer = createAdStormPlayer(this.video, {\n licenseKey: this.config.licenseKey || \"\",\n debug: this.config.debugAdTiming ?? false\n });\n }\n async load() {\n if (!this.attached) {\n this.attach();\n }\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Using native HLS playback:\", {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls\n });\n }\n this.adPlayer.initialize();\n this.adPlayer.setAllowNativeHls(!!this.config.allowNativeHls);\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n return;\n }\n this.hls = new import_hls.default({\n enableWorker: true,\n backBufferLength: 30,\n liveDurationInfinity: true,\n lowLatencyMode: !!this.config.lowLatencyMode,\n maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1,\n ...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {},\n maxBufferLength: 30,\n maxMaxBufferLength: 600,\n maxBufferSize: 60 * 1e3 * 1e3,\n maxBufferHole: 0.5,\n highBufferWatchdogPeriod: 2,\n nudgeOffset: 0.1,\n nudgeMaxRetry: 3,\n startPosition: -1\n });\n this.hls.on(import_hls.default.Events.MEDIA_ATTACHED, () => {\n this.hls?.loadSource(this.config.src);\n });\n this.hls.on(import_hls.default.Events.MANIFEST_PARSED, async () => {\n this.isLiveStream = this.hls?.levels?.some(\n (level) => level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n isLive: this.isLiveStream\n });\n }\n this.adPlayer.initialize();\n this.adPlayer.setAllowNativeHls(!!this.config.allowNativeHls);\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Waiting for\",\n minSegments,\n \"segments to buffer before playback\"\n );\n }\n if (minSegments === 0 || !this.config.autoplay) {\n this.hasInitialBufferCompleted = true;\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {\n });\n }\n }\n });\n this.hls.on(import_hls.default.Events.FRAG_BUFFERED, async () => {\n if (this.hasInitialBufferCompleted) {\n return;\n }\n this.bufferedSegmentsCount++;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n );\n }\n if (this.bufferedSegmentsCount >= minSegments) {\n this.hasInitialBufferCompleted = true;\n if (this.shouldAutoplayAfterBuffering) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete. Starting playback.`\n );\n }\n await this.video.play()?.catch((err) => {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n this.hls.on(import_hls.default.Events.FRAG_PARSING_METADATA, (_evt, data) => {\n const id3Tags = (data?.samples || []).map((s) => ({\n key: \"ID3\",\n value: s?.data,\n ptsSeconds: s?.pts\n }));\n id3Tags.forEach((tag) => this.onId3Tag(tag));\n });\n this.hls.on(import_hls.default.Events.FRAG_CHANGED, (_evt, data) => {\n const frag = data?.frag;\n const tagList = frag?.tagList;\n if (!Array.isArray(tagList)) return;\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n value = \"\";\n }\n }\n if (!tag) continue;\n if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n this.onScte35Marker({\n type: \"start\",\n ...durationSeconds !== void 0 ? { durationSeconds } : {},\n raw: { tag, value }\n });\n } else if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = this.parseCueOutCont(value);\n this.onScte35Marker({\n type: \"progress\",\n ...prog?.duration !== void 0 ? { durationSeconds: prog.duration } : {},\n ...prog?.elapsed !== void 0 ? { ptsSeconds: prog.elapsed } : {},\n raw: { tag, value }\n });\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut = \"SCTE35-OUT\" in attrs;\n const hasScteIn = \"SCTE35-IN\" in attrs;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]) ?? this.toNumber(attrs[\"PLANNED-DURATION\"]);\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n this.onScte35Marker({\n type: \"start\",\n ...duration !== void 0 ? { durationSeconds: duration } : {},\n raw: { tag, value, attrs }\n });\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\n });\n this.hls.on(import_hls.default.Events.ERROR, (_evt, data) => {\n if (data?.fatal) {\n switch (data.type) {\n case import_hls.default.ErrorTypes.NETWORK_ERROR:\n this.hls?.startLoad();\n break;\n case import_hls.default.ErrorTypes.MEDIA_ERROR:\n this.hls?.recoverMediaError();\n break;\n default:\n this.destroy();\n break;\n }\n }\n });\n this.hls.attachMedia(this.video);\n }\n attach() {\n if (this.attached) return;\n this.attached = true;\n this.video.autoplay = !!this.config.autoplay;\n this.video.muted = !!this.config.muted;\n this.adPlayer.initialize();\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n this.adPlayer.on(\"all_ads_completed\", () => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad completed - ending ad break\");\n }\n if (this.inAdBreak) {\n this.handleAdPodComplete();\n }\n });\n this.adPlayer.on(\"ad_error\", () => {\n console.error(\"[StormcloudVideoPlayer] Ad error occurred\");\n if (this.inAdBreak) {\n this.handleAdPodComplete();\n }\n });\n this.adPlayer.on(\"content_pause\", () => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content paused for ad\");\n }\n });\n this.adPlayer.on(\"content_resume\", () => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content resuming after ad\");\n }\n });\n this.timeUpdateHandler = () => {\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n this.emptiedHandler = () => {\n if (this.nativeHlsMode && this.videoSrcProtection && !this.adPlayer.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Video src was cleared, restoring\");\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {\n });\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n shouldUseNativeHls() {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return true;\n }\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n onId3Tag(tag) {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n parseScte35FromId3(tag) {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return void 0;\n const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) || text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n return {\n type: \"start\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...dur !== void 0 ? { durationSeconds: dur } : {},\n raw: { id3: text }\n };\n }\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n return {\n type: \"progress\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n ...cont?.duration !== void 0 ? { durationSeconds: cont.duration } : {},\n raw: { id3: text }\n };\n }\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n return {\n type: \"end\",\n ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},\n raw: { id3: text }\n };\n }\n return void 0;\n }\n decodeId3ValueToText(value) {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++) {\n out += String.fromCharCode(value[i]);\n }\n return out;\n } catch {\n return void 0;\n }\n }\n async onScte35Marker(marker) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime\n });\n }\n if (marker.type === \"start\") {\n if (this.inAdBreak) {\n return;\n }\n this.inAdBreak = true;\n const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : 3e4;\n this.expectedAdBreakDurationMs = durationMs;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break:\", {\n durationMs,\n durationSeconds: marker.durationSeconds\n });\n }\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n await this.handleAdStart(marker);\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;\n }\n return;\n }\n if (marker.type === \"end\") {\n if (!this.inAdBreak) return;\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.clearAdStopTimer();\n if (this.adPlayer.isAdPlaying()) {\n await this.adPlayer.stop();\n }\n this.handleAdPodComplete();\n return;\n }\n }\n async handleAdStart(marker) {\n const durationSeconds = marker.durationSeconds ?? 30;\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Requesting ads for duration:\", durationSeconds);\n }\n try {\n await this.adPlayer.requestAds(String(durationSeconds));\n await this.adPlayer.play();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Ad request/play failed:\", error);\n }\n this.handleAdPodComplete();\n }\n }\n parseCueOutDuration(value) {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match = value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) || value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const d = parseFloat(match[1]);\n return Number.isNaN(d) ? void 0 : d;\n }\n return void 0;\n }\n parseCueOutCont(value) {\n const elapsedMatch = value.match(/Elapsed\\s*=\\s*([0-9.]+)/i);\n const durationMatch = value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n const res = {};\n if (elapsedMatch && elapsedMatch[1] != null) {\n const e = parseFloat(elapsedMatch[1]);\n if (!Number.isNaN(e)) res.elapsed = e;\n }\n if (durationMatch && durationMatch[1] != null) {\n const d = parseFloat(durationMatch[1]);\n if (!Number.isNaN(d)) res.duration = d;\n }\n if (\"elapsed\" in res || \"duration\" in res) return res;\n return void 0;\n }\n parseAttributeList(value) {\n const attrs = {};\n const regex = /([A-Z0-9-]+)=((\"[^\"]*\")|([^\",]*))(?:,|$)/gi;\n let match;\n while ((match = regex.exec(value)) !== null) {\n const key = match[1] ?? \"\";\n let rawVal = match[3] ?? match[4] ?? \"\";\n if (rawVal.startsWith('\"') && rawVal.endsWith('\"')) {\n rawVal = rawVal.slice(1, -1);\n }\n if (key) {\n attrs[key] = rawVal;\n }\n }\n return attrs;\n }\n toNumber(val) {\n if (val == null) return void 0;\n const n = typeof val === \"string\" ? parseFloat(val) : Number(val);\n return Number.isNaN(n) ? void 0 : n;\n }\n scheduleAdStopCountdown(remainingMs) {\n this.clearAdStopTimer();\n const ms = Math.max(0, Math.floor(remainingMs));\n if (ms === 0) {\n this.handleAdPodComplete();\n return;\n }\n this.adStopTimerId = window.setTimeout(() => {\n this.handleAdPodComplete();\n }, ms);\n }\n clearAdStopTimer() {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = void 0;\n }\n }\n updatePtsDrift(ptsSecondsSample) {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1e3;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 6e4) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n handleAdPodComplete() {\n this.clearAdStopTimer();\n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = void 0;\n this.adPlayer.stop().catch(() => {\n });\n const restoredMuted = this.adPlayer.getOriginalMutedState();\n const restoredVolume = this.adPlayer.getOriginalVolume();\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n if (this.video.paused) {\n this.video.play()?.catch(() => {\n });\n }\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad break complete\");\n }\n }\n isAdPlaying() {\n return this.inAdBreak && this.adPlayer.isAdPlaying();\n }\n isShowingAds() {\n return this.adPlayer.isAdPlaying();\n }\n getStreamType() {\n const url = this.config.src.toLowerCase();\n if (url.includes(\".m3u8\") || url.includes(\"/hls/\") || url.includes(\"application/vnd.apple.mpegurl\")) {\n return \"hls\";\n }\n return \"other\";\n }\n shouldShowNativeControls() {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return !(this.config.showCustomControls ?? false);\n }\n return !!(this.config.allowNativeHls && !(this.config.showCustomControls ?? false));\n }\n toggleMute() {\n if (this.adPlayer.isAdPlaying()) {\n const currentMuted = this.video.muted;\n const newMutedState = !currentMuted;\n this.adPlayer.updateOriginalMutedState(newMutedState, this.video.volume);\n this.adPlayer.setAdVolume(newMutedState ? 0 : 1);\n } else {\n this.video.muted = !this.video.muted;\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n }\n }\n toggleFullscreen() {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container.requestFullscreen().then(() => resolve()).catch(reject);\n } else {\n document.exitFullscreen().then(() => resolve()).catch(reject);\n }\n });\n }\n isMuted() {\n return this.video.muted;\n }\n setMuted(muted) {\n this.video.muted = muted;\n this.adPlayer.updateOriginalMutedState(muted, this.video.volume);\n if (this.adPlayer.isAdPlaying()) {\n this.adPlayer.setAdVolume(muted ? 0 : 1);\n }\n }\n setVolume(volume) {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n if (this.adPlayer.isAdPlaying()) {\n this.adPlayer.setAdVolume(clampedVolume);\n this.adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n }\n }\n isFullscreen() {\n return !!document.fullscreenElement;\n }\n isLive() {\n return this.isLiveStream;\n }\n get videoElement() {\n return this.video;\n }\n resize() {\n if (this.adPlayer && this.adPlayer.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 360;\n this.adPlayer.resize(width, height);\n }\n }\n destroy() {\n this.clearAdStopTimer();\n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n this.hls?.destroy();\n this.adPlayer?.destroy();\n }\n getCurrentAdIndex() {\n return 0;\n }\n getTotalAdsInBreak() {\n return 1;\n }\n};\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/HlsPlayer.tsx\nvar HlsPlayer = class extends import_react.Component {\n constructor() {\n super(...arguments);\n this.player = null;\n this.mounted = false;\n this.load = async () => {\n if (!this.props.videoElement || !this.props.src) return;\n try {\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n const config = {\n src: this.props.src,\n videoElement: this.props.videoElement\n };\n if (this.props.autoplay !== void 0)\n config.autoplay = this.props.autoplay;\n if (this.props.muted !== void 0) config.muted = this.props.muted;\n if (this.props.lowLatencyMode !== void 0)\n config.lowLatencyMode = this.props.lowLatencyMode;\n if (this.props.allowNativeHls !== void 0)\n config.allowNativeHls = this.props.allowNativeHls;\n if (this.props.driftToleranceMs !== void 0)\n config.driftToleranceMs = this.props.driftToleranceMs;\n if (this.props.immediateManifestAds !== void 0)\n config.immediateManifestAds = this.props.immediateManifestAds;\n if (this.props.debugAdTiming !== void 0)\n config.debugAdTiming = this.props.debugAdTiming;\n if (this.props.showCustomControls !== void 0)\n config.showCustomControls = this.props.showCustomControls;\n if (this.props.onVolumeToggle !== void 0)\n config.onVolumeToggle = this.props.onVolumeToggle;\n if (this.props.onFullscreenToggle !== void 0)\n config.onFullscreenToggle = this.props.onFullscreenToggle;\n if (this.props.onControlClick !== void 0)\n config.onControlClick = this.props.onControlClick;\n if (this.props.licenseKey !== void 0)\n config.licenseKey = this.props.licenseKey;\n if (this.props.adFailsafeTimeoutMs !== void 0)\n config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;\n if (this.props.minSegmentsBeforePlay !== void 0)\n config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;\n this.player = new StormcloudVideoPlayer(config);\n this.props.onMount?.(this);\n await this.player.load();\n if (this.mounted) {\n this.props.onReady?.();\n }\n } catch (error) {\n if (this.mounted) {\n this.props.onError?.(error);\n }\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(\"[HlsPlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n this.props.onPlay?.();\n } else {\n console.warn(\"[HlsPlayer] Cannot play: video has no valid source\");\n }\n }\n };\n this.pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n this.props.onPause?.();\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.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 === \"player\") return this.player;\n if (key === \"video\") return this.props.videoElement;\n if (key === \"hls\" && this.player) return this.player.hls;\n return null;\n };\n }\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n componentWillUnmount() {\n this.mounted = false;\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n }\n componentDidUpdate(prevProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n render() {\n return null;\n }\n};\nHlsPlayer.displayName = \"HlsPlayer\";\nHlsPlayer.canPlay = canPlay.hls;\n","import type { AdController } from \"../types\";\n\ninterface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\nconst SUPPORTED_VIDEO_EXTENSIONS = ['.mp4', '.webm', '.ogg', '.m3u8', '.ts'];\nconst UNSUPPORTED_VIDEO_EXTENSIONS = ['.flv', '.f4v', '.swf', '.wmv', '.avi', '.mov', '.mkv'];\n\nfunction getFileExtension(url: string): string {\n try {\n const pathname = new URL(url, 'http://dummy').pathname;\n const lastDot = pathname.lastIndexOf('.');\n if (lastDot === -1) return '';\n return pathname.slice(lastDot).toLowerCase();\n } catch {\n const lastDot = url.lastIndexOf('.');\n if (lastDot === -1) return '';\n const ext = url.slice(lastDot).split(/[?#]/)[0];\n return (ext || '').toLowerCase();\n }\n}\n\nfunction isUnsupportedFormat(url: string): boolean {\n const ext = getFileExtension(url);\n return UNSUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1;\n}\n\nfunction replaceFlvExtension(url: string): string {\n const ext = getFileExtension(url);\n if (ext === '.flv') {\n return url.replace(/\\.flv(\\?|$)/i, '.mp4$1');\n }\n return url;\n}\n\nfunction isSupportedFormat(url: string, mimeType: string): boolean {\n if (isUnsupportedFormat(url)) {\n return false;\n }\n \n const ext = getFileExtension(url);\n \n if (SUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1) {\n return true;\n }\n \n if (ext === '' || ext === '.') {\n return mimeType.includes('video/mp4') || \n mimeType.includes('video/webm') || \n mimeType.includes('m3u8') ||\n mimeType.includes('application/x-mpegurl');\n }\n \n return false;\n}\n\ninterface VastTrackingUrls {\n impression: string[];\n start: string[];\n firstQuartile: string[];\n midpoint: string[];\n thirdQuartile: string[];\n complete: string[];\n error: string[];\n}\n\ninterface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\ninterface AdStormMetadata {\n video?: {\n codec?: string;\n width?: number;\n height?: number;\n fps?: number;\n bitrate?: number;\n profile?: string;\n pix_fmt?: string;\n has_b_frames?: number;\n };\n audio?: {\n codec?: string;\n sample_rate?: number;\n bitrate?: number;\n };\n}\n\nexport interface AdStormPlayerOptions {\n licenseKey: string;\n debug?: boolean;\n}\n\nexport function createAdStormPlayer(\n contentVideo: HTMLVideoElement,\n options: AdStormPlayerOptions\n): AdController {\n const { licenseKey, debug = false } = options;\n \n let adPlaying = false;\n let originalMutedState = false;\n let originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n \n let adVideoElement: HTMLVideoElement | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let currentAd: VastAd | undefined;\n let destroyed = false;\n let allowNativeHls = false;\n \n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n function log(...args: any[]): void {\n if (debug) {\n console.log(\"[AdStormPlayer]\", ...args);\n }\n }\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(`[AdStormPlayer] Error in event listener for ${event}:`, error);\n }\n }\n }\n\n function fireTrackingPixels(urls: string[]): void {\n if (!urls || urls.length === 0) return;\n \n urls.forEach((url) => {\n try {\n const img = new Image(1, 1);\n img.src = url;\n log(\"Fired tracking pixel:\", url);\n } catch (error) {\n console.warn(\"[AdStormPlayer] Error firing tracking pixel:\", error);\n }\n });\n }\n\n function buildVastUrl(durationSeconds: number, metadata?: AdStormMetadata): string {\n const baseUrl = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${licenseKey}/pod`;\n \n const defaultMetadata: AdStormMetadata = {\n video: {\n codec: \"h264\",\n width: contentVideo.videoWidth || 1280,\n height: contentVideo.videoHeight || 720,\n fps: 29.97,\n bitrate: 5000,\n profile: \"high\",\n pix_fmt: \"yuv420p\",\n has_b_frames: 0,\n },\n audio: {\n codec: \"aac\",\n sample_rate: 48000,\n bitrate: 128,\n },\n };\n \n const finalMetadata = metadata || defaultMetadata;\n const metadataStr = encodeURIComponent(JSON.stringify(finalMetadata));\n \n return `${baseUrl}?duration=${Math.ceil(durationSeconds)}&metadata=${metadataStr}`;\n }\n\n function parseVastXml(xmlString: string): VastAd[] {\n const ads: VastAd[] = [];\n \n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n \n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\"[AdStormPlayer] XML parsing error:\", parserError.textContent);\n return [];\n }\n \n const adElements = xmlDoc.querySelectorAll(\"Ad\");\n \n adElements.forEach((adElement) => {\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = adElement.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n \n const durationText = adElement.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration =\n parseInt(durationParts[0] || \"0\", 10) * 3600 +\n parseInt(durationParts[1] || \"0\", 10) * 60 +\n parseFloat(durationParts[2] || \"0\");\n \n const mediaFileElements = adElement.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n \n mediaFileElements.forEach((mf) => {\n const type = mf.getAttribute(\"type\") || \"\";\n let url = mf.textContent?.trim() || \"\";\n const width = parseInt(mf.getAttribute(\"width\") || \"1920\", 10);\n const height = parseInt(mf.getAttribute(\"height\") || \"1080\", 10);\n const bitrate = mf.getAttribute(\"bitrate\") \n ? parseInt(mf.getAttribute(\"bitrate\")!, 10) \n : undefined;\n \n if (!url) {\n log(`Skipping empty MediaFile URL`);\n return;\n }\n \n const originalUrl = url;\n url = replaceFlvExtension(url);\n if (url !== originalUrl) {\n log(`Converted FLV to MP4: ${originalUrl} -> ${url}`);\n }\n \n if (isUnsupportedFormat(url)) {\n const ext = getFileExtension(url);\n log(`Skipping unsupported format: ${url} (extension: ${ext}, declared type: ${type})`);\n return;\n }\n \n if (isSupportedFormat(url, type)) {\n mediaFiles.push({ url, type, width, height, bitrate });\n log(`Found media file: ${url} (${type}, ${width}x${height})`);\n } else {\n log(`Skipping incompatible media file: ${url} (type: ${type})`);\n }\n });\n \n if (mediaFiles.length === 0) {\n log(\"No valid media files found in ad:\", adId);\n return;\n }\n \n const trackingUrls: VastTrackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n error: [],\n };\n \n adElement.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n \n adElement.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event as keyof VastTrackingUrls;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n \n const clickThrough = adElement.querySelector(\"ClickThrough\")?.textContent?.trim();\n \n ads.push({\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough,\n });\n \n log(`Parsed ad: ${title}, duration: ${duration}s, media files: ${mediaFiles.length}`);\n });\n \n } catch (error) {\n console.error(\"[AdStormPlayer] Error parsing VAST XML:\", error);\n }\n \n return ads;\n }\n\n function selectBestMediaFile(mediaFiles: VastMediaFile[]): VastMediaFile | null {\n if (mediaFiles.length === 0) return null;\n if (mediaFiles.length === 1) return mediaFiles[0]!;\n \n const mp4Files = mediaFiles.filter(mf => mf.type.includes(\"video/mp4\"));\n const candidates = mp4Files.length > 0 ? mp4Files : mediaFiles;\n \n const targetWidth = contentVideo.videoWidth || 1280;\n const targetHeight = contentVideo.videoHeight || 720;\n \n candidates.sort((a, b) => {\n const diffA = Math.abs(a.width - targetWidth) + Math.abs(a.height - targetHeight);\n const diffB = Math.abs(b.width - targetWidth) + Math.abs(b.height - targetHeight);\n return diffA - diffB;\n });\n \n return candidates[0] || null;\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.style.zIndex = \"15\";\n video.playsInline = true;\n video.muted = false;\n video.volume = originalMutedState ? 0 : originalVolume;\n \n return video;\n }\n\n function setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement || !currentAd) return;\n \n const ad = currentAd;\n \n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!ad || !adVideoElement) return;\n \n const progress = adVideoElement.currentTime / ad.duration;\n \n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(ad.trackingUrls.firstQuartile);\n }\n \n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(ad.trackingUrls.midpoint);\n }\n \n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(ad.trackingUrls.thirdQuartile);\n }\n });\n \n adVideoElement.addEventListener(\"playing\", () => {\n if (!ad || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(ad.trackingUrls.start);\n log(\"Ad started playing\");\n });\n \n adVideoElement.addEventListener(\"ended\", () => {\n if (!ad || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(ad.trackingUrls.complete);\n log(\"Ad completed\");\n handleAdComplete();\n });\n \n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[AdStormPlayer] Ad video error:\", e);\n if (ad) {\n fireTrackingPixels(ad.trackingUrls.error);\n }\n handleAdError();\n });\n }\n\n function handleAdComplete(): void {\n log(\"Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n \n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n \n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n \n emit(\"content_resume\");\n emit(\"all_ads_completed\");\n }\n\n function handleAdError(): void {\n log(\"Handling ad error\");\n adPlaying = false;\n setAdPlayingFlag(false);\n \n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n \n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n \n emit(\"ad_error\");\n }\n\n async function fetchVast(durationSeconds: number): Promise<VastAd[]> {\n const vastUrl = buildVastUrl(durationSeconds);\n log(\"Fetching VAST from:\", vastUrl);\n \n const response = await fetch(vastUrl, {\n headers: {\n \"Accept\": \"application/xml\",\n },\n });\n \n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.status} ${response.statusText}`);\n }\n \n const xmlText = await response.text();\n log(\"VAST response received, length:\", xmlText.length);\n \n return parseVastXml(xmlText);\n }\n\n return {\n initialize() {\n log(\"Initializing\");\n \n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n container.style.transition = \"opacity 0.3s ease-in-out\";\n container.style.opacity = \"0\";\n \n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n\n async requestAds(duration: string) {\n log(\"Requesting ads for duration:\", duration);\n \n if (adPlaying) {\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n \n try {\n let durationSeconds = 30;\n const parsed = parseInt(duration, 10);\n if (!isNaN(parsed) && parsed > 0) {\n durationSeconds = parsed;\n }\n \n const ads = await fetchVast(durationSeconds);\n \n if (ads.length === 0) {\n log(\"No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.resolve();\n }\n \n currentAd = ads[0];\n log(`Ad loaded: ${currentAd!.title}, duration: ${currentAd!.duration}s`);\n \n fireTrackingPixels(currentAd!.trackingUrls.impression);\n trackingFired.impression = true;\n \n return Promise.resolve();\n } catch (error) {\n console.error(\"[AdStormPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n\n async play() {\n if (!currentAd) {\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n \n log(\"Starting ad playback\");\n \n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n \n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n \n contentVideo.style.transition = \"opacity 0.3s ease-in-out\";\n contentVideo.style.opacity = \"0\";\n setTimeout(() => {\n contentVideo.style.visibility = \"hidden\";\n }, 300);\n contentVideo.muted = true;\n contentVideo.volume = 0;\n \n if (allowNativeHls) {\n contentVideo.pause();\n }\n \n adPlaying = true;\n setAdPlayingFlag(true);\n \n if (adVideoElement) {\n adVideoElement.volume = originalMutedState ? 0 : originalVolume;\n adVideoElement.muted = originalMutedState;\n }\n \n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n adContainerEl.offsetHeight;\n adContainerEl.style.opacity = \"1\";\n }\n \n emit(\"content_pause\");\n \n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available\");\n }\n \n log(\"Playing media file:\", mediaFile.url);\n adVideoElement!.src = mediaFile.url;\n \n await adVideoElement!.play();\n \n return Promise.resolve();\n } catch (error) {\n console.error(\"[AdStormPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n\n async stop() {\n log(\"Stopping ad\");\n adPlaying = false;\n setAdPlayingFlag(false);\n \n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n \n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n \n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n \n currentAd = undefined;\n },\n\n destroy() {\n log(\"Destroying\");\n destroyed = true;\n adPlaying = false;\n setAdPlayingFlag(false);\n \n contentVideo.muted = originalMutedState;\n contentVideo.volume = originalVolume;\n contentVideo.style.visibility = \"visible\";\n contentVideo.style.opacity = \"1\";\n \n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n \n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n \n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\n log(`Resizing to ${width}x${height}`);\n \n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n \n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n\n updateOriginalMutedState(muted: boolean, volume?: number) {\n const nextVolume =\n typeof volume === \"number\" && !Number.isNaN(volume)\n ? Math.max(0, Math.min(1, volume))\n : originalVolume;\n log(`updateOriginalMutedState: muted=${muted}, volume=${nextVolume}`);\n originalMutedState = muted;\n originalVolume = nextVolume;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n\n getOriginalVolume() {\n return originalVolume;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n adVideoElement.muted = volume === 0;\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n\n showPlaceholder() {\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"10\";\n container.style.backgroundColor = \"#000\";\n \n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n \n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.opacity = \"1\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n },\n\n hidePlaceholder() {\n if (adContainerEl) {\n adContainerEl.style.opacity = \"0\";\n setTimeout(() => {\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n }, 300);\n }\n },\n\n setAllowNativeHls(value: boolean) {\n allowNativeHls = value;\n log(`allowNativeHls set to: ${value}`);\n },\n };\n}\n\n","import { Component } from \"react\";\nimport { StormcloudVideoPlayer } from \"../player/StormcloudVideoPlayer\";\nimport type { StormcloudVideoPlayerConfig } from \"../types\";\nimport { canPlay } from \"../patterns\";\n\nexport interface HlsPlayerProps extends StormcloudVideoPlayerConfig {\n onMount?: (player: any) => void;\n onReady?: () => void;\n onPlay?: () => void;\n onPause?: () => void;\n onEnded?: () => void;\n onLoaded?: () => void;\n onError?: (error: any) => void;\n}\n\nexport default class HlsPlayer extends Component<HlsPlayerProps> {\n static displayName = \"HlsPlayer\";\n\n static canPlay = canPlay.hls;\n\n private player: StormcloudVideoPlayer | null = null;\n private mounted = false;\n\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n\n componentWillUnmount() {\n this.mounted = false;\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n }\n\n componentDidUpdate(prevProps: HlsPlayerProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n\n load = async () => {\n if (!this.props.videoElement || !this.props.src) return;\n\n try {\n if (this.player) {\n this.player.destroy();\n this.player = null;\n }\n\n const config: StormcloudVideoPlayerConfig = {\n src: this.props.src,\n videoElement: this.props.videoElement,\n };\n\n if (this.props.autoplay !== undefined)\n config.autoplay = this.props.autoplay;\n if (this.props.muted !== undefined) config.muted = this.props.muted;\n if (this.props.lowLatencyMode !== undefined)\n config.lowLatencyMode = this.props.lowLatencyMode;\n if (this.props.allowNativeHls !== undefined)\n config.allowNativeHls = this.props.allowNativeHls;\n if (this.props.driftToleranceMs !== undefined)\n config.driftToleranceMs = this.props.driftToleranceMs;\n if (this.props.immediateManifestAds !== undefined)\n config.immediateManifestAds = this.props.immediateManifestAds;\n if (this.props.debugAdTiming !== undefined)\n config.debugAdTiming = this.props.debugAdTiming;\n if (this.props.showCustomControls !== undefined)\n config.showCustomControls = this.props.showCustomControls;\n if (this.props.onVolumeToggle !== undefined)\n config.onVolumeToggle = this.props.onVolumeToggle;\n if (this.props.onFullscreenToggle !== undefined)\n config.onFullscreenToggle = this.props.onFullscreenToggle;\n if (this.props.onControlClick !== undefined)\n config.onControlClick = this.props.onControlClick;\n if (this.props.licenseKey !== undefined)\n config.licenseKey = this.props.licenseKey;\n if (this.props.adFailsafeTimeoutMs !== undefined)\n config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;\n if (this.props.minSegmentsBeforePlay !== undefined)\n config.minSegmentsBeforePlay = this.props.minSegmentsBeforePlay;\n\n this.player = new StormcloudVideoPlayer(config);\n\n this.props.onMount?.(this);\n\n await this.player.load();\n\n if (this.mounted) {\n this.props.onReady?.();\n }\n } catch (error) {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n }\n };\n\n play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource =\n video.src ||\n (video.currentSrc && video.currentSrc !== \"\") ||\n video.readyState >= 1;\n\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[HlsPlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n this.props.onPlay?.();\n } else {\n console.warn(\"[HlsPlayer] Cannot play: video has no valid source\");\n }\n }\n };\n\n pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n this.props.onPause?.();\n }\n };\n\n stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n\n seekTo = (seconds: number, keepPlaying?: boolean) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n\n setVolume = (volume: number) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n\n mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n\n unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n\n setPlaybackRate = (rate: number) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n\n getDuration = (): number | null => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n\n getCurrentTime = (): number | null => {\n if (\n this.props.videoElement &&\n isFinite(this.props.videoElement.currentTime)\n ) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n\n getSecondsLoaded = (): number | null => {\n if (\n this.props.videoElement &&\n this.props.videoElement.buffered.length > 0\n ) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n\n getInternalPlayer = (key = \"player\") => {\n if (key === \"player\") return this.player;\n if (key === \"video\") return this.props.videoElement;\n if (key === \"hls\" && this.player) return (this.player as any).hls;\n return null;\n };\n\n render() {\n return null;\n }\n}\n","import Hls from \"hls.js\";\nimport type {\n StormcloudVideoPlayerConfig,\n Scte35Marker,\n Id3TagInfo,\n AdController,\n} from \"../types\";\nimport { createAdStormPlayer } from \"../sdk/adstormPlayer\";\nimport { initializePolyfills } from \"../utils/polyfills\";\nimport { getBrowserConfigOverrides, logBrowserInfo } from \"../utils/browserCompat\";\n\nexport class StormcloudVideoPlayer {\n private readonly video: HTMLVideoElement;\n private readonly config: StormcloudVideoPlayerConfig;\n private hls?: Hls;\n private adPlayer: AdController;\n private attached = false;\n private inAdBreak = false;\n private expectedAdBreakDurationMs: number | undefined;\n private adStopTimerId: number | undefined;\n private ptsDriftEmaMs = 0;\n private isLiveStream: boolean = false;\n private nativeHlsMode: boolean = false;\n private videoSrcProtection: string | null = null;\n private bufferedSegmentsCount: number = 0;\n private shouldAutoplayAfterBuffering: boolean = false;\n private hasInitialBufferCompleted: boolean = false;\n private timeUpdateHandler?: (event: Event) => void;\n private emptiedHandler?: (event: Event) => void;\n\n constructor(config: StormcloudVideoPlayerConfig) {\n initializePolyfills();\n\n const browserOverrides = getBrowserConfigOverrides();\n this.config = { ...config, ...browserOverrides };\n this.video = config.videoElement;\n\n logBrowserInfo(config.debugAdTiming);\n\n if (!this.config.licenseKey) {\n console.warn(\"[StormcloudVideoPlayer] No license key provided - ads will not work\");\n }\n\n this.adPlayer = createAdStormPlayer(this.video, {\n licenseKey: this.config.licenseKey || \"\",\n debug: this.config.debugAdTiming ?? false,\n });\n }\n\n async load(): Promise<void> {\n if (!this.attached) {\n this.attach();\n }\n\n if (this.shouldUseNativeHls()) {\n this.nativeHlsMode = true;\n this.videoSrcProtection = this.config.src;\n this.video.src = this.config.src;\n\n this.isLiveStream = this.config.lowLatencyMode ?? false;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Using native HLS playback:\", {\n isLive: this.isLiveStream,\n allowNativeHls: this.config.allowNativeHls,\n });\n }\n\n this.adPlayer.initialize();\n this.adPlayer.setAllowNativeHls(!!this.config.allowNativeHls);\n\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n return;\n }\n\n this.hls = new Hls({\n enableWorker: true,\n backBufferLength: 30,\n liveDurationInfinity: true,\n lowLatencyMode: !!this.config.lowLatencyMode,\n maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1.0,\n ...(this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}),\n maxBufferLength: 30,\n maxMaxBufferLength: 600,\n maxBufferSize: 60 * 1000 * 1000,\n maxBufferHole: 0.5,\n highBufferWatchdogPeriod: 2,\n nudgeOffset: 0.1,\n nudgeMaxRetry: 3,\n startPosition: -1,\n });\n\n this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {\n this.hls?.loadSource(this.config.src);\n });\n\n this.hls.on(Hls.Events.MANIFEST_PARSED, async () => {\n this.isLiveStream =\n this.hls?.levels?.some(\n (level) =>\n level?.details?.live === true || level?.details?.type === \"LIVE\"\n ) ?? false;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Stream type detected:\", {\n isLive: this.isLiveStream,\n });\n }\n\n this.adPlayer.initialize();\n this.adPlayer.setAllowNativeHls(!!this.config.allowNativeHls);\n\n this.bufferedSegmentsCount = 0;\n this.hasInitialBufferCompleted = false;\n this.shouldAutoplayAfterBuffering = !!this.config.autoplay;\n\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n\n if (this.config.debugAdTiming) {\n console.log(\n \"[StormcloudVideoPlayer] Waiting for\",\n minSegments,\n \"segments to buffer before playback\"\n );\n }\n\n if (minSegments === 0 || !this.config.autoplay) {\n this.hasInitialBufferCompleted = true;\n if (this.config.autoplay) {\n await this.video.play()?.catch(() => {});\n }\n }\n });\n\n this.hls.on(Hls.Events.FRAG_BUFFERED, async () => {\n if (this.hasInitialBufferCompleted) {\n return;\n }\n\n this.bufferedSegmentsCount++;\n const minSegments = this.config.minSegmentsBeforePlay ?? 2;\n\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Buffered segment ${this.bufferedSegmentsCount}/${minSegments}`\n );\n }\n\n if (this.bufferedSegmentsCount >= minSegments) {\n this.hasInitialBufferCompleted = true;\n\n if (this.shouldAutoplayAfterBuffering) {\n if (this.config.debugAdTiming) {\n console.log(\n `[StormcloudVideoPlayer] Initial buffer complete. Starting playback.`\n );\n }\n await this.video.play()?.catch((err) => {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Autoplay failed:\", err);\n }\n });\n }\n }\n });\n\n this.hls.on(Hls.Events.FRAG_PARSING_METADATA, (_evt, data: any) => {\n const id3Tags: Id3TagInfo[] = (data?.samples || []).map((s: any) => ({\n key: \"ID3\",\n value: s?.data,\n ptsSeconds: s?.pts,\n }));\n id3Tags.forEach((tag) => this.onId3Tag(tag));\n });\n\n this.hls.on(Hls.Events.FRAG_CHANGED, (_evt, data: any) => {\n const frag = data?.frag;\n const tagList: any[] | undefined = frag?.tagList;\n if (!Array.isArray(tagList)) return;\n\n for (const entry of tagList) {\n let tag = \"\";\n let value = \"\";\n if (Array.isArray(entry)) {\n tag = String(entry[0] ?? \"\");\n value = String(entry[1] ?? \"\");\n } else if (typeof entry === \"string\") {\n const idx = entry.indexOf(\":\");\n if (idx >= 0) {\n tag = entry.substring(0, idx);\n value = entry.substring(idx + 1);\n } else {\n tag = entry;\n value = \"\";\n }\n }\n\n if (!tag) continue;\n \n if (tag.includes(\"EXT-X-CUE-OUT\")) {\n const durationSeconds = this.parseCueOutDuration(value);\n this.onScte35Marker({\n type: \"start\",\n ...(durationSeconds !== undefined ? { durationSeconds } : {}),\n raw: { tag, value },\n });\n } else if (tag.includes(\"EXT-X-CUE-OUT-CONT\")) {\n const prog = this.parseCueOutCont(value);\n this.onScte35Marker({\n type: \"progress\",\n ...(prog?.duration !== undefined ? { durationSeconds: prog.duration } : {}),\n ...(prog?.elapsed !== undefined ? { ptsSeconds: prog.elapsed } : {}),\n raw: { tag, value },\n });\n } else if (tag.includes(\"EXT-X-CUE-IN\")) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value } });\n } else if (tag.includes(\"EXT-X-DATERANGE\")) {\n const attrs = this.parseAttributeList(value);\n const hasScteOut = \"SCTE35-OUT\" in attrs;\n const hasScteIn = \"SCTE35-IN\" in attrs;\n const klass = String(attrs[\"CLASS\"] ?? \"\");\n const duration = this.toNumber(attrs[\"DURATION\"]) ?? this.toNumber(attrs[\"PLANNED-DURATION\"]);\n\n if (hasScteOut || /com\\.apple\\.hls\\.cue/i.test(klass)) {\n this.onScte35Marker({\n type: \"start\",\n ...(duration !== undefined ? { durationSeconds: duration } : {}),\n raw: { tag, value, attrs },\n });\n }\n if (hasScteIn) {\n this.onScte35Marker({ type: \"end\", raw: { tag, value, attrs } });\n }\n }\n }\n });\n\n this.hls.on(Hls.Events.ERROR, (_evt, data) => {\n if (data?.fatal) {\n switch (data.type) {\n case Hls.ErrorTypes.NETWORK_ERROR:\n this.hls?.startLoad();\n break;\n case Hls.ErrorTypes.MEDIA_ERROR:\n this.hls?.recoverMediaError();\n break;\n default:\n this.destroy();\n break;\n }\n }\n });\n\n this.hls.attachMedia(this.video);\n }\n\n private attach(): void {\n if (this.attached) return;\n this.attached = true;\n this.video.autoplay = !!this.config.autoplay;\n this.video.muted = !!this.config.muted;\n\n this.adPlayer.initialize();\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n \n this.adPlayer.on(\"all_ads_completed\", () => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad completed - ending ad break\");\n }\n if (this.inAdBreak) {\n this.handleAdPodComplete();\n }\n });\n \n this.adPlayer.on(\"ad_error\", () => {\n console.error(\"[StormcloudVideoPlayer] Ad error occurred\");\n if (this.inAdBreak) {\n this.handleAdPodComplete();\n }\n });\n \n this.adPlayer.on(\"content_pause\", () => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content paused for ad\");\n }\n });\n \n this.adPlayer.on(\"content_resume\", () => {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Content resuming after ad\");\n }\n });\n\n this.timeUpdateHandler = () => {\n };\n this.video.addEventListener(\"timeupdate\", this.timeUpdateHandler);\n\n this.emptiedHandler = () => {\n if (this.nativeHlsMode && this.videoSrcProtection && !this.adPlayer.isAdPlaying()) {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Video src was cleared, restoring\");\n }\n const currentTime = this.video.currentTime;\n const wasPaused = this.video.paused;\n this.video.src = this.videoSrcProtection;\n this.video.currentTime = currentTime;\n if (!wasPaused) {\n this.video.play().catch(() => {});\n }\n }\n };\n this.video.addEventListener(\"emptied\", this.emptiedHandler);\n }\n\n private shouldUseNativeHls(): boolean {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return true;\n }\n const canNative = this.video.canPlayType(\"application/vnd.apple.mpegurl\");\n return !!(this.config.allowNativeHls && canNative);\n }\n\n private onId3Tag(tag: Id3TagInfo): void {\n if (typeof tag.ptsSeconds === \"number\") {\n this.updatePtsDrift(tag.ptsSeconds);\n }\n const marker = this.parseScte35FromId3(tag);\n if (marker) {\n this.onScte35Marker(marker);\n }\n }\n\n private parseScte35FromId3(tag: Id3TagInfo): Scte35Marker | undefined {\n const text = this.decodeId3ValueToText(tag.value);\n if (!text) return undefined;\n\n const cueOutMatch =\n text.match(/EXT-X-CUE-OUT(?::([^\\r\\n]*))?/i) ||\n text.match(/CUE-OUT(?::([^\\r\\n]*))?/i);\n if (cueOutMatch) {\n const arg = (cueOutMatch[1] ?? \"\").trim();\n const dur = this.parseCueOutDuration(arg);\n return {\n type: \"start\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(dur !== undefined ? { durationSeconds: dur } : {}),\n raw: { id3: text },\n };\n }\n\n const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\\r\\n]*)/i);\n if (cueOutContMatch) {\n const arg = (cueOutContMatch[1] ?? \"\").trim();\n const cont = this.parseCueOutCont(arg);\n return {\n type: \"progress\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n ...(cont?.duration !== undefined ? { durationSeconds: cont.duration } : {}),\n raw: { id3: text },\n };\n }\n\n const cueInMatch = text.match(/EXT-X-CUE-IN\\b/i) || text.match(/CUE-IN\\b/i);\n if (cueInMatch) {\n return {\n type: \"end\",\n ...(tag.ptsSeconds !== undefined ? { ptsSeconds: tag.ptsSeconds } : {}),\n raw: { id3: text },\n };\n }\n\n return undefined;\n }\n\n private decodeId3ValueToText(value: string | Uint8Array): string | undefined {\n try {\n if (typeof value === \"string\") return value;\n const decoder = new TextDecoder(\"utf-8\", { fatal: false });\n const text = decoder.decode(value);\n if (text && /[\\x20-\\x7E]/.test(text)) return text;\n let out = \"\";\n for (let i = 0; i < value.length; i++) {\n out += String.fromCharCode(value[i]!);\n }\n return out;\n } catch {\n return undefined;\n }\n }\n\n private async onScte35Marker(marker: Scte35Marker): Promise<void> {\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] SCTE-35 marker detected:\", {\n type: marker.type,\n ptsSeconds: marker.ptsSeconds,\n durationSeconds: marker.durationSeconds,\n currentTime: this.video.currentTime,\n });\n }\n\n if (marker.type === \"start\") {\n if (this.inAdBreak) {\n return;\n }\n\n this.inAdBreak = true;\n const durationMs = marker.durationSeconds != null\n ? marker.durationSeconds * 1000\n : 30000;\n \n this.expectedAdBreakDurationMs = durationMs;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Starting ad break:\", {\n durationMs,\n durationSeconds: marker.durationSeconds,\n });\n }\n\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n\n await this.handleAdStart(marker);\n\n if (this.expectedAdBreakDurationMs != null) {\n this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);\n }\n return;\n }\n\n if (marker.type === \"progress\" && this.inAdBreak) {\n if (marker.durationSeconds != null) {\n this.expectedAdBreakDurationMs = marker.durationSeconds * 1000;\n }\n return;\n }\n\n if (marker.type === \"end\") {\n if (!this.inAdBreak) return;\n \n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = undefined;\n this.clearAdStopTimer();\n\n if (this.adPlayer.isAdPlaying()) {\n await this.adPlayer.stop();\n }\n\n this.handleAdPodComplete();\n return;\n }\n }\n\n private async handleAdStart(marker: Scte35Marker): Promise<void> {\n const durationSeconds = marker.durationSeconds ?? 30;\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Requesting ads for duration:\", durationSeconds);\n }\n\n try {\n await this.adPlayer.requestAds(String(durationSeconds));\n \n await this.adPlayer.play();\n } catch (error) {\n if (this.config.debugAdTiming) {\n console.warn(\"[StormcloudVideoPlayer] Ad request/play failed:\", error);\n }\n this.handleAdPodComplete();\n }\n }\n\n private parseCueOutDuration(value: string): number | undefined {\n const num = parseFloat(value.trim());\n if (!Number.isNaN(num)) return num;\n const match =\n value.match(/(?:^|[,\\s])DURATION\\s*=\\s*([0-9.]+)/i) ||\n value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n if (match && match[1] != null) {\n const d = parseFloat(match[1]);\n return Number.isNaN(d) ? undefined : d;\n }\n return undefined;\n }\n\n private parseCueOutCont(value: string): { elapsed?: number; duration?: number } | undefined {\n const elapsedMatch = value.match(/Elapsed\\s*=\\s*([0-9.]+)/i);\n const durationMatch = value.match(/Duration\\s*=\\s*([0-9.]+)/i);\n const res: { elapsed?: number; duration?: number } = {};\n if (elapsedMatch && elapsedMatch[1] != null) {\n const e = parseFloat(elapsedMatch[1]);\n if (!Number.isNaN(e)) res.elapsed = e;\n }\n if (durationMatch && durationMatch[1] != null) {\n const d = parseFloat(durationMatch[1]);\n if (!Number.isNaN(d)) res.duration = d;\n }\n if (\"elapsed\" in res || \"duration\" in res) return res;\n return undefined;\n }\n\n private parseAttributeList(value: string): Record<string, string> {\n const attrs: Record<string, string> = {};\n const regex = /([A-Z0-9-]+)=((\"[^\"]*\")|([^\",]*))(?:,|$)/gi;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(value)) !== null) {\n const key: string = (match[1] ?? \"\") as string;\n let rawVal: string = (match[3] ?? match[4] ?? \"\") as string;\n if (rawVal.startsWith('\"') && rawVal.endsWith('\"')) {\n rawVal = rawVal.slice(1, -1);\n }\n if (key) {\n attrs[key] = rawVal;\n }\n }\n return attrs;\n }\n\n private toNumber(val: unknown): number | undefined {\n if (val == null) return undefined;\n const n = typeof val === \"string\" ? parseFloat(val) : Number(val);\n return Number.isNaN(n) ? undefined : n;\n }\n\n private scheduleAdStopCountdown(remainingMs: number): void {\n this.clearAdStopTimer();\n const ms = Math.max(0, Math.floor(remainingMs));\n if (ms === 0) {\n this.handleAdPodComplete();\n return;\n }\n this.adStopTimerId = window.setTimeout(() => {\n this.handleAdPodComplete();\n }, ms) as unknown as number;\n }\n\n private clearAdStopTimer(): void {\n if (this.adStopTimerId != null) {\n clearTimeout(this.adStopTimerId);\n this.adStopTimerId = undefined;\n }\n }\n\n private updatePtsDrift(ptsSecondsSample: number): void {\n const sampleMs = (this.video.currentTime - ptsSecondsSample) * 1000;\n if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 60000) return;\n const alpha = 0.1;\n this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;\n }\n\n private handleAdPodComplete(): void {\n this.clearAdStopTimer();\n \n this.inAdBreak = false;\n this.expectedAdBreakDurationMs = undefined;\n\n this.adPlayer.stop().catch(() => {});\n\n const restoredMuted = this.adPlayer.getOriginalMutedState();\n const restoredVolume = this.adPlayer.getOriginalVolume();\n\n if (this.video.muted !== restoredMuted) {\n this.video.muted = restoredMuted;\n }\n if (Math.abs(this.video.volume - restoredVolume) > 0.01) {\n this.video.volume = restoredVolume;\n }\n\n if (this.video.paused) {\n this.video.play()?.catch(() => {});\n }\n\n if (this.config.debugAdTiming) {\n console.log(\"[StormcloudVideoPlayer] Ad break complete\");\n }\n }\n\n isAdPlaying(): boolean {\n return this.inAdBreak && this.adPlayer.isAdPlaying();\n }\n\n isShowingAds(): boolean {\n return this.adPlayer.isAdPlaying();\n }\n\n getStreamType(): \"hls\" | \"other\" {\n const url = this.config.src.toLowerCase();\n if (\n url.includes(\".m3u8\") ||\n url.includes(\"/hls/\") ||\n url.includes(\"application/vnd.apple.mpegurl\")\n ) {\n return \"hls\";\n }\n return \"other\";\n }\n\n shouldShowNativeControls(): boolean {\n const streamType = this.getStreamType();\n if (streamType === \"other\") {\n return !(this.config.showCustomControls ?? false);\n }\n return !!(\n this.config.allowNativeHls && !(this.config.showCustomControls ?? false)\n );\n }\n\n toggleMute(): void {\n if (this.adPlayer.isAdPlaying()) {\n const currentMuted = this.video.muted;\n const newMutedState = !currentMuted;\n\n this.adPlayer.updateOriginalMutedState(newMutedState, this.video.volume);\n this.adPlayer.setAdVolume(newMutedState ? 0 : 1);\n } else {\n this.video.muted = !this.video.muted;\n this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);\n }\n }\n\n toggleFullscreen(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!document.fullscreenElement) {\n const container = this.video.parentElement;\n if (!container) {\n reject(new Error(\"No parent container found for fullscreen\"));\n return;\n }\n container\n .requestFullscreen()\n .then(() => resolve())\n .catch(reject);\n } else {\n document.exitFullscreen().then(() => resolve()).catch(reject);\n }\n });\n }\n\n isMuted(): boolean {\n return this.video.muted;\n }\n\n setMuted(muted: boolean): void {\n this.video.muted = muted;\n this.adPlayer.updateOriginalMutedState(muted, this.video.volume);\n\n if (this.adPlayer.isAdPlaying()) {\n this.adPlayer.setAdVolume(muted ? 0 : 1);\n }\n }\n\n setVolume(volume: number): void {\n const clampedVolume = Math.max(0, Math.min(1, volume));\n\n if (this.adPlayer.isAdPlaying()) {\n this.adPlayer.setAdVolume(clampedVolume);\n this.adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n } else {\n this.video.volume = clampedVolume;\n this.video.muted = clampedVolume === 0;\n this.adPlayer.updateOriginalMutedState(clampedVolume === 0, clampedVolume);\n }\n }\n\n isFullscreen(): boolean {\n return !!document.fullscreenElement;\n }\n\n isLive(): boolean {\n return this.isLiveStream;\n }\n\n get videoElement(): HTMLVideoElement {\n return this.video;\n }\n\n resize(): void {\n if (this.adPlayer && this.adPlayer.isAdPlaying()) {\n const width = this.video.clientWidth || 640;\n const height = this.video.clientHeight || 360;\n this.adPlayer.resize(width, height);\n }\n }\n\n destroy(): void {\n this.clearAdStopTimer();\n\n if (this.timeUpdateHandler) {\n this.video.removeEventListener(\"timeupdate\", this.timeUpdateHandler);\n delete this.timeUpdateHandler;\n }\n if (this.emptiedHandler) {\n this.video.removeEventListener(\"emptied\", this.emptiedHandler);\n delete this.emptiedHandler;\n }\n\n this.hls?.destroy();\n this.adPlayer?.destroy();\n }\n\n getCurrentAdIndex(): number {\n return 0;\n }\n\n getTotalAdsInBreak(): number {\n return 1;\n }\n}\n","export function polyfillURLSearchParams(): void {\n if (typeof URLSearchParams !== 'undefined') {\n return;\n }\n\n class URLSearchParamsPolyfill {\n private params: Map<string, string[]>;\n\n constructor(init?: string | URLSearchParamsPolyfill) {\n this.params = new Map();\n\n if (typeof init === 'string') {\n this.parseQueryString(init);\n } else if (init instanceof URLSearchParamsPolyfill) {\n init.forEach((value, key) => {\n this.append(key, value);\n });\n }\n }\n\n private parseQueryString(query: string): void {\n const cleanQuery = query.startsWith('?') ? query.slice(1) : query;\n if (!cleanQuery) return;\n\n cleanQuery.split('&').forEach((param) => {\n const [key, value] = param.split('=');\n if (key) {\n const decodedKey = this.safeDecodeURIComponent(key);\n const decodedValue = value ? this.safeDecodeURIComponent(value) : '';\n this.append(decodedKey, decodedValue);\n }\n });\n }\n\n private safeDecodeURIComponent(str: string): string {\n try {\n return decodeURIComponent(str.replace(/\\+/g, ' '));\n } catch (e) {\n return str;\n }\n }\n\n append(name: string, value: string): void {\n const values = this.params.get(name) || [];\n values.push(String(value));\n this.params.set(name, values);\n }\n\n delete(name: string): void {\n this.params.delete(name);\n }\n\n get(name: string): string | null {\n const values = this.params.get(name);\n return values && values.length > 0 && values[0] !== undefined ? values[0] : null;\n }\n\n getAll(name: string): string[] {\n return this.params.get(name) || [];\n }\n\n has(name: string): boolean {\n return this.params.has(name);\n }\n\n set(name: string, value: string): void {\n this.params.set(name, [String(value)]);\n }\n\n forEach(callback: (value: string, key: string, parent: URLSearchParamsPolyfill) => void): void {\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n callback(value, key, this);\n });\n });\n }\n\n toString(): string {\n const parts: string[] = [];\n this.params.forEach((values, key) => {\n values.forEach((value) => {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n });\n });\n return parts.join('&');\n }\n }\n\n // @ts-ignore\n window.URLSearchParams = URLSearchParamsPolyfill;\n}\n\nexport function polyfillTextEncoder(): void {\n if (typeof TextEncoder !== 'undefined') {\n return;\n }\n\n class TextEncoderPolyfill {\n encoding = 'utf-8';\n\n encode(str: string): Uint8Array {\n const utf8: number[] = [];\n for (let i = 0; i < str.length; i++) {\n let charcode = str.charCodeAt(i);\n if (charcode < 0x80) {\n utf8.push(charcode);\n } else if (charcode < 0x800) {\n utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f));\n } else if (charcode < 0xd800 || charcode >= 0xe000) {\n utf8.push(\n 0xe0 | (charcode >> 12),\n 0x80 | ((charcode >> 6) & 0x3f),\n 0x80 | (charcode & 0x3f)\n );\n } else {\n i++;\n charcode = 0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));\n utf8.push(\n 0xf0 | (charcode >> 18),\n 0x80 | ((charcode >> 12) & 0x3f),\n 0x80 | ((charcode >> 6) & 0x3f),\n 0x80 | (charcode & 0x3f)\n );\n }\n }\n return new Uint8Array(utf8);\n }\n }\n\n // @ts-ignore\n window.TextEncoder = TextEncoderPolyfill;\n}\n\nexport function polyfillPromiseFinally(): void {\n if (typeof Promise !== 'undefined' && !Promise.prototype.finally) {\n Promise.prototype.finally = function (callback: () => void) {\n const constructor = this.constructor as PromiseConstructor;\n return this.then(\n (value) => constructor.resolve(callback()).then(() => value),\n (reason) =>\n constructor.resolve(callback()).then(() => {\n throw reason;\n })\n );\n };\n }\n}\n\nexport function polyfillObjectAssign(): void {\n if (typeof Object.assign !== 'function') {\n Object.assign = function (target: any, ...sources: any[]) {\n if (target == null) {\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n const to = Object(target);\n\n for (let i = 0; i < sources.length; i++) {\n const nextSource = sources[i];\n\n if (nextSource != null) {\n for (const nextKey in nextSource) {\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n\n return to;\n };\n }\n}\n\nexport function polyfillArrayFrom(): void {\n if (!Array.from) {\n Array.from = function (arrayLike: any, mapFn?: any, thisArg?: any) {\n const items = Object(arrayLike);\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object');\n }\n\n const len = items.length >>> 0;\n const result = new Array(len);\n\n for (let i = 0; i < len; i++) {\n if (mapFn) {\n result[i] = mapFn.call(thisArg, items[i], i);\n } else {\n result[i] = items[i];\n }\n }\n\n return result;\n };\n }\n}\n\nexport function polyfillStringStartsWith(): void {\n if (!String.prototype.startsWith) {\n String.prototype.startsWith = function (search: string, pos?: number) {\n pos = !pos || pos < 0 ? 0 : +pos;\n return this.substring(pos, pos + search.length) === search;\n };\n }\n}\n\nexport function polyfillStringEndsWith(): void {\n if (!String.prototype.endsWith) {\n String.prototype.endsWith = function (search: string, length?: number) {\n if (length === undefined || length > this.length) {\n length = this.length;\n }\n return this.substring(length - search.length, length) === search;\n };\n }\n}\n\nexport function polyfillStringIncludes(): void {\n if (!String.prototype.includes) {\n String.prototype.includes = function (search: string, start?: number) {\n if (typeof start !== 'number') {\n start = 0;\n }\n if (start + search.length > this.length) {\n return false;\n }\n return this.indexOf(search, start) !== -1;\n };\n }\n}\n\nexport function initializePolyfills(): void {\n polyfillObjectAssign();\n polyfillArrayFrom();\n polyfillStringStartsWith();\n polyfillStringEndsWith();\n polyfillStringIncludes();\n polyfillURLSearchParams();\n polyfillTextEncoder();\n polyfillPromiseFinally();\n}\n\n","interface NavigatorUAData {\n platform?: string;\n brands?: Array<{ brand: string; version: string }>;\n mobile?: boolean;\n}\n\ndeclare global {\n interface Navigator {\n userAgentData?: NavigatorUAData;\n }\n}\n\nexport interface BrowserInfo {\n name: string;\n version: string;\n majorVersion: number;\n isSmartTV: boolean;\n isLegacyTV: boolean;\n platform: string;\n supportsModernJS: boolean;\n}\n\nfunction getChromeVersion(ua: string): number {\n const match = ua.match(/Chrome\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\n\nfunction getWebKitVersion(ua: string): number {\n const match = ua.match(/AppleWebKit\\/(\\d+)/);\n return match && match[1] ? parseInt(match[1], 10) : 0;\n}\n\nfunction getPlatform(): string {\n if ('userAgentData' in navigator && navigator.userAgentData?.platform) {\n return navigator.userAgentData.platform;\n }\n\n const ua = navigator.userAgent;\n if (/Mac|iPhone|iPad|iPod/i.test(ua)) {\n return /iPhone|iPad|iPod/i.test(ua) ? 'iPhone' : 'MacIntel';\n }\n if (/Win/i.test(ua)) {\n return 'Win32';\n }\n if (/Linux/i.test(ua)) {\n return /Android/i.test(ua) ? 'Linux armv8l' : 'Linux x86_64';\n }\n if (/CrOS/i.test(ua)) {\n return 'CrOS';\n }\n\n // eslint-disable-next-line deprecation/deprecation\n return (navigator as any).platform || 'Unknown';\n}\n\nexport function detectBrowser(): BrowserInfo {\n const ua = navigator.userAgent;\n const platform = getPlatform();\n\n let name = 'Unknown';\n let version = '0';\n let majorVersion = 0;\n let isSmartTV = false;\n let isLegacyTV = false;\n let supportsModernJS = true;\n\n if (/Web0S|webOS/i.test(ua)) {\n name = 'LG WebOS';\n isSmartTV = true;\n const match = ua.match(/Web0S[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : 'Unknown';\n if (version !== 'Unknown') {\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/Tizen/i.test(ua)) {\n name = 'Samsung Tizen';\n isSmartTV = true;\n const match = ua.match(/Tizen[/\\s]*([\\d.]+)/i);\n version = match && match[1] ? match[1] : 'Unknown';\n if (version !== 'Unknown') {\n const parts = version.split('.');\n majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;\n }\n } else if (/SMART-TV|SmartTV/i.test(ua)) {\n name = 'Smart TV';\n isSmartTV = true;\n } else if (/NetCast/i.test(ua)) {\n name = 'LG NetCast';\n isSmartTV = true;\n isLegacyTV = true;\n } else if (/BRAVIA/i.test(ua)) {\n name = 'Sony BRAVIA';\n isSmartTV = true;\n }\n\n const chromeVersion = getChromeVersion(ua);\n const webkitVersion = getWebKitVersion(ua);\n\n if (chromeVersion > 0) {\n if (!isSmartTV) {\n name = 'Chrome';\n version = chromeVersion.toString();\n majorVersion = chromeVersion;\n }\n\n if (chromeVersion < 50) {\n supportsModernJS = false;\n isLegacyTV = true;\n }\n }\n\n if (webkitVersion > 0 && webkitVersion < 600) {\n supportsModernJS = false;\n if (isSmartTV) {\n isLegacyTV = true;\n }\n }\n\n if (typeof Promise === 'undefined' ||\n typeof Map === 'undefined' ||\n typeof Set === 'undefined') {\n supportsModernJS = false;\n }\n\n if (typeof URLSearchParams === 'undefined') {\n supportsModernJS = false;\n }\n\n return {\n name,\n version,\n majorVersion,\n isSmartTV,\n isLegacyTV,\n platform,\n supportsModernJS,\n };\n}\n\nexport function supportsModernJS(): boolean {\n try {\n return (\n typeof Promise !== 'undefined' &&\n typeof Map !== 'undefined' &&\n typeof Set !== 'undefined' &&\n typeof Array.from !== 'undefined' &&\n typeof Object.assign !== 'undefined' &&\n typeof Array.prototype.forEach !== 'undefined' &&\n typeof String.prototype.includes !== 'undefined'\n );\n } catch (e) {\n return false;\n }\n}\n\nexport function logBrowserInfo(debug: boolean = false): void {\n if (!debug) return;\n\n const browser = detectBrowser();\n\n console.log('[StormcloudVideoPlayer] Browser Compatibility Info:', {\n browser: `${browser.name} ${browser.version}`,\n platform: browser.platform,\n isSmartTV: browser.isSmartTV,\n isLegacyTV: browser.isLegacyTV,\n supportsModernJS: browser.supportsModernJS,\n userAgent: navigator.userAgent,\n });\n}\n\nexport function getBrowserConfigOverrides(): {\n allowNativeHls?: boolean;\n} {\n const browser = detectBrowser();\n const overrides: { allowNativeHls?: boolean } = {};\n\n if (browser.isSmartTV) {\n overrides.allowNativeHls = true;\n }\n\n return overrides;\n}\n\nexport function supportsFeature(feature: string): boolean {\n switch (feature) {\n case 'urlsearchparams':\n return typeof URLSearchParams !== 'undefined';\n case 'textencoder':\n return typeof TextEncoder !== 'undefined';\n case 'promises':\n return typeof Promise !== 'undefined';\n case 'fetch':\n return typeof fetch !== 'undefined';\n case 'crypto':\n return typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined';\n default:\n return false;\n }\n}\n"]}