From b86dcfbb8d5456ac4e11c93722d522afc8b1ea3b Mon Sep 17 00:00:00 2001 From: Marco Mooren Date: Mon, 11 May 2026 17:55:09 +0200 Subject: [PATCH] Add master display UI with audio output management and styling - Implement main.js for the master display functionality, including WebSocket connection, audio output management, and state handling. - Create style.css for the master display's visual design, ensuring a cohesive look and feel with a dark theme and responsive layout. - Integrate device management with a fallback for non-Electron environments, allowing users to select audio outputs. - Add features for managing favorites, including toggling favorites and filtering by genre. - Enhance user experience with a responsive favorites grid and drag-to-scroll functionality. --- .gitignore | 1 + package.json | 3 +- server/db/index.js | 16 + server/db/schema.sql | 37 + server/index.js | 36 +- server/media/images.js | 168 +++ server/public/admin/index.html | 6 +- server/public/assets/admin-BRU0y9A4.js | 1 - ...{admin-CJZ4D7u-.css => admin-C-qnWY0z.css} | 2 +- server/public/assets/admin-GqZPhz-K.js | 1 + server/public/assets/dom-BvorgAdo.js | 1 - server/public/assets/kiosk-CdZttV5P.css | 1 - server/public/assets/kiosk-CzWLja7k.js | 1 + server/public/assets/kiosk-PzkUrLf6.css | 1 + server/public/assets/master-CpJfsvtJ.css | 1 + server/public/assets/master-kSyrThjc.js | 1 + .../{kiosk-C37Mmo8O.js => player-BBOsFRH-.js} | 40 +- server/public/assets/ws-BM1PmMVd.js | 1 + server/public/docs/index.html | 2 +- server/public/index.html | 7 +- server/public/master/index.html | 19 + server/rooms.js | 142 +++ server/routes/admin.js | 242 +++- server/routes/rooms.js | 61 + server/routes/stations.js | 35 +- server/routes/v1.js | 4 +- server/scripts/download-images.js | 65 ++ server/sources/iconScraper.js | 71 +- server/stations.js | 9 +- server/stats.js | 111 +- server/ws.js | 217 +++- vite.config.js | 7 +- web/admin/main.js | 1021 ++++++++++++++--- web/admin/style.css | 233 ++++ web/main.js | 255 +++- web/master/index.html | 16 + web/master/main.js | 602 ++++++++++ web/master/style.css | 723 ++++++++++++ web/shared/ws.js | 14 +- web/style.css | 43 + 40 files changed, 3943 insertions(+), 274 deletions(-) create mode 100644 server/media/images.js delete mode 100644 server/public/assets/admin-BRU0y9A4.js rename server/public/assets/{admin-CJZ4D7u-.css => admin-C-qnWY0z.css} (55%) create mode 100644 server/public/assets/admin-GqZPhz-K.js delete mode 100644 server/public/assets/dom-BvorgAdo.js delete mode 100644 server/public/assets/kiosk-CdZttV5P.css create mode 100644 server/public/assets/kiosk-CzWLja7k.js create mode 100644 server/public/assets/kiosk-PzkUrLf6.css create mode 100644 server/public/assets/master-CpJfsvtJ.css create mode 100644 server/public/assets/master-kSyrThjc.js rename server/public/assets/{kiosk-C37Mmo8O.js => player-BBOsFRH-.js} (50%) create mode 100644 server/public/assets/ws-BM1PmMVd.js create mode 100644 server/public/master/index.html create mode 100644 server/rooms.js create mode 100644 server/routes/rooms.js create mode 100644 server/scripts/download-images.js create mode 100644 web/master/index.html create mode 100644 web/master/main.js create mode 100644 web/master/style.css diff --git a/.gitignore b/.gitignore index b8f80a7..3fce3b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ node_modules/ dist/ data/db/ +data/images/ .env .DS_Store *.log diff --git a/package.json b/package.json index 0f547ae..3b29fd4 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "dev:api": "node --watch server/index.js", "build": "vite build", "start": "node server/index.js", - "seed": "node server/scripts/seed.js" + "seed": "node server/scripts/seed.js", + "images:fetch": "node server/scripts/download-images.js" }, "dependencies": { "bcryptjs": "^2.4.3", diff --git a/server/db/index.js b/server/db/index.js index 412c6e6..f76227e 100644 --- a/server/db/index.js +++ b/server/db/index.js @@ -34,6 +34,12 @@ function runMigrations(db) { if (!stationCols.has('category')) { db.exec('ALTER TABLE stations ADD COLUMN category TEXT'); } + if (!stationCols.has('image_path')) { + db.exec('ALTER TABLE stations ADD COLUMN image_path TEXT'); + } + if (!stationCols.has('image_source')) { + db.exec('ALTER TABLE stations ADD COLUMN image_source TEXT'); + } const streamCols = new Set(db.prepare("PRAGMA table_info(streams)").all().map((c) => c.name)); if (!streamCols.has('uuid')) { db.exec('ALTER TABLE streams ADD COLUMN uuid TEXT'); @@ -55,5 +61,15 @@ function runMigrations(db) { db.exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_stations_uuid ON stations(uuid)'); db.exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_streams_uuid ON streams(uuid)'); db.exec('CREATE INDEX IF NOT EXISTS idx_stations_category ON stations(category)'); + + // station_plays gained session/listen-time aggregates so the leaderboard + // can rank by actual playtime, not just play-button taps. + const playCols = new Set(db.prepare("PRAGMA table_info(station_plays)").all().map((c) => c.name)); + if (!playCols.has('sessions')) { + db.exec('ALTER TABLE station_plays ADD COLUMN sessions INTEGER NOT NULL DEFAULT 0'); + } + if (!playCols.has('total_play_ms')) { + db.exec('ALTER TABLE station_plays ADD COLUMN total_play_ms INTEGER NOT NULL DEFAULT 0'); + } } diff --git a/server/db/schema.sql b/server/db/schema.sql index b9aa38a..cd28e1f 100644 --- a/server/db/schema.sql +++ b/server/db/schema.sql @@ -30,6 +30,8 @@ CREATE TABLE IF NOT EXISTS stations ( genres TEXT, -- JSON array description TEXT, image_url TEXT, + image_path TEXT, -- relative path under data/images, e.g. "stations/12.jpg" + image_source TEXT, -- 'remote' | 'scraped' | 'upload' source TEXT NOT NULL CHECK (source IN ('seed','radiobrowser','manual')), source_ref TEXT, category TEXT, @@ -93,8 +95,43 @@ CREATE INDEX IF NOT EXISTS idx_votes_station ON station_votes(station_id); -- Aggregate play counter. Cheaper than COUNT(*) over play_history every render -- and lets anonymous/public listing show play counts without exposing history. +-- `total_play_ms` and `sessions` accumulate from closed play_history rows so +-- the leaderboard can rank by actual listen time, not just play-button taps. CREATE TABLE IF NOT EXISTS station_plays ( station_id INTEGER PRIMARY KEY REFERENCES stations(id) ON DELETE CASCADE, plays INTEGER NOT NULL DEFAULT 0, + sessions INTEGER NOT NULL DEFAULT 0, + total_play_ms INTEGER NOT NULL DEFAULT 0, last_played_at TEXT ); + +-- Named listening rooms. One "display" client + many controller/panel clients +-- per room share state (now-playing, volume, votes). A personal room is +-- auto-provisioned per user so single-user kiosks Just Work. +CREATE TABLE IF NOT EXISTS rooms ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + slug TEXT NOT NULL UNIQUE, + name TEXT NOT NULL, + created_by INTEGER REFERENCES users(id) ON DELETE SET NULL, + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS room_members ( + room_id INTEGER NOT NULL REFERENCES rooms(id) ON DELETE CASCADE, + user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, + role TEXT NOT NULL DEFAULT 'member' CHECK (role IN ('owner','member','guest')), + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (room_id, user_id) +); +CREATE INDEX IF NOT EXISTS idx_room_members_user ON room_members(user_id); + +-- Last-known playback state per room. Persisted so clients reconnecting see +-- the same now-playing card immediately, even after a server restart. +CREATE TABLE IF NOT EXISTS room_state ( + room_id INTEGER PRIMARY KEY REFERENCES rooms(id) ON DELETE CASCADE, + station_id INTEGER REFERENCES stations(id) ON DELETE SET NULL, + playing INTEGER NOT NULL DEFAULT 0, + volume REAL NOT NULL DEFAULT 0.7, + updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP +); + diff --git a/server/index.js b/server/index.js index 15ac92d..8f3f70e 100644 --- a/server/index.js +++ b/server/index.js @@ -10,12 +10,14 @@ import { authMiddleware, ensureBootstrapAdmin } from './auth.js'; import { applySeedIfEmpty } from './sources/seed.js'; import { scheduleHealthCheck } from './streams/checker.js'; import { attachWs } from './ws.js'; +import { ensureImageDirs, getImageRoot } from './media/images.js'; import { router as authRoutes } from './routes/auth.js'; import { router as stationRoutes } from './routes/stations.js'; import { router as meRoutes } from './routes/me.js'; import { router as adminRoutes } from './routes/admin.js'; import { router as v1Routes } from './routes/v1.js'; +import { router as roomRoutes } from './routes/rooms.js'; const __dirname = dirname(fileURLToPath(import.meta.url)); const PORT = Number(process.env.PORT) || 4173; @@ -27,6 +29,7 @@ ensureBootstrapAdmin({ }); const seedResult = applySeedIfEmpty(); console.log('[seed]', seedResult); +ensureImageDirs(); const app = express(); app.use(express.json({ limit: '512kb' })); @@ -36,15 +39,40 @@ app.use('/api/auth', authRoutes); app.use('/api/stations', stationRoutes); app.use('/api/me', meRoutes); app.use('/api/admin', adminRoutes); +app.use('/api/rooms', roomRoutes); app.use('/api/v1', v1Routes); +// Locally-cached cover art and other media live under data/images and are +// served unauthenticated on the LAN. Long cache OK — file names include the +// station id and we rewrite the file on update (browsers also revalidate). +app.use('/media', express.static(getImageRoot(), { + maxAge: '1h', + fallthrough: false, + setHeaders(res) { res.setHeader('Cache-Control', 'public, max-age=3600'); } +})); + // Static assets (built by Vite). In dev these don't exist; Vite serves them on :5173. +// HTML entry files must NOT be cached — they reference hashed JS/CSS that changes +// every build. Hashed assets under /assets/ can be cached aggressively. const publicDir = resolve(__dirname, 'public'); +const sendHtml = (file) => (_req, res) => { + res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); + res.sendFile(resolve(publicDir, file)); +}; if (existsSync(publicDir)) { - app.use(express.static(publicDir)); - app.get('/admin', (_req, res) => res.sendFile(resolve(publicDir, 'admin/index.html'))); - app.get('/docs', (_req, res) => res.sendFile(resolve(publicDir, 'docs/index.html'))); - app.get('*', (_req, res) => res.sendFile(resolve(publicDir, 'index.html'))); + app.use(express.static(publicDir, { + setHeaders(res, filePath) { + if (filePath.endsWith('.html')) { + res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); + } else if (filePath.includes(`${publicDir}\\assets\\`) || filePath.includes(`${publicDir}/assets/`)) { + res.setHeader('Cache-Control', 'public, max-age=31536000, immutable'); + } + } + })); + app.get('/admin', sendHtml('admin/index.html')); + app.get('/docs', sendHtml('docs/index.html')); + app.get('/master', sendHtml('master/index.html')); + app.get('*', sendHtml('index.html')); } app.use((err, _req, res, _next) => { diff --git a/server/media/images.js b/server/media/images.js new file mode 100644 index 0000000..4069eff --- /dev/null +++ b/server/media/images.js @@ -0,0 +1,168 @@ +// Local cover-art storage for stations. +// +// Files live under /data/images/stations/. and are served by +// express.static at /media/stations/.. The DB tracks just the +// relative path in stations.image_path (e.g. "stations/12.jpg"), while +// stations.image_url keeps the original remote URL for refetch/debugging. + +import { mkdirSync, existsSync, writeFileSync, readdirSync, unlinkSync, statSync } from 'node:fs'; +import { resolve, join, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { getDb } from '../db/index.js'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const ROOT = resolve(__dirname, '..', '..', 'data', 'images'); +const STATIONS_DIR = join(ROOT, 'stations'); +// A browser-like UA is required by Wikimedia and several CDNs; an opaque +// UA like "OnlineRadioExplorer/0.1" gets HTTP 400/403 from upload.wikimedia.org. +// Override via env if you want to publish a contact URL. +const UA = process.env.IMAGE_FETCH_UA + || 'Mozilla/5.0 (compatible; OnlineRadioExplorer/0.1; +https://github.com/marcoheine/onlineRadioExplorer)'; +const FETCH_TIMEOUT_MS = 10_000; +const MAX_BYTES = 4 * 1024 * 1024; // 4 MB per image + +const MIME_EXT = { + 'image/jpeg': 'jpg', + 'image/jpg': 'jpg', + 'image/pjpeg': 'jpg', + 'image/png': 'png', + 'image/webp': 'webp', + 'image/gif': 'gif', + 'image/svg+xml': 'svg', + 'image/x-icon': 'ico', + 'image/vnd.microsoft.icon': 'ico' +}; + +export function ensureImageDirs() { + mkdirSync(STATIONS_DIR, { recursive: true }); +} + +export function getImageRoot() { return ROOT; } + +// Strip any existing file for this station id (with any extension). +function removeExistingStationFile(id) { + if (!existsSync(STATIONS_DIR)) return; + const prefix = `${id}.`; + for (const f of readdirSync(STATIONS_DIR)) { + if (f.startsWith(prefix)) { + try { unlinkSync(join(STATIONS_DIR, f)); } catch { } + } + } +} + +function extFromMime(mime) { + if (!mime) return null; + const base = mime.split(';')[0].trim().toLowerCase(); + return MIME_EXT[base] || null; +} + +function extFromMagic(buf) { + if (buf.length < 12) return null; + // PNG + if (buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4E && buf[3] === 0x47) return 'png'; + // JPEG + if (buf[0] === 0xFF && buf[1] === 0xD8 && buf[2] === 0xFF) return 'jpg'; + // GIF + if (buf[0] === 0x47 && buf[1] === 0x49 && buf[2] === 0x46) return 'gif'; + // WEBP: "RIFF...WEBP" + if (buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 + && buf[8] === 0x57 && buf[9] === 0x45 && buf[10] === 0x42 && buf[11] === 0x50) return 'webp'; + // SVG: starts with " ctl.abort(), FETCH_TIMEOUT_MS); + try { + const res = await fetch(url, { + headers: { 'User-Agent': UA, 'Accept': 'image/*' }, + redirect: 'follow', + signal: ctl.signal + }); + if (!res.ok) throw new Error(`HTTP ${res.status}`); + const ct = res.headers.get('content-type') || ''; + const reader = res.body?.getReader(); + if (!reader) throw new Error('no body'); + const chunks = []; + let received = 0; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + received += value.length; + if (received > MAX_BYTES) { try { await reader.cancel(); } catch { } throw new Error('too large'); } + chunks.push(Buffer.from(value)); + } + return { buffer: Buffer.concat(chunks), contentType: ct }; + } finally { clearTimeout(t); } +} + +/** + * Persist a buffer as the station's cover-art file and update the DB. + * Returns the relative path (e.g. "stations/12.jpg"). + */ +export function saveStationImageFromBuffer(stationId, buf, mime, { source = 'upload' } = {}) { + ensureImageDirs(); + // Reject obvious HTML responses (404 pages, SPA index, login walls) even + // when the upstream lies about the content-type. + const head = buf.slice(0, 512).toString('utf8').trimStart().toLowerCase(); + if (head.startsWith(' Radio Admin - + - - + + diff --git a/server/public/assets/admin-BRU0y9A4.js b/server/public/assets/admin-BRU0y9A4.js deleted file mode 100644 index c1be104..0000000 --- a/server/public/assets/admin-BRU0y9A4.js +++ /dev/null @@ -1 +0,0 @@ -import"./modulepreload-polyfill-B5Qt9EMX.js";import{a as i,c as g,e}from"./dom-BvorgAdo.js";const b=document.getElementById("app"),n={user:null,view:"stations",stations:[],users:[],system:null,search:""};async function v(){try{n.user=await i.get("/api/auth/me")}catch{return C()}if(n.user.role!=="admin"){b.innerHTML=``;return}await u(),m()}async function u(){const a=[i.get("/api/stations?all=1")];n.view==="users"&&a.push(i.get("/api/auth/users")),n.view==="system"&&a.push(i.get("/api/admin/system"));const[t,s,p]=await Promise.all(a);n.stations=t,n.view==="users"&&(n.users=s||[]),n.view==="system"&&(n.system=s||p||null)}function C(){g(b),b.appendChild(e("div",{class:"login"},e("form",{onSubmit:async a=>{a.preventDefault();const t=new FormData(a.target);try{n.user=await i.post("/api/auth/login",{username:t.get("username"),password:t.get("password")}),await v()}catch(s){a.target.querySelector(".err").textContent=s.message}}},e("h1",{},"Admin sign in"),e("input",{name:"username",placeholder:"Username",required:!0}),e("input",{name:"password",type:"password",placeholder:"Password",required:!0}),e("div",{class:"err"}),e("button",{class:"btn primary",type:"submit"},"Sign in"))))}function m(){g(b);const a=e("aside",{class:"side"},e("h1",{},"Online Radio Explorer"),...["stations","import","users","system"].map(s=>e("button",{class:`nav ${n.view===s?"active":""}`,onClick:async()=>{n.view=s,await u(),m()}},k(s))),e("div",{class:"me"},`Signed in as ${n.user.username}`,e("br"),e("a",{href:"#",onClick:async s=>{s.preventDefault(),await i.post("/api/auth/logout"),location.reload()}},"Sign out"))),t=e("main",{class:"main"});n.view==="stations"?S(t):n.view==="import"?I(t):n.view==="users"?$(t):n.view==="system"&&E(t),b.appendChild(e("div",{class:"shell"},a,t))}function k(a){return{stations:"Stations",import:"Import",users:"Users",system:"System"}[a]}function S(a){a.appendChild(e("div",{class:"bar"},e("input",{placeholder:"Search…",value:n.search,onInput:s=>{n.search=s.target.value,w()}}),e("button",{class:"btn primary",onClick:()=>f()},"+ Add station"),e("button",{class:"btn",onClick:async()=>{await i.post("/api/admin/health-check"),alert("Health check finished"),await u(),m()}},"Run health check")));const t=e("div",{id:"tableWrap"});a.appendChild(t),w()}function w(){const a=document.getElementById("tableWrap");if(!a)return;g(a);const t=n.search.toLowerCase(),s=n.stations.filter(o=>!t||o.name.toLowerCase().includes(t)||(o.country||"").toLowerCase().includes(t)||(o.genres||[]).some(c=>c.toLowerCase().includes(t))),p=e("table",{},e("thead",{},e("tr",{},e("th",{},"Name"),e("th",{},"Source"),e("th",{},"Genres"),e("th",{},"Country"),e("th",{},"Enabled"),e("th",{},"Actions"))),e("tbody",{},...s.map(o=>e("tr",{},e("td",{},e("strong",{},o.name),e("br"),e("small",{},o.homepage||"")),e("td",{},o.source),e("td",{},...(o.genres||[]).slice(0,4).map(c=>e("span",{class:"tag"},c))),e("td",{},o.country||""),e("td",{},o.enabled?"✅":"⛔"),e("td",{},e("button",{class:"btn",onClick:()=>f(o.id)},"Edit")," ",e("button",{class:"btn danger",onClick:async()=>{confirm(`Delete ${o.name}?`)&&(await i.del(`/api/stations/${o.id}`),await u(),m())}},"Delete"))))));a.appendChild(p)}async function f(a){const t=a?await i.get(`/api/stations/${a}`):{name:"",genres:[],streams:[],enabled:!0},s=e("dialog"),p=e("div",{class:"streams"});function o(){var l;g(p),p.appendChild(e("div",{style:{fontWeight:600,marginBottom:"6px"}},"Streams")),(l=t.streams)!=null&&l.length||p.appendChild(e("div",{style:{color:"#6b7280"}},"No streams yet."));for(const r of t.streams||[])p.appendChild(e("div",{class:"stream-row"},e("select",{onChange:d=>r.format=d.target.value},...["mp3","aac","hls","m3u","pls","ogg","unknown"].map(d=>e("option",{value:d,selected:r.format===d},d))),e("input",{value:r.url,placeholder:"https://…",onInput:d=>r.url=d.target.value}),e("input",{type:"number",placeholder:"kbps",value:r.bitrate||"",onInput:d=>r.bitrate=Number(d.target.value)||null}),e("input",{value:r.label||"",placeholder:"Label",onInput:d=>r.label=d.target.value}),r.last_status?e("span",{class:`pill ${r.last_status==="up"?"up":"down"}`},r.last_status):e("span"),e("button",{class:"btn danger",type:"button",onClick:()=>{t.streams=t.streams.filter(d=>d!==r),o()}},"×")));p.appendChild(e("button",{class:"btn",type:"button",onClick:()=>{var r;t.streams=[...t.streams||[],{url:"",format:"mp3",priority:((r=t.streams)==null?void 0:r.length)||0}],o()}},"+ Add stream"))}const c=e("form",{method:"dialog",onSubmit:async l=>{l.preventDefault();const r={name:t.name,homepage:t.homepage,country:t.country,genres:t.genres,description:t.description,image_url:t.image_url,enabled:t.enabled};if(a){await i.patch(`/api/stations/${a}`,r);const d=await i.get(`/api/stations/${a}`);for(const y of d.streams||[])await i.del(`/api/stations/${a}/streams/${y.id}`);for(const y of t.streams||[])y.url&&await i.post(`/api/stations/${a}/streams`,y)}else r.streams=(t.streams||[]).filter(d=>d.url),await i.post("/api/stations",r);s.close(),await u(),m()}},e("h2",{},a?"Edit station":"Add station"),e("div",{class:"row"},e("label",{},"Name"),e("input",{value:t.name,onInput:l=>t.name=l.target.value,required:!0})),e("div",{class:"row"},e("label",{},"Homepage"),e("input",{value:t.homepage||"",onInput:l=>t.homepage=l.target.value})),e("div",{class:"row"},e("label",{},"Country"),e("input",{value:t.country||"",maxlength:4,onInput:l=>t.country=l.target.value})),e("div",{class:"row"},e("label",{},"Genres"),e("input",{value:(t.genres||[]).join(", "),onInput:l=>t.genres=l.target.value.split(",").map(r=>r.trim()).filter(Boolean)})),e("div",{class:"row"},e("label",{},"Image URL"),e("input",{value:t.image_url||"",onInput:l=>t.image_url=l.target.value})),e("div",{class:"row col"},e("textarea",{rows:2,placeholder:"Description",onInput:l=>t.description=l.target.value},t.description||"")),e("div",{class:"row"},e("label",{},"Enabled"),e("input",{type:"checkbox",checked:t.enabled,onChange:l=>t.enabled=l.target.checked})),p,e("div",{class:"actions"},e("button",{class:"btn",type:"button",onClick:()=>s.close()},"Cancel"),e("button",{class:"btn primary",type:"submit"},"Save")));o(),s.appendChild(c),document.body.appendChild(s),s.showModal(),s.addEventListener("close",()=>s.remove())}function I(a){let t=[];const s=e("div");a.appendChild(e("h2",{},"Import from Radio-Browser")),a.appendChild(e("div",{class:"bar"},e("input",{id:"rbq",placeholder:"Search by name…"}),e("input",{id:"rbcountry",placeholder:"Country (e.g. NL)",style:{minWidth:"120px"}}),e("input",{id:"rbtag",placeholder:"Tag/genre"}),e("button",{class:"btn primary",onClick:async()=>{const o=new URLSearchParams({q:document.getElementById("rbq").value,country:document.getElementById("rbcountry").value,tag:document.getElementById("rbtag").value});t=await i.get(`/api/stations/sources/radiobrowser/search?${o}`),p()}},"Search"))),a.appendChild(s);function p(){if(g(s),!t.length){s.appendChild(e("p",{},"No results yet."));return}const o=e("table",{},e("thead",{},e("tr",{},e("th",{},"Name"),e("th",{},"Country"),e("th",{},"Tags"),e("th",{},"Stream"),e("th",{},""))),e("tbody",{},...t.map(c=>{var l,r;return e("tr",{},e("td",{},c.name),e("td",{},c.country||""),e("td",{},...(c.genres||[]).slice(0,4).map(d=>e("span",{class:"tag"},d))),e("td",{},e("small",{},(((l=c.streams[0])==null?void 0:l.format)||"")+" "+(((r=c.streams[0])==null?void 0:r.bitrate)||""))),e("td",{},e("button",{class:"btn primary",onClick:async()=>{await i.post("/api/stations/sources/radiobrowser/import",c),alert(`Imported ${c.name}`)}},"Import")))})));s.appendChild(o)}}function $(a){a.appendChild(e("div",{class:"bar"},e("h2",{style:{margin:0,flex:1}},"Users"),e("button",{class:"btn primary",onClick:D},"+ Add user"))),a.appendChild(e("table",{},e("thead",{},e("tr",{},e("th",{},"Username"),e("th",{},"Role"),e("th",{},"Created"),e("th",{},""))),e("tbody",{},...n.users.map(t=>e("tr",{},e("td",{},t.username),e("td",{},t.role),e("td",{},t.created_at),e("td",{},e("button",{class:"btn",onClick:async()=>{const s=prompt(`New password for ${t.username}:`);s&&(await i.patch(`/api/auth/users/${t.id}`,{password:s}),alert("Updated"))}},"Reset PW")," ",e("button",{class:"btn",onClick:async()=>{const s=t.role==="admin"?"user":"admin";await i.patch(`/api/auth/users/${t.id}`,{role:s}),await u(),m()}},"Toggle role")," ",t.id!==n.user.id?e("button",{class:"btn danger",onClick:async()=>{confirm(`Delete ${t.username}?`)&&(await i.del(`/api/auth/users/${t.id}`),await u(),m())}},"Delete"):null))))))}function D(){const a=e("dialog");a.appendChild(e("form",{method:"dialog",onSubmit:async t=>{t.preventDefault();const s=new FormData(t.target);await i.post("/api/auth/users",{username:s.get("username"),password:s.get("password"),role:s.get("role")}),a.close(),await u(),m()}},e("h2",{},"New user"),e("div",{class:"row"},e("label",{},"Username"),e("input",{name:"username",required:!0})),e("div",{class:"row"},e("label",{},"Password"),e("input",{name:"password",type:"password",required:!0})),e("div",{class:"row"},e("label",{},"Role"),e("select",{name:"role"},e("option",{value:"user"},"user"),e("option",{value:"admin"},"admin"))),e("div",{class:"actions"},e("button",{class:"btn",type:"button",onClick:()=>a.close()},"Cancel"),e("button",{class:"btn primary",type:"submit"},"Create")))),document.body.appendChild(a),a.showModal(),a.addEventListener("close",()=>a.remove())}function E(a){const t=n.system||{};a.appendChild(e("h2",{},"System")),a.appendChild(e("div",{class:"system-grid"},h("Stations",t.stations),h("Streams",t.streams),h("Users",t.users),h("Favorites",t.favorites),h("Node",t.node),h("Uptime (s)",t.uptime_s))),a.appendChild(e("div",{class:"bar",style:{marginTop:"16px"}},e("button",{class:"btn",onClick:async()=>{await i.post("/api/admin/health-check"),alert("Health check finished"),await u(),m()}},"Run health check"),e("button",{class:"btn",onClick:async()=>{const s=await i.post("/api/admin/reseed");alert(JSON.stringify(s))}},"Reseed (if empty)")))}function h(a,t){return e("div",{class:"stat"},e("div",{class:"k"},a),e("div",{class:"v"},t??"—"))}v(); diff --git a/server/public/assets/admin-CJZ4D7u-.css b/server/public/assets/admin-C-qnWY0z.css similarity index 55% rename from server/public/assets/admin-CJZ4D7u-.css rename to server/public/assets/admin-C-qnWY0z.css index 84f304d..1296b59 100644 --- a/server/public/assets/admin-CJZ4D7u-.css +++ b/server/public/assets/admin-C-qnWY0z.css @@ -1 +1 @@ -:root{--bg: #f7f7fa;--panel: #fff;--fg: #14161b;--muted: #6b7280;--border: #e3e5ec;--accent: #ff6a26;--good: #178a6a;--bad: #c2342f;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg)}button{font:inherit;cursor:pointer}a{color:var(--accent)}.shell{display:grid;grid-template-columns:240px 1fr;min-height:100vh}.side{background:#14161b;color:#e8eaef;padding:20px;display:flex;flex-direction:column;gap:8px}.side h1{font-size:18px;margin:0 0 16px}.side button.nav{text-align:left;background:transparent;color:#cdd1da;border:0;padding:10px 12px;border-radius:8px;font-size:14px}.side button.nav.active{background:var(--accent);color:#1a0a00;font-weight:700}.side .me{margin-top:auto;font-size:12px;color:#8a8f9c}.main{padding:24px}.bar{display:flex;gap:8px;margin-bottom:16px;align-items:center;flex-wrap:wrap}.bar input,.bar select{padding:8px 10px;border:1px solid var(--border);border-radius:8px;background:var(--panel);font-size:14px;min-width:220px}.btn{padding:8px 14px;border-radius:8px;border:1px solid var(--border);background:var(--panel);font-size:14px}.btn.primary{background:var(--accent);color:#1a0a00;border-color:var(--accent);font-weight:700}.btn.danger{color:var(--bad);border-color:var(--bad)}table{width:100%;border-collapse:collapse;background:var(--panel);border-radius:12px;overflow:hidden}th,td{padding:10px 12px;border-bottom:1px solid var(--border);text-align:left;font-size:14px;vertical-align:top}th{background:#f0f1f5;font-weight:600}tr:last-child td{border-bottom:0}.tag{display:inline-block;font-size:11px;padding:2px 8px;border-radius:999px;background:#eef0f4;margin-right:4px}.pill{font-size:11px;padding:2px 8px;border-radius:999px}.pill.up{background:#dff5ec;color:var(--good)}.pill.down{background:#fde7e6;color:var(--bad)}.pill.unknown{background:#eef0f4;color:var(--muted)}dialog{border:0;border-radius:14px;padding:0;max-width:720px;width:90%;box-shadow:0 12px 40px #0003}dialog form{padding:24px;display:flex;flex-direction:column;gap:12px}dialog h2{margin:0 0 4px}dialog input,dialog textarea,dialog select{padding:8px 10px;border:1px solid var(--border);border-radius:8px;font-size:14px;width:100%}dialog .row{display:grid;grid-template-columns:140px 1fr;gap:12px;align-items:center}dialog .row.col{grid-template-columns:1fr}dialog .actions{display:flex;gap:8px;justify-content:flex-end;margin-top:8px}.streams{background:#f7f7fa;border-radius:8px;padding:12px}.stream-row{display:grid;grid-template-columns:100px 1fr 80px 110px auto;gap:8px;align-items:center;padding:6px 0;border-bottom:1px dashed var(--border)}.stream-row:last-child{border-bottom:0}.login{min-height:100vh;display:flex;align-items:center;justify-content:center}.login form{background:var(--panel);padding:32px;border-radius:12px;width:360px;display:flex;flex-direction:column;gap:12px;box-shadow:0 8px 24px #00000014}.login h1{margin:0}.err{color:var(--bad);font-size:13px;min-height:16px}.system-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px}.stat{background:var(--panel);border:1px solid var(--border);border-radius:12px;padding:16px}.stat .v{font-size:28px;font-weight:700}.stat .k{color:var(--muted);font-size:12px;text-transform:uppercase;letter-spacing:.05em}:root{--bg: #ffffff;--panel: #ffffff;--fg: #000000;--muted: #555555;--border: #000000;--accent: #ff5b00;--good: #007a3d;--bad: #c2001a}*,*:before,*:after{border-radius:0!important}button,input,select,textarea,dialog{border-radius:0!important}a{color:var(--fg);text-decoration:underline}.shell{border:0}.side{background:#000!important;color:#fff!important;border-right:1px solid #000}.side h1{text-transform:uppercase;letter-spacing:.08em;font-weight:900;font-size:16px}.side button.nav{border:1px solid transparent!important;text-transform:uppercase;letter-spacing:.04em;font-weight:700;font-size:13px;color:#ccc}.side button.nav:hover{color:#fff;border-color:#333!important}.side button.nav.active{background:var(--accent)!important;color:#000!important;border-color:var(--accent)!important}.side .me{text-transform:uppercase;letter-spacing:.06em;font-size:11px;color:#888}.bar input,.bar select{border:1px solid var(--border)!important;background:var(--panel)!important;outline:none}.bar input:focus,.bar select:focus{border-color:var(--accent)!important}.btn{border:1px solid var(--border)!important;background:var(--panel)!important;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;transition:background 80ms linear,color 80ms linear}.btn:hover{background:#000!important;color:#fff!important}.btn.primary{background:var(--accent)!important;color:#000!important;border-color:var(--accent)!important}.btn.primary:hover{background:#000!important;color:#fff!important;border-color:#000!important}.btn.danger{color:var(--bad)!important;border-color:var(--bad)!important;background:var(--panel)!important}.btn.danger:hover{background:var(--bad)!important;color:#fff!important}table{background:var(--panel)!important;border:1px solid var(--border)!important;overflow:visible!important}th{background:#000!important;color:#fff!important;font-weight:800;text-transform:uppercase;letter-spacing:.06em;font-size:11px;border-bottom:1px solid #000}td{border-bottom:1px solid #cccccc!important;font-size:13px}tbody tr:hover{background:#f3f3f3}.tag{background:#000!important;color:#fff!important;text-transform:uppercase;letter-spacing:.06em;font-weight:700;font-size:10px}.pill{text-transform:uppercase;letter-spacing:.06em;font-weight:800;font-size:10px;border:1px solid currentColor}.pill.up{background:var(--good)!important;color:#fff!important;border-color:var(--good)!important}.pill.down{background:var(--bad)!important;color:#fff!important;border-color:var(--bad)!important}.pill.unknown{background:#fff!important;color:var(--muted)!important;border-color:#ccc!important}dialog{border:1px solid var(--border)!important;box-shadow:none!important;background:var(--panel)!important;color:var(--fg)!important}dialog::backdrop{background:#00000080}dialog h2{margin:0 0 8px;text-transform:uppercase;letter-spacing:.04em;font-weight:900;font-size:16px;border-bottom:1px solid var(--border);padding-bottom:8px}dialog input,dialog textarea,dialog select{border:1px solid var(--border)!important;background:var(--panel)!important;color:var(--fg)!important;outline:none}dialog input:focus,dialog textarea:focus,dialog select:focus{border-color:var(--accent)!important}dialog .actions{padding-top:12px;border-top:1px solid #cccccc}.streams{background:#f5f5f5!important;border:1px solid #cccccc!important}.stream-row{border-bottom:1px solid #cccccc!important}.stream-row:last-child{border-bottom:0!important}.login{background:#fff}.login form{border:1px solid var(--border)!important;box-shadow:none!important;background:var(--panel)!important}.login h1{text-transform:uppercase;letter-spacing:.04em;font-weight:900;font-size:20px}.err{font-weight:600}.system-grid{gap:0!important}.stat{border:1px solid var(--border)!important;margin:-1px 0 0 -1px}.stat .v{font-weight:900;letter-spacing:-.01em}.stat .k{font-weight:700;letter-spacing:.08em} +:root{--bg: #f7f7fa;--panel: #fff;--fg: #14161b;--muted: #6b7280;--border: #e3e5ec;--accent: #ff6a26;--good: #178a6a;--bad: #c2342f;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg)}button{font:inherit;cursor:pointer}a{color:var(--accent)}.shell{display:grid;grid-template-columns:240px 1fr;min-height:100vh}.side{background:#14161b;color:#e8eaef;padding:20px;display:flex;flex-direction:column;gap:8px}.side h1{font-size:18px;margin:0 0 16px}.side button.nav{text-align:left;background:transparent;color:#cdd1da;border:0;padding:10px 12px;border-radius:8px;font-size:14px}.side button.nav.active{background:var(--accent);color:#1a0a00;font-weight:700}.side .me{margin-top:auto;font-size:12px;color:#8a8f9c}.main{padding:24px}.bar{display:flex;gap:8px;margin-bottom:16px;align-items:center;flex-wrap:wrap}.bar input,.bar select{padding:8px 10px;border:1px solid var(--border);border-radius:8px;background:var(--panel);font-size:14px;min-width:220px}.btn{padding:8px 14px;border-radius:8px;border:1px solid var(--border);background:var(--panel);font-size:14px}.btn.primary{background:var(--accent);color:#1a0a00;border-color:var(--accent);font-weight:700}.btn.danger{color:var(--bad);border-color:var(--bad)}table{width:100%;border-collapse:collapse;background:var(--panel);border-radius:12px;overflow:hidden}th,td{padding:10px 12px;border-bottom:1px solid var(--border);text-align:left;font-size:14px;vertical-align:top}th{background:#f0f1f5;font-weight:600}tr:last-child td{border-bottom:0}.tag{display:inline-block;font-size:11px;padding:2px 8px;border-radius:999px;background:#eef0f4;margin-right:4px}.pill{font-size:11px;padding:2px 8px;border-radius:999px}.pill.up{background:#dff5ec;color:var(--good)}.pill.down{background:#fde7e6;color:var(--bad)}.pill.unknown{background:#eef0f4;color:var(--muted)}dialog{border:0;border-radius:14px;padding:0;max-width:720px;width:90%;box-shadow:0 12px 40px #0003}dialog form{padding:24px;display:flex;flex-direction:column;gap:12px}dialog h2{margin:0 0 4px}dialog input,dialog textarea,dialog select{padding:8px 10px;border:1px solid var(--border);border-radius:8px;font-size:14px;width:100%}dialog .row{display:grid;grid-template-columns:140px 1fr;gap:12px;align-items:center}dialog .row.col{grid-template-columns:1fr}dialog .actions{display:flex;gap:8px;justify-content:flex-end;margin-top:8px}.streams{background:#f7f7fa;border-radius:8px;padding:12px}.stream-row{display:grid;grid-template-columns:100px 1fr 80px 110px auto;gap:8px;align-items:center;padding:6px 0;border-bottom:1px dashed var(--border)}.stream-row:last-child{border-bottom:0}.login{min-height:100vh;display:flex;align-items:center;justify-content:center}.login form{background:var(--panel);padding:32px;border-radius:12px;width:360px;display:flex;flex-direction:column;gap:12px;box-shadow:0 8px 24px #00000014}.login h1{margin:0}.err{color:var(--bad);font-size:13px;min-height:16px}.system-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px}.stat{background:var(--panel);border:1px solid var(--border);border-radius:12px;padding:16px}.stat .v{font-size:28px;font-weight:700}.stat .k{color:var(--muted);font-size:12px;text-transform:uppercase;letter-spacing:.05em}:root{--bg: #ffffff;--panel: #ffffff;--fg: #000000;--muted: #555555;--border: #000000;--accent: #ff5b00;--good: #007a3d;--bad: #c2001a}*,*:before,*:after{border-radius:0!important}button,input,select,textarea,dialog{border-radius:0!important}a{color:var(--fg);text-decoration:underline}.shell{border:0}.side{background:#000!important;color:#fff!important;border-right:1px solid #000}.side h1{text-transform:uppercase;letter-spacing:.08em;font-weight:900;font-size:16px}.side button.nav{border:1px solid transparent!important;text-transform:uppercase;letter-spacing:.04em;font-weight:700;font-size:13px;color:#ccc}.side button.nav:hover{color:#fff;border-color:#333!important}.side button.nav.active{background:var(--accent)!important;color:#000!important;border-color:var(--accent)!important}.side .me{text-transform:uppercase;letter-spacing:.06em;font-size:11px;color:#888}.bar input,.bar select{border:1px solid var(--border)!important;background:var(--panel)!important;outline:none}.bar input:focus,.bar select:focus{border-color:var(--accent)!important}.btn{border:1px solid var(--border)!important;background:var(--panel)!important;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;transition:background 80ms linear,color 80ms linear}.btn:hover{background:#000!important;color:#fff!important}.btn.primary{background:var(--accent)!important;color:#000!important;border-color:var(--accent)!important}.btn.primary:hover{background:#000!important;color:#fff!important;border-color:#000!important}.btn.danger{color:var(--bad)!important;border-color:var(--bad)!important;background:var(--panel)!important}.btn.danger:hover{background:var(--bad)!important;color:#fff!important}table{background:var(--panel)!important;border:1px solid var(--border)!important;overflow:visible!important}th{background:#000!important;color:#fff!important;font-weight:800;text-transform:uppercase;letter-spacing:.06em;font-size:11px;border-bottom:1px solid #000}td{border-bottom:1px solid #cccccc!important;font-size:13px}tbody tr:hover{background:#f3f3f3}.tag{background:#000!important;color:#fff!important;text-transform:uppercase;letter-spacing:.06em;font-weight:700;font-size:10px}.pill{text-transform:uppercase;letter-spacing:.06em;font-weight:800;font-size:10px;border:1px solid currentColor}.pill.up{background:var(--good)!important;color:#fff!important;border-color:var(--good)!important}.pill.down{background:var(--bad)!important;color:#fff!important;border-color:var(--bad)!important}.pill.unknown{background:#fff!important;color:var(--muted)!important;border-color:#ccc!important}dialog{border:1px solid var(--border)!important;box-shadow:none!important;background:var(--panel)!important;color:var(--fg)!important}dialog::backdrop{background:#00000080}dialog h2{margin:0 0 8px;text-transform:uppercase;letter-spacing:.04em;font-weight:900;font-size:16px;border-bottom:1px solid var(--border);padding-bottom:8px}dialog input,dialog textarea,dialog select{border:1px solid var(--border)!important;background:var(--panel)!important;color:var(--fg)!important;outline:none}dialog input:focus,dialog textarea:focus,dialog select:focus{border-color:var(--accent)!important}dialog .actions{padding-top:12px;border-top:1px solid #cccccc}.streams{background:#f5f5f5!important;border:1px solid #cccccc!important}.stream-row{border-bottom:1px solid #cccccc!important}.stream-row:last-child{border-bottom:0!important}.login{background:#fff}.login form{border:1px solid var(--border)!important;box-shadow:none!important;background:var(--panel)!important}.login h1{text-transform:uppercase;letter-spacing:.04em;font-weight:900;font-size:20px}.err{font-weight:600}.system-grid{gap:0!important}.stat{border:1px solid var(--border)!important;margin:-1px 0 0 -1px}.stat .v{font-weight:900;letter-spacing:-.01em}.stat .k{font-weight:700;letter-spacing:.08em}.tabs{display:flex;gap:0;border-bottom:1px solid var(--border);margin:4px 0 12px}.tabs button{background:var(--panel);border:1px solid var(--border);border-bottom:0;padding:8px 14px;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;margin-right:-1px}.tabs button.active{background:var(--accent);color:#000;border-color:var(--accent)}.tab-body{padding:6px 0}.row.image-row{grid-template-columns:1fr}.image-area{display:grid;grid-template-columns:140px 1fr;gap:16px;align-items:start}.image-area .preview{width:140px;height:140px;border:1px solid var(--border);background-size:cover;background-position:center;background-color:#f5f5f5;position:relative;display:grid;place-items:center;color:var(--muted);font-size:11px}.image-area .actions-col{display:grid;gap:6px;align-content:start}.image-area .dropzone{border:2px dashed #999;padding:10px 12px;font-size:12px;color:var(--muted);text-align:center;cursor:pointer;-webkit-user-select:none;user-select:none}.image-area .dropzone.over{border-color:var(--accent);color:var(--fg);background:#fff4ec}.bulkbar{position:sticky;top:0;z-index:2;background:#000;color:#fff;padding:8px 12px;margin-bottom:8px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}.bulkbar .btn{background:#111!important;color:#fff!important;border-color:#444!important}.bulkbar .btn:hover{background:var(--accent)!important;color:#000!important;border-color:var(--accent)!important}.bulkbar .count{font-weight:800;text-transform:uppercase;letter-spacing:.06em;font-size:12px}.station-art-thumb{width:48px;height:48px;background-color:#f3f3f3;border:1px solid var(--border);flex-shrink:0;overflow:hidden;position:relative;display:block}.station-art-thumb img{width:100%;height:100%;object-fit:cover;display:block}.station-art-thumb.empty:after{content:"♪";position:absolute;top:0;right:0;bottom:0;left:0;display:grid;place-items:center;color:var(--muted);font-size:22px}.station-cell{display:flex;align-items:center;gap:10px}.station-cell .meta{min-width:0}.station-cell .meta small{color:var(--muted);display:block;max-width:360px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.preview-player{display:inline-flex;align-items:center;gap:6px;font-size:11px;border:1px solid var(--border);padding:2px 6px}.preview-player button{background:transparent;border:0;font-size:14px;padding:0 2px;cursor:pointer}.preview-player.playing button{color:var(--accent)}.leaderboard{display:grid;gap:8px}.leader-row{display:grid;grid-template-columns:32px 60px 1fr repeat(6,auto);align-items:center;gap:10px;padding:8px 12px;border:1px solid var(--border);background:var(--panel)}.leader-row .rank{font-weight:900;font-size:18px}.leader-row .art{width:48px;height:48px;border-radius:6px;overflow:hidden;background:#f3f3f3;display:flex;align-items:center;justify-content:center;flex:none}.leader-row .art img{width:100%;height:100%;object-fit:cover;display:block}.leader-row .art.empty:after{content:"♪";color:var(--muted);font-size:22px}.leader-row .name b{font-size:14px}.leader-row .stat-num{font-weight:800;font-size:13px;white-space:nowrap}dialog.wide{max-width:880px}dialog.danger-confirm{border:2px solid var(--bad);max-width:560px;width:92%}dialog.danger-confirm form{gap:14px;padding:22px}dialog.danger-confirm .danger-header{display:flex;align-items:center;gap:12px}dialog.danger-confirm .danger-icon{width:44px;height:44px;display:grid;place-items:center;background:var(--bad);color:#fff;font-size:26px;font-weight:900;flex-shrink:0}dialog.danger-confirm h2{margin:0;color:var(--bad);text-transform:uppercase;letter-spacing:.04em;font-size:20px}dialog.danger-confirm .danger-body{display:flex;flex-direction:column;gap:12px;font-size:14px}dialog.danger-confirm .lede{margin:0;padding:12px;background:#fde7e6;border-left:4px solid var(--bad);color:#2a0000}dialog.danger-confirm .impact{margin:0;padding-left:22px;font-size:13px;color:var(--fg);line-height:1.5}dialog.danger-confirm .impact code,dialog.danger-confirm .type-to-confirm code,dialog.danger-confirm .mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;background:#f0f1f5;padding:1px 6px;font-size:12px}dialog.danger-confirm .impact-list{background:#fafafc;border:1px solid var(--border);padding:8px 12px;font-size:12px;max-height:180px;overflow:auto}dialog.danger-confirm .impact-list-head{font-weight:700;margin-bottom:4px;text-transform:uppercase;letter-spacing:.06em;font-size:11px;color:var(--muted)}dialog.danger-confirm .impact-list ul{margin:0;padding-left:18px;list-style:square}dialog.danger-confirm .impact-list li.more{color:var(--muted);font-style:italic;list-style:none;margin-left:-16px}dialog.danger-confirm .type-to-confirm{display:flex;flex-direction:column;gap:6px;font-size:13px}dialog.danger-confirm .type-to-confirm input{border:2px solid var(--bad);font-size:15px;padding:10px 12px}dialog.danger-confirm .actions .btn.danger:disabled{opacity:.35;cursor:not-allowed;background:var(--panel);color:var(--bad)}dialog.danger-confirm .actions .btn.danger:not(:disabled){background:var(--bad);color:#fff;border-color:var(--bad);font-weight:700}.readonly-meta{margin-top:8px;padding:10px 12px;background:#fafafc;border:1px solid var(--border);display:grid;gap:4px;font-size:12px}.readonly-meta-head{text-transform:uppercase;letter-spacing:.06em;color:var(--muted);font-weight:700;margin-bottom:4px;font-size:11px}.readonly-meta .meta-row{display:grid;grid-template-columns:140px 1fr;gap:8px;align-items:center}.readonly-meta .meta-k{color:var(--muted)}.readonly-meta .meta-v.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;word-break:break-all}tr.discover-existing{opacity:.55}tr.discover-existing td{background:#fafafc}.main .muted{color:var(--muted)} diff --git a/server/public/assets/admin-GqZPhz-K.js b/server/public/assets/admin-GqZPhz-K.js new file mode 100644 index 0000000..79df943 --- /dev/null +++ b/server/public/assets/admin-GqZPhz-K.js @@ -0,0 +1 @@ +import"./modulepreload-polyfill-B5Qt9EMX.js";import{P,a as c,c as y,e}from"./player-BBOsFRH-.js";const C=document.getElementById("app"),l={user:null,view:"stations",stations:[],users:[],rooms:[],leaderboard:[],system:null,search:"",sourceFilter:"",selected:new Set,discoverResults:[],discoverQuery:{q:"",country:"",tag:""}},I=new P({onState:s=>{Object.assign(f,s),R()}}),f={stationId:null,playing:!1,loading:!1};async function L(){try{l.user=await c.get("/api/auth/me")}catch{return q()}if(l.user.role!=="admin"){C.innerHTML=``;return}await h(),g()}async function h(){const s=[c.get("/api/stations?all=1")];l.view==="users"&&s.push(c.get("/api/auth/users")),l.view==="system"&&s.push(c.get("/api/admin/system")),l.view==="rooms"&&s.push(c.get("/api/admin/rooms")),l.view==="leaderboard"&&s.push(c.get("/api/admin/leaderboard"));const t=await Promise.all(s);l.stations=t[0],l.view==="users"&&(l.users=t[1]||[]),l.view==="system"&&(l.system=t[1]||null),l.view==="rooms"&&(l.rooms=t[1]||[]),l.view==="leaderboard"&&(l.leaderboard=t[1]||[])}function q(){y(C),C.appendChild(e("div",{class:"login"},e("form",{onSubmit:async s=>{s.preventDefault();const t=new FormData(s.target);try{l.user=await c.post("/api/auth/login",{username:t.get("username"),password:t.get("password")}),await L()}catch(a){s.target.querySelector(".err").textContent=a.message}}},e("h1",{},"Admin sign in"),e("input",{name:"username",placeholder:"Username",required:!0}),e("input",{name:"password",type:"password",placeholder:"Password",required:!0}),e("div",{class:"err"}),e("button",{class:"btn primary",type:"submit"},"Sign in"))))}function g(){y(C);const s=["stations","discover","leaderboard","rooms","users","system"],t=e("aside",{class:"side"},e("h1",{},"OnlineRadio · Admin"),...s.map(i=>e("button",{class:`nav ${l.view===i?"active":""}`,onClick:async()=>{l.view=i,l.selected.clear(),await h(),g()}},B(i))),e("div",{class:"me"},`Signed in as ${l.user.username}`,e("br"),e("a",{href:"/master",target:"_blank"},"Open master ↗"),e("br"),e("a",{href:"/",target:"_blank"},"Open kiosk ↗"),e("br"),e("a",{href:"#",onClick:async i=>{i.preventDefault(),await c.post("/api/auth/logout"),location.reload()}},"Sign out"))),a=e("main",{class:"main"});C.appendChild(e("div",{class:"shell"},t,a)),l.view==="stations"?N(a):l.view==="discover"?A(a):l.view==="leaderboard"?j(a):l.view==="rooms"?G(a):l.view==="users"?H(a):l.view==="system"&&V(a)}const B=s=>({stations:"Stations",discover:"Discover",leaderboard:"Leaderboard",rooms:"Rooms",users:"Users",system:"System"})[s];function N(s){s.appendChild(e("div",{class:"bar"},e("input",{placeholder:"Search name / country / genre…",value:l.search,onInput:t=>{l.search=t.target.value,w()}}),e("select",{onChange:t=>{l.sourceFilter=t.target.value,w()}},e("option",{value:""},"All sources"),...U(l.stations).map(t=>e("option",{value:t,selected:l.sourceFilter===t},t))),e("button",{class:"btn primary",onClick:()=>T()},"+ Add station"),e("button",{class:"btn",onClick:async()=>{if(!confirm("Run health check on every stream?"))return;const t=await c.post("/api/admin/health-check");alert(`Checked ${t.checked} streams.`),await h(),g()}},"Health check"))),s.appendChild(e("div",{id:"bulkSlot"})),s.appendChild(e("div",{id:"tableWrap"})),w()}function U(s){return[...new Set(s.map(t=>t.source).filter(Boolean))].sort()}function w(){const s=document.getElementById("tableWrap"),t=document.getElementById("bulkSlot");if(!s||!t)return;y(s),y(t);const a=l.search.toLowerCase(),i=l.sourceFilter,n=l.stations.filter(o=>(!i||o.source===i)&&(!a||o.name.toLowerCase().includes(a)||(o.country||"").toLowerCase().includes(a)||(o.genres||[]).some(m=>m.toLowerCase().includes(a))));l.selected.size&&t.appendChild(O());const r=n.length&&n.every(o=>l.selected.has(o.id)),d=e("table",{},e("thead",{},e("tr",{},e("th",{style:{width:"32px"}},e("input",{type:"checkbox",checked:r,onChange:o=>{o.target.checked?n.forEach(m=>l.selected.add(m.id)):n.forEach(m=>l.selected.delete(m.id)),w()}})),e("th",{},"Name"),e("th",{},"Source"),e("th",{},"Genres"),e("th",{},"Country"),e("th",{},"Streams"),e("th",{},"▲/▼/▶"),e("th",{},"On"),e("th",{},"Actions"))),e("tbody",{},...n.map(o=>{const m=o.image_display_url||o.image_url;return e("tr",{"data-id":o.id},e("td",{},e("input",{type:"checkbox",checked:l.selected.has(o.id),onChange:p=>{p.target.checked?l.selected.add(o.id):l.selected.delete(o.id),w()}})),e("td",{},e("div",{class:"station-cell"},e("div",{class:"station-art-thumb"+(m?"":" empty")},m?e("img",{src:m,alt:"",loading:"lazy",referrerpolicy:"no-referrer",onError:p=>{const u=p.target.parentNode;p.target.remove(),u&&u.classList.add("empty")}}):null),e("div",{class:"meta"},e("strong",{},o.name),e("small",{},o.homepage||o.uuid)))),e("td",{},o.source||""),e("td",{},...(o.genres||[]).slice(0,3).map(p=>e("span",{class:"tag"},p))),e("td",{},o.country||""),e("td",{},String(o.stream_count??"—")),e("td",{},`${o.up||0}/${o.down||0}/${o.plays||0}`),e("td",{},o.enabled?"✓":"✗"),e("td",{},W(o)," ",e("button",{class:"btn",onClick:()=>T(o.id)},"Edit")," ",e("button",{class:"btn danger",onClick:async()=>{await _({stations:[o]})&&(await c.del(`/api/admin/stations/${o.id}`),await h(),g())}},"×")))})));s.appendChild(d)}function O(s){const t=[...l.selected];async function a(n,r){if(r&&!confirm(`${r} (${t.length} stations)`))return;const d=await c.post("/api/admin/stations/bulk",{ids:t,action:n});alert(`${n}: ${d.ok} ok / ${d.failed} failed`),l.selected.clear(),await h(),g()}async function i(){const n=l.stations.filter(d=>l.selected.has(d.id));if(!n.length||!await _({stations:n}))return;const r=await c.post("/api/admin/stations/bulk",{ids:n.map(d=>d.id),action:"delete"});alert(`delete: ${r.ok} ok / ${r.failed} failed`),l.selected.clear(),await h(),g()}return e("div",{class:"bulkbar"},e("span",{class:"count"},`${t.length} selected`),e("button",{class:"btn",onClick:()=>a("enable")},"Enable"),e("button",{class:"btn",onClick:()=>a("disable")},"Disable"),e("button",{class:"btn",onClick:()=>a("scrape-icon","Scrape icons for")},"Scrape icons"),e("button",{class:"btn",onClick:()=>a("refetch-image","Refetch images for")},"Refetch images"),e("button",{class:"btn danger",onClick:()=>i()},"Delete"),e("button",{class:"btn",onClick:()=>{l.selected.clear(),w()}},"Clear"))}function W(s){const t=f.stationId===s.id&&f.playing;return e("span",{class:"preview-player"+(t?" playing":""),"data-preview-station":s.id},e("button",{title:"Preview",onClick:a=>{a.stopPropagation(),f.stationId===s.id&&f.playing?(I.stop(),f.stationId=null,f.playing=!1):(f.stationId=s.id,I.play(s)),R()}},t?"❚❚":"▶"))}function R(){document.querySelectorAll(".preview-player").forEach(s=>{const t=Number(s.getAttribute("data-preview-station")),a=f.stationId===t&&f.playing;s.classList.toggle("playing",a);const i=s.querySelector("button");i&&(i.textContent=a?"❚❚":f.stationId===t&&f.loading?"…":"▶")})}async function T(s){const t=s?await c.get(`/api/stations/${s}`):{name:"",genres:[],streams:[],enabled:!0,image_url:"",country:"",homepage:""},a=e("dialog",{class:"wide"});let i="details";const n=e("div",{class:"tab-body"}),r=e("div",{class:"tabs"},...[["details","Details"],["streams","Streams"],["image","Image"],["stats","Stats"]].map(([m,p])=>e("button",{type:"button",class:i===m?"active":"",onClick:()=>{i=m,d()}},p)));function d(){y(n),r.querySelectorAll("button").forEach((m,p)=>{const u=["details","streams","image","stats"][p];m.classList.toggle("active",u===i)}),i==="details"?M(n,t):i==="streams"?F(n,t):i==="image"?z(n,t,async()=>{s&&Object.assign(t,await c.get(`/api/stations/${s}`)),d()}):i==="stats"&&S(n,t,s)}d();const o=e("div",{class:"actions"},s?e("button",{class:"btn danger",type:"button",onClick:async()=>{await _({stations:[t]})&&(await c.del(`/api/admin/stations/${s}`),a.close(),await h(),g())}},"Delete"):null,e("button",{class:"btn",type:"button",onClick:()=>a.close()},"Cancel"),e("button",{class:"btn primary",type:"button",onClick:async()=>{const m={name:t.name,homepage:t.homepage,country:t.country,genres:t.genres,description:t.description,image_url:t.image_url,category:t.category,enabled:t.enabled};if(s)await c.patch(`/api/admin/stations/${s}`,m);else{m.streams=(t.streams||[]).filter(u=>u.url);const p=await c.post("/api/stations",m);Object.assign(t,p)}a.close(),await h(),g()}},"Save"));a.appendChild(e("form",{method:"dialog",onSubmit:m=>m.preventDefault()},e("h2",{},s?`Edit · ${t.name}`:"Add station"),r,n,o)),document.body.appendChild(a),a.showModal(),a.addEventListener("close",()=>a.remove())}function M(s,t){if(s.appendChild(e("div",{class:"row"},e("label",{},"Name"),e("input",{value:t.name||"",onInput:a=>t.name=a.target.value,required:!0}))),s.appendChild(e("div",{class:"row"},e("label",{},"Homepage"),e("input",{value:t.homepage||"",onInput:a=>t.homepage=a.target.value}))),s.appendChild(e("div",{class:"row"},e("label",{},"Country"),e("input",{value:t.country||"",maxlength:4,onInput:a=>t.country=a.target.value}))),s.appendChild(e("div",{class:"row"},e("label",{},"Genres (CSV)"),e("input",{value:(t.genres||[]).join(", "),onInput:a=>t.genres=a.target.value.split(",").map(i=>i.trim()).filter(Boolean)}))),s.appendChild(e("div",{class:"row"},e("label",{},"Category"),e("input",{value:t.category||"",onInput:a=>t.category=a.target.value}))),s.appendChild(e("div",{class:"row"},e("label",{},"Description"),e("textarea",{rows:4,placeholder:"Short description shown to listeners",onInput:a=>t.description=a.target.value},t.description||""))),s.appendChild(e("div",{class:"row"},e("label",{},"Enabled"),e("input",{type:"checkbox",checked:t.enabled,onChange:a=>t.enabled=a.target.checked}))),t.id){const a=(i,n)=>e("div",{class:"meta-row"},e("span",{class:"meta-k"},i),e("span",{class:"meta-v mono"},n==null||n===""?"—":String(n)));s.appendChild(e("div",{class:"readonly-meta"},e("div",{class:"readonly-meta-head"},"Read-only metadata (used by the public API)"),a("id",t.id),a("uuid",t.uuid),a("slug",t.slug),a("source",t.source),a("source_ref",t.source_ref),a("image_source",t.image_source),a("image_path",t.image_path),a("created_at",t.created_at),a("updated_at",t.updated_at)))}}function F(s,t){if(!t.id){const r=e("div",{class:"streams"}),d=()=>{y(r),r.appendChild(e("div",{style:{fontWeight:700,marginBottom:"6px"}},"Streams"));for(const o of t.streams||[])r.appendChild(x(o,()=>{t.streams=t.streams.filter(m=>m!==o),d()}));r.appendChild(e("button",{class:"btn",type:"button",onClick:()=>{var o;t.streams=[...t.streams||[],{url:"",format:"mp3",priority:((o=t.streams)==null?void 0:o.length)||0}],d()}},"+ Add stream"))};d(),s.appendChild(r);return}const a=e("div",{class:"streams"}),i=async()=>{t.streams=await c.get(`/api/admin/stations/${t.id}/streams`),n()},n=()=>{y(a),a.appendChild(e("div",{style:{fontWeight:700,marginBottom:"6px"}},"Streams"));for(const r of t.streams||[])a.appendChild(x(r,async()=>{confirm("Delete stream?")&&(await c.del(`/api/admin/streams/${r.id}`),await i())},async()=>{await c.patch(`/api/admin/streams/${r.id}`,{url:r.url,format:r.format,bitrate:r.bitrate||null,label:r.label||null,priority:r.priority||0})},async()=>{const d=await c.post(`/api/admin/streams/${r.id}/probe`);r.last_status=d.status,n()}));a.appendChild(e("button",{class:"btn",type:"button",onClick:async()=>{var d;const r=await c.post(`/api/admin/stations/${t.id}/streams`,{url:"",format:"mp3",priority:((d=t.streams)==null?void 0:d.length)||0});t.streams=[...t.streams||[],r],n()}},"+ Add stream"))};n(),s.appendChild(a)}function x(s,t,a,i){const n=(r,d)=>{s[r]=d};return e("div",{class:"stream-row"},e("select",{onChange:r=>n("format",r.target.value)},...["mp3","aac","hls","m3u","pls","ogg","unknown"].map(r=>e("option",{value:r,selected:s.format===r},r))),e("input",{value:s.url||"",placeholder:"https://…",onInput:r=>n("url",r.target.value)}),e("input",{type:"number",placeholder:"kbps",value:s.bitrate||"",onInput:r=>n("bitrate",Number(r.target.value)||null)}),e("input",{value:s.label||"",placeholder:"Label",onInput:r=>n("label",r.target.value)}),s.last_status?e("span",{class:`pill ${s.last_status==="up"?"up":s.last_status==="down"?"down":"unknown"}`},s.last_status):e("span"),e("span",{style:{display:"flex",gap:"4px"}},i?e("button",{class:"btn",type:"button",onClick:i},"Test"):null,a?e("button",{class:"btn",type:"button",onClick:a},"Save"):null,e("button",{class:"btn danger",type:"button",onClick:t},"×")))}function z(s,t,a){if(!t.id){s.appendChild(e("p",{},"Save the station first, then come back to upload an image."));return}const i=t.image_display_url||t.image_url,n=e("div",{class:"image-area"}),r=e("div",{class:"preview",style:i?{backgroundImage:`url("${i}")`}:{}},i?"":"No image"),d=e("div",{class:"dropzone"},"Drop image file here, or click to upload"),o=e("input",{type:"file",accept:"image/*",style:{display:"none"}});async function m(u){if(!u)return;if(u.size>5*1024*1024)return alert("File is too large (5 MB max).");const v=await u.arrayBuffer(),D=await fetch(`/api/admin/stations/${t.id}/image`,{method:"PUT",headers:{"Content-Type":u.type||"application/octet-stream"},credentials:"same-origin",body:v});if(!D.ok){alert("Upload failed: "+D.status);return}await a()}d.addEventListener("click",()=>o.click()),d.addEventListener("dragover",u=>{u.preventDefault(),d.classList.add("over")}),d.addEventListener("dragleave",()=>d.classList.remove("over")),d.addEventListener("drop",u=>{var v;u.preventDefault(),d.classList.remove("over"),m((v=u.dataTransfer.files)==null?void 0:v[0])}),o.addEventListener("change",()=>{var u;return m((u=o.files)==null?void 0:u[0])});const p=e("div",{class:"actions-col"},e("div",{class:"row"},e("label",{},"Image URL"),e("input",{value:t.image_url||"",onInput:u=>t.image_url=u.target.value})),d,o,e("div",{style:{display:"flex",gap:"6px",flexWrap:"wrap"}},e("button",{class:"btn",type:"button",onClick:async()=>{await c.patch(`/api/admin/stations/${t.id}`,{image_url:t.image_url});const u=await fetch(`/api/admin/stations/${t.id}/image/refetch`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"same-origin",body:JSON.stringify({url:t.image_url})});if(!u.ok){alert("Refetch failed: "+u.status);return}await a()}},"Refetch from URL"),e("button",{class:"btn",type:"button",onClick:async()=>{const u=await c.post(`/api/admin/stations/${t.id}/scrape-icon`).catch(v=>({error:v.message}));u.error&&alert("Scrape failed: "+u.error),await a()}},"Auto-scrape"),e("button",{class:"btn danger",type:"button",onClick:async()=>{confirm("Drop the cached image?")&&(await c.del(`/api/admin/stations/${t.id}/image`),await a())}},"Clear cache")),e("div",{style:{fontSize:"11px",color:"var(--muted)"}},`Source: ${t.image_source||"—"} · Path: ${t.image_path||"—"}`));n.appendChild(r),n.appendChild(p),s.appendChild(n)}function S(s,t,a){if(!a){s.appendChild(e("p",{},"Stats are available after the station is created."));return}s.appendChild(e("div",{class:"system-grid"},b("Votes up",t.up||0),b("Votes down",t.down||0),b("Score",(t.score||0).toFixed(2)),b("Plays",t.plays||0),b("Streams",(t.streams||[]).length))),s.appendChild(e("div",{style:{marginTop:"12px",display:"flex",gap:"8px",flexWrap:"wrap"}},e("button",{class:"btn danger",onClick:async()=>{confirm("Delete all votes for this station?")&&(await c.del(`/api/admin/stations/${a}/votes`),Object.assign(t,await c.get(`/api/stations/${a}`)),S($(s),t,a))}},"Reset votes"),e("button",{class:"btn danger",onClick:async()=>{confirm("Delete all plays for this station?")&&(await c.del(`/api/admin/stations/${a}/plays`),Object.assign(t,await c.get(`/api/stations/${a}`)),S($(s),t,a))}},"Reset plays")))}function $(s){return y(s),s}function b(s,t){return e("div",{class:"stat"},e("div",{class:"v"},String(t)),e("div",{class:"k"},s))}function _({stations:s}){const t=Array.isArray(s)?s:[s],a=t.length===1?t[0]:null,i=a?a.name:"DELETE";return new Promise(n=>{const r=e("dialog",{class:"danger-confirm"});let d="";const o=e("input",{placeholder:`Type "${i}" to confirm`,autocomplete:"off",onInput:p=>{d=p.target.value,m.disabled=d.trim()!==i}}),m=e("button",{class:"btn danger",type:"button",disabled:!0,onClick:()=>{r.close(),n(!0)}},a?"Permanently delete":`Permanently delete ${t.length} stations`);r.appendChild(e("form",{method:"dialog",onSubmit:p=>p.preventDefault()},e("div",{class:"danger-header"},e("div",{class:"danger-icon"},"⚠"),e("h2",{},a?`Delete "${a.name}"?`:`Delete ${t.length} stations?`)),e("div",{class:"danger-body"},e("p",{class:"lede"},"This is irreversible and ",e("b",{},"will break the public API")," for any client (kiosk, master, third-party integration, bookmarks, scripts) ","that references these stations by id, uuid or slug."),e("ul",{class:"impact"},e("li",{},e("code",{},"GET /api/v1/stations/{id}")," will return 404"),e("li",{},e("code",{},"GET /api/v1/stations/{uuid}")," will return 404"),e("li",{},"All streams, votes, plays and favorites attached to ",a?"this station":"these stations"," are dropped (cascade)"),e("li",{},"Active listeners playing ",a?"this station":"one of these"," will receive a stop event"),e("li",{},"Cached image files are unlinked from disk")),t.length>1||a?e("div",{class:"impact-list"},e("div",{class:"impact-list-head"},"Targets:"),e("ul",{},...t.slice(0,12).map(p=>e("li",{},e("b",{},p.name),p.uuid?e("span",{class:"mono"},` · ${p.uuid}`):null,e("span",{class:"mono"},` · id=${p.id}`))),t.length>12?e("li",{class:"more"},`…and ${t.length-12} more`):null)):null,e("label",{class:"type-to-confirm"},"Type ",e("code",{},i)," to confirm:",o)),e("div",{class:"actions"},e("button",{class:"btn",type:"button",onClick:()=>{r.close(),n(!1)}},"Cancel"),m))),document.body.appendChild(r),r.addEventListener("close",()=>r.remove()),r.showModal(),setTimeout(()=>o.focus(),50)})}function A(s){s.appendChild(e("h2",{},"Discover · Radio-Browser"));const t=l.discoverQuery;async function a(){const i=new URLSearchParams;t.q&&i.set("q",t.q),t.country&&i.set("country",t.country),t.tag&&i.set("tag",t.tag),i.set("limit","50");const n=document.getElementById("discoverWrap");n&&(y(n),n.appendChild(e("p",{class:"muted"},"Loading…")));try{l.discoverResults=await c.get(`/api/stations/sources/radiobrowser/search?${i}`)}catch(r){l.discoverResults=[],n&&(y(n),n.appendChild(e("p",{class:"err"},r.message||"Search failed")));return}k()}s.appendChild(e("div",{class:"bar"},e("input",{placeholder:"Name…",value:t.q,onInput:i=>t.q=i.target.value,onKeyDown:i=>{i.key==="Enter"&&a()}}),e("input",{placeholder:"Country (e.g. NL)",value:t.country,onInput:i=>t.country=i.target.value,onKeyDown:i=>{i.key==="Enter"&&a()},style:{minWidth:"120px"}}),e("input",{placeholder:"Tag/genre",value:t.tag,onInput:i=>t.tag=i.target.value,onKeyDown:i=>{i.key==="Enter"&&a()}}),e("button",{class:"btn primary",onClick:a},"Search"),e("button",{class:"btn",onClick:()=>{t.q="",t.country="",t.tag="",A($(s))}},"Reset"),e("button",{class:"btn",onClick:async()=>{const i=l.discoverResults.filter(n=>n.__import);if(!i.length)return alert("Nothing selected.");if(confirm(`Import ${i.length} stations?`)){for(const n of i)await c.post("/api/stations/sources/radiobrowser/import",n).catch(()=>{});alert("Done."),await h(),await a()}}},"Import selected"))),s.appendChild(e("div",{id:"discoverWrap"})),l.discoverResults.length?k():a()}function k(){const s=document.getElementById("discoverWrap");if(!s)return;y(s);const t=l.discoverResults;if(!t.length){s.appendChild(e("p",{class:"muted"},"No results. Try a different query — leave fields blank for the top stations on Radio-Browser."));return}const a=new Set(l.stations.map(n=>n.uuid).filter(Boolean)),i=t.length&&t.every(n=>n.__import);s.appendChild(e("table",{},e("thead",{},e("tr",{},e("th",{style:{width:"32px"}},e("input",{type:"checkbox",checked:!!i,onChange:n=>{t.forEach(r=>{r.__import=n.target.checked&&!a.has(r.uuid)}),k()}})),e("th",{},"Name"),e("th",{},"Country"),e("th",{},"Tags"),e("th",{},"Stream"),e("th",{},"Status"),e("th",{},""))),e("tbody",{},...t.map(n=>{var o,m;const r=a.has(n.uuid),d=n.image_url;return e("tr",{class:r?"discover-existing":""},e("td",{},e("input",{type:"checkbox",checked:!!n.__import,disabled:r,onChange:p=>{n.__import=p.target.checked}})),e("td",{},e("div",{class:"station-cell"},e("div",{class:"station-art-thumb"+(d?"":" empty")},d?e("img",{src:d,alt:"",loading:"lazy",referrerpolicy:"no-referrer",onError:p=>{const u=p.target.parentNode;p.target.remove(),u&&u.classList.add("empty")}}):null),e("div",{class:"meta"},e("strong",{},n.name),e("small",{},n.homepage||n.uuid)))),e("td",{},n.country||""),e("td",{},...(n.genres||[]).slice(0,4).map(p=>e("span",{class:"tag"},p))),e("td",{},e("small",{},(((o=n.streams[0])==null?void 0:o.format)||"")+" "+((m=n.streams[0])!=null&&m.bitrate?`· ${n.streams[0].bitrate}kbps`:""))),e("td",{},r?e("span",{class:"pill up"},"in library"):e("span",{class:"pill unknown"},"new")),e("td",{},r?e("button",{class:"btn",disabled:!0},"Imported"):e("button",{class:"btn primary",onClick:async p=>{p.target.disabled=!0;try{await c.post("/api/stations/sources/radiobrowser/import",n),await h(),k()}catch(u){alert("Import failed: "+u.message)}}},"Import")))}))))}function j(s){s.appendChild(e("h2",{},"Leaderboard")),s.appendChild(e("p",{style:{color:"var(--muted)",marginTop:0}},"Top stations by total listen time. Use the reset buttons to moderate runaway counters."));const t=e("div",{class:"leaderboard"});l.leaderboard.forEach((a,i)=>{const n=a.image_display_url||(a.image_path?`/media/${a.image_path}`:a.image_url);t.appendChild(e("div",{class:"leader-row"},e("div",{class:"rank"},String(i+1)),e("div",{class:"art"+(n?"":" empty")},n?e("img",{src:n,alt:"",loading:"lazy",referrerpolicy:"no-referrer",onError:r=>{const d=r.target.parentNode;r.target.remove(),d&&d.classList.add("empty")}}):null),e("div",{class:"name"},e("b",{},a.name),e("br"),e("small",{},a.country||"")),e("div",{class:"stat-num",title:"Total listen time"},`⏱ ${E(a.total_play_ms)}`),e("div",{class:"stat-num",title:"Average session length"},`Ø ${E(a.avg_session_ms)}`),e("div",{class:"stat-num",title:"Play taps"},`▶ ${a.plays}`),e("div",{class:"stat-num",title:"Sessions credited"},`· ${a.sessions}`),e("div",{class:"stat-num"},`▲ ${a.up}`),e("div",{class:"stat-num"},`▼ ${a.down}`)))}),s.appendChild(t)}function E(s){const t=Math.max(0,Math.round((s||0)/1e3));if(t<60)return`${t}s`;const a=Math.floor(t/60);if(a<60)return`${a}m${String(t%60).padStart(2,"0")}s`;const i=Math.floor(a/60);return i<24?`${i}h${String(a%60).padStart(2,"0")}m`:`${Math.floor(i/24)}d${String(i%24).padStart(2,"0")}h`}function G(s){s.appendChild(e("h2",{},"Rooms")),s.appendChild(e("table",{},e("thead",{},e("tr",{},e("th",{},"Slug"),e("th",{},"Name"),e("th",{},"Members"),e("th",{},"Active station"),e("th",{},"Created"),e("th",{},""))),e("tbody",{},...l.rooms.map(t=>e("tr",{},e("td",{},e("code",{},t.slug)),e("td",{},t.name),e("td",{},String(t.members)),e("td",{},t.active?"●":"—"),e("td",{},e("small",{},t.created_at)),e("td",{},t.slug.startsWith("u-")?e("small",{style:{color:"var(--muted)"}},"personal"):e("button",{class:"btn danger",onClick:async()=>{confirm(`Delete room ${t.slug}?`)&&(await c.del(`/api/admin/rooms/${t.slug}`),await h(),g())}},"Delete")))))))}function H(s){s.appendChild(e("div",{class:"bar"},e("h2",{style:{margin:0,flex:1}},"Users"),e("button",{class:"btn primary",onClick:K},"+ Add user"))),s.appendChild(e("table",{},e("thead",{},e("tr",{},e("th",{},"Username"),e("th",{},"Role"),e("th",{},"Created"),e("th",{},""))),e("tbody",{},...l.users.map(t=>e("tr",{},e("td",{},t.username),e("td",{},t.role),e("td",{},t.created_at),e("td",{},e("button",{class:"btn",onClick:async()=>{const a=prompt(`New password for ${t.username}:`);a&&(await c.patch(`/api/auth/users/${t.id}`,{password:a}),alert("Updated"))}},"Reset PW")," ",e("button",{class:"btn",onClick:async()=>{const a=t.role==="admin"?"user":"admin";await c.patch(`/api/auth/users/${t.id}`,{role:a}),await h(),g()}},"Toggle role")," ",t.id!==l.user.id?e("button",{class:"btn danger",onClick:async()=>{confirm(`Delete ${t.username}?`)&&(await c.del(`/api/auth/users/${t.id}`),await h(),g())}},"Delete"):null))))))}function K(){const s=e("dialog");s.appendChild(e("form",{method:"dialog",onSubmit:async t=>{t.preventDefault();const a=new FormData(t.target);await c.post("/api/auth/users",{username:a.get("username"),password:a.get("password"),role:a.get("role")}),s.close(),await h(),g()}},e("h2",{},"New user"),e("div",{class:"row"},e("label",{},"Username"),e("input",{name:"username",required:!0})),e("div",{class:"row"},e("label",{},"Password"),e("input",{name:"password",type:"password",required:!0})),e("div",{class:"row"},e("label",{},"Role"),e("select",{name:"role"},e("option",{value:"user"},"user"),e("option",{value:"admin"},"admin"))),e("div",{class:"actions"},e("button",{class:"btn",type:"button",onClick:()=>s.close()},"Cancel"),e("button",{class:"btn primary",type:"submit"},"Create")))),document.body.appendChild(s),s.showModal(),s.addEventListener("close",()=>s.remove())}function V(s){var a;s.appendChild(e("h2",{},"System"));const t=l.system||{};s.appendChild(e("div",{class:"system-grid"},b("Stations",t.stations||0),b("Streams",t.streams||0),b("Users",t.users||0),b("Favorites",t.favorites||0),b("Cached images",((a=t.image_cache)==null?void 0:a.files)||0),b("Cache size (MB)",t.image_cache?(t.image_cache.bytes/1048576).toFixed(1):"0"),b("Node",t.node||""),b("Uptime (s)",t.uptime_s||0))),s.appendChild(e("div",{style:{marginTop:"16px",display:"flex",gap:"8px"}},e("button",{class:"btn",onClick:async()=>{if(!confirm("Re-seed from data/seed/?"))return;const i=await c.post("/api/admin/reseed");alert(JSON.stringify(i)),await h(),g()}},"Re-seed"),e("button",{class:"btn",onClick:async()=>{const i=await c.post("/api/admin/scrape-icons?all=1");alert(`Updated ${i.updated}, failed ${i.failed}`),await h(),g()}},"Scrape all icons")))}L(); diff --git a/server/public/assets/dom-BvorgAdo.js b/server/public/assets/dom-BvorgAdo.js deleted file mode 100644 index 0c5b70a..0000000 --- a/server/public/assets/dom-BvorgAdo.js +++ /dev/null @@ -1 +0,0 @@ -async function a(t,i,o){const s=await fetch(i,{method:t,credentials:"same-origin",headers:o?{"Content-Type":"application/json"}:{},body:o?JSON.stringify(o):void 0});if(s.status===204)return null;const e=(s.headers.get("content-type")||"").includes("json")?await s.json():await s.text();if(!s.ok)throw Object.assign(new Error((e==null?void 0:e.error)||s.statusText),{status:s.status,data:e});return e}const c={get:t=>a("GET",t),post:(t,i)=>a("POST",t,i),put:(t,i)=>a("PUT",t,i),patch:(t,i)=>a("PATCH",t,i),del:t=>a("DELETE",t)};function r(t,i={},...o){const s=document.createElement(t);for(const[n,e]of Object.entries(i||{}))n==="class"?s.className=e:n==="style"&&typeof e=="object"?Object.assign(s.style,e):n.startsWith("on")&&typeof e=="function"?s.addEventListener(n.slice(2).toLowerCase(),e):n==="html"?s.innerHTML=e:e!==!1&&e!=null&&s.setAttribute(n,e===!0?"":e);for(const n of o.flat())n==null||n===!1||s.appendChild(n instanceof Node?n:document.createTextNode(String(n)));return s}function l(t){for(;t.firstChild;)t.removeChild(t.firstChild)}export{c as a,l as c,r as e}; diff --git a/server/public/assets/kiosk-CdZttV5P.css b/server/public/assets/kiosk-CdZttV5P.css deleted file mode 100644 index 084e28c..0000000 --- a/server/public/assets/kiosk-CdZttV5P.css +++ /dev/null @@ -1 +0,0 @@ -:root{--bg-0: #07080b;--bg-1: #0e1116;--bg-2: #161a22;--bg-3: #1f242e;--line: #262b36;--fg: #e9ecf2;--muted: #8a90a0;--muted-2: #5d6373;--accent: #ff7a3d;--accent-2: #ffb37a;--accent-glow: rgba(255, 122, 61, .35);--good: #4ec9a6;--bad: #ec6a6a;--radius-sm: 10px;--radius: 14px;--radius-lg: 20px;--pad: 16px;--shadow-sm: 0 1px 2px rgba(0,0,0,.4);--shadow: 0 8px 24px rgba(0,0,0,.45);--shadow-lg: 0 18px 40px rgba(0,0,0,.55);font-family:Inter,system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-feature-settings:"ss01","cv11";color-scheme:dark}*{box-sizing:border-box}html,body{margin:0;padding:0;background:radial-gradient(1200px 600px at 30% -10%,rgba(255,122,61,.08),transparent 60%),radial-gradient(900px 500px at 100% 110%,rgba(78,201,166,.06),transparent 60%),var(--bg-0);color:var(--fg)}body{-webkit-tap-highlight-color:transparent;touch-action:manipulation;-webkit-user-select:none;user-select:none;overflow:hidden}button{font:inherit;color:inherit;background:none;border:0;cursor:pointer;padding:0}input,select,textarea{font:inherit;color:inherit}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--bg-3);border-radius:8px}::-webkit-scrollbar-thumb:hover{background:#2c323e}.kiosk #app{width:1080px;height:660px;margin:0 auto;display:grid;grid-template-rows:92px 1fr;gap:12px;padding:12px}.now{display:grid;grid-template-columns:1fr auto;gap:16px;padding:10px 16px;background:linear-gradient(135deg,#ffffff0a,#ffffff03),var(--bg-1);border:1px solid var(--line);border-radius:var(--radius);align-items:center;box-shadow:var(--shadow-sm);position:relative;overflow:hidden}.now:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:radial-gradient(400px 120px at 0% 0%,var(--accent-glow),transparent 70%);opacity:.5;pointer-events:none}.now>*{position:relative}@keyframes pulse{0%,to{box-shadow:0 0 0 0 var(--accent-glow)}50%{box-shadow:0 0 0 6px transparent}}.now .meta{min-width:0;display:flex;flex-direction:column;gap:4px}.now .meta .name{font-size:19px;font-weight:700;letter-spacing:-.01em;line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.now .meta .sub{color:var(--muted);font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:6px}.now .meta .tags{display:flex;gap:5px;flex-wrap:wrap;margin-top:2px}.tag{font-size:11px;font-weight:500;padding:2px 8px;border-radius:999px;background:#ffb37a1a;color:var(--accent-2);border:1px solid rgba(255,179,122,.18)}.now .controls{display:flex;gap:10px;align-items:center}.btn-play,.btn-stop{width:46px;height:46px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:18px;transition:transform 80ms ease,background .12s ease,box-shadow .12s ease}.btn-play{background:var(--accent);color:#1a0a00;font-weight:900;box-shadow:0 6px 20px var(--accent-glow)}.btn-play:hover{background:#ff8a55}.btn-play:active{transform:scale(.94)}.btn-play.loading{opacity:.65}.btn-stop{background:var(--bg-2);color:var(--muted);border:1px solid var(--line)}.btn-stop:not(:disabled):hover{background:var(--bg-3);color:var(--fg)}.btn-stop:disabled{opacity:.35;cursor:default}.vol{width:170px;display:flex;align-items:center;gap:8px;padding:6px 10px;background:var(--bg-2);border:1px solid var(--line);border-radius:999px}.vol .vol-icon{font-size:13px}.vol input[type=range]{flex:1;height:18px;accent-color:var(--accent)}.vol .val{width:28px;text-align:right;color:var(--muted);font-variant-numeric:tabular-nums;font-size:11px}.lib{background:var(--bg-1);border:1px solid var(--line);border-radius:var(--radius);padding:10px 10px 6px;display:flex;flex-direction:column;min-height:0;gap:8px;box-shadow:var(--shadow-sm)}.header{display:flex;align-items:center;gap:8px}.tabs{display:flex;gap:4px;flex:1;min-width:0}.tab{padding:9px 14px;border-radius:10px;background:transparent;color:var(--muted);font-size:13px;font-weight:600;min-height:38px;border:1px solid transparent;transition:background .12s ease,color .12s ease,border-color .12s ease}.tab:hover{color:var(--fg);background:var(--bg-2)}.tab.active{background:linear-gradient(180deg,#ff7a3d2e,#ff7a3d14);color:var(--accent-2);border-color:#ff7a3d4d}.header-tools{display:flex;gap:6px;align-items:center}.search{width:220px;padding:8px 12px;height:36px;background:var(--bg-2);color:var(--fg);border:1px solid var(--line);border-radius:999px;font-size:13px;outline:none;transition:border-color .12s ease,box-shadow .12s ease}.search::placeholder{color:var(--muted-2)}.search:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-glow)}.btn-add{width:36px;height:36px;border-radius:50%;background:var(--accent);color:#1a0a00;font-size:22px;font-weight:800;line-height:1;box-shadow:0 4px 12px var(--accent-glow);transition:transform 80ms ease,background .12s ease}.btn-add:hover{background:#ff8a55}.btn-add:active{transform:scale(.94)}.btn-random{display:flex;align-items:center;gap:6px;height:36px;padding:0 12px;border-radius:999px;background:var(--bg-2);color:var(--fg);border:1px solid var(--line);font-size:13px;font-weight:600;transition:background .12s,border-color .12s,transform 80ms}.btn-random:hover{background:var(--bg-3);border-color:#ff7a3d66}.btn-random:active{transform:scale(.96)}.btn-random .rand-icon{font-size:15px;line-height:1}.btn-random .rand-mode{font-size:11px;padding:2px 6px;border-radius:999px;background:#ff7a3d2e;color:var(--accent-2);border:1px solid rgba(255,122,61,.3);letter-spacing:.02em}.btn-docs{display:flex;align-items:center;justify-content:center;height:36px;padding:0 12px;border-radius:999px;background:var(--bg-2);color:var(--muted);border:1px solid var(--line);font-size:12px;font-weight:700;letter-spacing:.06em;text-decoration:none;transition:background .12s,color .12s,border-color .12s}.btn-docs:hover{background:var(--bg-3);color:var(--fg);border-color:#4ec9a666}.chips{display:flex;flex-wrap:wrap;gap:5px;max-height:64px;overflow-y:auto;padding:2px}.chip{padding:4px 10px;border-radius:999px;background:var(--bg-2);color:var(--muted);border:1px solid var(--line);font-size:11px;font-weight:600;min-height:26px;transition:background .12s,color .12s,border-color .12s}.chip:hover{color:var(--fg)}.chip.active{background:#ff7a3d2e;color:var(--accent-2);border-color:#ff7a3d66}.grid{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:4px;padding:2px 4px 6px 2px}.card{display:grid;grid-template-columns:44px 1fr auto auto;align-items:center;gap:12px;padding:6px 10px 6px 6px;background:var(--bg-2);border:1px solid transparent;border-radius:10px;min-height:56px;text-align:left;cursor:pointer;transition:background .1s ease,border-color .1s ease,transform 80ms ease;position:relative}.card:hover{background:var(--bg-3)}.card:active{transform:scale(.995)}.card.playing{background:linear-gradient(90deg,rgba(255,122,61,.14),var(--bg-2) 60%);border-color:#ff7a3d59}.card.playing:before{content:"";position:absolute;left:0;top:8px;bottom:8px;width:3px;border-radius:0 3px 3px 0;background:var(--accent)}.card .art{width:44px;height:44px;border-radius:8px;background:var(--bg-3) center/cover no-repeat;display:flex;align-items:center;justify-content:center;font-size:16px;color:var(--muted-2);flex-shrink:0;border:1px solid var(--line);overflow:hidden}.card .art .art-img{width:100%;height:100%;object-fit:cover;display:block}.card .card-body{min-width:0}.card .n{font-weight:600;font-size:14px;line-height:1.2;letter-spacing:-.005em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.card .g{font-size:11.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:2px}.card .fav,.card .more{width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:16px;color:var(--muted);transition:background .1s,color .1s}.card .fav:hover,.card .more:hover{background:#ffffff0f;color:var(--fg)}.card .fav.on{color:var(--accent)}.card .more{font-weight:700;letter-spacing:1px}.empty{color:var(--muted);padding:32px 16px;text-align:center;font-size:13px}.login{position:fixed;top:0;right:0;bottom:0;left:0;background:radial-gradient(800px 500px at 50% 0%,rgba(255,122,61,.1),transparent 60%),#07080bf7;display:flex;align-items:center;justify-content:center;z-index:50}.login form{background:var(--bg-1);border:1px solid var(--line);padding:32px;border-radius:var(--radius-lg);display:flex;flex-direction:column;gap:14px;width:380px;box-shadow:var(--shadow-lg)}.login h1{margin:0 0 8px;font-size:24px;letter-spacing:-.01em}.login input{background:var(--bg-2);border:1px solid var(--line);color:var(--fg);padding:13px 14px;border-radius:var(--radius-sm);font-size:15px;outline:none;transition:border-color .12s,box-shadow .12s}.login input:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-glow)}.login button{background:var(--accent);color:#1a0a00;font-weight:700;padding:13px;border-radius:var(--radius-sm);font-size:15px;box-shadow:0 6px 18px var(--accent-glow);transition:background .12s}.login button:hover{background:#ff8a55}.login .err{color:var(--bad);font-size:13px;min-height:18px}dialog.add-station{border:1px solid var(--line);background:var(--bg-1);color:var(--fg);border-radius:var(--radius-lg);padding:0;max-width:520px;width:90%;box-shadow:var(--shadow-lg)}dialog.add-station::backdrop{background:#07080ba6;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}dialog.add-station form{padding:24px;display:flex;flex-direction:column;gap:12px}dialog.add-station h2{margin:0 0 4px;font-size:18px;letter-spacing:-.01em}dialog.add-station label{display:flex;flex-direction:column;gap:4px;font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}dialog.add-station input,dialog.add-station select{background:var(--bg-2);border:1px solid var(--line);color:var(--fg);padding:9px 11px;border-radius:var(--radius-sm);font-size:14px;outline:none;transition:border-color .12s,box-shadow .12s}dialog.add-station input:focus,dialog.add-station select:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-glow)}dialog.add-station .row2{display:grid;grid-template-columns:1fr 1fr;gap:12px}dialog.add-station .err{color:var(--bad);font-size:12px;min-height:14px}dialog.add-station .actions{display:flex;gap:8px;justify-content:flex-end;margin-top:4px}.btn-primary{background:var(--accent);color:#1a0a00;font-weight:700;padding:9px 16px;border-radius:var(--radius-sm);font-size:14px;transition:background .12s}.btn-primary:hover{background:#ff8a55}.btn-ghost{background:transparent;color:var(--muted);padding:9px 16px;border-radius:var(--radius-sm);font-size:14px;border:1px solid var(--line);transition:color .12s,background .12s}.btn-ghost:hover{color:var(--fg);background:var(--bg-2)}.ctx-menu{position:fixed;z-index:100;min-width:360px;max-width:460px;background:var(--bg-1);color:var(--fg);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-lg);padding:10px;display:flex;flex-direction:column;gap:2px;animation:ctxIn .1s ease-out}@keyframes ctxIn{0%{opacity:0;transform:translateY(-4px) scale(.98)}to{opacity:1;transform:none}}.ctx-title{font-weight:700;font-size:13px;padding:4px 8px 0;letter-spacing:-.005em}.ctx-sub{font-size:10.5px;color:var(--muted-2);padding:0 8px 8px;border-bottom:1px solid var(--line);font-family:ui-monospace,SF Mono,Menlo,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ctx-row{display:grid;grid-template-columns:1fr auto auto;gap:6px;align-items:center;padding:6px 8px;border-radius:8px}.ctx-row:hover{background:var(--bg-2)}.ctx-row-text{min-width:0}.ctx-label{font-size:12px;color:var(--fg);font-weight:500}.ctx-url{font-size:11px;color:var(--muted);font-family:ui-monospace,SF Mono,Menlo,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ctx-btn{width:28px;height:28px;border-radius:6px;background:var(--bg-2);color:var(--muted);font-size:13px;display:flex;align-items:center;justify-content:center;transition:background .1s,color .1s;border:1px solid var(--line)}.ctx-btn:hover{background:var(--bg-3);color:var(--fg)}.ctx-empty{padding:8px;color:var(--muted);font-size:12px}.ctx-danger{margin-top:4px;padding:7px 10px;border-radius:8px;background:transparent;color:var(--bad);border:1px solid rgba(236,106,106,.25);font-size:12px;font-weight:600;text-align:left}.ctx-danger:hover{background:#ec6a6a1a}.toast{position:fixed;bottom:20px;left:50%;transform:translate(-50%);background:var(--bg-1);padding:10px 18px;border-radius:999px;font-size:13px;color:var(--fg);z-index:200;border:1px solid var(--line);box-shadow:var(--shadow);animation:toastIn .18s ease-out}@keyframes toastIn{0%{opacity:0;transform:translate(-50%,8px)}to{opacity:1;transform:translate(-50%)}}:root{--bg-0: #000000;--bg-1: #0a0a0a;--bg-2: #141414;--bg-3: #1f1f1f;--line: #2e2e2e;--fg: #ffffff;--muted: #a0a0a0;--muted-2: #6a6a6a;--accent: #ff5b00;--accent-2: #ff5b00;--accent-glow: transparent;--good: #00d27a;--bad: #ff3030;--radius-sm: 0;--radius: 0;--radius-lg: 0;--shadow-sm: none;--shadow: none;--shadow-lg: none}html,body{background:var(--bg-0)!important}*,*:before,*:after{border-radius:0!important}button,input,select,textarea,dialog{border-radius:0!important}::-webkit-scrollbar-thumb{background:var(--bg-3)!important}::-webkit-scrollbar-thumb:hover{background:var(--line)!important}.now{background:var(--bg-1)!important;box-shadow:none!important;border-color:var(--line)!important}.now:before{display:none!important}@keyframes pulse{0%,to{border-color:var(--accent)}50%{border-color:var(--line)}}.now .meta .name{text-transform:uppercase;letter-spacing:.01em;font-weight:800}.tag{background:var(--bg-2)!important;color:var(--fg)!important;border-color:var(--line)!important;text-transform:uppercase;letter-spacing:.05em;font-weight:700}.btn-play,.btn-stop,.btn-add{box-shadow:none!important;border:1px solid var(--line);transition:background 80ms linear,color 80ms linear,transform 60ms linear!important}.btn-play,.btn-add{background:var(--accent)!important;color:#000!important;border-color:var(--accent)!important}.btn-play:hover,.btn-add:hover{background:#fff!important;color:#000!important;border-color:#fff!important}.btn-stop{background:var(--bg-2)!important;color:var(--fg)!important}.btn-stop:not(:disabled):hover{background:#fff!important;color:#000!important;border-color:#fff!important}.vol{background:var(--bg-2)!important;border-color:var(--line)!important}.lib{background:var(--bg-1)!important;box-shadow:none!important;border-color:var(--line)!important}.tabs{gap:0!important}.tab{border:1px solid var(--line)!important;margin-right:-1px!important;background:transparent!important;text-transform:uppercase;letter-spacing:.06em;font-weight:700;font-size:12px}.tab:hover{background:var(--bg-2)!important;color:var(--fg)!important}.tab.active{background:var(--accent)!important;color:#000!important;border-color:var(--accent)!important;position:relative;z-index:1}.search{background:var(--bg-2)!important;border-color:var(--line)!important}.search:focus{border-color:var(--accent)!important;box-shadow:none!important}.chip{background:var(--bg-2)!important;border-color:var(--line)!important;text-transform:uppercase;letter-spacing:.04em;font-weight:700}.chip:hover{color:var(--fg)!important;border-color:var(--fg)!important}.chip.active{background:var(--accent)!important;color:#000!important;border-color:var(--accent)!important}.grid{gap:0!important}.card{background:var(--bg-1)!important;border:1px solid var(--line)!important;margin-bottom:-1px;transition:background 60ms linear,border-color 60ms linear!important}.card:hover{background:var(--bg-2)!important;border-color:var(--muted-2)!important;z-index:1}.card:active{transform:none!important}.card.playing{background:var(--bg-2)!important;border-color:var(--accent)!important;z-index:2}.card.playing:before{left:0!important;top:0!important;bottom:0!important;width:4px!important;background:var(--accent)!important}.card .art{box-shadow:none!important}.card .n{font-weight:700}.card .g{text-transform:uppercase;letter-spacing:.03em}.card .fav:hover,.card .more:hover{background:var(--bg-3)!important;color:var(--fg)!important;border:1px solid var(--line)!important}.empty{text-transform:uppercase;letter-spacing:.06em}.login{background:#000!important}.login form{border:1px solid #fff!important;box-shadow:none!important}.login h1{text-transform:uppercase;letter-spacing:.04em;font-weight:900}.login input{background:var(--bg-2)!important;border-color:var(--line)!important}.login input:focus{border-color:var(--accent)!important;box-shadow:none!important}.login button{background:var(--accent)!important;color:#000!important;border:1px solid var(--accent)!important;box-shadow:none!important;text-transform:uppercase;letter-spacing:.08em;font-weight:900}.login button:hover{background:#fff!important;color:#000!important;border-color:#fff!important}dialog.add-station{border:1px solid #fff!important;box-shadow:none!important}dialog.add-station::backdrop{background:#000000d9!important;-webkit-backdrop-filter:none!important;backdrop-filter:none!important}dialog.add-station h2{text-transform:uppercase;letter-spacing:.04em;font-weight:900}dialog.add-station label{letter-spacing:.08em;font-weight:700}dialog.add-station input,dialog.add-station select{background:var(--bg-2)!important;border-color:var(--line)!important}dialog.add-station input:focus,dialog.add-station select:focus{border-color:var(--accent)!important;box-shadow:none!important}.btn-primary{background:var(--accent)!important;color:#000!important;border:1px solid var(--accent)!important;text-transform:uppercase;letter-spacing:.06em;font-weight:900}.btn-primary:hover{background:#fff!important;color:#000!important;border-color:#fff!important}.btn-ghost{background:transparent!important;border:1px solid var(--line)!important;text-transform:uppercase;letter-spacing:.06em;font-weight:700}.btn-ghost:hover{color:var(--fg)!important;background:var(--bg-2)!important;border-color:var(--fg)!important}.ctx-menu{border:1px solid #fff!important;box-shadow:none!important}.ctx-title{text-transform:uppercase;letter-spacing:.06em;font-weight:900;font-size:12px}.ctx-row{border:1px solid transparent}.ctx-row:hover{background:var(--bg-2)!important;border-color:var(--line)}.ctx-btn{background:var(--bg-2)!important;border:1px solid var(--line)!important;color:var(--muted)}.ctx-btn:hover{background:#fff!important;color:#000!important;border-color:#fff!important}.ctx-danger{background:transparent!important;border:1px solid var(--bad)!important;color:var(--bad)!important;text-transform:uppercase;letter-spacing:.06em;font-weight:800}.ctx-danger:hover{background:var(--bad)!important;color:#000!important}.toast{background:#fff!important;color:#000!important;border:1px solid #fff!important;box-shadow:none!important;text-transform:uppercase;letter-spacing:.06em;font-weight:800;font-size:12px}.vote-group{display:flex;gap:0;margin-right:6px}.vote{display:flex;align-items:center;gap:6px;height:46px;min-width:64px;padding:0 12px;background:var(--bg-2)!important;color:var(--fg);border:1px solid var(--line)!important;font-weight:800;font-size:14px;font-variant-numeric:tabular-nums;transition:background 80ms linear,color 80ms linear,border-color 80ms linear!important}.vote+.vote{margin-left:-1px}.vote:disabled{opacity:.35;cursor:not-allowed}.vote .vote-icon{font-size:17px;line-height:1}.vote .vote-count{font-size:13px;letter-spacing:.02em}.vote.up:not(:disabled):hover{background:var(--good)!important;color:#000!important;border-color:var(--good)!important}.vote.down:not(:disabled):hover{background:var(--bad)!important;color:#000!important;border-color:var(--bad)!important}.vote.up.on{background:var(--good)!important;color:#000!important;border-color:var(--good)!important}.vote.down.on{background:var(--bad)!important;color:#000!important;border-color:var(--bad)!important}.sort{height:36px;padding:0 28px 0 12px;background:var(--bg-2)!important;color:var(--fg);border:1px solid var(--line)!important;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),linear-gradient(135deg,var(--muted) 50%,transparent 50%);background-position:calc(100% - 14px) 50%,calc(100% - 9px) 50%;background-size:5px 5px,5px 5px;background-repeat:no-repeat;outline:none;cursor:pointer}.sort:focus,.sort:hover{border-color:var(--accent)!important}.sort option{background:var(--bg-1);color:var(--fg)}.card{grid-template-columns:44px 1fr auto auto auto!important}.score-badge{display:inline-flex;align-items:center;justify-content:center;min-width:36px;height:26px;padding:0 8px;background:var(--bg-2);border:1px solid var(--line);color:var(--muted);font-weight:800;font-size:12px;font-variant-numeric:tabular-nums;letter-spacing:.02em}.score-badge.pos{color:var(--good);border-color:#00d27a59}.score-badge.neg{color:var(--bad);border-color:#ff303059}.score-badge.neu{color:var(--muted-2)}.card.playing .score-badge{border-color:var(--accent)} diff --git a/server/public/assets/kiosk-CzWLja7k.js b/server/public/assets/kiosk-CzWLja7k.js new file mode 100644 index 0000000..2bd867d --- /dev/null +++ b/server/public/assets/kiosk-CzWLja7k.js @@ -0,0 +1 @@ +import"./modulepreload-polyfill-B5Qt9EMX.js";import{P as N,a as c,c as x,e as a}from"./player-BBOsFRH-.js";import{c as R}from"./ws-BM1PmMVd.js";const w=document.getElementById("app"),t={user:null,tab:"favorites",stations:[],categories:[],selectedCategory:null,favorites:[],history:[],query:"",sort:"hot",randomMode:localStorage.getItem("oradio.randomMode")==="favorites"?"favorites":"all",rooms:[],roomSlug:localStorage.getItem("oradio.room")||null,mode:localStorage.getItem("oradio.mode")==="follow-room"?"follow-room":"play-here",roomState:null,roomPeers:[],roomDevices:{list:[],current:null},player:{stationId:null,stationName:null,genres:[],playing:!1,loading:!1,volume:.7,votes:null},session:null},h=new N({onState:e=>{t.player={...t.player,...e},l()}});let p;async function q(){try{t.user=await c.get("/api/auth/me")}catch{B();return}await M();try{t.rooms=await c.get("/api/rooms"),(!t.roomSlug||!t.rooms.find(e=>e.slug===t.roomSlug))&&(t.roomSlug=t.rooms[0]&&t.rooms[0].slug||`u-${t.user.id}`,localStorage.setItem("oradio.room",t.roomSlug))}catch{t.roomSlug=t.roomSlug||`u-${t.user.id}`}k(),l(),Z()}function k(){if(p)try{p.close()}catch{}const e=t.mode==="follow-room"?"panel":"controller";p=R(U,{room:t.roomSlug,kind:e})}function E(e){e!=="play-here"&&e!=="follow-room"||t.mode!==e&&(t.mode=e,localStorage.setItem("oradio.mode",e),e==="follow-room"&&t.player.stationId&&(h.stop(),I()),k(),l())}function T(e){!e||t.roomSlug===e||(t.roomSlug=e,localStorage.setItem("oradio.room",e),t.roomPeers=[],t.roomState=null,k(),l())}async function M(){const[e,o,n,s]=await Promise.all([c.get(`/api/stations?sort=${encodeURIComponent(t.sort)}`),c.get("/api/me/favorites").catch(()=>[]),c.get("/api/me/history").catch(()=>[]),c.get("/api/v1/categories").catch(()=>[])]);t.stations=e,t.favorites=o,t.history=n,t.categories=s}async function F(){t.stations=await c.get(`/api/stations?sort=${encodeURIComponent(t.sort)}`)}function U(e){if(!(!e||!e.type))switch(e.type){case"hello":t.roomState=e.state||null,t.roomPeers=e.peers||[],t.mode==="follow-room"&&P(),l();return;case"presence":t.roomPeers=e.peers||[],l();return;case"devices":t.roomDevices={list:e.list||[],current:e.current||null},l();return;case"state":t.roomState={...t.roomState,...e},t.mode==="follow-room"&&P(),l();return;case"vote":{const o=e.stationId,n=e.stats||{};for(const s of[t.stations,t.favorites]){const i=s.find(d=>d.id===o);i&&("up"in n&&(i.up=n.up),"down"in n&&(i.down=n.down),"score"in n&&(i.score=n.score))}t.player.votes&&t.player.stationId===o&&(t.player.votes={...t.player.votes,...n}),l();return}case"plays":{const o=e.stationId;for(const n of[t.stations,t.favorites]){const s=n.find(i=>i.id===o);s&&(s.plays=e.plays)}t.player.votes&&t.player.stationId===o&&(t.player.votes={...t.player.votes,plays:e.plays}),l();return}case"command":{if(t.mode!=="play-here")return;if(e.action==="play"&&e.stationId){const o=t.stations.find(n=>n.id===e.stationId);o&&C(o)}else e.action==="pause"?h.togglePause():e.action==="volume"?h.setVolume(e.value):e.action==="stop"&&h.stop();return}default:return}}function P(){var o,n,s;const e=t.roomState;e&&(t.player={...t.player,stationId:e.station_id??((o=e.station)==null?void 0:o.id)??null,stationName:((n=e.station)==null?void 0:n.name)||null,genres:((s=e.station)==null?void 0:s.genres)||[],playing:!!e.playing,loading:!1,volume:typeof e.volume=="number"?e.volume:t.player.volume,error:null})}function B(){x(w);const e=a("div",{class:"login"},a("form",{onSubmit:async o=>{o.preventDefault();const n=new FormData(o.target);try{t.user=await c.post("/api/auth/login",{username:n.get("username"),password:n.get("password")}),await q()}catch(s){o.target.querySelector(".err").textContent=s.message}}},a("h1",{},"Sign in"),a("input",{name:"username",placeholder:"Username",autocomplete:"username",required:!0}),a("input",{name:"password",type:"password",placeholder:"Password",autocomplete:"current-password",required:!0}),a("div",{class:"err"}),a("button",{type:"submit"},"Continue")));w.appendChild(e)}let f=0;function l(){if(!t.user)return;const e=w.querySelector(".grid");e&&e.scrollTop>0&&(f=e.scrollTop),S(),x(w);const o=t.player,n=new Set(t.favorites.map(r=>r.id)),s=o.votes,i=a("section",{class:"now"},a("div",{class:"meta"},a("div",{class:"name"},o.stationName||"Select a station"),a("div",{class:"sub"},o.loading?"Connecting…":o.playing?"On air":o.error?o.error:o.stationId?"Paused":"Idle"),a("div",{class:"tags"},...(o.genres||[]).slice(0,4).map(r=>a("span",{class:"tag"},r)))),a("div",{class:"controls"},a("div",{class:"vote-group",title:"Vote on current station"},a("button",{class:`vote up ${(s==null?void 0:s.myVote)===1?"on":""}`,disabled:!o.stationId,title:"Upvote",onClick:()=>L(1)},a("span",{class:"vote-icon"},"▲"),a("span",{class:"vote-count"},String((s==null?void 0:s.up)??0))),a("button",{class:`vote down ${(s==null?void 0:s.myVote)===-1?"on":""}`,disabled:!o.stationId,title:"Downvote",onClick:()=>L(-1)},a("span",{class:"vote-icon"},"▼"),a("span",{class:"vote-count"},String((s==null?void 0:s.down)??0)))),a("button",{class:`btn-play ${o.loading?"loading":""}`,title:o.playing?"Pause":"Play",onClick:()=>{var r;t.mode==="follow-room"?p==null||p.send({type:"command",action:o.playing?"pause":(o.stationId,"play"),stationId:o.stationId||((r=t.favorites[0])==null?void 0:r.id)}):o.stationId?h.togglePause():t.favorites[0]&&C(t.favorites[0])}},o.playing?"❚❚":"▶"),a("button",{class:"btn-stop",title:"Stop",disabled:!o.stationId,onClick:()=>{t.mode==="follow-room"?p==null||p.send({type:"command",action:"stop"}):(h.stop(),I())}},"■"),a("div",{class:"vol"},a("span",{class:"vol-icon"},o.volume===0?"🔇":o.volume<.5?"🔈":"🔊"),a("input",{type:"range",min:0,max:1,step:.05,value:o.volume,"aria-label":"Volume",onInput:r=>{const g=Number(r.target.value);t.mode==="follow-room"?(t.player.volume=g,p==null||p.send({type:"command",action:"volume",value:g})):h.setVolume(g)}}),a("span",{class:"val"},Math.round(o.volume*100))))),d=t.user.role==="admin",y=a("div",{class:"header"},a("div",{class:"tabs"},...["favorites","browse","recent"].map(r=>a("button",{class:`tab ${t.tab===r?"active":""}`,onClick:()=>{t.tab=r,f=0,l()}},r==="favorites"?"★ Favorites":r==="browse"?"🌐 Browse":"⏱ Recent"))),a("div",{class:"header-tools"},V(),t.tab==="browse"?a("select",{class:"sort",title:"Sort browse list",onChange:r=>{t.sort=r.target.value,f=0,F().then(l)}},a("option",{value:"hot",selected:t.sort==="hot"},"🔥 Hot (smart)"),a("option",{value:"top",selected:t.sort==="top"},"▲ Top voted"),a("option",{value:"plays",selected:t.sort==="plays"},"▶ Most played"),a("option",{value:"controversial",selected:t.sort==="controversial"},"⚡ Controversial"),a("option",{value:"name",selected:t.sort==="name"},"A → Z")):null,a("input",{class:"search",type:"search",placeholder:"Search…",value:t.query,onInput:r=>{t.query=r.target.value,G()}}),a("button",{class:"btn-random",title:`Play random station (mode: ${t.randomMode}). Right-click to switch mode.`,onClick:z,onContextMenu:r=>{r.preventDefault(),j()}},a("span",{class:"rand-icon"},"🎲"),a("span",{class:"rand-mode"},t.randomMode==="favorites"?"★":"All")),a("a",{class:"btn-docs",href:"/docs/",target:"_blank",rel:"noopener",title:"Open API reference"},"API"),d?a("button",{class:"btn-add",title:"Add station",onClick:Y},"+"):null)),b=a("section",{class:"lib"},y);t.tab==="browse"&&t.categories.length&&b.appendChild(H());const u=a("div",{class:"grid"});u.id="grid",u.addEventListener("scroll",()=>{f=u.scrollTop},{passive:!0}),b.appendChild(u),w.appendChild(i),w.appendChild(b),D(u,n),f&&(u.scrollTop=f,requestAnimationFrame(()=>{f&&(u.scrollTop=f)}))}function V(){const e=t.roomPeers||[],o=e.some(n=>n.kind==="display");return a("div",{class:"room-pill",title:"Listening room"},a("span",{class:"room-icon"},"🏠"),a("select",{class:"room-select",onChange:n=>T(n.target.value),"aria-label":"Room"},...(t.rooms.length?t.rooms:[{slug:t.roomSlug||"",name:"My room"}]).map(n=>a("option",{value:n.slug,selected:n.slug===t.roomSlug},n.name))),a("span",{class:"room-peers",title:`${e.length} client(s)${o?" • display online":""}`},`${e.length}${o?"◉":""}`),a("button",{class:`room-mode ${t.mode}`,title:t.mode==="follow-room"?"Mirroring the room display. Click to play audio in this browser.":"Playing audio in this browser. Click to follow the room display.",onClick:()=>E(t.mode==="follow-room"?"play-here":"follow-room")},t.mode==="follow-room"?"Follow":"Here"))}function H(){return a("div",{class:"chips"},a("button",{class:`chip ${t.selectedCategory?"":"active"}`,onClick:()=>{t.selectedCategory=null,f=0,l()}},`All (${t.stations.length})`),...t.categories.filter(e=>e.count>0).map(e=>a("button",{class:`chip ${t.selectedCategory===e.id?"active":""}`,onClick:()=>{t.selectedCategory=e.id,f=0,l()}},`${e.icon||""} ${e.label} (${e.count})`.trim())))}function W(){let e=[];if(t.tab==="favorites")e=t.favorites;else if(t.tab==="browse")e=t.stations,t.selectedCategory&&(e=e.filter(n=>n.category===t.selectedCategory));else if(t.tab==="recent"){const n=new Set;e=t.history.filter(s=>!n.has(s.station_id)&&n.add(s.station_id)).map(s=>t.stations.find(i=>i.id===s.station_id)).filter(Boolean)}const o=t.query.trim().toLowerCase();return o&&(e=e.filter(n=>n.name.toLowerCase().includes(o)||(n.country||"").toLowerCase().includes(o)||(n.genres||[]).some(s=>s.toLowerCase().includes(o)))),e}function G(){const e=document.getElementById("grid");if(!e)return;const o=new Set(t.favorites.map(n=>n.id));D(e,o)}function D(e,o){x(e);const n=W();if(!n.length){e.appendChild(a("div",{class:"empty"},t.tab==="favorites"?"No favorites yet — long-press or tap ★ on a station.":t.query?"No matches.":"Nothing here yet."));return}const s=t.player;for(const i of n){const d=typeof i.score=="number"?i.score:0,y=(i.up??0)-(i.down??0),b=y>0?"pos":y<0?"neg":"neu",u=a("div",{class:`card ${s.stationId===i.id?"playing":""}`,role:"button",tabindex:0,onClick:()=>C(i),onContextMenu:r=>{r.preventDefault(),_(r.clientX,r.clientY,i)}},a("div",{class:"art"},i.image_display_url||i.image_url?a("img",{class:"art-img",src:i.image_display_url||i.image_url,alt:"",loading:"lazy",referrerpolicy:"no-referrer",onError:r=>{const g=r.target.parentNode;r.target.remove(),g&&g.appendChild(a("span",{class:"art-glyph"},"♪"))}}):a("span",{class:"art-glyph"},"♪")),a("div",{class:"card-body"},a("div",{class:"n"},i.name),a("div",{class:"g"},(i.genres||[]).slice(0,3).join(" · ")||i.country||"—")),a("div",{class:`score-badge ${b}`,title:`▲${i.up??0} · ▼${i.down??0} · ▶${i.plays??0} · score ${d.toFixed(2)}`},y>0?`+${y}`:String(y)),a("button",{class:`fav ${o.has(i.id)?"on":""}`,title:o.has(i.id)?"Remove favorite":"Add favorite",onClick:r=>{r.stopPropagation(),O(i)}},o.has(i.id)?"★":"☆"),a("button",{class:"more",title:"API endpoints",onClick:r=>{r.stopPropagation();const g=r.currentTarget.getBoundingClientRect();_(g.right,g.bottom,i)}},"⋯"));e.appendChild(u)}}async function O(e){t.favorites.some(n=>n.id===e.id)?await c.del(`/api/me/favorites/${e.id}`):await c.put(`/api/me/favorites/${e.id}`,{position:t.favorites.length}),t.favorites=await c.get("/api/me/favorites"),l()}function j(){t.randomMode=t.randomMode==="favorites"?"all":"favorites",localStorage.setItem("oradio.randomMode",t.randomMode),v(`Random mode: ${t.randomMode==="favorites"?"favorites only":"all stations"}`),l()}async function z(){try{const e=t.randomMode==="favorites"?"/api/me/favorites/random":"/api/v1/stations/random",o=await c.get(e);let n=o;if(n.id==null&&(n=t.stations.find(s=>s.uuid===o.uuid)||null),!n){v("Random station not in cache");return}C(n)}catch(e){const o=t.randomMode==="favorites"?t.favorites:t.stations;if(!o.length){v(e.message||"No stations available");return}C(o[Math.floor(Math.random()*o.length)])}}function J(e){t.history.unshift({station_id:e,started_at:new Date().toISOString()})}async function C(e){if(t.player.votes=null,I(),t.mode==="follow-room"){p==null||p.send({type:"command",action:"play",stationId:e.id}),t.player={...t.player,stationId:e.id,stationName:e.name,genres:e.genres||[],playing:!0,loading:!1,error:null},l();try{const o=await c.get(`/api/stations/${e.id}/votes`);t.player.stationId===e.id&&(t.player.votes=o,$(e.id,o),l())}catch{}return}h.play(e),J(e.id);try{const o=await c.post(`/api/stations/${e.id}/play`);t.player.stationId===e.id?(t.player.votes=o,o.sessionId&&(t.session={id:o.sessionId,stationId:e.id,startedAt:Date.now()}),$(e.id,o),l()):o.sessionId&&c.post(`/api/stations/${e.id}/play/end`,{sessionId:o.sessionId,duration_ms:0}).catch(()=>{})}catch{try{const n=await c.get(`/api/stations/${e.id}/votes`);t.player.stationId===e.id&&(t.player.votes=n,$(e.id,n),l())}catch{}}}function I({beacon:e=!1}={}){const o=t.session;if(!o||!o.id)return;t.session=null;const n={sessionId:o.id,duration_ms:Math.max(0,Date.now()-o.startedAt)},s=`/api/stations/${o.stationId}/play/end`;if(e&&typeof navigator<"u"&&navigator.sendBeacon)try{navigator.sendBeacon(s,new Blob([JSON.stringify(n)],{type:"application/json"}));return}catch{}c.post(s,n).catch(()=>{})}typeof window<"u"&&(window.addEventListener("pagehide",()=>I({beacon:!0})),window.addEventListener("beforeunload",()=>I({beacon:!0})));async function L(e){var i;const o=t.player.stationId;if(!o)return;const s=(((i=t.player.votes)==null?void 0:i.myVote)||0)===e?0:e;try{const d=await c.post(`/api/stations/${o}/vote`,{value:s});t.player.votes=d,$(o,d),l()}catch(d){v(d.message||"Vote failed")}}function $(e,o){const n=[t.stations,t.favorites];for(const s of n){const i=s.find(d=>d.id===e);i&&(i.up=o.up,i.down=o.down,i.plays=o.plays,i.score=o.score,i.my_vote=o.myVote)}}let m=null;function S(){m&&(m.remove(),m=null)}function X(e){const o=location.origin,n=`${o}/api/v1`,s=[];return e.id!=null&&s.push({label:"Station (original)",url:`${o}/api/stations/${e.id}`}),e.uuid&&s.push({label:"Station detail",url:`${n}/stations/${e.uuid}`},{label:"Stream redirect",url:`${n}/stations/${e.uuid}/stream`},{label:"MP3 stream",url:`${n}/stations/${e.uuid}/stream?format=mp3`},{label:"AAC stream",url:`${n}/stations/${e.uuid}/stream?format=aac`},{label:"HLS stream",url:`${n}/stations/${e.uuid}/stream?format=hls`}),s.push({label:"All stations",url:`${n}/stations`},{label:"Health",url:`${n}/health`}),s}function _(e,o,n){S();const s=X(n);m=a("div",{class:"ctx-menu",role:"menu"},a("div",{class:"ctx-title"},n.name),a("div",{class:"ctx-sub"},n.uuid?`uuid · ${n.uuid}`:n.id!=null?`id · ${n.id} (no uuid — public v1 hidden)`:"no identifier"),...s.length?s.map(u=>a("div",{class:"ctx-row"},a("div",{class:"ctx-row-text"},a("div",{class:"ctx-label"},u.label),a("div",{class:"ctx-url"},u.url)),a("button",{class:"ctx-btn",title:"Copy",onClick:async r=>{r.stopPropagation();try{await navigator.clipboard.writeText(u.url),v("Copied")}catch{v("Copy failed")}}},"⧉"),a("button",{class:"ctx-btn",title:"Open",onClick:r=>{r.stopPropagation(),window.open(u.url,"_blank","noopener")}},"↗"))):[a("div",{class:"ctx-empty"},"No public API for this station yet (missing uuid).")],t.user.role==="admin"?a("button",{class:"ctx-danger",onClick:async()=>{if(S(),!!confirm(`Delete ${n.name}?`))try{await c.del(`/api/stations/${n.id}`),await M(),l(),v("Deleted")}catch(u){v(u.message||"Delete failed")}}},"🗑 Delete"):null),document.body.appendChild(m);const i=m.offsetWidth,d=m.offsetHeight,y=Math.min(e,window.innerWidth-i-8),b=Math.min(o,window.innerHeight-d-8);m.style.left=`${Math.max(8,y)}px`,m.style.top=`${Math.max(8,b)}px`}document.addEventListener("click",e=>{m&&!m.contains(e.target)&&S()});document.addEventListener("keydown",e=>{e.key==="Escape"&&S()});async function Y(){const e=document.createElement("dialog");e.className="add-station";const o={name:"",country:"",genres:"",image_url:"",homepage:"",streamUrl:"",streamFormat:"mp3"},n=a("div",{class:"err"});e.appendChild(a("form",{method:"dialog",onSubmit:async s=>{s.preventDefault(),n.textContent="";const i={name:o.name.trim(),country:o.country.trim()||null,homepage:o.homepage.trim()||null,image_url:o.image_url.trim()||null,genres:o.genres.split(",").map(d=>d.trim()).filter(Boolean),streams:o.streamUrl.trim()?[{url:o.streamUrl.trim(),format:o.streamFormat,priority:0}]:[]};if(!i.name){n.textContent="Name is required.";return}try{await c.post("/api/stations",i),e.close(),await M(),l(),v("Station added")}catch(d){n.textContent=d.message||"Failed to add station"}}},a("h2",{},"Add station"),a("label",{},"Name",a("input",{required:!0,autofocus:!0,onInput:s=>o.name=s.target.value})),a("div",{class:"row2"},a("label",{},"Country",a("input",{maxlength:4,placeholder:"NL",onInput:s=>o.country=s.target.value})),a("label",{},"Genres",a("input",{placeholder:"jazz, electronic",onInput:s=>o.genres=s.target.value}))),a("label",{},"Homepage",a("input",{type:"url",placeholder:"https://…",onInput:s=>o.homepage=s.target.value})),a("label",{},"Image URL",a("input",{type:"url",placeholder:"https://…/logo.png",onInput:s=>o.image_url=s.target.value})),a("div",{class:"row2"},a("label",{},"Stream URL",a("input",{type:"url",placeholder:"https://…/stream",onInput:s=>o.streamUrl=s.target.value})),a("label",{},"Format",a("select",{onChange:s=>o.streamFormat=s.target.value},...["mp3","aac","ogg","hls","m3u","pls","unknown"].map(s=>a("option",{value:s,selected:s==="mp3"},s))))),n,a("div",{class:"actions"},a("button",{class:"btn-ghost",type:"button",onClick:()=>e.close()},"Cancel"),a("button",{class:"btn-primary",type:"submit"},"Add")))),document.body.appendChild(e),e.showModal(),e.addEventListener("close",()=>e.remove())}let A=null;function v(e){const o=document.querySelector(".toast");o&&o.remove();const n=a("div",{class:"toast"},e);document.body.appendChild(n),clearTimeout(A),A=setTimeout(()=>n.remove(),2200)}async function Z(){var e;try{await((e=navigator.wakeLock)==null?void 0:e.request("screen"))}catch{}document.addEventListener("visibilitychange",()=>{var o;document.visibilityState==="visible"&&((o=navigator.wakeLock)==null||o.request("screen").catch(()=>{}))})}document.addEventListener("contextmenu",e=>{window.matchMedia("(display-mode: fullscreen)").matches&&e.preventDefault()});q(); diff --git a/server/public/assets/kiosk-PzkUrLf6.css b/server/public/assets/kiosk-PzkUrLf6.css new file mode 100644 index 0000000..10d67a6 --- /dev/null +++ b/server/public/assets/kiosk-PzkUrLf6.css @@ -0,0 +1 @@ +:root{--bg-0: #07080b;--bg-1: #0e1116;--bg-2: #161a22;--bg-3: #1f242e;--line: #262b36;--fg: #e9ecf2;--muted: #8a90a0;--muted-2: #5d6373;--accent: #ff7a3d;--accent-2: #ffb37a;--accent-glow: rgba(255, 122, 61, .35);--good: #4ec9a6;--bad: #ec6a6a;--radius-sm: 10px;--radius: 14px;--radius-lg: 20px;--pad: 16px;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);--shadow: 0 8px 24px rgba(0, 0, 0, .45);--shadow-lg: 0 18px 40px rgba(0, 0, 0, .55);font-family:Inter,system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-feature-settings:"ss01","cv11";color-scheme:dark}*{box-sizing:border-box}html,body{margin:0;padding:0;background:radial-gradient(1200px 600px at 30% -10%,rgba(255,122,61,.08),transparent 60%),radial-gradient(900px 500px at 100% 110%,rgba(78,201,166,.06),transparent 60%),var(--bg-0);color:var(--fg)}body{-webkit-tap-highlight-color:transparent;touch-action:manipulation;-webkit-user-select:none;user-select:none;overflow:hidden}button{font:inherit;color:inherit;background:none;border:0;cursor:pointer;padding:0}input,select,textarea{font:inherit;color:inherit}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--bg-3);border-radius:8px}::-webkit-scrollbar-thumb:hover{background:#2c323e}.kiosk #app{width:1080px;height:660px;margin:0 auto;display:grid;grid-template-rows:92px 1fr;gap:12px;padding:12px}.now{display:grid;grid-template-columns:1fr auto;gap:16px;padding:10px 16px;background:linear-gradient(135deg,#ffffff0a,#ffffff03),var(--bg-1);border:1px solid var(--line);border-radius:var(--radius);align-items:center;box-shadow:var(--shadow-sm);position:relative;overflow:hidden}.now:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:radial-gradient(400px 120px at 0% 0%,var(--accent-glow),transparent 70%);opacity:.5;pointer-events:none}.now>*{position:relative}@keyframes pulse{0%,to{box-shadow:0 0 0 0 var(--accent-glow)}50%{box-shadow:0 0 0 6px transparent}}.now .meta{min-width:0;display:flex;flex-direction:column;gap:4px}.now .meta .name{font-size:19px;font-weight:700;letter-spacing:-.01em;line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.now .meta .sub{color:var(--muted);font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:6px}.now .meta .tags{display:flex;gap:5px;flex-wrap:wrap;margin-top:2px}.tag{font-size:11px;font-weight:500;padding:2px 8px;border-radius:999px;background:#ffb37a1a;color:var(--accent-2);border:1px solid rgba(255,179,122,.18)}.now .controls{display:flex;gap:10px;align-items:center}.btn-play,.btn-stop{width:46px;height:46px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:18px;transition:transform 80ms ease,background .12s ease,box-shadow .12s ease}.btn-play{background:var(--accent);color:#1a0a00;font-weight:900;box-shadow:0 6px 20px var(--accent-glow)}.btn-play:hover{background:#ff8a55}.btn-play:active{transform:scale(.94)}.btn-play.loading{opacity:.65}.btn-stop{background:var(--bg-2);color:var(--muted);border:1px solid var(--line)}.btn-stop:not(:disabled):hover{background:var(--bg-3);color:var(--fg)}.btn-stop:disabled{opacity:.35;cursor:default}.vol{width:170px;display:flex;align-items:center;gap:8px;padding:6px 10px;background:var(--bg-2);border:1px solid var(--line);border-radius:999px}.vol .vol-icon{font-size:13px}.vol input[type=range]{flex:1;height:18px;accent-color:var(--accent)}.vol .val{width:28px;text-align:right;color:var(--muted);font-variant-numeric:tabular-nums;font-size:11px}.lib{background:var(--bg-1);border:1px solid var(--line);border-radius:var(--radius);padding:10px 10px 6px;display:flex;flex-direction:column;min-height:0;gap:8px;box-shadow:var(--shadow-sm)}.header{display:flex;align-items:center;gap:8px}.tabs{display:flex;gap:4px;flex:1;min-width:0}.tab{padding:9px 14px;border-radius:10px;background:transparent;color:var(--muted);font-size:13px;font-weight:600;min-height:38px;border:1px solid transparent;transition:background .12s ease,color .12s ease,border-color .12s ease}.tab:hover{color:var(--fg);background:var(--bg-2)}.tab.active{background:linear-gradient(180deg,#ff7a3d2e,#ff7a3d14);color:var(--accent-2);border-color:#ff7a3d4d}.header-tools{display:flex;gap:6px;align-items:center}.room-pill{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;height:36px;background:var(--bg-2);border:1px solid var(--line);border-radius:999px;font-size:12px}.room-pill .room-icon{opacity:.7}.room-pill .room-select{background:transparent;color:var(--fg);border:none;outline:none;font-size:12px;max-width:140px}.room-pill .room-peers{color:var(--muted-2);font-variant-numeric:tabular-nums;min-width:18px;text-align:center}.room-pill .room-mode{height:26px;padding:0 10px;border-radius:999px;border:1px solid var(--line);background:var(--bg-1);color:var(--fg);font-size:11px;cursor:pointer}.room-pill .room-mode.follow-room{background:linear-gradient(180deg,#ff7a3d2e,#ff7a3d14);color:var(--accent-2);border-color:#ff7a3d4d}.search{width:220px;padding:8px 12px;height:36px;background:var(--bg-2);color:var(--fg);border:1px solid var(--line);border-radius:999px;font-size:13px;outline:none;transition:border-color .12s ease,box-shadow .12s ease}.search::placeholder{color:var(--muted-2)}.search:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-glow)}.btn-add{width:36px;height:36px;border-radius:50%;background:var(--accent);color:#1a0a00;font-size:22px;font-weight:800;line-height:1;box-shadow:0 4px 12px var(--accent-glow);transition:transform 80ms ease,background .12s ease}.btn-add:hover{background:#ff8a55}.btn-add:active{transform:scale(.94)}.btn-random{display:flex;align-items:center;gap:6px;height:36px;padding:0 12px;border-radius:999px;background:var(--bg-2);color:var(--fg);border:1px solid var(--line);font-size:13px;font-weight:600;transition:background .12s,border-color .12s,transform 80ms}.btn-random:hover{background:var(--bg-3);border-color:#ff7a3d66}.btn-random:active{transform:scale(.96)}.btn-random .rand-icon{font-size:15px;line-height:1}.btn-random .rand-mode{font-size:11px;padding:2px 6px;border-radius:999px;background:#ff7a3d2e;color:var(--accent-2);border:1px solid rgba(255,122,61,.3);letter-spacing:.02em}.btn-docs{display:flex;align-items:center;justify-content:center;height:36px;padding:0 12px;border-radius:999px;background:var(--bg-2);color:var(--muted);border:1px solid var(--line);font-size:12px;font-weight:700;letter-spacing:.06em;text-decoration:none;transition:background .12s,color .12s,border-color .12s}.btn-docs:hover{background:var(--bg-3);color:var(--fg);border-color:#4ec9a666}.chips{display:flex;flex-wrap:wrap;gap:5px;max-height:64px;overflow-y:auto;padding:2px}.chip{padding:4px 10px;border-radius:999px;background:var(--bg-2);color:var(--muted);border:1px solid var(--line);font-size:11px;font-weight:600;min-height:26px;transition:background .12s,color .12s,border-color .12s}.chip:hover{color:var(--fg)}.chip.active{background:#ff7a3d2e;color:var(--accent-2);border-color:#ff7a3d66}.grid{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:4px;padding:2px 4px 6px 2px}.card{display:grid;grid-template-columns:44px 1fr auto auto;align-items:center;gap:12px;padding:6px 10px 6px 6px;background:var(--bg-2);border:1px solid transparent;border-radius:10px;min-height:56px;text-align:left;cursor:pointer;transition:background .1s ease,border-color .1s ease,transform 80ms ease;position:relative}.card:hover{background:var(--bg-3)}.card:active{transform:scale(.995)}.card.playing{background:linear-gradient(90deg,rgba(255,122,61,.14),var(--bg-2) 60%);border-color:#ff7a3d59}.card.playing:before{content:"";position:absolute;left:0;top:8px;bottom:8px;width:3px;border-radius:0 3px 3px 0;background:var(--accent)}.card .art{width:44px;height:44px;border-radius:8px;background:var(--bg-3) center/cover no-repeat;display:flex;align-items:center;justify-content:center;font-size:16px;color:var(--muted-2);flex-shrink:0;border:1px solid var(--line);overflow:hidden}.card .art .art-img{width:100%;height:100%;object-fit:cover;display:block}.card .card-body{min-width:0}.card .n{font-weight:600;font-size:14px;line-height:1.2;letter-spacing:-.005em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.card .g{font-size:11.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:2px}.card .fav,.card .more{width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:16px;color:var(--muted);transition:background .1s,color .1s}.card .fav:hover,.card .more:hover{background:#ffffff0f;color:var(--fg)}.card .fav.on{color:var(--accent)}.card .more{font-weight:700;letter-spacing:1px}.empty{color:var(--muted);padding:32px 16px;text-align:center;font-size:13px}.login{position:fixed;top:0;right:0;bottom:0;left:0;background:radial-gradient(800px 500px at 50% 0%,rgba(255,122,61,.1),transparent 60%),#07080bf7;display:flex;align-items:center;justify-content:center;z-index:50}.login form{background:var(--bg-1);border:1px solid var(--line);padding:32px;border-radius:var(--radius-lg);display:flex;flex-direction:column;gap:14px;width:380px;box-shadow:var(--shadow-lg)}.login h1{margin:0 0 8px;font-size:24px;letter-spacing:-.01em}.login input{background:var(--bg-2);border:1px solid var(--line);color:var(--fg);padding:13px 14px;border-radius:var(--radius-sm);font-size:15px;outline:none;transition:border-color .12s,box-shadow .12s}.login input:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-glow)}.login button{background:var(--accent);color:#1a0a00;font-weight:700;padding:13px;border-radius:var(--radius-sm);font-size:15px;box-shadow:0 6px 18px var(--accent-glow);transition:background .12s}.login button:hover{background:#ff8a55}.login .err{color:var(--bad);font-size:13px;min-height:18px}dialog.add-station{border:1px solid var(--line);background:var(--bg-1);color:var(--fg);border-radius:var(--radius-lg);padding:0;max-width:520px;width:90%;box-shadow:var(--shadow-lg)}dialog.add-station::backdrop{background:#07080ba6;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}dialog.add-station form{padding:24px;display:flex;flex-direction:column;gap:12px}dialog.add-station h2{margin:0 0 4px;font-size:18px;letter-spacing:-.01em}dialog.add-station label{display:flex;flex-direction:column;gap:4px;font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}dialog.add-station input,dialog.add-station select{background:var(--bg-2);border:1px solid var(--line);color:var(--fg);padding:9px 11px;border-radius:var(--radius-sm);font-size:14px;outline:none;transition:border-color .12s,box-shadow .12s}dialog.add-station input:focus,dialog.add-station select:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-glow)}dialog.add-station .row2{display:grid;grid-template-columns:1fr 1fr;gap:12px}dialog.add-station .err{color:var(--bad);font-size:12px;min-height:14px}dialog.add-station .actions{display:flex;gap:8px;justify-content:flex-end;margin-top:4px}.btn-primary{background:var(--accent);color:#1a0a00;font-weight:700;padding:9px 16px;border-radius:var(--radius-sm);font-size:14px;transition:background .12s}.btn-primary:hover{background:#ff8a55}.btn-ghost{background:transparent;color:var(--muted);padding:9px 16px;border-radius:var(--radius-sm);font-size:14px;border:1px solid var(--line);transition:color .12s,background .12s}.btn-ghost:hover{color:var(--fg);background:var(--bg-2)}.ctx-menu{position:fixed;z-index:100;min-width:360px;max-width:460px;background:var(--bg-1);color:var(--fg);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-lg);padding:10px;display:flex;flex-direction:column;gap:2px;animation:ctxIn .1s ease-out}@keyframes ctxIn{0%{opacity:0;transform:translateY(-4px) scale(.98)}to{opacity:1;transform:none}}.ctx-title{font-weight:700;font-size:13px;padding:4px 8px 0;letter-spacing:-.005em}.ctx-sub{font-size:10.5px;color:var(--muted-2);padding:0 8px 8px;border-bottom:1px solid var(--line);font-family:ui-monospace,SF Mono,Menlo,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ctx-row{display:grid;grid-template-columns:1fr auto auto;gap:6px;align-items:center;padding:6px 8px;border-radius:8px}.ctx-row:hover{background:var(--bg-2)}.ctx-row-text{min-width:0}.ctx-label{font-size:12px;color:var(--fg);font-weight:500}.ctx-url{font-size:11px;color:var(--muted);font-family:ui-monospace,SF Mono,Menlo,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ctx-btn{width:28px;height:28px;border-radius:6px;background:var(--bg-2);color:var(--muted);font-size:13px;display:flex;align-items:center;justify-content:center;transition:background .1s,color .1s;border:1px solid var(--line)}.ctx-btn:hover{background:var(--bg-3);color:var(--fg)}.ctx-empty{padding:8px;color:var(--muted);font-size:12px}.ctx-danger{margin-top:4px;padding:7px 10px;border-radius:8px;background:transparent;color:var(--bad);border:1px solid rgba(236,106,106,.25);font-size:12px;font-weight:600;text-align:left}.ctx-danger:hover{background:#ec6a6a1a}.toast{position:fixed;bottom:20px;left:50%;transform:translate(-50%);background:var(--bg-1);padding:10px 18px;border-radius:999px;font-size:13px;color:var(--fg);z-index:200;border:1px solid var(--line);box-shadow:var(--shadow);animation:toastIn .18s ease-out}@keyframes toastIn{0%{opacity:0;transform:translate(-50%,8px)}to{opacity:1;transform:translate(-50%)}}:root{--bg-0: #000000;--bg-1: #0a0a0a;--bg-2: #141414;--bg-3: #1f1f1f;--line: #2e2e2e;--fg: #ffffff;--muted: #a0a0a0;--muted-2: #6a6a6a;--accent: #ff5b00;--accent-2: #ff5b00;--accent-glow: transparent;--good: #00d27a;--bad: #ff3030;--radius-sm: 0;--radius: 0;--radius-lg: 0;--shadow-sm: none;--shadow: none;--shadow-lg: none}html,body{background:var(--bg-0)!important}*,*:before,*:after{border-radius:0!important}button,input,select,textarea,dialog{border-radius:0!important}::-webkit-scrollbar-thumb{background:var(--bg-3)!important}::-webkit-scrollbar-thumb:hover{background:var(--line)!important}.now{background:var(--bg-1)!important;box-shadow:none!important;border-color:var(--line)!important}.now:before{display:none!important}@keyframes pulse{0%,to{border-color:var(--accent)}50%{border-color:var(--line)}}.now .meta .name{text-transform:uppercase;letter-spacing:.01em;font-weight:800}.tag{background:var(--bg-2)!important;color:var(--fg)!important;border-color:var(--line)!important;text-transform:uppercase;letter-spacing:.05em;font-weight:700}.btn-play,.btn-stop,.btn-add{box-shadow:none!important;border:1px solid var(--line);transition:background 80ms linear,color 80ms linear,transform 60ms linear!important}.btn-play,.btn-add{background:var(--accent)!important;color:#000!important;border-color:var(--accent)!important}.btn-play:hover,.btn-add:hover{background:#fff!important;color:#000!important;border-color:#fff!important}.btn-stop{background:var(--bg-2)!important;color:var(--fg)!important}.btn-stop:not(:disabled):hover{background:#fff!important;color:#000!important;border-color:#fff!important}.vol{background:var(--bg-2)!important;border-color:var(--line)!important}.lib{background:var(--bg-1)!important;box-shadow:none!important;border-color:var(--line)!important}.tabs{gap:0!important}.tab{border:1px solid var(--line)!important;margin-right:-1px!important;background:transparent!important;text-transform:uppercase;letter-spacing:.06em;font-weight:700;font-size:12px}.tab:hover{background:var(--bg-2)!important;color:var(--fg)!important}.tab.active{background:var(--accent)!important;color:#000!important;border-color:var(--accent)!important;position:relative;z-index:1}.search{background:var(--bg-2)!important;border-color:var(--line)!important}.search:focus{border-color:var(--accent)!important;box-shadow:none!important}.chip{background:var(--bg-2)!important;border-color:var(--line)!important;text-transform:uppercase;letter-spacing:.04em;font-weight:700}.chip:hover{color:var(--fg)!important;border-color:var(--fg)!important}.chip.active{background:var(--accent)!important;color:#000!important;border-color:var(--accent)!important}.grid{gap:0!important}.card{background:var(--bg-1)!important;border:1px solid var(--line)!important;margin-bottom:-1px;transition:background 60ms linear,border-color 60ms linear!important}.card:hover{background:var(--bg-2)!important;border-color:var(--muted-2)!important;z-index:1}.card:active{transform:none!important}.card.playing{background:var(--bg-2)!important;border-color:var(--accent)!important;z-index:2}.card.playing:before{left:0!important;top:0!important;bottom:0!important;width:4px!important;background:var(--accent)!important}.card .art{box-shadow:none!important}.card .n{font-weight:700}.card .g{text-transform:uppercase;letter-spacing:.03em}.card .fav:hover,.card .more:hover{background:var(--bg-3)!important;color:var(--fg)!important;border:1px solid var(--line)!important}.empty{text-transform:uppercase;letter-spacing:.06em}.login{background:#000!important}.login form{border:1px solid #fff!important;box-shadow:none!important}.login h1{text-transform:uppercase;letter-spacing:.04em;font-weight:900}.login input{background:var(--bg-2)!important;border-color:var(--line)!important}.login input:focus{border-color:var(--accent)!important;box-shadow:none!important}.login button{background:var(--accent)!important;color:#000!important;border:1px solid var(--accent)!important;box-shadow:none!important;text-transform:uppercase;letter-spacing:.08em;font-weight:900}.login button:hover{background:#fff!important;color:#000!important;border-color:#fff!important}dialog.add-station{border:1px solid #fff!important;box-shadow:none!important}dialog.add-station::backdrop{background:#000000d9!important;-webkit-backdrop-filter:none!important;backdrop-filter:none!important}dialog.add-station h2{text-transform:uppercase;letter-spacing:.04em;font-weight:900}dialog.add-station label{letter-spacing:.08em;font-weight:700}dialog.add-station input,dialog.add-station select{background:var(--bg-2)!important;border-color:var(--line)!important}dialog.add-station input:focus,dialog.add-station select:focus{border-color:var(--accent)!important;box-shadow:none!important}.btn-primary{background:var(--accent)!important;color:#000!important;border:1px solid var(--accent)!important;text-transform:uppercase;letter-spacing:.06em;font-weight:900}.btn-primary:hover{background:#fff!important;color:#000!important;border-color:#fff!important}.btn-ghost{background:transparent!important;border:1px solid var(--line)!important;text-transform:uppercase;letter-spacing:.06em;font-weight:700}.btn-ghost:hover{color:var(--fg)!important;background:var(--bg-2)!important;border-color:var(--fg)!important}.ctx-menu{border:1px solid #fff!important;box-shadow:none!important}.ctx-title{text-transform:uppercase;letter-spacing:.06em;font-weight:900;font-size:12px}.ctx-row{border:1px solid transparent}.ctx-row:hover{background:var(--bg-2)!important;border-color:var(--line)}.ctx-btn{background:var(--bg-2)!important;border:1px solid var(--line)!important;color:var(--muted)}.ctx-btn:hover{background:#fff!important;color:#000!important;border-color:#fff!important}.ctx-danger{background:transparent!important;border:1px solid var(--bad)!important;color:var(--bad)!important;text-transform:uppercase;letter-spacing:.06em;font-weight:800}.ctx-danger:hover{background:var(--bad)!important;color:#000!important}.toast{background:#fff!important;color:#000!important;border:1px solid #fff!important;box-shadow:none!important;text-transform:uppercase;letter-spacing:.06em;font-weight:800;font-size:12px}.vote-group{display:flex;gap:0;margin-right:6px}.vote{display:flex;align-items:center;gap:6px;height:46px;min-width:64px;padding:0 12px;background:var(--bg-2)!important;color:var(--fg);border:1px solid var(--line)!important;font-weight:800;font-size:14px;font-variant-numeric:tabular-nums;transition:background 80ms linear,color 80ms linear,border-color 80ms linear!important}.vote+.vote{margin-left:-1px}.vote:disabled{opacity:.35;cursor:not-allowed}.vote .vote-icon{font-size:17px;line-height:1}.vote .vote-count{font-size:13px;letter-spacing:.02em}.vote.up:not(:disabled):hover{background:var(--good)!important;color:#000!important;border-color:var(--good)!important}.vote.down:not(:disabled):hover{background:var(--bad)!important;color:#000!important;border-color:var(--bad)!important}.vote.up.on{background:var(--good)!important;color:#000!important;border-color:var(--good)!important}.vote.down.on{background:var(--bad)!important;color:#000!important;border-color:var(--bad)!important}.sort{height:36px;padding:0 28px 0 12px;background:var(--bg-2)!important;color:var(--fg);border:1px solid var(--line)!important;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),linear-gradient(135deg,var(--muted) 50%,transparent 50%);background-position:calc(100% - 14px) 50%,calc(100% - 9px) 50%;background-size:5px 5px,5px 5px;background-repeat:no-repeat;outline:none;cursor:pointer}.sort:focus,.sort:hover{border-color:var(--accent)!important}.sort option{background:var(--bg-1);color:var(--fg)}.card{grid-template-columns:44px 1fr auto auto auto!important}.score-badge{display:inline-flex;align-items:center;justify-content:center;min-width:36px;height:26px;padding:0 8px;background:var(--bg-2);border:1px solid var(--line);color:var(--muted);font-weight:800;font-size:12px;font-variant-numeric:tabular-nums;letter-spacing:.02em}.score-badge.pos{color:var(--good);border-color:#00d27a59}.score-badge.neg{color:var(--bad);border-color:#ff303059}.score-badge.neu{color:var(--muted-2)}.card.playing .score-badge{border-color:var(--accent)} diff --git a/server/public/assets/master-CpJfsvtJ.css b/server/public/assets/master-CpJfsvtJ.css new file mode 100644 index 0000000..6d6f80b --- /dev/null +++ b/server/public/assets/master-CpJfsvtJ.css @@ -0,0 +1 @@ +:root{--bg-0: #07080b;--bg-1: #0e1116;--bg-2: #161a22;--bg-3: #1f242e;--fg: #e9ecf2;--muted: #8a90a0;--muted-2: #5d6373;--line: #262b36;--accent: #ff7a3d;--accent-2: #ffb37a;--accent-glow: rgba(255, 122, 61, .35);--ok: #4ec9a6;--warn: #ffd166;--err: #ec6a6a}*{box-sizing:border-box}html,body{margin:0;padding:0;height:100%;background:radial-gradient(1200px 600px at 30% -10%,rgba(255,122,61,.06),transparent 60%),var(--bg-0);color:var(--fg);font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,system-ui,sans-serif;overflow:hidden}#app{height:100%;width:100%}.login{display:grid;place-items:center;height:100%}.login form{display:grid;gap:8px;padding:24px;background:var(--bg-1);border:1px solid var(--line);min-width:280px}.login input,.login button{padding:10px 12px;background:var(--bg-2);color:var(--fg);border:1px solid var(--line);font-size:14px}.login button{background:var(--accent);color:#1a0a00;font-weight:700;cursor:pointer;border-color:var(--accent)}.login .err{color:var(--err);font-size:12px;min-height:1em}.master{display:grid;grid-template-rows:56px auto 1fr;height:100%;gap:0}.master .topbar{display:flex;align-items:center;gap:10px;padding:0 18px;border-bottom:1px solid var(--line);background:var(--bg-1);font-size:13px}.master .topbar h1{margin:0;font-size:14px;font-weight:700;letter-spacing:.06em}.master .topbar .grow{flex:1}.master .topbar .pill{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;height:32px;background:var(--bg-2);border:1px solid var(--line);font-size:12px}.master .topbar select,.master .topbar input,.master .topbar button{background:var(--bg-2);color:var(--fg);border:1px solid var(--line);height:32px;padding:0 12px;font-size:12px}.master .topbar button{cursor:pointer}.master .topbar .peers{color:var(--muted);font-variant-numeric:tabular-nums}.master .topbar .status-on{color:var(--ok)}.master .topbar .status-off{color:var(--muted-2)}.master .stage{padding:12px 16px 8px;overflow:hidden;min-height:0}.master .np{display:grid;grid-template-columns:auto 1fr;gap:20px;align-items:stretch;background:linear-gradient(135deg,#ffffff08,#ffffff03),var(--bg-1);border:1px solid var(--line);padding:14px;position:relative;overflow:hidden}.master .np:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:radial-gradient(600px 220px at 0% 0%,var(--accent-glow),transparent 70%);opacity:.35;pointer-events:none}.master .np>*{position:relative}.master .np .art{height:clamp(180px,28vh,300px);aspect-ratio:1 / 1;width:auto;background:var(--bg-2);background-size:cover;background-position:center;box-shadow:0 24px 60px #0009;border:1px solid var(--line);position:relative;overflow:hidden;flex-shrink:0}.master .np .art .art-img{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;object-fit:cover;display:block}.master .np .art.empty:after{content:"♪";position:absolute;top:0;right:0;bottom:0;left:0;display:grid;place-items:center;font-size:64px;color:var(--muted-2)}.master .np .meta{display:grid;gap:6px;align-content:center;min-width:0}.master .np .meta .tiny{color:var(--muted-2);text-transform:uppercase;letter-spacing:.14em;font-size:10px}.master .np .meta h2{margin:0;font-size:clamp(20px,2.4vw,34px);font-weight:800;line-height:1.05;letter-spacing:-.01em}.master .np .meta .genres{display:flex;flex-wrap:wrap;gap:6px}.master .np .meta .tag{padding:3px 10px;background:#ffb37a1a;color:var(--accent-2);border:1px solid rgba(255,179,122,.18);font-size:12px}.master .np .meta .stats{display:flex;gap:16px;color:var(--muted);font-size:13px}.master .np .meta .stats b{color:var(--fg)}.master .np .transport{display:flex;align-items:center;gap:10px;margin-top:2px}.master .ctrl{width:38px;height:38px;display:grid;place-items:center;background:var(--bg-2);border:1px solid var(--line);color:var(--fg);font-size:15px;cursor:pointer;transition:background .12s,border-color .12s,transform 80ms}.master .ctrl:hover:not(:disabled){background:var(--bg-3);border-color:var(--accent)}.master .ctrl:active:not(:disabled){transform:scale(.96)}.master .ctrl:disabled{opacity:.35;cursor:default}.master .ctrl.primary{width:46px;height:46px;background:var(--accent);border-color:var(--accent);color:#1a0a00;font-size:18px;font-weight:900;box-shadow:0 6px 20px var(--accent-glow)}.master .ctrl.primary:hover:not(:disabled){background:#ff8a55;border-color:#ff8a55}.master .vol{display:flex;align-items:center;gap:10px;padding:6px 12px;background:var(--bg-2);border:1px solid var(--line);color:var(--muted);font-size:12px;flex:1;max-width:320px}.master .vol .vol-icon{font-size:14px}.master .vol input[type=range]{flex:1;accent-color:var(--accent)}.master .vol .val{width:36px;text-align:right;color:var(--muted);font-variant-numeric:tabular-nums}.master .np .peer-line{display:flex;flex-wrap:wrap;align-items:center;gap:8px;color:var(--muted);font-size:12px;margin-top:4px}.master .np .peer-line-label{color:var(--muted-2);text-transform:uppercase;letter-spacing:.1em;font-size:10px}.master .peer{display:inline-flex;align-items:center;gap:6px}.master .peer .role-tag{font-size:10px;padding:1px 6px;background:var(--bg-2);border:1px solid var(--line);text-transform:uppercase;letter-spacing:.08em}.master .peer.role-display .role-tag{color:var(--accent-2);border-color:#ff7a3d66}.master .stations-bar{padding:0 24px 20px;overflow:hidden;min-height:0}.master .err-banner{background:#ec6a6a1f;border:1px solid rgba(236,106,106,.4);color:var(--err);padding:4px 10px;font-size:12px;margin-left:12px}.master .np .meta .title-row{display:flex;align-items:center;gap:14px}.master .np .meta .title-row h2{margin:0;flex:1;min-width:0;word-break:break-word}.master .np .meta .fav-toggle{width:40px;height:40px;background:var(--bg-2);border:1px solid var(--line);color:var(--muted);font-size:20px;line-height:1;cursor:pointer;display:grid;place-items:center;flex-shrink:0;transition:background .12s,color .12s,border-color .12s}.master .np .meta .fav-toggle:hover{border-color:var(--accent);color:var(--accent-2)}.master .np .meta .fav-toggle.on{background:linear-gradient(180deg,#ff7a3d40,#ff7a3d1f);border-color:#ff7a3d80;color:var(--accent);text-shadow:0 0 12px var(--accent-glow)}.master .topbar .out-btn{cursor:pointer;max-width:280px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.master .topbar .out-btn.active{border-color:var(--accent);color:var(--accent-2)}.out-popover-wrap{position:fixed;top:0;right:0;bottom:0;left:0;background:#0000008c;display:grid;place-items:start center;padding-top:64px;z-index:50;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.out-popover{width:min(440px,92vw);max-height:70vh;overflow:auto;background:var(--bg-1);border:1px solid var(--line);padding:14px;box-shadow:0 24px 80px #00000080}.out-popover-head{display:flex;align-items:center;gap:8px;margin-bottom:8px}.out-popover-head h3{flex:1;margin:0;font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.12em}.out-popover .close{width:32px;height:32px;background:var(--bg-2);border:1px solid var(--line);color:var(--fg);font-size:18px;cursor:pointer}.out-popover .device-list{display:grid;gap:6px}.out-popover .device{display:flex;align-items:center;gap:10px;padding:8px 10px;background:var(--bg-2);border:1px solid var(--line);cursor:pointer;font-size:13px;color:var(--fg);text-align:left}.out-popover .device:hover{border-color:var(--accent)}.out-popover .device.active{background:linear-gradient(180deg,#ff7a3d2e,#ff7a3d14);border-color:#ff7a3d66;color:var(--accent-2)}.out-popover .device .dot{width:8px;height:8px;border-radius:50%;background:var(--muted-2);flex-shrink:0}.out-popover .device.active .dot{background:var(--accent);box-shadow:0 0 8px var(--accent-glow)}.out-popover .device .name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.out-popover .device .kind{color:var(--muted-2);font-size:11px;text-transform:uppercase;letter-spacing:.06em}.master .favs-card{background:var(--bg-1);border:1px solid var(--line);padding:10px 12px;height:100%;display:flex;flex-direction:column;min-height:0}.master .favs-card .favs-header{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-shrink:0}.master .favs-card .favs-header h3{flex:1;margin:0;font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.12em;font-weight:600}.master .favs-card .genre-filter{background:var(--bg-2);color:var(--fg);border:1px solid var(--line);padding:4px 8px;font-size:12px;max-width:200px}.master .favs-nav{width:32px;height:32px;display:grid;place-items:center;background:var(--bg-2);border:1px solid var(--line);color:var(--fg);font-size:20px;line-height:1;cursor:pointer;transition:background .12s,border-color .12s,transform 80ms}.master .favs-nav:hover{background:var(--bg-3);border-color:var(--accent)}.master .favs-nav:active{transform:scale(.94)}.master .favs-grid{flex:1;min-height:0;display:flex;flex-direction:column;flex-wrap:wrap;align-content:flex-start;overflow-x:auto;overflow-y:hidden;gap:8px;padding:2px 2px 8px;scroll-snap-type:x proximity;scrollbar-gutter:stable;cursor:grab;-webkit-user-select:none;user-select:none;scroll-behavior:smooth}.master .favs-grid.dragging{cursor:grabbing;scroll-behavior:auto}.master .favs-grid.dragging .fav-tile{pointer-events:none}.master .favs-grid::-webkit-scrollbar{height:10px}.master .fav-tile{display:grid;grid-template-rows:1fr auto;gap:6px;padding:6px;background:var(--bg-2);border:1px solid var(--line);color:var(--fg);cursor:pointer;text-align:left;transition:transform 80ms ease,border-color .12s,background .12s;height:calc((100% - 8px)/2);aspect-ratio:1 / 1;flex-shrink:0;scroll-snap-align:start;min-height:0}.master .fav-tile:hover{border-color:var(--accent);background:var(--bg-3)}.master .fav-tile:active{transform:scale(.97)}.master .fav-tile.active{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset,0 0 16px var(--accent-glow)}.master .fav-art{width:100%;min-height:0;background:var(--bg-1) center/cover no-repeat;position:relative;aspect-ratio:1 / 1;justify-self:center;max-height:100%}.master .fav-art.empty:after{content:"♪";position:absolute;top:0;right:0;bottom:0;left:0;display:grid;place-items:center;color:var(--muted-2);font-size:28px}.master .fav-name{font-size:12px;line-height:1.2;color:var(--fg);overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.master .favs-empty{color:var(--muted);font-size:12px;padding:12px 4px;text-align:center;width:100%} diff --git a/server/public/assets/master-kSyrThjc.js b/server/public/assets/master-kSyrThjc.js new file mode 100644 index 0000000..7b3c9c8 --- /dev/null +++ b/server/public/assets/master-kSyrThjc.js @@ -0,0 +1 @@ +import"./modulepreload-polyfill-B5Qt9EMX.js";import{a as v,P as E,c as C,e as s}from"./player-BBOsFRH-.js";import{c as D}from"./ws-BM1PmMVd.js";const F=[{id:"default",label:"System default",kind:"speakers"},{id:"speakers-internal",label:"Built-in speakers",kind:"speakers"},{id:"headphones-jack",label:"Headphones (3.5mm)",kind:"headphones"},{id:"hdmi-tv",label:"HDMI – Living-room TV",kind:"hdmi"},{id:"bt-marshall",label:"Bluetooth – Marshall Stanmore",kind:"bluetooth"},{id:"usb-audient",label:"USB – Audient EVO 4",kind:"usb"}],f=document.getElementById("app"),t={user:null,rooms:[],roomSlug:null,room:null,peers:[],devices:{list:[],current:"default"},np:{stationId:null,station:null,playing:!1,loading:!1,volume:.7,error:null},voteStats:null,favorites:[],favGenre:"",showOutputs:!1,session:null},c=window.oradioNative||null;let p=null,u=null;async function I(){var a,o;try{t.user=await v.get("/api/auth/me")}catch{return x()}const n=new URLSearchParams(location.search).get("room");try{t.rooms=await v.get("/api/rooms")}catch{t.rooms=[]}t.roomSlug=n||t.rooms[0]&&t.rooms[0].slug||`u-${t.user.id}`,c!=null&&c.listOutputs?(t.devices.list=await c.listOutputs(),t.devices.current=await c.getCurrent()||((a=t.devices.list[0])==null?void 0:a.id),(o=c.onCurrentChanged)==null||o.call(c,d=>{t.devices.current=d,S(),i()})):(t.devices.list=F,t.devices.current="default"),u=new E({onState:d=>{Object.assign(t.np,d),b(),i()}});try{t.favorites=await v.get("/api/me/favorites")}catch{t.favorites=[]}L(),i()}typeof window<"u"&&(window.addEventListener("pagehide",()=>h({beacon:!0})),window.addEventListener("beforeunload",()=>h({beacon:!0})));function L(){if(p)try{p.close()}catch{}p=D(P,{room:t.roomSlug,kind:"display",onOpen:()=>S()})}function P(e){var n;if(!(!e||!e.type))switch(e.type){case"hello":{t.room=e.room,t.peers=e.peers||[],(n=e.you)!=null&&n.kind&&e.you.kind!=="display"&&(t.np.error=`This room already has a display (${B(e.peers)} active). You were joined as ${e.you.kind}.`);const a=e.state;a!=null&&a.station_id&&a.station&&a.station_id!==t.np.stationId&&w(a.station,{silent:!0}),typeof(a==null?void 0:a.volume)=="number"&&u.setVolume(a.volume),i();return}case"presence":t.peers=e.peers||[],i();return;case"command":_(e);return;case"vote":case"plays":e.stationId===t.np.stationId&&(t.voteStats={...t.voteStats||{},...e.stats||{}},e.type==="plays"&&(t.voteStats.plays=e.plays),i());return;default:return}}function _(e){switch(e.action){case"play":{const n=Number(e.stationId);if(!Number.isFinite(n))return;v.get(`/api/stations/${n}`).then(a=>w(a)).catch(()=>{});return}case"pause":u.togglePause();return;case"stop":u.stop(),h(),t.np.playing=!1,t.np.stationId=null,b(),i();return;case"volume":typeof e.value=="number"&&u.setVolume(e.value);return;case"setSink":$(String(e.deviceId||""));return;default:return}}async function w(e,{silent:n}={}){if(e&&(h(),t.np.station=e,t.np.stationId=e.id,t.voteStats={up:e.up||0,down:e.down||0,plays:e.plays||0,score:e.score||0},i(),await u.play(e),!n))try{const a=await v.post(`/api/stations/${e.id}/play`);t.np.stationId===e.id?(t.session={id:a.sessionId,stationId:e.id,startedAt:Date.now()},t.voteStats={...t.voteStats,...a}):a.sessionId&&v.post(`/api/stations/${e.id}/play/end`,{sessionId:a.sessionId,duration_ms:0}).catch(()=>{})}catch{}}function h({beacon:e=!1}={}){const n=t.session;if(!n||!n.id)return;t.session=null;const a={sessionId:n.id,duration_ms:Math.max(0,Date.now()-n.startedAt)},o=`/api/stations/${n.stationId}/play/end`;if(e&&typeof navigator<"u"&&navigator.sendBeacon)try{navigator.sendBeacon(o,new Blob([JSON.stringify(a)],{type:"application/json"}));return}catch{}v.post(o,a).catch(()=>{})}function b(){if(!p||!t.np.stationId){p==null||p.send({type:"state",stationId:t.np.stationId,playing:!!t.np.playing,volume:t.np.volume});return}p.send({type:"state",stationId:t.np.stationId,playing:!!t.np.playing,volume:t.np.volume})}function S(){p==null||p.send({type:"devices",list:t.devices.list,current:t.devices.current})}async function $(e){var n;if(e){if(c!=null&&c.setOutput)try{await c.setOutput(e)}catch(a){console.warn("[master] setOutput failed",a);return}if(t.devices.current=e,(n=u==null?void 0:u.audio)!=null&&n.setSinkId&&/^[a-f0-9]{16,}$/.test(e))try{await u.audio.setSinkId(e)}catch{}S(),t.showOutputs=!1,i()}}function B(e){return(e||[]).filter(n=>n.kind==="display").length}function O(e){return!!e&&t.favorites.some(n=>n.id===e)}async function M(e){if(!e)return;const n=O(e);try{n?await v.del(`/api/me/favorites/${e}`):await v.put(`/api/me/favorites/${e}`,{position:t.favorites.length}),t.favorites=await v.get("/api/me/favorites"),i()}catch(a){console.warn("[master] toggleFavorite failed",a)}}function A(){const e=new Map;for(const n of t.favorites)for(const a of n.genres||[])e.set(a,(e.get(a)||0)+1);return[...e.entries()].sort((n,a)=>a[1]-n[1]||n[0].localeCompare(a[0])).map(([n,a])=>({genre:n,count:a}))}function G(){return t.favGenre?t.favorites.filter(e=>(e.genres||[]).includes(t.favGenre)):t.favorites}function i(){var l;const e=((l=f.querySelector(".favs-grid"))==null?void 0:l.scrollLeft)??0;C(f);const n=t.np,a=n.station,o=(a==null?void 0:a.image_display_url)||(a==null?void 0:a.image_url)||null,d=O(a==null?void 0:a.id),g=s("div",{class:"master"},s("header",{class:"topbar"},s("h1",{},"◉ MASTER"),s("div",{class:"pill"},s("span",{},"Room:"),s("select",{onChange:r=>{t.roomSlug=r.target.value,history.replaceState(null,"",`?room=${encodeURIComponent(t.roomSlug)}`),L()}},...t.rooms.map(r=>s("option",{value:r.slug,selected:r.slug===t.roomSlug},r.name)))),s("div",{class:"pill peers"},`${t.peers.length} peer${t.peers.length===1?"":"s"}`),n.error?s("div",{class:"err-banner"},n.error):null,s("div",{class:"grow"}),s("button",{class:"pill out-btn"+(t.showOutputs?" active":""),title:"Audio output",onClick:()=>{t.showOutputs=!t.showOutputs,i()}},"🔊 ",V()),s("div",{class:"pill"},c?"native":"browser"),s("div",{class:"pill"},t.user.username)),s("section",{class:"stage"},s("div",{class:"np"},s("div",{class:"art"+(o?"":" empty")},o?s("img",{class:"art-img",src:o,alt:"",referrerpolicy:"no-referrer",onError:r=>{const y=r.target.parentNode;r.target.remove(),y&&y.classList.add("empty")}}):null),s("div",{class:"meta"},s("div",{class:"tiny"},n.loading?"Loading…":n.playing?"Now playing":a?"Paused":"Idle"),s("div",{class:"title-row"},s("h2",{},(a==null?void 0:a.name)||"—"),a?s("button",{class:"fav-toggle"+(d?" on":""),title:d?"Remove favorite":"Add favorite",onClick:()=>M(a.id)},d?"★":"☆"):null),s("div",{class:"genres"},...((a==null?void 0:a.genres)||[]).slice(0,6).map(r=>s("span",{class:"tag"},r))),t.voteStats?s("div",{class:"stats"},s("span",{},"▲ ",s("b",{},String(t.voteStats.up||0))),s("span",{},"▼ ",s("b",{},String(t.voteStats.down||0))),s("span",{},"▶ ",s("b",{},String(t.voteStats.plays||0)))):null,a!=null&&a.country?s("div",{class:"stats"},s("span",{},a.country)):null,s("div",{class:"transport"},s("button",{class:"ctrl primary",title:"Play / pause",disabled:!a,onClick:()=>u.togglePause()},n.playing?"❚❚":"▶"),s("button",{class:"ctrl",title:"Stop",disabled:!a,onClick:()=>{u.stop(),h(),t.np.playing=!1,b(),i()}},"■"),s("div",{class:"vol"},s("span",{class:"vol-icon"},"🔊"),s("input",{type:"range",min:0,max:1,step:.01,value:n.volume,onInput:r=>u.setVolume(Number(r.target.value))}),s("span",{class:"val"},Math.round(n.volume*100)+"%"))),s("div",{class:"peer-line"},s("span",{class:"peer-line-label"},"In room:"),...t.peers.length?t.peers.map(r=>{var y;return s("span",{class:"peer role-"+r.kind},s("span",{class:"role-tag"},r.kind),s("span",{},((y=r.user)==null?void 0:y.username)||"?"))}):[s("span",{class:"peer"},"Just you.")])))),s("section",{class:"stations-bar"},q()),t.showOutputs?T():null);f.appendChild(g);const m=f.querySelector(".favs-grid");m&&(e&&(m.scrollLeft=e),N(m))}function N(e){if(e.dataset.dragBound==="1")return;e.dataset.dragBound="1";let n=!1,a=!1,o=0,d=0,g=-1;e.addEventListener("pointerdown",l=>{l.pointerType==="mouse"&&l.button!==0||(n=!0,a=!1,o=l.clientX,d=e.scrollLeft,g=l.pointerId)}),e.addEventListener("pointermove",l=>{if(!n)return;const r=l.clientX-o;if(!a&&Math.abs(r)>5){a=!0;try{e.setPointerCapture(g)}catch{}e.classList.add("dragging")}a&&(e.scrollLeft=d-r,l.preventDefault())});const m=()=>{if(n=!1,a){const l=r=>{r.stopPropagation(),r.preventDefault()};e.addEventListener("click",l,{capture:!0,once:!0}),setTimeout(()=>e.removeEventListener("click",l,!0),0)}a=!1,e.classList.remove("dragging");try{e.releasePointerCapture(g)}catch{}};e.addEventListener("pointerup",m),e.addEventListener("pointercancel",m),e.addEventListener("pointerleave",()=>{n&&!a&&(n=!1)})}function k(e){const n=f.querySelector(".favs-grid");if(!n)return;const a=Math.max(160,Math.round(n.clientWidth*.8));n.scrollBy({left:e*a,behavior:"smooth"})}function q(){const e=A(),n=G();return s("div",{class:"card favs-card"},s("div",{class:"favs-header"},s("h3",{},`Favorites (${n.length}${t.favGenre?`/${t.favorites.length}`:""})`),e.length?s("select",{class:"genre-filter",title:"Filter by genre",onChange:a=>{t.favGenre=a.target.value,i()}},s("option",{value:""},"All genres"),...e.map(({genre:a,count:o})=>s("option",{value:a,selected:t.favGenre===a},`${a} (${o})`))):null,s("button",{class:"favs-nav",title:"Scroll left",onClick:()=>k(-1)},"‹"),s("button",{class:"favs-nav",title:"Scroll right",onClick:()=>k(1)},"›")),s("div",{class:"favs-grid"},...n.length?n.map(a=>{const o=a.image_display_url||a.image_url,d=t.np.stationId===a.id;return s("button",{class:"fav-tile"+(d?" active":""),title:a.name,onClick:()=>w(a)},s("div",{class:"fav-art"+(o?"":" empty"),style:o?{backgroundImage:`url("${o}")`}:{}}),s("div",{class:"fav-name"},a.name))}):[s("div",{class:"favs-empty"},t.favGenre?"No favorites in this genre.":"No favorites yet. Star a station to add it.")]))}function T(){return s("div",{class:"out-popover-wrap",onClick:e=>{e.target===e.currentTarget&&(t.showOutputs=!1,i())}},s("div",{class:"out-popover card"},s("div",{class:"out-popover-head"},s("h3",{},"Audio output"),s("button",{class:"close",title:"Close",onClick:()=>{t.showOutputs=!1,i()}},"×")),s("div",{class:"device-list"},...t.devices.list.map(e=>s("button",{class:"device"+(e.id===t.devices.current?" active":""),onClick:()=>{$(e.id)}},s("span",{class:"dot"}),s("span",{class:"name"},e.label),s("span",{class:"kind"},e.kind))))))}function V(){const e=t.devices.list.find(n=>n.id===t.devices.current);return e?e.label:"—"}function x(){C(f),f.appendChild(s("div",{class:"login"},s("form",{onSubmit:async e=>{e.preventDefault();const n=new FormData(e.target);try{t.user=await v.post("/api/auth/login",{username:n.get("username"),password:n.get("password")}),await I()}catch(a){e.target.querySelector(".err").textContent=a.message}}},s("h1",{},"Master sign in"),s("input",{name:"username",placeholder:"Username",required:!0}),s("input",{name:"password",type:"password",placeholder:"Password",required:!0}),s("div",{class:"err"}),s("button",{type:"submit"},"Sign in"))))}I(); diff --git a/server/public/assets/kiosk-C37Mmo8O.js b/server/public/assets/player-BBOsFRH-.js similarity index 50% rename from server/public/assets/kiosk-C37Mmo8O.js rename to server/public/assets/player-BBOsFRH-.js index 6e0e3ef..fec1642 100644 --- a/server/public/assets/kiosk-C37Mmo8O.js +++ b/server/public/assets/player-BBOsFRH-.js @@ -1,40 +1,40 @@ -import"./modulepreload-polyfill-B5Qt9EMX.js";import{a as Te,c as Ii,e as k}from"./dom-BvorgAdo.js";function io(a){let e,t=0,s=!1;function i(){const r=location.protocol==="https:"?"wss":"ws";e=new WebSocket(`${r}://${location.host}/ws`),e.addEventListener("open",()=>{t=0}),e.addEventListener("message",n=>{try{a(JSON.parse(n.data))}catch{}}),e.addEventListener("close",()=>{s||(t=Math.min(t+1,6),setTimeout(i,500*2**t))}),e.addEventListener("error",()=>e.close())}return i(),{send(r){(e==null?void 0:e.readyState)===WebSocket.OPEN&&e.send(JSON.stringify(r))},close(){s=!0,e==null||e.close()}}}const B=Number.isFinite||function(a){return typeof a=="number"&&isFinite(a)},ro=Number.isSafeInteger||function(a){return typeof a=="number"&&Math.abs(a)<=no},no=Number.MAX_SAFE_INTEGER||9007199254740991;let Y=function(a){return a.NETWORK_ERROR="networkError",a.MEDIA_ERROR="mediaError",a.KEY_SYSTEM_ERROR="keySystemError",a.MUX_ERROR="muxError",a.OTHER_ERROR="otherError",a}({}),R=function(a){return a.KEY_SYSTEM_NO_KEYS="keySystemNoKeys",a.KEY_SYSTEM_NO_ACCESS="keySystemNoAccess",a.KEY_SYSTEM_NO_SESSION="keySystemNoSession",a.KEY_SYSTEM_NO_CONFIGURED_LICENSE="keySystemNoConfiguredLicense",a.KEY_SYSTEM_LICENSE_REQUEST_FAILED="keySystemLicenseRequestFailed",a.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED="keySystemServerCertificateRequestFailed",a.KEY_SYSTEM_SERVER_CERTIFICATE_UPDATE_FAILED="keySystemServerCertificateUpdateFailed",a.KEY_SYSTEM_SESSION_UPDATE_FAILED="keySystemSessionUpdateFailed",a.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED="keySystemStatusOutputRestricted",a.KEY_SYSTEM_STATUS_INTERNAL_ERROR="keySystemStatusInternalError",a.KEY_SYSTEM_DESTROY_MEDIA_KEYS_ERROR="keySystemDestroyMediaKeysError",a.KEY_SYSTEM_DESTROY_CLOSE_SESSION_ERROR="keySystemDestroyCloseSessionError",a.KEY_SYSTEM_DESTROY_REMOVE_SESSION_ERROR="keySystemDestroyRemoveSessionError",a.MANIFEST_LOAD_ERROR="manifestLoadError",a.MANIFEST_LOAD_TIMEOUT="manifestLoadTimeOut",a.MANIFEST_PARSING_ERROR="manifestParsingError",a.MANIFEST_INCOMPATIBLE_CODECS_ERROR="manifestIncompatibleCodecsError",a.LEVEL_EMPTY_ERROR="levelEmptyError",a.LEVEL_LOAD_ERROR="levelLoadError",a.LEVEL_LOAD_TIMEOUT="levelLoadTimeOut",a.LEVEL_PARSING_ERROR="levelParsingError",a.LEVEL_SWITCH_ERROR="levelSwitchError",a.AUDIO_TRACK_LOAD_ERROR="audioTrackLoadError",a.AUDIO_TRACK_LOAD_TIMEOUT="audioTrackLoadTimeOut",a.SUBTITLE_LOAD_ERROR="subtitleTrackLoadError",a.SUBTITLE_TRACK_LOAD_TIMEOUT="subtitleTrackLoadTimeOut",a.FRAG_LOAD_ERROR="fragLoadError",a.FRAG_LOAD_TIMEOUT="fragLoadTimeOut",a.FRAG_DECRYPT_ERROR="fragDecryptError",a.FRAG_PARSING_ERROR="fragParsingError",a.FRAG_GAP="fragGap",a.REMUX_ALLOC_ERROR="remuxAllocError",a.KEY_LOAD_ERROR="keyLoadError",a.KEY_LOAD_TIMEOUT="keyLoadTimeOut",a.BUFFER_ADD_CODEC_ERROR="bufferAddCodecError",a.BUFFER_INCOMPATIBLE_CODECS_ERROR="bufferIncompatibleCodecsError",a.BUFFER_APPEND_ERROR="bufferAppendError",a.BUFFER_APPENDING_ERROR="bufferAppendingError",a.BUFFER_STALLED_ERROR="bufferStalledError",a.BUFFER_FULL_ERROR="bufferFullError",a.BUFFER_SEEK_OVER_HOLE="bufferSeekOverHole",a.BUFFER_NUDGE_ON_STALL="bufferNudgeOnStall",a.ASSET_LIST_LOAD_ERROR="assetListLoadError",a.ASSET_LIST_LOAD_TIMEOUT="assetListLoadTimeout",a.ASSET_LIST_PARSING_ERROR="assetListParsingError",a.INTERSTITIAL_ASSET_ITEM_ERROR="interstitialAssetItemError",a.INTERNAL_EXCEPTION="internalException",a.INTERNAL_ABORTED="aborted",a.ATTACH_MEDIA_ERROR="attachMediaError",a.UNKNOWN="unknown",a}({}),m=function(a){return a.MEDIA_ATTACHING="hlsMediaAttaching",a.MEDIA_ATTACHED="hlsMediaAttached",a.MEDIA_DETACHING="hlsMediaDetaching",a.MEDIA_DETACHED="hlsMediaDetached",a.MEDIA_ENDED="hlsMediaEnded",a.STALL_RESOLVED="hlsStallResolved",a.BUFFER_RESET="hlsBufferReset",a.BUFFER_CODECS="hlsBufferCodecs",a.BUFFER_CREATED="hlsBufferCreated",a.BUFFER_APPENDING="hlsBufferAppending",a.BUFFER_APPENDED="hlsBufferAppended",a.BUFFER_EOS="hlsBufferEos",a.BUFFERED_TO_END="hlsBufferedToEnd",a.BUFFER_FLUSHING="hlsBufferFlushing",a.BUFFER_FLUSHED="hlsBufferFlushed",a.MANIFEST_LOADING="hlsManifestLoading",a.MANIFEST_LOADED="hlsManifestLoaded",a.MANIFEST_PARSED="hlsManifestParsed",a.LEVEL_SWITCHING="hlsLevelSwitching",a.LEVEL_SWITCHED="hlsLevelSwitched",a.LEVEL_LOADING="hlsLevelLoading",a.LEVEL_LOADED="hlsLevelLoaded",a.LEVEL_UPDATED="hlsLevelUpdated",a.LEVEL_PTS_UPDATED="hlsLevelPtsUpdated",a.LEVELS_UPDATED="hlsLevelsUpdated",a.AUDIO_TRACKS_UPDATED="hlsAudioTracksUpdated",a.AUDIO_TRACK_SWITCHING="hlsAudioTrackSwitching",a.AUDIO_TRACK_SWITCHED="hlsAudioTrackSwitched",a.AUDIO_TRACK_LOADING="hlsAudioTrackLoading",a.AUDIO_TRACK_LOADED="hlsAudioTrackLoaded",a.AUDIO_TRACK_UPDATED="hlsAudioTrackUpdated",a.SUBTITLE_TRACKS_UPDATED="hlsSubtitleTracksUpdated",a.SUBTITLE_TRACKS_CLEARED="hlsSubtitleTracksCleared",a.SUBTITLE_TRACK_SWITCH="hlsSubtitleTrackSwitch",a.SUBTITLE_TRACK_LOADING="hlsSubtitleTrackLoading",a.SUBTITLE_TRACK_LOADED="hlsSubtitleTrackLoaded",a.SUBTITLE_TRACK_UPDATED="hlsSubtitleTrackUpdated",a.SUBTITLE_FRAG_PROCESSED="hlsSubtitleFragProcessed",a.CUES_PARSED="hlsCuesParsed",a.NON_NATIVE_TEXT_TRACKS_FOUND="hlsNonNativeTextTracksFound",a.INIT_PTS_FOUND="hlsInitPtsFound",a.FRAG_LOADING="hlsFragLoading",a.FRAG_LOAD_EMERGENCY_ABORTED="hlsFragLoadEmergencyAborted",a.FRAG_LOADED="hlsFragLoaded",a.FRAG_DECRYPTED="hlsFragDecrypted",a.FRAG_PARSING_INIT_SEGMENT="hlsFragParsingInitSegment",a.FRAG_PARSING_USERDATA="hlsFragParsingUserdata",a.FRAG_PARSING_METADATA="hlsFragParsingMetadata",a.FRAG_PARSED="hlsFragParsed",a.FRAG_BUFFERED="hlsFragBuffered",a.FRAG_CHANGED="hlsFragChanged",a.FPS_DROP="hlsFpsDrop",a.FPS_DROP_LEVEL_CAPPING="hlsFpsDropLevelCapping",a.MAX_AUTO_LEVEL_UPDATED="hlsMaxAutoLevelUpdated",a.ERROR="hlsError",a.DESTROYING="hlsDestroying",a.KEY_LOADING="hlsKeyLoading",a.KEY_LOADED="hlsKeyLoaded",a.LIVE_BACK_BUFFER_REACHED="hlsLiveBackBufferReached",a.BACK_BUFFER_REACHED="hlsBackBufferReached",a.STEERING_MANIFEST_LOADED="hlsSteeringManifestLoaded",a.ASSET_LIST_LOADING="hlsAssetListLoading",a.ASSET_LIST_LOADED="hlsAssetListLoaded",a.INTERSTITIALS_UPDATED="hlsInterstitialsUpdated",a.INTERSTITIALS_BUFFERED_TO_BOUNDARY="hlsInterstitialsBufferedToBoundary",a.INTERSTITIAL_ASSET_PLAYER_CREATED="hlsInterstitialAssetPlayerCreated",a.INTERSTITIAL_STARTED="hlsInterstitialStarted",a.INTERSTITIAL_ASSET_STARTED="hlsInterstitialAssetStarted",a.INTERSTITIAL_ASSET_ENDED="hlsInterstitialAssetEnded",a.INTERSTITIAL_ASSET_ERROR="hlsInterstitialAssetError",a.INTERSTITIAL_ENDED="hlsInterstitialEnded",a.INTERSTITIALS_PRIMARY_RESUMED="hlsInterstitialsPrimaryResumed",a.PLAYOUT_LIMIT_REACHED="hlsPlayoutLimitReached",a.EVENT_CUE_ENTER="hlsEventCueEnter",a}({});var J={MANIFEST:"manifest",LEVEL:"level",AUDIO_TRACK:"audioTrack",SUBTITLE_TRACK:"subtitleTrack"},U={MAIN:"main",AUDIO:"audio",SUBTITLE:"subtitle"};class Et{constructor(e,t=0,s=0){this.halfLife=void 0,this.alpha_=void 0,this.estimate_=void 0,this.totalWeight_=void 0,this.halfLife=e,this.alpha_=e?Math.exp(Math.log(.5)/e):0,this.estimate_=t,this.totalWeight_=s}sample(e,t){const s=Math.pow(this.alpha_,e);this.estimate_=t*(1-s)+s*this.estimate_,this.totalWeight_+=e}getTotalWeight(){return this.totalWeight_}getEstimate(){if(this.alpha_){const e=1-Math.pow(this.alpha_,this.totalWeight_);if(e)return this.estimate_/e}return this.estimate_}}class ao{constructor(e,t,s,i=100){this.defaultEstimate_=void 0,this.minWeight_=void 0,this.minDelayMs_=void 0,this.slow_=void 0,this.fast_=void 0,this.defaultTTFB_=void 0,this.ttfb_=void 0,this.defaultEstimate_=s,this.minWeight_=.001,this.minDelayMs_=50,this.slow_=new Et(e),this.fast_=new Et(t),this.defaultTTFB_=i,this.ttfb_=new Et(e)}update(e,t){const{slow_:s,fast_:i,ttfb_:r}=this;s.halfLife!==e&&(this.slow_=new Et(e,s.getEstimate(),s.getTotalWeight())),i.halfLife!==t&&(this.fast_=new Et(t,i.getEstimate(),i.getTotalWeight())),r.halfLife!==e&&(this.ttfb_=new Et(e,r.getEstimate(),r.getTotalWeight()))}sample(e,t){e=Math.max(e,this.minDelayMs_);const s=8*t,i=e/1e3,r=s/i;this.fast_.sample(i,r),this.slow_.sample(i,r)}sampleTTFB(e){const t=e/1e3,s=Math.sqrt(2)*Math.exp(-Math.pow(t,2)/2);this.ttfb_.sample(s,Math.max(e,5))}canEstimate(){return this.fast_.getTotalWeight()>=this.minWeight_}getEstimate(){return this.canEstimate()?Math.min(this.fast_.getEstimate(),this.slow_.getEstimate()):this.defaultEstimate_}getEstimateTTFB(){return this.ttfb_.getTotalWeight()>=this.minWeight_?this.ttfb_.getEstimate():this.defaultTTFB_}get defaultEstimate(){return this.defaultEstimate_}destroy(){}}function oo(a,e,t){return(e=co(e))in a?Object.defineProperty(a,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):a[e]=t,a}function ne(){return ne=Object.assign?Object.assign.bind():function(a){for(var e=1;e`):it}function sr(a,e,t){return e[a]?e[a].bind(e):uo(a,t)}const ni=ri();function fo(a,e,t){const s=ri();if(typeof console=="object"&&a===!0||typeof a=="object"){const i=["debug","log","info","warn","error"];i.forEach(r=>{s[r]=sr(r,a,t)});try{s.log(`Debug logs enabled for "${e}" in hls.js version 1.6.16`)}catch{return ri()}i.forEach(r=>{ni[r]=sr(r,a)})}else ne(ni,s);return s}const re=ni;function at(a=!0){return typeof self>"u"?void 0:(a||!self.MediaSource)&&self.ManagedMediaSource||self.MediaSource||self.WebKitMediaSource}function go(a){return typeof self<"u"&&a===self.ManagedMediaSource}function xn(a,e){const t=Object.keys(a),s=Object.keys(e),i=t.length,r=s.length;return!i||!r||i===r&&!t.some(n=>s.indexOf(n)===-1)}function De(a,e=!1){if(typeof TextDecoder<"u"){const l=new TextDecoder("utf-8").decode(a);if(e){const h=l.indexOf("\0");return h!==-1?l.substring(0,h):l}return l.replace(/\0/g,"")}const t=a.length;let s,i,r,n="",o=0;for(;o>4){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:n+=String.fromCharCode(s);break;case 12:case 13:i=a[o++],n+=String.fromCharCode((s&31)<<6|i&63);break;case 14:i=a[o++],r=a[o++],n+=String.fromCharCode((s&15)<<12|(i&63)<<6|(r&63)<<0);break}}return n}function ye(a){let e="";for(let t=0;t1||i===1&&(t=this.levelkeys[s[0]])!=null&&t.encrypted)return!0}return!1}get programDateTime(){return this._programDateTime===null&&this.rawProgramDateTime&&(this.programDateTime=Date.parse(this.rawProgramDateTime)),this._programDateTime}set programDateTime(e){if(!B(e)){this._programDateTime=this.rawProgramDateTime=null;return}this._programDateTime=e}get ref(){return de(this)?(this._ref||(this._ref={base:this.base,start:this.start,duration:this.duration,sn:this.sn,programDateTime:this.programDateTime}),this._ref):null}addStart(e){this.setStart(this.start+e)}setStart(e){this.start=e,this._ref&&(this._ref.start=e)}setDuration(e){this.duration=e,this._ref&&(this._ref.duration=e)}setKeyFormat(e){const t=this.levelkeys;if(t){var s;const i=t[e];i&&!((s=this._decryptdata)!=null&&s.keyId)&&(this._decryptdata=i.getDecryptData(this.sn,t))}}abortRequests(){var e,t;(e=this.loader)==null||e.abort(),(t=this.keyLoader)==null||t.abort()}setElementaryStreamInfo(e,t,s,i,r,n=!1){const{elementaryStreams:o}=this,c=o[e];if(!c){o[e]={startPTS:t,endPTS:s,startDTS:i,endDTS:r,partial:n};return}c.startPTS=Math.min(c.startPTS,t),c.endPTS=Math.max(c.endPTS,s),c.startDTS=Math.min(c.startDTS,i),c.endDTS=Math.max(c.endDTS,r)}}class yo extends In{constructor(e,t,s,i,r){super(s),this.fragOffset=0,this.duration=0,this.gap=!1,this.independent=!1,this.relurl=void 0,this.fragment=void 0,this.index=void 0,this.duration=e.decimalFloatingPoint("DURATION"),this.gap=e.bool("GAP"),this.independent=e.bool("INDEPENDENT"),this.relurl=e.enumeratedString("URI"),this.fragment=t,this.index=i;const n=e.enumeratedString("BYTERANGE");n&&this.setByteRange(n,r),r&&(this.fragOffset=r.fragOffset+r.duration)}get start(){return this.fragment.start+this.fragOffset}get end(){return this.start+this.duration}get loaded(){const{elementaryStreams:e}=this;return!!(e.audio||e.video||e.audiovideo)}}function Ln(a,e){const t=Object.getPrototypeOf(a);if(t){const s=Object.getOwnPropertyDescriptor(t,e);return s||Ln(t,e)}}function Eo(a,e){const t=Ln(a,e);t&&(t.enumerable=!0,Object.defineProperty(a,e,t))}const rr=Math.pow(2,32)-1,To=[].push,Rn={video:1,audio:2,id3:3,text:4};function ue(a){return String.fromCharCode.apply(null,a)}function bn(a,e){const t=a[e]<<8|a[e+1];return t<0?65536+t:t}function j(a,e){const t=_n(a,e);return t<0?4294967296+t:t}function nr(a,e){let t=j(a,e);return t*=Math.pow(2,32),t+=j(a,e+4),t}function _n(a,e){return a[e]<<24|a[e+1]<<16|a[e+2]<<8|a[e+3]}function So(a){const e=a.byteLength;for(let t=0;t8&&a[t+4]===109&&a[t+5]===111&&a[t+6]===111&&a[t+7]===102)return!0;t=s>1?t+s:e}return!1}function Z(a,e){const t=[];if(!e.length)return t;const s=a.byteLength;for(let i=0;i1?i+r:s;if(n===e[0])if(e.length===1)t.push(a.subarray(i+8,o));else{const c=Z(a.subarray(i+8,o),e.slice(1));c.length&&To.apply(t,c)}i=o}return t}function vo(a){const e=[],t=a[0];let s=8;const i=j(a,s);s+=4;let r=0,n=0;t===0?(r=j(a,s),n=j(a,s+4),s+=8):(r=nr(a,s),n=nr(a,s+8),s+=16),s+=2;let o=a.length+n;const c=bn(a,s);s+=2;for(let l=0;l>>31===1)return re.warn("SIDX has hierarchical references (not supported)"),null;const g=j(a,h);h+=4,e.push({referenceSize:u,subsegmentDuration:g,info:{duration:g/i,start:o,end:o+u-1}}),o+=u,h+=4,s=h}return{earliestPresentationTime:r,timescale:i,version:t,referencesCount:c,references:e}}function Dn(a){const e=[],t=Z(a,["moov","trak"]);for(let i=0;i{const r=j(i,4),n=e[r];n&&(n.default={duration:j(i,12),flags:j(i,20)})}),e}function xo(a){const e=a.subarray(8),t=e.subarray(86),s=ue(e.subarray(4,8));let i=s,r;const n=s==="enca"||s==="encv";if(n){const l=Z(e,[s])[0].subarray(s==="enca"?28:78);Z(l,["sinf"]).forEach(d=>{const u=Z(d,["schm"])[0];if(u){const f=ue(u.subarray(4,8));if(f==="cbcs"||f==="cenc"){const g=Z(d,["frma"])[0];g&&(i=ue(g))}}})}const o=i;switch(i){case"avc1":case"avc2":case"avc3":case"avc4":{const c=Z(t,["avcC"])[0];c&&c.length>3&&(i+="."+Qt(c[1])+Qt(c[2])+Qt(c[3]),r=zt(o==="avc1"?"dva1":"dvav",t));break}case"mp4a":{const c=Z(e,[s])[0],l=Z(c.subarray(28),["esds"])[0];if(l&&l.length>7){let h=4;if(l[h++]!==3)break;h=Ms(l,h),h+=2;const d=l[h++];if(d&128&&(h+=2),d&64&&(h+=l[h++]),l[h++]!==4)break;h=Ms(l,h);const u=l[h++];if(u===64)i+="."+Qt(u);else break;if(h+=12,l[h++]!==5)break;h=Ms(l,h);const f=l[h++];let g=(f&248)>>3;g===31&&(g+=1+((f&7)<<3)+((l[h]&224)>>5)),i+="."+g}break}case"hvc1":case"hev1":{const c=Z(t,["hvcC"])[0];if(c&&c.length>12){const l=c[1],h=["","A","B","C"][l>>6],d=l&31,u=j(c,2),f=(l&32)>>5?"H":"L",g=c[12],y=c.subarray(6,12);i+="."+h+d,i+="."+Ao(u).toString(16).toUpperCase(),i+="."+f+g;let p="";for(let E=y.length;E--;){const T=y[E];(T||p)&&(p="."+T.toString(16).toUpperCase()+p)}i+=p}r=zt(o=="hev1"?"dvhe":"dvh1",t);break}case"dvh1":case"dvhe":case"dvav":case"dva1":case"dav1":{i=zt(i,t)||i;break}case"vp09":{const c=Z(t,["vpcC"])[0];if(c&&c.length>6){const l=c[4],h=c[5],d=c[6]>>4&15;i+="."+Ke(l)+"."+Ke(h)+"."+Ke(d)}break}case"av01":{const c=Z(t,["av1C"])[0];if(c&&c.length>2){const l=c[1]>>>5,h=c[1]&31,d=c[2]>>>7?"H":"M",u=(c[2]&64)>>6,f=(c[2]&32)>>5,g=l===2&&u?f?12:10:u?10:8,y=(c[2]&16)>>4,p=(c[2]&8)>>3,E=(c[2]&4)>>2,T=c[2]&3;i+="."+l+"."+Ke(h)+d+"."+Ke(g)+"."+y+"."+p+E+T+"."+Ke(1)+"."+Ke(1)+"."+Ke(1)+"."+0,r=zt("dav1",t)}break}}return{codec:i,encrypted:n,supplemental:r}}function zt(a,e){const t=Z(e,["dvvC"]),s=t.length?t[0]:Z(e,["dvcC"])[0];if(s){const i=s[2]>>1&127,r=s[2]<<5&32|s[3]>>3&31;return a+"."+Ke(i)+"."+Ke(r)}}function Ao(a){let e=0;for(let t=0;t<32;t++)e|=(a>>t&1)<<31-t;return e>>>0}function Ms(a,e){const t=e+5;for(;a[e++]&128&&e{const r=s.subarray(8,24);r.some(n=>n!==0)||(re.log(`[eme] Patching keyId in 'enc${i?"a":"v"}>sinf>>tenc' box: ${ye(r)} -> ${ye(t)}`),s.set(t,8))})}function Lo(a){const e=[];return Cn(a,t=>e.push(t.subarray(8,24))),e}function Cn(a,e){Z(a,["moov","trak"]).forEach(s=>{const i=Z(s,["mdia","minf","stbl","stsd"])[0];if(!i)return;const r=i.subarray(8);let n=Z(r,["enca"]);const o=n.length>0;o||(n=Z(r,["encv"])),n.forEach(c=>{const l=o?c.subarray(28):c.subarray(78);Z(l,["sinf"]).forEach(d=>{const u=Pn(d);u&&e(u,o)})})})}function Pn(a){const e=Z(a,["schm"])[0];if(e){const t=ue(e.subarray(4,8));if(t==="cbcs"||t==="cenc"){const s=Z(a,["schi","tenc"])[0];if(s)return s}}}function Ro(a,e,t){const s={},i=Z(a,["moof","traf"]);for(let r=0;rs[r].duration)){let r=1/0,n=0;const o=Z(a,["sidx"]);for(let c=0;cd+u.info.duration||0,0);n=Math.max(n,h+l.earliestPresentationTime/l.timescale)}}n&&B(n)&&Object.keys(s).forEach(c=>{s[c].duration||(s[c].duration=n*s[c].timescale-s[c].start)})}return s}function bo(a){const e={valid:null,remainder:null},t=Z(a,["moof"]);if(t.length<2)return e.remainder=a,e;const s=t[t.length-1];return e.valid=a.slice(0,s.byteOffset-8),e.remainder=a.slice(s.byteOffset-8),e}function we(a,e){const t=new Uint8Array(a.length+e.length);return t.set(a),t.set(e,a.length),t}function ar(a,e){const t=[],s=e.samples,i=e.timescale,r=e.id;let n=!1;return Z(s,["moof"]).map(c=>{const l=c.byteOffset-8;Z(c,["traf"]).map(d=>{const u=Z(d,["tfdt"]).map(f=>{const g=f[0];let y=j(f,4);return g===1&&(y*=Math.pow(2,32),y+=j(f,8)),y/i})[0];return u!==void 0&&(a=u),Z(d,["tfhd"]).map(f=>{const g=j(f,4),y=j(f,0)&16777215,p=(y&1)!==0,E=(y&2)!==0,T=(y&8)!==0;let S=0;const v=(y&16)!==0;let x=0;const D=(y&32)!==0;let A=8;g===r&&(p&&(A+=8),E&&(A+=4),T&&(S=j(f,A),A+=4),v&&(x=j(f,A),A+=4),D&&(A+=4),e.type==="video"&&(n=Ds(e.codec)),Z(d,["trun"]).map(_=>{const b=_[0],I=j(_,0)&16777215,P=(I&1)!==0;let M=0;const G=(I&4)!==0,W=(I&256)!==0;let K=0;const w=(I&512)!==0;let V=0;const $=(I&1024)!==0,H=(I&2048)!==0;let q=0;const O=j(_,4);let F=8;P&&(M=j(_,F),F+=4),G&&(F+=4);let z=M+l;for(let se=0;se>1&63;return t===39||t===40}else return(e&31)===6}function bi(a,e,t,s){const i=kn(a);let r=0;r+=e;let n=0,o=0,c=0;for(;r=i.length)break;c=i[r++],n+=c}while(c===255);o=0;do{if(r>=i.length)break;c=i[r++],o+=c}while(c===255);const l=i.length-r;let h=r;if(ol){re.error(`Malformed SEI payload. ${o} is too small, only ${l} bytes left to parse.`);break}if(n===4){if(i[h++]===181){const u=bn(i,h);if(h+=2,u===49){const f=j(i,h);if(h+=4,f===1195456820){const g=i[h++];if(g===3){const y=i[h++],p=31&y,E=64&y,T=E?2+p*3:0,S=new Uint8Array(T);if(E){S[0]=y;for(let v=1;v16){const d=[];for(let g=0;g<16;g++){const y=i[h++].toString(16);d.push(y.length==1?"0"+y:y),(g===3||g===5||g===7||g===9)&&d.push("-")}const u=o-16,f=new Uint8Array(u);for(let g=0;g>24&255,r[1]=s>>16&255,r[2]=s>>8&255,r[3]=s&255,r.set(a,4),i=0,s=8;i0?(r=new Uint8Array(4),e.length>0&&new DataView(r.buffer).setUint32(0,e.length,!1)):r=new Uint8Array;const n=new Uint8Array(4);return t.byteLength>0&&new DataView(n.buffer).setUint32(0,t.byteLength,!1),Co([112,115,115,104],new Uint8Array([s,0,0,0]),a,r,i,n,t)}function ko(a){const e=[];if(a instanceof ArrayBuffer){const t=a.byteLength;let s=0;for(;s+32>>24;if(r!==0&&r!==1)return{offset:t,size:e};const n=a.buffer,o=ye(new Uint8Array(n,t+12,16));let c=null,l=null,h=0;if(r===0)h=28;else{const u=a.getUint32(28);if(!u||s<32+u*16)return{offset:t,size:e};c=[];for(let f=0;f/\(Windows.+Firefox\//i.test(navigator.userAgent),Pt={audio:{a3ds:1,"ac-3":.95,"ac-4":1,alac:.9,alaw:1,dra1:1,"dts+":1,"dts-":1,dtsc:1,dtse:1,dtsh:1,"ec-3":.9,enca:1,fLaC:.9,flac:.9,FLAC:.9,g719:1,g726:1,m4ae:1,mha1:1,mha2:1,mhm1:1,mhm2:1,mlpa:1,mp4a:1,"raw ":1,Opus:1,opus:1,samr:1,sawb:1,sawp:1,sevc:1,sqcp:1,ssmv:1,twos:1,ulaw:1},video:{avc1:1,avc2:1,avc3:1,avc4:1,avcp:1,av01:.8,dav1:.8,drac:1,dva1:1,dvav:1,dvh1:.7,dvhe:.7,encv:1,hev1:.75,hvc1:.75,mjp2:1,mp4v:1,mvc1:1,mvc2:1,mvc3:1,mvc4:1,resv:1,rv60:1,s263:1,svc1:1,svc2:1,"vc-1":1,vp08:1,vp09:.9},text:{stpp:1,wvtt:1}};function _i(a,e){const t=Pt[e];return!!t&&!!t[a.slice(0,4)]}function Ut(a,e,t=!0){return!a.split(",").some(s=>!Di(s,e,t))}function Di(a,e,t=!0){var s;const i=at(t);return(s=i==null?void 0:i.isTypeSupported(Gt(a,e)))!=null?s:!1}function Gt(a,e){return`${e}/mp4;codecs=${a}`}function or(a){if(a){const e=a.substring(0,4);return Pt.video[e]}return 2}function Es(a){const e=wn();return a.split(",").reduce((t,s)=>{const r=e&&Ds(s)?9:Pt.video[s];return r?(r*2+t)/(t?3:2):(Pt.audio[s]+t)/(t?2:1)},0)}const Ns={};function Oo(a,e=!0){if(Ns[a])return Ns[a];const t={flac:["flac","fLaC","FLAC"],opus:["opus","Opus"],"mp4a.40.34":["mp3"]}[a];for(let i=0;iOo(t.toLowerCase(),e))}function Mo(a,e){const t=[];if(a){const s=a.split(",");for(let i=0;i4||["ac-3","ec-3","alac","fLaC","Opus"].indexOf(a)!==-1)&&(lr(a,"audio")||lr(a,"video")))return a;if(e){const t=e.split(",");if(t.length>1){if(a){for(let s=t.length;s--;)if(t[s].substring(0,4)===a.substring(0,4))return t[s]}return t[0]}}return e||a}function lr(a,e){return _i(a,e)&&Di(a,e)}function No(a){const e=a.split(",");for(let t=0;t2&&s[0]==="avc1"&&(e[t]=`avc1.${parseInt(s[1]).toString(16)}${("000"+parseInt(s[2]).toString(16)).slice(-4)}`)}return e.join(",")}function Bo(a){if(a.startsWith("av01.")){const e=a.split("."),t=["0","111","01","01","01","0"];for(let s=e.length;s>4&&s<10;s++)e[s]=t[s-4];return e.join(".")}return a}function cr(a){const e=at(a)||{isTypeSupported:()=>!1};return{mpeg:e.isTypeSupported("audio/mpeg"),mp3:e.isTypeSupported('audio/mp4; codecs="mp3"'),ac3:e.isTypeSupported('audio/mp4; codecs="ac-3"')}}function ai(a){return a.replace(/^.+codecs=["']?([^"']+).*$/,"$1")}const $o={supported:!0,powerEfficient:!0,smooth:!0},Uo={supported:!1,smooth:!1,powerEfficient:!1},On={supported:!0,configurations:[],decodingInfoResults:[$o]};function Fn(a,e){return{supported:!1,configurations:e,decodingInfoResults:[Uo],error:a}}function Go(a,e,t,s,i,r){const n=a.videoCodec,o=a.audioCodec?a.audioGroups:null,c=r==null?void 0:r.audioCodec,l=r==null?void 0:r.channels,h=l?parseInt(l):c?1/0:2;let d=null;if(o!=null&&o.length)try{o.length===1&&o[0]?d=e.groups[o[0]].channels:d=o.reduce((u,f)=>{if(f){const g=e.groups[f];if(!g)throw new Error(`Audio track group ${f} not found`);Object.keys(g.channels).forEach(y=>{u[y]=(u[y]||0)+g.channels[y]})}return u},{2:0})}catch{return!0}return n!==void 0&&(n.split(",").some(u=>Ds(u))||a.width>1920&&a.height>1088||a.height>1920&&a.width>1088||a.frameRate>Math.max(s,30)||a.videoRange!=="SDR"&&a.videoRange!==t||a.bitrate>Math.max(i,8e6))||!!d&&B(h)&&Object.keys(d).some(u=>parseInt(u)>h)}function Mn(a,e,t,s={}){const i=a.videoCodec;if(!i&&!a.audioCodec||!t)return Promise.resolve(On);const r=[],n=Ko(a),o=n.length,c=Vo(a,e,o>0),l=c.length;for(let h=o||1*l||1;h--;){const d={type:"media-source"};if(o&&(d.video=n[h%o]),l){d.audio=c[h%l];const u=d.audio.bitrate;d.video&&u&&(d.video.bitrate-=u)}r.push(d)}if(i){const h=navigator.userAgent;if(i.split(",").some(d=>Ds(d))&&wn())return Promise.resolve(Fn(new Error(`Overriding Windows Firefox HEVC MediaCapabilities result based on user-agent string: (${h})`),r))}return Promise.all(r.map(h=>{const d=Yo(h);return s[d]||(s[d]=t.decodingInfo(h))})).then(h=>({supported:!h.some(d=>!d.supported),configurations:r,decodingInfoResults:h})).catch(h=>({supported:!1,configurations:r,decodingInfoResults:[],error:h}))}function Ko(a){var e;const t=(e=a.videoCodec)==null?void 0:e.split(","),s=Nn(a),i=a.width||640,r=a.height||480,n=a.frameRate||30,o=a.videoRange.toLowerCase();return t?t.map(c=>{const l={contentType:Gt(Bo(c),"video"),width:i,height:r,bitrate:s,framerate:n};return o!=="sdr"&&(l.transferFunction=o),l}):[]}function Vo(a,e,t){var s;const i=(s=a.audioCodec)==null?void 0:s.split(","),r=Nn(a);return i&&a.audioGroups?a.audioGroups.reduce((n,o)=>{var c;const l=o?(c=e.groups[o])==null?void 0:c.tracks:null;return l?l.reduce((h,d)=>{if(d.groupId===o){const u=parseFloat(d.channels||"");i.forEach(f=>{const g={contentType:Gt(f,"audio"),bitrate:t?Ho(f,r):r};u&&(g.channels=""+u),h.push(g)})}return h},n):n},[]):[]}function Ho(a,e){if(e<=1)return 1;let t=128e3;return a==="ec-3"?t=768e3:a==="ac-3"&&(t=64e4),Math.min(e/2,t)}function Nn(a){return Math.ceil(Math.max(a.bitrate*.9,a.averageBitrate)/1e3)*1e3||1}function Yo(a){let e="";const{audio:t,video:s}=a;if(s){const i=ai(s.contentType);e+=`${i}_r${s.height}x${s.width}f${Math.ceil(s.framerate)}${s.transferFunction||"sd"}_${Math.ceil(s.bitrate/1e5)}`}if(t){const i=ai(t.contentType);e+=`${s?"_":""}${i}_c${t.channels}`}return e}const oi=["NONE","TYPE-0","TYPE-1",null];function Wo(a){return oi.indexOf(a)>-1}const Ss=["SDR","PQ","HLG"];function qo(a){return!!a&&Ss.indexOf(a)>-1}var ds={No:"",Yes:"YES",v2:"v2"};function hr(a){const{canSkipUntil:e,canSkipDateRanges:t,age:s}=a,i=s!!s).map(s=>s.substring(0,4)).join(","),"supplemental"in e){var t;this.supplemental=e.supplemental;const s=(t=e.supplemental)==null?void 0:t.videoCodec;s&&s!==e.videoCodec&&(this.codecSet+=`,${s.substring(0,4)}`)}this.addGroupId("audio",e.attrs.AUDIO),this.addGroupId("text",e.attrs.SUBTITLES)}get maxBitrate(){return Math.max(this.realBitrate,this.bitrate)}get averageBitrate(){return this._avgBitrate||this.realBitrate||this.bitrate}get attrs(){return this._attrs[0]}get codecs(){return this.attrs.CODECS||""}get pathwayId(){return this.attrs["PATHWAY-ID"]||"."}get videoRange(){return this.attrs["VIDEO-RANGE"]||"SDR"}get score(){return this.attrs.optionalFloat("SCORE",0)}get uri(){return this.url[0]||""}hasAudioGroup(e){return ur(this._audioGroups,e)}hasSubtitleGroup(e){return ur(this._subtitleGroups,e)}get audioGroups(){return this._audioGroups}get subtitleGroups(){return this._subtitleGroups}addGroupId(e,t){if(t){if(e==="audio"){let s=this._audioGroups;s||(s=this._audioGroups=[]),s.indexOf(t)===-1&&s.push(t)}else if(e==="text"){let s=this._subtitleGroups;s||(s=this._subtitleGroups=[]),s.indexOf(t)===-1&&s.push(t)}}}get urlId(){return 0}set urlId(e){}get audioGroupIds(){return this.audioGroups?[this.audioGroupId]:void 0}get textGroupIds(){return this.subtitleGroups?[this.textGroupId]:void 0}get audioGroupId(){var e;return(e=this.audioGroups)==null?void 0:e[0]}get textGroupId(){var e;return(e=this.subtitleGroups)==null?void 0:e[0]}addFallback(){}}function ur(a,e){return!e||!a?!1:a.indexOf(e)!==-1}function jo(){if(typeof matchMedia=="function"){const a=matchMedia("(dynamic-range: high)"),e=matchMedia("bad query");if(a.media!==e.media)return a.matches===!0}return!1}function Xo(a,e){let t=!1,s=[];if(a&&(t=a!=="SDR",s=[a]),e){s=e.allowedVideoRanges||Ss.slice(0);const i=s.join("")!=="SDR"&&!e.videoCodec;t=e.preferHDR!==void 0?e.preferHDR:i&&jo(),t||(s=["SDR"])}return{preferHDR:t,allowedVideoRanges:s}}const zo=a=>{const e=new WeakSet;return(t,s)=>{if(a&&(s=a(t,s)),typeof s=="object"&&s!==null){if(e.has(s))return;e.add(s)}return s}},oe=(a,e)=>JSON.stringify(a,zo(e));function Qo(a,e,t,s,i){const r=Object.keys(a),n=s==null?void 0:s.channels,o=s==null?void 0:s.audioCodec,c=i==null?void 0:i.videoCodec,l=n&&parseInt(n)===2;let h=!1,d=!1,u=1/0,f=1/0,g=1/0,y=1/0,p=0,E=[];const{preferHDR:T,allowedVideoRanges:S}=Xo(e,i);for(let _=r.length;_--;){const b=a[r[_]];h||(h=b.channels[2]>0),u=Math.min(u,b.minHeight),f=Math.min(f,b.minFramerate),g=Math.min(g,b.minBitrate),S.filter(P=>b.videoRanges[P]>0).length>0&&(d=!0)}u=B(u)?u:0,f=B(f)?f:0;const v=Math.max(1080,u),x=Math.max(30,f);g=B(g)?g:t,t=Math.max(g,t),d||(e=void 0);const D=r.length>1;return{codecSet:r.reduce((_,b)=>{const I=a[b];if(b===_)return _;if(E=d?S.filter(P=>I.videoRanges[P]>0):[],D){if(I.minBitrate>t)return Ue(b,`min bitrate of ${I.minBitrate} > current estimate of ${t}`),_;if(!I.hasDefaultAudio)return Ue(b,"no renditions with default or auto-select sound found"),_;if(o&&b.indexOf(o.substring(0,4))%5!==0)return Ue(b,`audio codec preference "${o}" not found`),_;if(n&&!l){if(!I.channels[n])return Ue(b,`no renditions with ${n} channel sound found (channels options: ${Object.keys(I.channels)})`),_}else if((!o||l)&&h&&I.channels[2]===0)return Ue(b,"no renditions with stereo sound found"),_;if(I.minHeight>v)return Ue(b,`min resolution of ${I.minHeight} > maximum of ${v}`),_;if(I.minFramerate>x)return Ue(b,`min framerate of ${I.minFramerate} > maximum of ${x}`),_;if(!E.some(P=>I.videoRanges[P]>0))return Ue(b,`no variants with VIDEO-RANGE of ${oe(E)} found`),_;if(c&&b.indexOf(c.substring(0,4))%5!==0)return Ue(b,`video codec preference "${c}" not found`),_;if(I.maxScore=Es(_)||I.fragmentError>a[_].fragmentError)?_:(y=I.minIndex,p=I.maxScore,b)},void 0),videoRanges:E,preferHDR:T,minFramerate:f,minBitrate:g,minIndex:y}}function Ue(a,e){re.log(`[abr] start candidates with "${a}" ignored because ${e}`)}function Bn(a){return a.reduce((e,t)=>{let s=e.groups[t.groupId];s||(s=e.groups[t.groupId]={tracks:[],channels:{2:0},hasDefault:!1,hasAutoSelect:!1}),s.tracks.push(t);const i=t.channels||"2";return s.channels[i]=(s.channels[i]||0)+1,s.hasDefault=s.hasDefault||t.default,s.hasAutoSelect=s.hasAutoSelect||t.autoselect,s.hasDefault&&(e.hasDefaultAudio=!0),s.hasAutoSelect&&(e.hasAutoSelectAudio=!0),e},{hasDefaultAudio:!1,hasAutoSelectAudio:!1,groups:{}})}function Zo(a,e,t,s){return a.slice(t,s+1).reduce((i,r,n)=>{if(!r.codecSet)return i;const o=r.audioGroups;let c=i[r.codecSet];c||(i[r.codecSet]=c={minBitrate:1/0,minHeight:1/0,minFramerate:1/0,minIndex:n,maxScore:0,videoRanges:{SDR:0},channels:{2:0},hasDefaultAudio:!o,fragmentError:0}),c.minBitrate=Math.min(c.minBitrate,r.bitrate);const l=Math.min(r.height,r.width);return c.minHeight=Math.min(c.minHeight,l),c.minFramerate=Math.min(c.minFramerate,r.frameRate),c.minIndex=Math.min(c.minIndex,n),c.maxScore=Math.max(c.maxScore,r.score),c.fragmentError+=r.fragmentError,c.videoRanges[r.videoRange]=(c.videoRanges[r.videoRange]||0)+1,o&&o.forEach(h=>{if(!h)return;const d=e.groups[h];d&&(c.hasDefaultAudio=c.hasDefaultAudio||e.hasDefaultAudio?d.hasDefault:d.hasAutoSelect||!e.hasDefaultAudio&&!e.hasAutoSelectAudio,Object.keys(d.channels).forEach(u=>{c.channels[u]=(c.channels[u]||0)+d.channels[u]}))}),i},{})}function fr(a){if(!a)return a;const{lang:e,assocLang:t,characteristics:s,channels:i,audioCodec:r}=a;return{lang:e,assocLang:t,characteristics:s,channels:i,audioCodec:r}}function We(a,e,t){if("attrs"in a){const s=e.indexOf(a);if(s!==-1)return s}for(let s=0;ss.indexOf(i)===-1)}function ft(a,e){const{audioCodec:t,channels:s}=a;return(t===void 0||(e.audioCodec||"").substring(0,4)===t.substring(0,4))&&(s===void 0||s===(e.channels||"2"))}function tl(a,e,t,s,i){const r=e[s],o=e.reduce((u,f,g)=>{const y=f.uri;return(u[y]||(u[y]=[])).push(g),u},{})[r.uri];o.length>1&&(s=Math.max.apply(Math,o));const c=r.videoRange,l=r.frameRate,h=r.codecSet.substring(0,4),d=gr(e,s,u=>{if(u.videoRange!==c||u.frameRate!==l||u.codecSet.substring(0,4)!==h)return!1;const f=u.audioGroups,g=t.filter(y=>!f||f.indexOf(y.groupId)!==-1);return We(a,g,i)>-1});return d>-1?d:gr(e,s,u=>{const f=u.audioGroups,g=t.filter(y=>!f||f.indexOf(y.groupId)!==-1);return We(a,g,i)>-1})}function gr(a,e,t){for(let s=e;s>-1;s--)if(t(a[s]))return s;for(let s=e+1;s{var s;const{fragCurrent:i,partCurrent:r,hls:n}=this,{autoLevelEnabled:o,media:c}=n;if(!i||!c)return;const l=performance.now(),h=r?r.stats:i.stats,d=r?r.duration:i.duration,u=l-h.loading.start,f=n.minAutoLevel,g=i.level,y=this._nextAutoLevel;if(h.aborted||h.loaded&&h.loaded===h.total||g<=f){this.clearTimer(),this._nextAutoLevel=-1;return}if(!o)return;const p=y>-1&&y!==g,E=!!t||p;if(!E&&(c.paused||!c.playbackRate||!c.readyState))return;const T=n.mainForwardBufferInfo;if(!E&&T===null)return;const S=this.bwEstimator.getEstimateTTFB(),v=Math.abs(c.playbackRate);if(u<=Math.max(S,1e3*(d/(v*2))))return;const x=T?T.len/v:0,D=h.loading.first?h.loading.first-h.loading.start:-1,A=h.loaded&&D>-1,_=this.getBwEstimate(),b=n.levels,I=b[g],P=Math.max(h.loaded,Math.round(d*(i.bitrate||I.averageBitrate)/8));let M=A?u-D:u;M<1&&A&&(M=Math.min(u,h.loaded*8/_));const G=A?h.loaded*1e3/M:0,W=S/1e3,K=G?(P-h.loaded)/G:P*8/_+W;if(K<=x)return;const w=G?G*8:_,V=((s=(t==null?void 0:t.details)||this.hls.latestLevelDetails)==null?void 0:s.live)===!0,$=this.hls.config.abrBandWidthUpFactor;let H=Number.POSITIVE_INFINITY,q;for(q=g-1;q>f;q--){const se=b[q].maxBitrate,Q=!b[q].details||V;if(H=this.getTimeToLoadFrag(W,w,d*se,Q),H=K||H>d*10)return;A?this.bwEstimator.sample(u-Math.min(S,D),h.loaded):this.bwEstimator.sampleTTFB(u);const O=b[q].maxBitrate;this.getBwEstimate()*$>O&&this.resetEstimator(O);const F=this.findBestLevel(O,f,q,0,x,1,1);F>-1&&(q=F),this.warn(`Fragment ${i.sn}${r?" part "+r.index:""} of level ${g} is loading too slowly; +async function Rt(a,e,t){const s=await fetch(e,{method:a,credentials:"same-origin",headers:t?{"Content-Type":"application/json"}:{},body:t?JSON.stringify(t):void 0});if(s.status===204)return null;const r=(s.headers.get("content-type")||"").includes("json")?await s.json():await s.text();if(!s.ok)throw Object.assign(new Error((r==null?void 0:r.error)||s.statusText),{status:s.status,data:r});return r}const Ua={get:a=>Rt("GET",a),post:(a,e)=>Rt("POST",a,e),put:(a,e)=>Rt("PUT",a,e),patch:(a,e)=>Rt("PATCH",a,e),del:a=>Rt("DELETE",a)};function Yu(a,e={},...t){const s=document.createElement(a);for(const[i,r]of Object.entries(e||{}))i==="class"?s.className=r:i==="style"&&typeof r=="object"?Object.assign(s.style,r):i.startsWith("on")&&typeof r=="function"?s.addEventListener(i.slice(2).toLowerCase(),r):i==="html"?s.innerHTML=r:r!==!1&&r!=null&&s.setAttribute(i,r===!0?"":r);for(const i of t.flat())i==null||i===!1||s.appendChild(i instanceof Node?i:document.createTextNode(String(i)));return s}function Wu(a){for(;a.firstChild;)a.removeChild(a.firstChild)}const M=Number.isFinite||function(a){return typeof a=="number"&&isFinite(a)},$a=Number.isSafeInteger||function(a){return typeof a=="number"&&Math.abs(a)<=Ga},Ga=Number.MAX_SAFE_INTEGER||9007199254740991;let V=function(a){return a.NETWORK_ERROR="networkError",a.MEDIA_ERROR="mediaError",a.KEY_SYSTEM_ERROR="keySystemError",a.MUX_ERROR="muxError",a.OTHER_ERROR="otherError",a}({}),R=function(a){return a.KEY_SYSTEM_NO_KEYS="keySystemNoKeys",a.KEY_SYSTEM_NO_ACCESS="keySystemNoAccess",a.KEY_SYSTEM_NO_SESSION="keySystemNoSession",a.KEY_SYSTEM_NO_CONFIGURED_LICENSE="keySystemNoConfiguredLicense",a.KEY_SYSTEM_LICENSE_REQUEST_FAILED="keySystemLicenseRequestFailed",a.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED="keySystemServerCertificateRequestFailed",a.KEY_SYSTEM_SERVER_CERTIFICATE_UPDATE_FAILED="keySystemServerCertificateUpdateFailed",a.KEY_SYSTEM_SESSION_UPDATE_FAILED="keySystemSessionUpdateFailed",a.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED="keySystemStatusOutputRestricted",a.KEY_SYSTEM_STATUS_INTERNAL_ERROR="keySystemStatusInternalError",a.KEY_SYSTEM_DESTROY_MEDIA_KEYS_ERROR="keySystemDestroyMediaKeysError",a.KEY_SYSTEM_DESTROY_CLOSE_SESSION_ERROR="keySystemDestroyCloseSessionError",a.KEY_SYSTEM_DESTROY_REMOVE_SESSION_ERROR="keySystemDestroyRemoveSessionError",a.MANIFEST_LOAD_ERROR="manifestLoadError",a.MANIFEST_LOAD_TIMEOUT="manifestLoadTimeOut",a.MANIFEST_PARSING_ERROR="manifestParsingError",a.MANIFEST_INCOMPATIBLE_CODECS_ERROR="manifestIncompatibleCodecsError",a.LEVEL_EMPTY_ERROR="levelEmptyError",a.LEVEL_LOAD_ERROR="levelLoadError",a.LEVEL_LOAD_TIMEOUT="levelLoadTimeOut",a.LEVEL_PARSING_ERROR="levelParsingError",a.LEVEL_SWITCH_ERROR="levelSwitchError",a.AUDIO_TRACK_LOAD_ERROR="audioTrackLoadError",a.AUDIO_TRACK_LOAD_TIMEOUT="audioTrackLoadTimeOut",a.SUBTITLE_LOAD_ERROR="subtitleTrackLoadError",a.SUBTITLE_TRACK_LOAD_TIMEOUT="subtitleTrackLoadTimeOut",a.FRAG_LOAD_ERROR="fragLoadError",a.FRAG_LOAD_TIMEOUT="fragLoadTimeOut",a.FRAG_DECRYPT_ERROR="fragDecryptError",a.FRAG_PARSING_ERROR="fragParsingError",a.FRAG_GAP="fragGap",a.REMUX_ALLOC_ERROR="remuxAllocError",a.KEY_LOAD_ERROR="keyLoadError",a.KEY_LOAD_TIMEOUT="keyLoadTimeOut",a.BUFFER_ADD_CODEC_ERROR="bufferAddCodecError",a.BUFFER_INCOMPATIBLE_CODECS_ERROR="bufferIncompatibleCodecsError",a.BUFFER_APPEND_ERROR="bufferAppendError",a.BUFFER_APPENDING_ERROR="bufferAppendingError",a.BUFFER_STALLED_ERROR="bufferStalledError",a.BUFFER_FULL_ERROR="bufferFullError",a.BUFFER_SEEK_OVER_HOLE="bufferSeekOverHole",a.BUFFER_NUDGE_ON_STALL="bufferNudgeOnStall",a.ASSET_LIST_LOAD_ERROR="assetListLoadError",a.ASSET_LIST_LOAD_TIMEOUT="assetListLoadTimeout",a.ASSET_LIST_PARSING_ERROR="assetListParsingError",a.INTERSTITIAL_ASSET_ITEM_ERROR="interstitialAssetItemError",a.INTERNAL_EXCEPTION="internalException",a.INTERNAL_ABORTED="aborted",a.ATTACH_MEDIA_ERROR="attachMediaError",a.UNKNOWN="unknown",a}({}),m=function(a){return a.MEDIA_ATTACHING="hlsMediaAttaching",a.MEDIA_ATTACHED="hlsMediaAttached",a.MEDIA_DETACHING="hlsMediaDetaching",a.MEDIA_DETACHED="hlsMediaDetached",a.MEDIA_ENDED="hlsMediaEnded",a.STALL_RESOLVED="hlsStallResolved",a.BUFFER_RESET="hlsBufferReset",a.BUFFER_CODECS="hlsBufferCodecs",a.BUFFER_CREATED="hlsBufferCreated",a.BUFFER_APPENDING="hlsBufferAppending",a.BUFFER_APPENDED="hlsBufferAppended",a.BUFFER_EOS="hlsBufferEos",a.BUFFERED_TO_END="hlsBufferedToEnd",a.BUFFER_FLUSHING="hlsBufferFlushing",a.BUFFER_FLUSHED="hlsBufferFlushed",a.MANIFEST_LOADING="hlsManifestLoading",a.MANIFEST_LOADED="hlsManifestLoaded",a.MANIFEST_PARSED="hlsManifestParsed",a.LEVEL_SWITCHING="hlsLevelSwitching",a.LEVEL_SWITCHED="hlsLevelSwitched",a.LEVEL_LOADING="hlsLevelLoading",a.LEVEL_LOADED="hlsLevelLoaded",a.LEVEL_UPDATED="hlsLevelUpdated",a.LEVEL_PTS_UPDATED="hlsLevelPtsUpdated",a.LEVELS_UPDATED="hlsLevelsUpdated",a.AUDIO_TRACKS_UPDATED="hlsAudioTracksUpdated",a.AUDIO_TRACK_SWITCHING="hlsAudioTrackSwitching",a.AUDIO_TRACK_SWITCHED="hlsAudioTrackSwitched",a.AUDIO_TRACK_LOADING="hlsAudioTrackLoading",a.AUDIO_TRACK_LOADED="hlsAudioTrackLoaded",a.AUDIO_TRACK_UPDATED="hlsAudioTrackUpdated",a.SUBTITLE_TRACKS_UPDATED="hlsSubtitleTracksUpdated",a.SUBTITLE_TRACKS_CLEARED="hlsSubtitleTracksCleared",a.SUBTITLE_TRACK_SWITCH="hlsSubtitleTrackSwitch",a.SUBTITLE_TRACK_LOADING="hlsSubtitleTrackLoading",a.SUBTITLE_TRACK_LOADED="hlsSubtitleTrackLoaded",a.SUBTITLE_TRACK_UPDATED="hlsSubtitleTrackUpdated",a.SUBTITLE_FRAG_PROCESSED="hlsSubtitleFragProcessed",a.CUES_PARSED="hlsCuesParsed",a.NON_NATIVE_TEXT_TRACKS_FOUND="hlsNonNativeTextTracksFound",a.INIT_PTS_FOUND="hlsInitPtsFound",a.FRAG_LOADING="hlsFragLoading",a.FRAG_LOAD_EMERGENCY_ABORTED="hlsFragLoadEmergencyAborted",a.FRAG_LOADED="hlsFragLoaded",a.FRAG_DECRYPTED="hlsFragDecrypted",a.FRAG_PARSING_INIT_SEGMENT="hlsFragParsingInitSegment",a.FRAG_PARSING_USERDATA="hlsFragParsingUserdata",a.FRAG_PARSING_METADATA="hlsFragParsingMetadata",a.FRAG_PARSED="hlsFragParsed",a.FRAG_BUFFERED="hlsFragBuffered",a.FRAG_CHANGED="hlsFragChanged",a.FPS_DROP="hlsFpsDrop",a.FPS_DROP_LEVEL_CAPPING="hlsFpsDropLevelCapping",a.MAX_AUTO_LEVEL_UPDATED="hlsMaxAutoLevelUpdated",a.ERROR="hlsError",a.DESTROYING="hlsDestroying",a.KEY_LOADING="hlsKeyLoading",a.KEY_LOADED="hlsKeyLoaded",a.LIVE_BACK_BUFFER_REACHED="hlsLiveBackBufferReached",a.BACK_BUFFER_REACHED="hlsBackBufferReached",a.STEERING_MANIFEST_LOADED="hlsSteeringManifestLoaded",a.ASSET_LIST_LOADING="hlsAssetListLoading",a.ASSET_LIST_LOADED="hlsAssetListLoaded",a.INTERSTITIALS_UPDATED="hlsInterstitialsUpdated",a.INTERSTITIALS_BUFFERED_TO_BOUNDARY="hlsInterstitialsBufferedToBoundary",a.INTERSTITIAL_ASSET_PLAYER_CREATED="hlsInterstitialAssetPlayerCreated",a.INTERSTITIAL_STARTED="hlsInterstitialStarted",a.INTERSTITIAL_ASSET_STARTED="hlsInterstitialAssetStarted",a.INTERSTITIAL_ASSET_ENDED="hlsInterstitialAssetEnded",a.INTERSTITIAL_ASSET_ERROR="hlsInterstitialAssetError",a.INTERSTITIAL_ENDED="hlsInterstitialEnded",a.INTERSTITIALS_PRIMARY_RESUMED="hlsInterstitialsPrimaryResumed",a.PLAYOUT_LIMIT_REACHED="hlsPlayoutLimitReached",a.EVENT_CUE_ENTER="hlsEventCueEnter",a}({});var Q={MANIFEST:"manifest",LEVEL:"level",AUDIO_TRACK:"audioTrack",SUBTITLE_TRACK:"subtitleTrack"},B={MAIN:"main",AUDIO:"audio",SUBTITLE:"subtitle"};class ht{constructor(e,t=0,s=0){this.halfLife=void 0,this.alpha_=void 0,this.estimate_=void 0,this.totalWeight_=void 0,this.halfLife=e,this.alpha_=e?Math.exp(Math.log(.5)/e):0,this.estimate_=t,this.totalWeight_=s}sample(e,t){const s=Math.pow(this.alpha_,e);this.estimate_=t*(1-s)+s*this.estimate_,this.totalWeight_+=e}getTotalWeight(){return this.totalWeight_}getEstimate(){if(this.alpha_){const e=1-Math.pow(this.alpha_,this.totalWeight_);if(e)return this.estimate_/e}return this.estimate_}}class Ka{constructor(e,t,s,i=100){this.defaultEstimate_=void 0,this.minWeight_=void 0,this.minDelayMs_=void 0,this.slow_=void 0,this.fast_=void 0,this.defaultTTFB_=void 0,this.ttfb_=void 0,this.defaultEstimate_=s,this.minWeight_=.001,this.minDelayMs_=50,this.slow_=new ht(e),this.fast_=new ht(t),this.defaultTTFB_=i,this.ttfb_=new ht(e)}update(e,t){const{slow_:s,fast_:i,ttfb_:r}=this;s.halfLife!==e&&(this.slow_=new ht(e,s.getEstimate(),s.getTotalWeight())),i.halfLife!==t&&(this.fast_=new ht(t,i.getEstimate(),i.getTotalWeight())),r.halfLife!==e&&(this.ttfb_=new ht(e,r.getEstimate(),r.getTotalWeight()))}sample(e,t){e=Math.max(e,this.minDelayMs_);const s=8*t,i=e/1e3,r=s/i;this.fast_.sample(i,r),this.slow_.sample(i,r)}sampleTTFB(e){const t=e/1e3,s=Math.sqrt(2)*Math.exp(-Math.pow(t,2)/2);this.ttfb_.sample(s,Math.max(e,5))}canEstimate(){return this.fast_.getTotalWeight()>=this.minWeight_}getEstimate(){return this.canEstimate()?Math.min(this.fast_.getEstimate(),this.slow_.getEstimate()):this.defaultEstimate_}getEstimateTTFB(){return this.ttfb_.getTotalWeight()>=this.minWeight_?this.ttfb_.getEstimate():this.defaultTTFB_}get defaultEstimate(){return this.defaultEstimate_}destroy(){}}function Va(a,e,t){return(e=Ya(e))in a?Object.defineProperty(a,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):a[e]=t,a}function ie(){return ie=Object.assign?Object.assign.bind():function(a){for(var e=1;e`):ze}function Vi(a,e,t){return e[a]?e[a].bind(e):qa(a,t)}const Xs=js();function ja(a,e,t){const s=js();if(typeof console=="object"&&a===!0||typeof a=="object"){const i=["debug","log","info","warn","error"];i.forEach(r=>{s[r]=Vi(r,a,t)});try{s.log(`Debug logs enabled for "${e}" in hls.js version 1.6.16`)}catch{return js()}i.forEach(r=>{Xs[r]=Vi(r,a)})}else ie(Xs,s);return s}const se=Xs;function Je(a=!0){return typeof self>"u"?void 0:(a||!self.MediaSource)&&self.ManagedMediaSource||self.MediaSource||self.WebKitMediaSource}function Xa(a){return typeof self<"u"&&a===self.ManagedMediaSource}function an(a,e){const t=Object.keys(a),s=Object.keys(e),i=t.length,r=s.length;return!i||!r||i===r&&!t.some(n=>s.indexOf(n)===-1)}function Re(a,e=!1){if(typeof TextDecoder<"u"){const l=new TextDecoder("utf-8").decode(a);if(e){const h=l.indexOf("\0");return h!==-1?l.substring(0,h):l}return l.replace(/\0/g,"")}const t=a.length;let s,i,r,n="",o=0;for(;o>4){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:n+=String.fromCharCode(s);break;case 12:case 13:i=a[o++],n+=String.fromCharCode((s&31)<<6|i&63);break;case 14:i=a[o++],r=a[o++],n+=String.fromCharCode((s&15)<<12|(i&63)<<6|(r&63)<<0);break}}return n}function me(a){let e="";for(let t=0;t1||i===1&&(t=this.levelkeys[s[0]])!=null&&t.encrypted)return!0}return!1}get programDateTime(){return this._programDateTime===null&&this.rawProgramDateTime&&(this.programDateTime=Date.parse(this.rawProgramDateTime)),this._programDateTime}set programDateTime(e){if(!M(e)){this._programDateTime=this.rawProgramDateTime=null;return}this._programDateTime=e}get ref(){return ce(this)?(this._ref||(this._ref={base:this.base,start:this.start,duration:this.duration,sn:this.sn,programDateTime:this.programDateTime}),this._ref):null}addStart(e){this.setStart(this.start+e)}setStart(e){this.start=e,this._ref&&(this._ref.start=e)}setDuration(e){this.duration=e,this._ref&&(this._ref.duration=e)}setKeyFormat(e){const t=this.levelkeys;if(t){var s;const i=t[e];i&&!((s=this._decryptdata)!=null&&s.keyId)&&(this._decryptdata=i.getDecryptData(this.sn,t))}}abortRequests(){var e,t;(e=this.loader)==null||e.abort(),(t=this.keyLoader)==null||t.abort()}setElementaryStreamInfo(e,t,s,i,r,n=!1){const{elementaryStreams:o}=this,c=o[e];if(!c){o[e]={startPTS:t,endPTS:s,startDTS:i,endDTS:r,partial:n};return}c.startPTS=Math.min(c.startPTS,t),c.endPTS=Math.max(c.endPTS,s),c.startDTS=Math.min(c.startDTS,i),c.endDTS=Math.max(c.endDTS,r)}}class Za extends ln{constructor(e,t,s,i,r){super(s),this.fragOffset=0,this.duration=0,this.gap=!1,this.independent=!1,this.relurl=void 0,this.fragment=void 0,this.index=void 0,this.duration=e.decimalFloatingPoint("DURATION"),this.gap=e.bool("GAP"),this.independent=e.bool("INDEPENDENT"),this.relurl=e.enumeratedString("URI"),this.fragment=t,this.index=i;const n=e.enumeratedString("BYTERANGE");n&&this.setByteRange(n,r),r&&(this.fragOffset=r.fragOffset+r.duration)}get start(){return this.fragment.start+this.fragOffset}get end(){return this.start+this.duration}get loaded(){const{elementaryStreams:e}=this;return!!(e.audio||e.video||e.audiovideo)}}function cn(a,e){const t=Object.getPrototypeOf(a);if(t){const s=Object.getOwnPropertyDescriptor(t,e);return s||cn(t,e)}}function Ja(a,e){const t=cn(a,e);t&&(t.enumerable=!0,Object.defineProperty(a,e,t))}const Yi=Math.pow(2,32)-1,eo=[].push,hn={video:1,audio:2,id3:3,text:4};function he(a){return String.fromCharCode.apply(null,a)}function un(a,e){const t=a[e]<<8|a[e+1];return t<0?65536+t:t}function W(a,e){const t=dn(a,e);return t<0?4294967296+t:t}function Wi(a,e){let t=W(a,e);return t*=Math.pow(2,32),t+=W(a,e+4),t}function dn(a,e){return a[e]<<24|a[e+1]<<16|a[e+2]<<8|a[e+3]}function to(a){const e=a.byteLength;for(let t=0;t8&&a[t+4]===109&&a[t+5]===111&&a[t+6]===111&&a[t+7]===102)return!0;t=s>1?t+s:e}return!1}function z(a,e){const t=[];if(!e.length)return t;const s=a.byteLength;for(let i=0;i1?i+r:s;if(n===e[0])if(e.length===1)t.push(a.subarray(i+8,o));else{const c=z(a.subarray(i+8,o),e.slice(1));c.length&&eo.apply(t,c)}i=o}return t}function so(a){const e=[],t=a[0];let s=8;const i=W(a,s);s+=4;let r=0,n=0;t===0?(r=W(a,s),n=W(a,s+4),s+=8):(r=Wi(a,s),n=Wi(a,s+8),s+=16),s+=2;let o=a.length+n;const c=un(a,s);s+=2;for(let l=0;l>>31===1)return se.warn("SIDX has hierarchical references (not supported)"),null;const g=W(a,h);h+=4,e.push({referenceSize:d,subsegmentDuration:g,info:{duration:g/i,start:o,end:o+d-1}}),o+=d,h+=4,s=h}return{earliestPresentationTime:r,timescale:i,version:t,referencesCount:c,references:e}}function fn(a){const e=[],t=z(a,["moov","trak"]);for(let i=0;i{const r=W(i,4),n=e[r];n&&(n.default={duration:W(i,12),flags:W(i,20)})}),e}function io(a){const e=a.subarray(8),t=e.subarray(86),s=he(e.subarray(4,8));let i=s,r;const n=s==="enca"||s==="encv";if(n){const l=z(e,[s])[0].subarray(s==="enca"?28:78);z(l,["sinf"]).forEach(u=>{const d=z(u,["schm"])[0];if(d){const f=he(d.subarray(4,8));if(f==="cbcs"||f==="cenc"){const g=z(u,["frma"])[0];g&&(i=he(g))}}})}const o=i;switch(i){case"avc1":case"avc2":case"avc3":case"avc4":{const c=z(t,["avcC"])[0];c&&c.length>3&&(i+="."+Gt(c[1])+Gt(c[2])+Gt(c[3]),r=$t(o==="avc1"?"dva1":"dvav",t));break}case"mp4a":{const c=z(e,[s])[0],l=z(c.subarray(28),["esds"])[0];if(l&&l.length>7){let h=4;if(l[h++]!==3)break;h=Rs(l,h),h+=2;const u=l[h++];if(u&128&&(h+=2),u&64&&(h+=l[h++]),l[h++]!==4)break;h=Rs(l,h);const d=l[h++];if(d===64)i+="."+Gt(d);else break;if(h+=12,l[h++]!==5)break;h=Rs(l,h);const f=l[h++];let g=(f&248)>>3;g===31&&(g+=1+((f&7)<<3)+((l[h]&224)>>5)),i+="."+g}break}case"hvc1":case"hev1":{const c=z(t,["hvcC"])[0];if(c&&c.length>12){const l=c[1],h=["","A","B","C"][l>>6],u=l&31,d=W(c,2),f=(l&32)>>5?"H":"L",g=c[12],y=c.subarray(6,12);i+="."+h+u,i+="."+ro(d).toString(16).toUpperCase(),i+="."+f+g;let p="";for(let E=y.length;E--;){const T=y[E];(T||p)&&(p="."+T.toString(16).toUpperCase()+p)}i+=p}r=$t(o=="hev1"?"dvhe":"dvh1",t);break}case"dvh1":case"dvhe":case"dvav":case"dva1":case"dav1":{i=$t(i,t)||i;break}case"vp09":{const c=z(t,["vpcC"])[0];if(c&&c.length>6){const l=c[4],h=c[5],u=c[6]>>4&15;i+="."+Ne(l)+"."+Ne(h)+"."+Ne(u)}break}case"av01":{const c=z(t,["av1C"])[0];if(c&&c.length>2){const l=c[1]>>>5,h=c[1]&31,u=c[2]>>>7?"H":"M",d=(c[2]&64)>>6,f=(c[2]&32)>>5,g=l===2&&d?f?12:10:d?10:8,y=(c[2]&16)>>4,p=(c[2]&8)>>3,E=(c[2]&4)>>2,T=c[2]&3;i+="."+l+"."+Ne(h)+u+"."+Ne(g)+"."+y+"."+p+E+T+"."+Ne(1)+"."+Ne(1)+"."+Ne(1)+"."+0,r=$t("dav1",t)}break}}return{codec:i,encrypted:n,supplemental:r}}function $t(a,e){const t=z(e,["dvvC"]),s=t.length?t[0]:z(e,["dvcC"])[0];if(s){const i=s[2]>>1&127,r=s[2]<<5&32|s[3]>>3&31;return a+"."+Ne(i)+"."+Ne(r)}}function ro(a){let e=0;for(let t=0;t<32;t++)e|=(a>>t&1)<<31-t;return e>>>0}function Rs(a,e){const t=e+5;for(;a[e++]&128&&e{const r=s.subarray(8,24);r.some(n=>n!==0)||(se.log(`[eme] Patching keyId in 'enc${i?"a":"v"}>sinf>>tenc' box: ${me(r)} -> ${me(t)}`),s.set(t,8))})}function ao(a){const e=[];return gn(a,t=>e.push(t.subarray(8,24))),e}function gn(a,e){z(a,["moov","trak"]).forEach(s=>{const i=z(s,["mdia","minf","stbl","stsd"])[0];if(!i)return;const r=i.subarray(8);let n=z(r,["enca"]);const o=n.length>0;o||(n=z(r,["encv"])),n.forEach(c=>{const l=o?c.subarray(28):c.subarray(78);z(l,["sinf"]).forEach(u=>{const d=mn(u);d&&e(d,o)})})})}function mn(a){const e=z(a,["schm"])[0];if(e){const t=he(e.subarray(4,8));if(t==="cbcs"||t==="cenc"){const s=z(a,["schi","tenc"])[0];if(s)return s}}}function oo(a,e,t){const s={},i=z(a,["moof","traf"]);for(let r=0;rs[r].duration)){let r=1/0,n=0;const o=z(a,["sidx"]);for(let c=0;cu+d.info.duration||0,0);n=Math.max(n,h+l.earliestPresentationTime/l.timescale)}}n&&M(n)&&Object.keys(s).forEach(c=>{s[c].duration||(s[c].duration=n*s[c].timescale-s[c].start)})}return s}function lo(a){const e={valid:null,remainder:null},t=z(a,["moof"]);if(t.length<2)return e.remainder=a,e;const s=t[t.length-1];return e.valid=a.slice(0,s.byteOffset-8),e.remainder=a.slice(s.byteOffset-8),e}function De(a,e){const t=new Uint8Array(a.length+e.length);return t.set(a),t.set(e,a.length),t}function qi(a,e){const t=[],s=e.samples,i=e.timescale,r=e.id;let n=!1;return z(s,["moof"]).map(c=>{const l=c.byteOffset-8;z(c,["traf"]).map(u=>{const d=z(u,["tfdt"]).map(f=>{const g=f[0];let y=W(f,4);return g===1&&(y*=Math.pow(2,32),y+=W(f,8)),y/i})[0];return d!==void 0&&(a=d),z(u,["tfhd"]).map(f=>{const g=W(f,4),y=W(f,0)&16777215,p=(y&1)!==0,E=(y&2)!==0,T=(y&8)!==0;let S=0;const v=(y&16)!==0;let x=0;const D=(y&32)!==0;let A=8;g===r&&(p&&(A+=8),E&&(A+=4),T&&(S=W(f,A),A+=4),v&&(x=W(f,A),A+=4),D&&(A+=4),e.type==="video"&&(n=Ts(e.codec)),z(u,["trun"]).map(_=>{const b=_[0],I=W(_,0)&16777215,P=(I&1)!==0;let F=0;const U=(I&4)!==0,H=(I&256)!==0;let $=0;const k=(I&512)!==0;let G=0;const N=(I&1024)!==0,K=(I&2048)!==0;let Y=0;const w=W(_,4);let O=8;P&&(F=W(_,O),O+=4),U&&(O+=4);let j=F+l;for(let ee=0;ee>1&63;return t===39||t===40}else return(e&31)===6}function mi(a,e,t,s){const i=pn(a);let r=0;r+=e;let n=0,o=0,c=0;for(;r=i.length)break;c=i[r++],n+=c}while(c===255);o=0;do{if(r>=i.length)break;c=i[r++],o+=c}while(c===255);const l=i.length-r;let h=r;if(ol){se.error(`Malformed SEI payload. ${o} is too small, only ${l} bytes left to parse.`);break}if(n===4){if(i[h++]===181){const d=un(i,h);if(h+=2,d===49){const f=W(i,h);if(h+=4,f===1195456820){const g=i[h++];if(g===3){const y=i[h++],p=31&y,E=64&y,T=E?2+p*3:0,S=new Uint8Array(T);if(E){S[0]=y;for(let v=1;v16){const u=[];for(let g=0;g<16;g++){const y=i[h++].toString(16);u.push(y.length==1?"0"+y:y),(g===3||g===5||g===7||g===9)&&u.push("-")}const d=o-16,f=new Uint8Array(d);for(let g=0;g>24&255,r[1]=s>>16&255,r[2]=s>>8&255,r[3]=s&255,r.set(a,4),i=0,s=8;i0?(r=new Uint8Array(4),e.length>0&&new DataView(r.buffer).setUint32(0,e.length,!1)):r=new Uint8Array;const n=new Uint8Array(4);return t.byteLength>0&&new DataView(n.buffer).setUint32(0,t.byteLength,!1),uo([112,115,115,104],new Uint8Array([s,0,0,0]),a,r,i,n,t)}function go(a){const e=[];if(a instanceof ArrayBuffer){const t=a.byteLength;let s=0;for(;s+32>>24;if(r!==0&&r!==1)return{offset:t,size:e};const n=a.buffer,o=me(new Uint8Array(n,t+12,16));let c=null,l=null,h=0;if(r===0)h=28;else{const d=a.getUint32(28);if(!d||s<32+d*16)return{offset:t,size:e};c=[];for(let f=0;f/\(Windows.+Firefox\//i.test(navigator.userAgent),xt={audio:{a3ds:1,"ac-3":.95,"ac-4":1,alac:.9,alaw:1,dra1:1,"dts+":1,"dts-":1,dtsc:1,dtse:1,dtsh:1,"ec-3":.9,enca:1,fLaC:.9,flac:.9,FLAC:.9,g719:1,g726:1,m4ae:1,mha1:1,mha2:1,mhm1:1,mhm2:1,mlpa:1,mp4a:1,"raw ":1,Opus:1,opus:1,samr:1,sawb:1,sawp:1,sevc:1,sqcp:1,ssmv:1,twos:1,ulaw:1},video:{avc1:1,avc2:1,avc3:1,avc4:1,avcp:1,av01:.8,dav1:.8,drac:1,dva1:1,dvav:1,dvh1:.7,dvhe:.7,encv:1,hev1:.75,hvc1:.75,mjp2:1,mp4v:1,mvc1:1,mvc2:1,mvc3:1,mvc4:1,resv:1,rv60:1,s263:1,svc1:1,svc2:1,"vc-1":1,vp08:1,vp09:.9},text:{stpp:1,wvtt:1}};function pi(a,e){const t=xt[e];return!!t&&!!t[a.slice(0,4)]}function kt(a,e,t=!0){return!a.split(",").some(s=>!yi(s,e,t))}function yi(a,e,t=!0){var s;const i=Je(t);return(s=i==null?void 0:i.isTypeSupported(wt(a,e)))!=null?s:!1}function wt(a,e){return`${e}/mp4;codecs=${a}`}function ji(a){if(a){const e=a.substring(0,4);return xt.video[e]}return 2}function ls(a){const e=yn();return a.split(",").reduce((t,s)=>{const r=e&&Ts(s)?9:xt.video[s];return r?(r*2+t)/(t?3:2):(xt.audio[s]+t)/(t?2:1)},0)}const bs={};function po(a,e=!0){if(bs[a])return bs[a];const t={flac:["flac","fLaC","FLAC"],opus:["opus","Opus"],"mp4a.40.34":["mp3"]}[a];for(let i=0;ipo(t.toLowerCase(),e))}function Eo(a,e){const t=[];if(a){const s=a.split(",");for(let i=0;i4||["ac-3","ec-3","alac","fLaC","Opus"].indexOf(a)!==-1)&&(Xi(a,"audio")||Xi(a,"video")))return a;if(e){const t=e.split(",");if(t.length>1){if(a){for(let s=t.length;s--;)if(t[s].substring(0,4)===a.substring(0,4))return t[s]}return t[0]}}return e||a}function Xi(a,e){return pi(a,e)&&yi(a,e)}function To(a){const e=a.split(",");for(let t=0;t2&&s[0]==="avc1"&&(e[t]=`avc1.${parseInt(s[1]).toString(16)}${("000"+parseInt(s[2]).toString(16)).slice(-4)}`)}return e.join(",")}function So(a){if(a.startsWith("av01.")){const e=a.split("."),t=["0","111","01","01","01","0"];for(let s=e.length;s>4&&s<10;s++)e[s]=t[s-4];return e.join(".")}return a}function zi(a){const e=Je(a)||{isTypeSupported:()=>!1};return{mpeg:e.isTypeSupported("audio/mpeg"),mp3:e.isTypeSupported('audio/mp4; codecs="mp3"'),ac3:e.isTypeSupported('audio/mp4; codecs="ac-3"')}}function zs(a){return a.replace(/^.+codecs=["']?([^"']+).*$/,"$1")}const vo={supported:!0,powerEfficient:!0,smooth:!0},xo={supported:!1,smooth:!1,powerEfficient:!1},En={supported:!0,configurations:[],decodingInfoResults:[vo]};function Tn(a,e){return{supported:!1,configurations:e,decodingInfoResults:[xo],error:a}}function Ao(a,e,t,s,i,r){const n=a.videoCodec,o=a.audioCodec?a.audioGroups:null,c=r==null?void 0:r.audioCodec,l=r==null?void 0:r.channels,h=l?parseInt(l):c?1/0:2;let u=null;if(o!=null&&o.length)try{o.length===1&&o[0]?u=e.groups[o[0]].channels:u=o.reduce((d,f)=>{if(f){const g=e.groups[f];if(!g)throw new Error(`Audio track group ${f} not found`);Object.keys(g.channels).forEach(y=>{d[y]=(d[y]||0)+g.channels[y]})}return d},{2:0})}catch{return!0}return n!==void 0&&(n.split(",").some(d=>Ts(d))||a.width>1920&&a.height>1088||a.height>1920&&a.width>1088||a.frameRate>Math.max(s,30)||a.videoRange!=="SDR"&&a.videoRange!==t||a.bitrate>Math.max(i,8e6))||!!u&&M(h)&&Object.keys(u).some(d=>parseInt(d)>h)}function Sn(a,e,t,s={}){const i=a.videoCodec;if(!i&&!a.audioCodec||!t)return Promise.resolve(En);const r=[],n=Io(a),o=n.length,c=Lo(a,e,o>0),l=c.length;for(let h=o||1*l||1;h--;){const u={type:"media-source"};if(o&&(u.video=n[h%o]),l){u.audio=c[h%l];const d=u.audio.bitrate;u.video&&d&&(u.video.bitrate-=d)}r.push(u)}if(i){const h=navigator.userAgent;if(i.split(",").some(u=>Ts(u))&&yn())return Promise.resolve(Tn(new Error(`Overriding Windows Firefox HEVC MediaCapabilities result based on user-agent string: (${h})`),r))}return Promise.all(r.map(h=>{const u=bo(h);return s[u]||(s[u]=t.decodingInfo(h))})).then(h=>({supported:!h.some(u=>!u.supported),configurations:r,decodingInfoResults:h})).catch(h=>({supported:!1,configurations:r,decodingInfoResults:[],error:h}))}function Io(a){var e;const t=(e=a.videoCodec)==null?void 0:e.split(","),s=vn(a),i=a.width||640,r=a.height||480,n=a.frameRate||30,o=a.videoRange.toLowerCase();return t?t.map(c=>{const l={contentType:wt(So(c),"video"),width:i,height:r,bitrate:s,framerate:n};return o!=="sdr"&&(l.transferFunction=o),l}):[]}function Lo(a,e,t){var s;const i=(s=a.audioCodec)==null?void 0:s.split(","),r=vn(a);return i&&a.audioGroups?a.audioGroups.reduce((n,o)=>{var c;const l=o?(c=e.groups[o])==null?void 0:c.tracks:null;return l?l.reduce((h,u)=>{if(u.groupId===o){const d=parseFloat(u.channels||"");i.forEach(f=>{const g={contentType:wt(f,"audio"),bitrate:t?Ro(f,r):r};d&&(g.channels=""+d),h.push(g)})}return h},n):n},[]):[]}function Ro(a,e){if(e<=1)return 1;let t=128e3;return a==="ec-3"?t=768e3:a==="ac-3"&&(t=64e4),Math.min(e/2,t)}function vn(a){return Math.ceil(Math.max(a.bitrate*.9,a.averageBitrate)/1e3)*1e3||1}function bo(a){let e="";const{audio:t,video:s}=a;if(s){const i=zs(s.contentType);e+=`${i}_r${s.height}x${s.width}f${Math.ceil(s.framerate)}${s.transferFunction||"sd"}_${Math.ceil(s.bitrate/1e5)}`}if(t){const i=zs(t.contentType);e+=`${s?"_":""}${i}_c${t.channels}`}return e}const Qs=["NONE","TYPE-0","TYPE-1",null];function _o(a){return Qs.indexOf(a)>-1}const hs=["SDR","PQ","HLG"];function Do(a){return!!a&&hs.indexOf(a)>-1}var ts={No:"",Yes:"YES",v2:"v2"};function Qi(a){const{canSkipUntil:e,canSkipDateRanges:t,age:s}=a,i=s!!s).map(s=>s.substring(0,4)).join(","),"supplemental"in e){var t;this.supplemental=e.supplemental;const s=(t=e.supplemental)==null?void 0:t.videoCodec;s&&s!==e.videoCodec&&(this.codecSet+=`,${s.substring(0,4)}`)}this.addGroupId("audio",e.attrs.AUDIO),this.addGroupId("text",e.attrs.SUBTITLES)}get maxBitrate(){return Math.max(this.realBitrate,this.bitrate)}get averageBitrate(){return this._avgBitrate||this.realBitrate||this.bitrate}get attrs(){return this._attrs[0]}get codecs(){return this.attrs.CODECS||""}get pathwayId(){return this.attrs["PATHWAY-ID"]||"."}get videoRange(){return this.attrs["VIDEO-RANGE"]||"SDR"}get score(){return this.attrs.optionalFloat("SCORE",0)}get uri(){return this.url[0]||""}hasAudioGroup(e){return Ji(this._audioGroups,e)}hasSubtitleGroup(e){return Ji(this._subtitleGroups,e)}get audioGroups(){return this._audioGroups}get subtitleGroups(){return this._subtitleGroups}addGroupId(e,t){if(t){if(e==="audio"){let s=this._audioGroups;s||(s=this._audioGroups=[]),s.indexOf(t)===-1&&s.push(t)}else if(e==="text"){let s=this._subtitleGroups;s||(s=this._subtitleGroups=[]),s.indexOf(t)===-1&&s.push(t)}}}get urlId(){return 0}set urlId(e){}get audioGroupIds(){return this.audioGroups?[this.audioGroupId]:void 0}get textGroupIds(){return this.subtitleGroups?[this.textGroupId]:void 0}get audioGroupId(){var e;return(e=this.audioGroups)==null?void 0:e[0]}get textGroupId(){var e;return(e=this.subtitleGroups)==null?void 0:e[0]}addFallback(){}}function Ji(a,e){return!e||!a?!1:a.indexOf(e)!==-1}function Co(){if(typeof matchMedia=="function"){const a=matchMedia("(dynamic-range: high)"),e=matchMedia("bad query");if(a.media!==e.media)return a.matches===!0}return!1}function Po(a,e){let t=!1,s=[];if(a&&(t=a!=="SDR",s=[a]),e){s=e.allowedVideoRanges||hs.slice(0);const i=s.join("")!=="SDR"&&!e.videoCodec;t=e.preferHDR!==void 0?e.preferHDR:i&&Co(),t||(s=["SDR"])}return{preferHDR:t,allowedVideoRanges:s}}const ko=a=>{const e=new WeakSet;return(t,s)=>{if(a&&(s=a(t,s)),typeof s=="object"&&s!==null){if(e.has(s))return;e.add(s)}return s}},ne=(a,e)=>JSON.stringify(a,ko(e));function wo(a,e,t,s,i){const r=Object.keys(a),n=s==null?void 0:s.channels,o=s==null?void 0:s.audioCodec,c=i==null?void 0:i.videoCodec,l=n&&parseInt(n)===2;let h=!1,u=!1,d=1/0,f=1/0,g=1/0,y=1/0,p=0,E=[];const{preferHDR:T,allowedVideoRanges:S}=Po(e,i);for(let _=r.length;_--;){const b=a[r[_]];h||(h=b.channels[2]>0),d=Math.min(d,b.minHeight),f=Math.min(f,b.minFramerate),g=Math.min(g,b.minBitrate),S.filter(P=>b.videoRanges[P]>0).length>0&&(u=!0)}d=M(d)?d:0,f=M(f)?f:0;const v=Math.max(1080,d),x=Math.max(30,f);g=M(g)?g:t,t=Math.max(g,t),u||(e=void 0);const D=r.length>1;return{codecSet:r.reduce((_,b)=>{const I=a[b];if(b===_)return _;if(E=u?S.filter(P=>I.videoRanges[P]>0):[],D){if(I.minBitrate>t)return Fe(b,`min bitrate of ${I.minBitrate} > current estimate of ${t}`),_;if(!I.hasDefaultAudio)return Fe(b,"no renditions with default or auto-select sound found"),_;if(o&&b.indexOf(o.substring(0,4))%5!==0)return Fe(b,`audio codec preference "${o}" not found`),_;if(n&&!l){if(!I.channels[n])return Fe(b,`no renditions with ${n} channel sound found (channels options: ${Object.keys(I.channels)})`),_}else if((!o||l)&&h&&I.channels[2]===0)return Fe(b,"no renditions with stereo sound found"),_;if(I.minHeight>v)return Fe(b,`min resolution of ${I.minHeight} > maximum of ${v}`),_;if(I.minFramerate>x)return Fe(b,`min framerate of ${I.minFramerate} > maximum of ${x}`),_;if(!E.some(P=>I.videoRanges[P]>0))return Fe(b,`no variants with VIDEO-RANGE of ${ne(E)} found`),_;if(c&&b.indexOf(c.substring(0,4))%5!==0)return Fe(b,`video codec preference "${c}" not found`),_;if(I.maxScore=ls(_)||I.fragmentError>a[_].fragmentError)?_:(y=I.minIndex,p=I.maxScore,b)},void 0),videoRanges:E,preferHDR:T,minFramerate:f,minBitrate:g,minIndex:y}}function Fe(a,e){se.log(`[abr] start candidates with "${a}" ignored because ${e}`)}function xn(a){return a.reduce((e,t)=>{let s=e.groups[t.groupId];s||(s=e.groups[t.groupId]={tracks:[],channels:{2:0},hasDefault:!1,hasAutoSelect:!1}),s.tracks.push(t);const i=t.channels||"2";return s.channels[i]=(s.channels[i]||0)+1,s.hasDefault=s.hasDefault||t.default,s.hasAutoSelect=s.hasAutoSelect||t.autoselect,s.hasDefault&&(e.hasDefaultAudio=!0),s.hasAutoSelect&&(e.hasAutoSelectAudio=!0),e},{hasDefaultAudio:!1,hasAutoSelectAudio:!1,groups:{}})}function Oo(a,e,t,s){return a.slice(t,s+1).reduce((i,r,n)=>{if(!r.codecSet)return i;const o=r.audioGroups;let c=i[r.codecSet];c||(i[r.codecSet]=c={minBitrate:1/0,minHeight:1/0,minFramerate:1/0,minIndex:n,maxScore:0,videoRanges:{SDR:0},channels:{2:0},hasDefaultAudio:!o,fragmentError:0}),c.minBitrate=Math.min(c.minBitrate,r.bitrate);const l=Math.min(r.height,r.width);return c.minHeight=Math.min(c.minHeight,l),c.minFramerate=Math.min(c.minFramerate,r.frameRate),c.minIndex=Math.min(c.minIndex,n),c.maxScore=Math.max(c.maxScore,r.score),c.fragmentError+=r.fragmentError,c.videoRanges[r.videoRange]=(c.videoRanges[r.videoRange]||0)+1,o&&o.forEach(h=>{if(!h)return;const u=e.groups[h];u&&(c.hasDefaultAudio=c.hasDefaultAudio||e.hasDefaultAudio?u.hasDefault:u.hasAutoSelect||!e.hasDefaultAudio&&!e.hasAutoSelectAudio,Object.keys(u.channels).forEach(d=>{c.channels[d]=(c.channels[d]||0)+u.channels[d]}))}),i},{})}function er(a){if(!a)return a;const{lang:e,assocLang:t,characteristics:s,channels:i,audioCodec:r}=a;return{lang:e,assocLang:t,characteristics:s,channels:i,audioCodec:r}}function $e(a,e,t){if("attrs"in a){const s=e.indexOf(a);if(s!==-1)return s}for(let s=0;ss.indexOf(i)===-1)}function at(a,e){const{audioCodec:t,channels:s}=a;return(t===void 0||(e.audioCodec||"").substring(0,4)===t.substring(0,4))&&(s===void 0||s===(e.channels||"2"))}function No(a,e,t,s,i){const r=e[s],o=e.reduce((d,f,g)=>{const y=f.uri;return(d[y]||(d[y]=[])).push(g),d},{})[r.uri];o.length>1&&(s=Math.max.apply(Math,o));const c=r.videoRange,l=r.frameRate,h=r.codecSet.substring(0,4),u=tr(e,s,d=>{if(d.videoRange!==c||d.frameRate!==l||d.codecSet.substring(0,4)!==h)return!1;const f=d.audioGroups,g=t.filter(y=>!f||f.indexOf(y.groupId)!==-1);return $e(a,g,i)>-1});return u>-1?u:tr(e,s,d=>{const f=d.audioGroups,g=t.filter(y=>!f||f.indexOf(y.groupId)!==-1);return $e(a,g,i)>-1})}function tr(a,e,t){for(let s=e;s>-1;s--)if(t(a[s]))return s;for(let s=e+1;s{var s;const{fragCurrent:i,partCurrent:r,hls:n}=this,{autoLevelEnabled:o,media:c}=n;if(!i||!c)return;const l=performance.now(),h=r?r.stats:i.stats,u=r?r.duration:i.duration,d=l-h.loading.start,f=n.minAutoLevel,g=i.level,y=this._nextAutoLevel;if(h.aborted||h.loaded&&h.loaded===h.total||g<=f){this.clearTimer(),this._nextAutoLevel=-1;return}if(!o)return;const p=y>-1&&y!==g,E=!!t||p;if(!E&&(c.paused||!c.playbackRate||!c.readyState))return;const T=n.mainForwardBufferInfo;if(!E&&T===null)return;const S=this.bwEstimator.getEstimateTTFB(),v=Math.abs(c.playbackRate);if(d<=Math.max(S,1e3*(u/(v*2))))return;const x=T?T.len/v:0,D=h.loading.first?h.loading.first-h.loading.start:-1,A=h.loaded&&D>-1,_=this.getBwEstimate(),b=n.levels,I=b[g],P=Math.max(h.loaded,Math.round(u*(i.bitrate||I.averageBitrate)/8));let F=A?d-D:d;F<1&&A&&(F=Math.min(d,h.loaded*8/_));const U=A?h.loaded*1e3/F:0,H=S/1e3,$=U?(P-h.loaded)/U:P*8/_+H;if($<=x)return;const k=U?U*8:_,G=((s=(t==null?void 0:t.details)||this.hls.latestLevelDetails)==null?void 0:s.live)===!0,N=this.hls.config.abrBandWidthUpFactor;let K=Number.POSITIVE_INFINITY,Y;for(Y=g-1;Y>f;Y--){const ee=b[Y].maxBitrate,X=!b[Y].details||G;if(K=this.getTimeToLoadFrag(H,k,u*ee,X),K=$||K>u*10)return;A?this.bwEstimator.sample(d-Math.min(S,D),h.loaded):this.bwEstimator.sampleTTFB(d);const w=b[Y].maxBitrate;this.getBwEstimate()*N>w&&this.resetEstimator(w);const O=this.findBestLevel(w,f,Y,0,x,1,1);O>-1&&(Y=O),this.warn(`Fragment ${i.sn}${r?" part "+r.index:""} of level ${g} is loading too slowly; Fragment duration: ${i.duration.toFixed(3)} Time to underbuffer: ${x.toFixed(3)} s - Estimated load time for current fragment: ${K.toFixed(3)} s - Estimated load time for down switch fragment: ${H.toFixed(3)} s + Estimated load time for current fragment: ${$.toFixed(3)} s + Estimated load time for down switch fragment: ${K.toFixed(3)} s TTFB estimate: ${D|0} ms - Current BW estimate: ${B(_)?_|0:"Unknown"} bps + Current BW estimate: ${M(_)?_|0:"Unknown"} bps New BW estimate: ${this.getBwEstimate()|0} bps - Switching to level ${q} @ ${O|0} bps`),n.nextLoadLevel=n.nextAutoLevel=q,this.clearTimer();const z=()=>{if(this.clearTimer(),this.fragCurrent===i&&this.hls.loadLevel===q&&q>0){const se=this.getStarvationDelay();if(this.warn(`Aborting inflight request ${q>0?"and switching down":""} + Switching to level ${Y} @ ${w|0} bps`),n.nextLoadLevel=n.nextAutoLevel=Y,this.clearTimer();const j=()=>{if(this.clearTimer(),this.fragCurrent===i&&this.hls.loadLevel===Y&&Y>0){const ee=this.getStarvationDelay();if(this.warn(`Aborting inflight request ${Y>0?"and switching down":""} Fragment duration: ${i.duration.toFixed(3)} s - Time to underbuffer: ${se.toFixed(3)} s`),i.abortRequests(),this.fragCurrent=this.partCurrent=null,q>f){let Q=this.findBestLevel(this.hls.levels[f].bitrate,f,q,0,se,1,1);Q===-1&&(Q=f),this.hls.nextLoadLevel=this.hls.nextAutoLevel=Q,this.resetEstimator(this.hls.levels[Q].bitrate)}}};p||K>H*2?z():this.timer=self.setInterval(z,H*1e3),n.trigger(m.FRAG_LOAD_EMERGENCY_ABORTED,{frag:i,part:r,stats:h})},this.hls=e,this.bwEstimator=this.initEstimator(),this.registerListeners()}resetEstimator(e){e&&(this.log(`setting initial bwe to ${e}`),this.hls.config.abrEwmaDefaultEstimate=e),this.firstSelection=-1,this.bwEstimator=this.initEstimator()}initEstimator(){const e=this.hls.config;return new ao(e.abrEwmaSlowVoD,e.abrEwmaFastVoD,e.abrEwmaDefaultEstimate)}registerListeners(){const{hls:e}=this;e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.FRAG_LOADING,this.onFragLoading,this),e.on(m.FRAG_LOADED,this.onFragLoaded,this),e.on(m.FRAG_BUFFERED,this.onFragBuffered,this),e.on(m.LEVEL_SWITCHING,this.onLevelSwitching,this),e.on(m.LEVEL_LOADED,this.onLevelLoaded,this),e.on(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.on(m.MAX_AUTO_LEVEL_UPDATED,this.onMaxAutoLevelUpdated,this),e.on(m.ERROR,this.onError,this)}unregisterListeners(){const{hls:e}=this;e&&(e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.FRAG_LOADING,this.onFragLoading,this),e.off(m.FRAG_LOADED,this.onFragLoaded,this),e.off(m.FRAG_BUFFERED,this.onFragBuffered,this),e.off(m.LEVEL_SWITCHING,this.onLevelSwitching,this),e.off(m.LEVEL_LOADED,this.onLevelLoaded,this),e.off(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.off(m.MAX_AUTO_LEVEL_UPDATED,this.onMaxAutoLevelUpdated,this),e.off(m.ERROR,this.onError,this))}destroy(){this.unregisterListeners(),this.clearTimer(),this.hls=this._abandonRulesCheck=this.supportedCache=null,this.fragCurrent=this.partCurrent=null}onManifestLoading(e,t){this.lastLoadedFragLevel=-1,this.firstSelection=-1,this.lastLevelLoadSec=0,this.supportedCache={},this.fragCurrent=this.partCurrent=null,this.onLevelsUpdated(),this.clearTimer()}onLevelsUpdated(){this.lastLoadedFragLevel>-1&&this.fragCurrent&&(this.lastLoadedFragLevel=this.fragCurrent.level),this._nextAutoLevel=-1,this.onMaxAutoLevelUpdated(),this.codecTiers=null,this.audioTracksByGroup=null}onMaxAutoLevelUpdated(){this.firstSelection=-1,this.nextAutoLevelKey=""}onFragLoading(e,t){const s=t.frag;if(!this.ignoreFragment(s)){if(!s.bitrateTest){var i;this.fragCurrent=s,this.partCurrent=(i=t.part)!=null?i:null}this.clearTimer(),this.timer=self.setInterval(this._abandonRulesCheck,100)}}onLevelSwitching(e,t){this.clearTimer()}onError(e,t){if(!t.fatal)switch(t.details){case R.BUFFER_ADD_CODEC_ERROR:case R.BUFFER_APPEND_ERROR:this.lastLoadedFragLevel=-1,this.firstSelection=-1;break;case R.FRAG_LOAD_TIMEOUT:{const s=t.frag,{fragCurrent:i,partCurrent:r}=this;if(s&&i&&s.sn===i.sn&&s.level===i.level){const n=performance.now(),o=r?r.stats:s.stats,c=n-o.loading.start,l=o.loading.first?o.loading.first-o.loading.start:-1;if(o.loaded&&l>-1){const d=this.bwEstimator.getEstimateTTFB();this.bwEstimator.sample(c-Math.min(d,l),o.loaded)}else this.bwEstimator.sampleTTFB(c)}break}}}getTimeToLoadFrag(e,t,s,i){const r=e+s/t,n=i?e+this.lastLevelLoadSec:0;return r+n}onLevelLoaded(e,t){const s=this.hls.config,{loading:i}=t.stats,r=i.end-i.first;B(r)&&(this.lastLevelLoadSec=r/1e3),t.details.live?this.bwEstimator.update(s.abrEwmaSlowLive,s.abrEwmaFastLive):this.bwEstimator.update(s.abrEwmaSlowVoD,s.abrEwmaFastVoD),this.timer>-1&&this._abandonRulesCheck(t.levelInfo)}onFragLoaded(e,{frag:t,part:s}){const i=s?s.stats:t.stats;if(t.type===U.MAIN&&this.bwEstimator.sampleTTFB(i.loading.first-i.loading.start),!this.ignoreFragment(t)){if(this.clearTimer(),t.level===this._nextAutoLevel&&(this._nextAutoLevel=-1),this.firstSelection=-1,this.hls.config.abrMaxWithRealBitrate){const r=s?s.duration:t.duration,n=this.hls.levels[t.level],o=(n.loaded?n.loaded.bytes:0)+i.loaded,c=(n.loaded?n.loaded.duration:0)+r;n.loaded={bytes:o,duration:c},n.realBitrate=Math.round(8*o/c)}if(t.bitrateTest){const r={stats:i,frag:t,part:s,id:t.type};this.onFragBuffered(m.FRAG_BUFFERED,r),t.bitrateTest=!1}else this.lastLoadedFragLevel=t.level}}onFragBuffered(e,t){const{frag:s,part:i}=t,r=i!=null&&i.stats.loaded?i.stats:s.stats;if(r.aborted||this.ignoreFragment(s))return;const n=r.parsing.end-r.loading.start-Math.min(r.loading.first-r.loading.start,this.bwEstimator.getEstimateTTFB());this.bwEstimator.sample(n,r.loaded),r.bwEstimate=this.getBwEstimate(),s.bitrateTest?this.bitrateTestDelay=n/1e3:this.bitrateTestDelay=0}ignoreFragment(e){return e.type!==U.MAIN||e.sn==="initSegment"}clearTimer(){this.timer>-1&&(self.clearInterval(this.timer),this.timer=-1)}get firstAutoLevel(){const{maxAutoLevel:e,minAutoLevel:t}=this.hls,s=this.getBwEstimate(),i=this.hls.config.maxStarvationDelay,r=this.findBestLevel(s,t,e,0,i,1,1);if(r>-1)return r;const n=this.hls.firstLevel,o=Math.min(Math.max(n,t),e);return this.warn(`Could not find best starting auto level. Defaulting to first in playlist ${n} clamped to ${o}`),o}get forcedAutoLevel(){return this.nextAutoLevelKey?-1:this._nextAutoLevel}get nextAutoLevel(){const e=this.forcedAutoLevel,s=this.bwEstimator.canEstimate(),i=this.lastLoadedFragLevel>-1;if(e!==-1&&(!s||!i||this.nextAutoLevelKey===this.getAutoLevelKey()))return e;const r=s&&i?this.getNextABRAutoLevel():this.firstAutoLevel;if(e!==-1){const n=this.hls.levels;if(n.length>Math.max(e,r)&&n[e].loadError<=n[r].loadError)return e}return this._nextAutoLevel=r,this.nextAutoLevelKey=this.getAutoLevelKey(),r}getAutoLevelKey(){return`${this.getBwEstimate()}_${this.getStarvationDelay().toFixed(2)}`}getNextABRAutoLevel(){const{fragCurrent:e,partCurrent:t,hls:s}=this;if(s.levels.length<=1)return s.loadLevel;const{maxAutoLevel:i,config:r,minAutoLevel:n}=s,o=t?t.duration:e?e.duration:0,c=this.getBwEstimate(),l=this.getStarvationDelay();let h=r.abrBandWidthFactor,d=r.abrBandWidthUpFactor;if(l){const p=this.findBestLevel(c,n,i,l,0,h,d);if(p>=0)return this.rebufferNotice=-1,p}let u=o?Math.min(o,r.maxStarvationDelay):r.maxStarvationDelay;if(!l){const p=this.bitrateTestDelay;p&&(u=(o?Math.min(o,r.maxLoadingDelay):r.maxLoadingDelay)-p,this.info(`bitrate test took ${Math.round(1e3*p)}ms, set first fragment max fetchDuration to ${Math.round(1e3*u)} ms`),h=d=1)}const f=this.findBestLevel(c,n,i,l,u,h,d);if(this.rebufferNotice!==f&&(this.rebufferNotice=f,this.info(`${l?"rebuffering expected":"buffer is empty"}, optimal quality level ${f}`)),f>-1)return f;const g=s.levels[n],y=s.loadLevelObj;return y&&(g==null?void 0:g.bitrate)=t;w--){var K;const V=g[w],$=w>d;if(!V)continue;if(E.useMediaCapabilities&&!V.supportedResult&&!V.supportedPromise){const Q=navigator.mediaCapabilities;typeof(Q==null?void 0:Q.decodingInfo)=="function"&&Go(V,I,D,A,e,_)?(V.supportedPromise=Mn(V,I,Q,this.supportedCache),V.supportedPromise.then(ee=>{if(!this.hls)return;V.supportedResult=ee;const Se=this.hls.levels,me=Se.indexOf(V);ee.error?this.warn(`MediaCapabilities decodingInfo error: "${ee.error}" for level ${me} ${oe(ee)}`):ee.supported?ee.decodingInfoResults.some(Pe=>Pe.smooth===!1||Pe.powerEfficient===!1)&&this.log(`MediaCapabilities decodingInfo for level ${me} not smooth or powerEfficient: ${oe(ee)}`):(this.warn(`Unsupported MediaCapabilities decodingInfo result for level ${me} ${oe(ee)}`),me>-1&&Se.length>1&&(this.log(`Removing unsupported level ${me}`),this.hls.removeLevel(me),this.hls.loadLevel===-1&&(this.hls.nextLoadLevel=0)))}).catch(ee=>{this.warn(`Error handling MediaCapabilities decodingInfo: ${ee}`)})):V.supportedResult=On}if((x&&V.codecSet!==x||D&&V.videoRange!==D||$&&A>V.frameRate||!$&&A>0&&AQ.smooth===!1))&&(!v||w!==P)){W.push(w);continue}const H=V.details,q=(f?H==null?void 0:H.partTarget:H==null?void 0:H.averagetargetduration)||M;let O;$?O=o*e:O=n*e;const F=M&&i>=M*2&&r===0?V.averageBitrate:V.maxBitrate,z=this.getTimeToLoadFrag(G,O,F*q,H===void 0);if(O>=F&&(w===h||V.loadError===0&&V.fragmentError===0)&&(z<=G||!B(z)||S&&!this.bitrateTestDelay||z${w} adjustedbw(${Math.round(O)})-bitrate=${Math.round(O-F)} ttfb:${G.toFixed(1)} avgDuration:${q.toFixed(1)} maxFetchDuration:${l.toFixed(1)} fetchDuration:${z.toFixed(1)} firstSelection:${v} codecSet:${V.codecSet} videoRange:${V.videoRange} hls.loadLevel:${p}`)),v&&(this.firstSelection=w),w}}return-1}set nextAutoLevel(e){const t=this.deriveNextAutoLevel(e);this._nextAutoLevel!==t&&(this.nextAutoLevelKey="",this._nextAutoLevel=t)}deriveNextAutoLevel(e){const{maxAutoLevel:t,minAutoLevel:s}=this.hls;return Math.min(Math.max(e,s),t)}}const $n={search:function(a,e){let t=0,s=a.length-1,i=null,r=null;for(;t<=s;){i=(t+s)/2|0,r=a[i];const n=e(r);if(n>0)t=i+1;else if(n<0)s=i-1;else return r}return null}};function il(a,e,t){if(e===null||!Array.isArray(a)||!a.length||!B(e))return null;const s=a[0].programDateTime;if(e<(s||0))return null;const i=a[a.length-1].endProgramDateTime;if(e>=(i||0))return null;for(let r=0;r0&&o<15e-7&&(t+=15e-7),r&&a.level!==r.level&&r.end<=a.end&&(r=e[2+a.sn-e[0].sn]||null)}else t===0&&e[0].start===0&&(r=e[0]);if(r&&((!a||a.level===r.level)&&mr(t,s,r)===0||rl(r,a,Math.min(i,s))))return r;const n=$n.search(e,mr.bind(null,t,s));return n&&(n!==a||!r)?n:r}function rl(a,e,t){if(e&&e.start===0&&e.level0){const s=e.tagList.reduce((i,r)=>(r[0]==="INF"&&(i+=parseFloat(r[1])),i),t);return a.start<=s}return!1}function mr(a=0,e=0,t){if(t.start<=a&&t.start+t.duration>a)return 0;const s=Math.min(e,t.duration+(t.deltaPTS?t.deltaPTS:0));return t.start+t.duration-s<=a?1:t.start-s>a&&t.start?-1:0}function nl(a,e,t){const s=Math.min(e,t.duration+(t.deltaPTS?t.deltaPTS:0))*1e3;return(t.endProgramDateTime||0)-s>a}function Un(a,e,t){if(a&&a.startCC<=e&&a.endCC>=e){let s=a.fragments;const{fragmentHint:i}=a;i&&(s=s.concat(i));let r;return $n.search(s,n=>n.cce?-1:(r=n,n.end<=t?1:n.start>t?-1:0)),r||null}return null}function xs(a){switch(a.details){case R.FRAG_LOAD_TIMEOUT:case R.KEY_LOAD_TIMEOUT:case R.LEVEL_LOAD_TIMEOUT:case R.MANIFEST_LOAD_TIMEOUT:return!0}return!1}function Gn(a){return a.details.startsWith("key")}function Kn(a){return Gn(a)&&!!a.frag&&!a.frag.decryptdata}function pr(a,e){const t=xs(e);return a.default[`${t?"timeout":"error"}Retry`]}function Ci(a,e){const t=a.backoff==="linear"?1:Math.pow(2,e);return Math.min(t*a.retryDelayMs,a.maxRetryDelayMs)}function yr(a){return ie(ie({},a),{errorRetry:null,timeoutRetry:null})}function As(a,e,t,s){if(!a)return!1;const i=s==null?void 0:s.code,r=e499)}function li(a){return a===0&&navigator.onLine===!1}var pe={DoNothing:0,SendAlternateToPenaltyBox:2,RemoveAlternatePermanently:3,RetryRequest:5},Re={None:0,MoveAllAlternatesMatchingHost:1,MoveAllAlternatesMatchingHDCP:2,MoveAllAlternatesMatchingKey:4};class ol extends Oe{constructor(e){super("error-controller",e.logger),this.hls=void 0,this.playlistError=0,this.hls=e,this.registerListeners()}registerListeners(){const e=this.hls;e.on(m.ERROR,this.onError,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.LEVEL_UPDATED,this.onLevelUpdated,this)}unregisterListeners(){const e=this.hls;e&&(e.off(m.ERROR,this.onError,this),e.off(m.ERROR,this.onErrorOut,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.LEVEL_UPDATED,this.onLevelUpdated,this))}destroy(){this.unregisterListeners(),this.hls=null}startLoad(e){}stopLoad(){this.playlistError=0}getVariantLevelIndex(e){return(e==null?void 0:e.type)===U.MAIN?e.level:this.getVariantIndex()}getVariantIndex(){var e;const t=this.hls,s=t.currentLevel;return(e=t.loadLevelObj)!=null&&e.details||s===-1?t.loadLevel:s}variantHasKey(e,t){if(e){var s;if((s=e.details)!=null&&s.hasKey(t))return!0;const i=e.audioGroups;if(i)return this.hls.allAudioTracks.filter(n=>i.indexOf(n.groupId)>=0).some(n=>{var o;return(o=n.details)==null?void 0:o.hasKey(t)})}return!1}onManifestLoading(){this.playlistError=0}onLevelUpdated(){this.playlistError=0}onError(e,t){var s;if(t.fatal)return;const i=this.hls,r=t.context;switch(t.details){case R.FRAG_LOAD_ERROR:case R.FRAG_LOAD_TIMEOUT:case R.KEY_LOAD_ERROR:case R.KEY_LOAD_TIMEOUT:t.errorAction=this.getFragRetryOrSwitchAction(t);return;case R.FRAG_PARSING_ERROR:if((s=t.frag)!=null&&s.gap){t.errorAction=bt();return}case R.FRAG_GAP:case R.FRAG_DECRYPT_ERROR:{t.errorAction=this.getFragRetryOrSwitchAction(t),t.errorAction.action=pe.SendAlternateToPenaltyBox;return}case R.LEVEL_EMPTY_ERROR:case R.LEVEL_PARSING_ERROR:{var n;const c=t.parent===U.MAIN?t.level:i.loadLevel;t.details===R.LEVEL_EMPTY_ERROR&&((n=t.context)!=null&&(n=n.levelDetails)!=null&&n.live)?t.errorAction=this.getPlaylistRetryOrSwitchAction(t,c):(t.levelRetry=!1,t.errorAction=this.getLevelSwitchAction(t,c))}return;case R.LEVEL_LOAD_ERROR:case R.LEVEL_LOAD_TIMEOUT:typeof(r==null?void 0:r.level)=="number"&&(t.errorAction=this.getPlaylistRetryOrSwitchAction(t,r.level));return;case R.AUDIO_TRACK_LOAD_ERROR:case R.AUDIO_TRACK_LOAD_TIMEOUT:case R.SUBTITLE_LOAD_ERROR:case R.SUBTITLE_TRACK_LOAD_TIMEOUT:if(r){const c=i.loadLevelObj;if(c&&(r.type===J.AUDIO_TRACK&&c.hasAudioGroup(r.groupId)||r.type===J.SUBTITLE_TRACK&&c.hasSubtitleGroup(r.groupId))){t.errorAction=this.getPlaylistRetryOrSwitchAction(t,i.loadLevel),t.errorAction.action=pe.SendAlternateToPenaltyBox,t.errorAction.flags=Re.MoveAllAlternatesMatchingHost;return}}return;case R.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED:t.errorAction={action:pe.SendAlternateToPenaltyBox,flags:Re.MoveAllAlternatesMatchingHDCP};return;case R.KEY_SYSTEM_SESSION_UPDATE_FAILED:case R.KEY_SYSTEM_STATUS_INTERNAL_ERROR:case R.KEY_SYSTEM_NO_SESSION:t.errorAction={action:pe.SendAlternateToPenaltyBox,flags:Re.MoveAllAlternatesMatchingKey};return;case R.BUFFER_ADD_CODEC_ERROR:case R.REMUX_ALLOC_ERROR:case R.BUFFER_APPEND_ERROR:if(!t.errorAction){var o;t.errorAction=this.getLevelSwitchAction(t,(o=t.level)!=null?o:i.loadLevel)}return;case R.INTERNAL_EXCEPTION:case R.BUFFER_APPENDING_ERROR:case R.BUFFER_FULL_ERROR:case R.LEVEL_SWITCH_ERROR:case R.BUFFER_STALLED_ERROR:case R.BUFFER_SEEK_OVER_HOLE:case R.BUFFER_NUDGE_ON_STALL:t.errorAction=bt();return}t.type===Y.KEY_SYSTEM_ERROR&&(t.levelRetry=!1,t.errorAction=bt())}getPlaylistRetryOrSwitchAction(e,t){const s=this.hls,i=pr(s.config.playlistLoadPolicy,e),r=this.playlistError++;if(As(i,r,xs(e),e.response))return{action:pe.RetryRequest,flags:Re.None,retryConfig:i,retryCount:r};const o=this.getLevelSwitchAction(e,t);return i&&(o.retryConfig=i,o.retryCount=r),o}getFragRetryOrSwitchAction(e){const t=this.hls,s=this.getVariantLevelIndex(e.frag),i=t.levels[s],{fragLoadPolicy:r,keyLoadPolicy:n}=t.config,o=pr(Gn(e)?n:r,e),c=t.levels.reduce((h,d)=>h+d.fragmentError,0);if(i&&(e.details!==R.FRAG_GAP&&i.fragmentError++,!Kn(e)&&As(o,c,xs(e),e.response)))return{action:pe.RetryRequest,flags:Re.None,retryConfig:o,retryCount:c};const l=this.getLevelSwitchAction(e,s);return o&&(l.retryConfig=o,l.retryCount=c),l}getLevelSwitchAction(e,t){const s=this.hls;t==null&&(t=s.loadLevel);const i=this.hls.levels[t];if(i){var r,n;const l=e.details;i.loadError++,l===R.BUFFER_APPEND_ERROR&&i.fragmentError++;let h=-1;const{levels:d,loadLevel:u,minAutoLevel:f,maxAutoLevel:g}=s;!s.autoLevelEnabled&&!s.config.preserveManualLevelOnError&&(s.loadLevel=-1);const y=(r=e.frag)==null?void 0:r.type,E=(y===U.AUDIO&&l===R.FRAG_PARSING_ERROR||e.sourceBufferName==="audio"&&(l===R.BUFFER_ADD_CODEC_ERROR||l===R.BUFFER_APPEND_ERROR))&&d.some(({audioCodec:D})=>i.audioCodec!==D),S=e.sourceBufferName==="video"&&(l===R.BUFFER_ADD_CODEC_ERROR||l===R.BUFFER_APPEND_ERROR)&&d.some(({codecSet:D,audioCodec:A})=>i.codecSet!==D&&i.audioCodec===A),{type:v,groupId:x}=(n=e.context)!=null?n:{};for(let D=d.length;D--;){const A=(D+u)%d.length;if(A!==u&&A>=f&&A<=g&&d[A].loadError===0){var o,c;const _=d[A];if(l===R.FRAG_GAP&&y===U.MAIN&&e.frag){const b=d[A].details;if(b){const I=pt(e.frag,b.fragments,e.frag.start);if(I!=null&&I.gap)continue}}else{if(v===J.AUDIO_TRACK&&_.hasAudioGroup(x)||v===J.SUBTITLE_TRACK&&_.hasSubtitleGroup(x))continue;if(y===U.AUDIO&&(o=i.audioGroups)!=null&&o.some(b=>_.hasAudioGroup(b))||y===U.SUBTITLE&&(c=i.subtitleGroups)!=null&&c.some(b=>_.hasSubtitleGroup(b))||E&&i.audioCodec===_.audioCodec||S&&i.codecSet===_.codecSet||!E&&i.codecSet!==_.codecSet)continue}h=A;break}}if(h>-1&&s.loadLevel!==h)return e.levelRetry=!0,this.playlistError=0,{action:pe.SendAlternateToPenaltyBox,flags:Re.None,nextAutoLevel:h}}return{action:pe.SendAlternateToPenaltyBox,flags:Re.MoveAllAlternatesMatchingHost}}onErrorOut(e,t){var s;switch((s=t.errorAction)==null?void 0:s.action){case pe.DoNothing:break;case pe.SendAlternateToPenaltyBox:this.sendAlternateToPenaltyBox(t),!t.errorAction.resolved&&t.details!==R.FRAG_GAP?t.fatal=!0:/MediaSource readyState: ended/.test(t.error.message)&&(this.warn(`MediaSource ended after "${t.sourceBufferName}" sourceBuffer append error. Attempting to recover from media error.`),this.hls.recoverMediaError());break}if(t.fatal){this.hls.stopLoad();return}}sendAlternateToPenaltyBox(e){const t=this.hls,s=e.errorAction;if(!s)return;const{flags:i}=s,r=s.nextAutoLevel;switch(i){case Re.None:this.switchLevel(e,r);break;case Re.MoveAllAlternatesMatchingHDCP:{const c=this.getVariantLevelIndex(e.frag),l=t.levels[c],h=l==null?void 0:l.attrs["HDCP-LEVEL"];if(s.hdcpLevel=h,h==="NONE")this.warn("HDCP policy resticted output with HDCP-LEVEL=NONE");else if(h){t.maxHdcpLevel=oi[oi.indexOf(h)-1],s.resolved=!0,this.warn(`Restricting playback to HDCP-LEVEL of "${t.maxHdcpLevel}" or lower`);break}}case Re.MoveAllAlternatesMatchingKey:{const c=e.decryptdata;if(c){const l=this.hls.levels,h=l.length;for(let u=h;u--;)if(this.variantHasKey(l[u],c)){var n,o;this.log(`Banned key found in level ${u} (${l[u].bitrate}bps) or audio group "${(n=l[u].audioGroups)==null?void 0:n.join(",")}" (${(o=e.frag)==null?void 0:o.type} fragment) ${ye(c.keyId||[])}`),l[u].fragmentError++,l[u].loadError++,this.log(`Removing level ${u} with key error (${e.error})`),this.hls.removeLevel(u)}const d=e.frag;if(this.hls.levels.length{const c=this.fragments[o];if(!c||n>=c.body.sn)return;if(!c.buffered&&(!c.loaded||r)){c.body.type===s&&this.removeFragment(c.body);return}const l=c.range[e];if(l){if(l.time.length===0){this.removeFragment(c.body);return}l.time.some(h=>{const d=!this.isTimeBuffered(h.startPTS,h.endPTS,t);return d&&this.removeFragment(c.body),d})}})}detectPartialFragments(e){const t=this.timeRanges;if(!t||e.frag.sn==="initSegment")return;const s=e.frag,i=Tt(s),r=this.fragments[i];if(!r||r.buffered&&s.gap)return;const n=!s.relurl;Object.keys(t).forEach(o=>{const c=s.elementaryStreams[o];if(!c)return;const l=t[o],h=n||c.partial===!0;r.range[o]=this.getBufferedTimes(s,e.part,h,l)}),r.loaded=null,Object.keys(r.range).length?(this.bufferedEnd(r,s),Zt(r)||this.removeParts(s.sn-1,s.type)):this.removeFragment(r.body)}bufferedEnd(e,t){e.buffered=!0,(e.body.endList=t.endList||e.body.endList)&&(this.endListFragments[e.body.type]=e)}removeParts(e,t){const s=this.activePartLists[t];s&&(this.activePartLists[t]=Er(s,i=>i.fragment.sn>=e))}fragBuffered(e,t){const s=Tt(e);let i=this.fragments[s];!i&&t&&(i=this.fragments[s]={body:e,appendedPTS:null,loaded:null,buffered:!1,range:Object.create(null)},e.gap&&(this.hasGaps=!0)),i&&(i.loaded=null,this.bufferedEnd(i,e))}getBufferedTimes(e,t,s,i){const r={time:[],partial:s},n=e.start,o=e.end,c=e.minEndPTS||o,l=e.maxStartPTS||n;for(let h=0;h=d&&c<=u){r.time.push({startPTS:Math.max(n,i.start(h)),endPTS:Math.min(o,i.end(h))});break}else if(nd){const f=Math.max(n,i.start(h)),g=Math.min(o,i.end(h));g>f&&(r.partial=!0,r.time.push({startPTS:f,endPTS:g}))}else if(o<=d)break}return r}getPartialFragment(e){let t=null,s,i,r,n=0;const{bufferPadding:o,fragments:c}=this;return Object.keys(c).forEach(l=>{const h=c[l];h&&Zt(h)&&(i=h.body.start-o,r=h.body.end+o,e>=i&&e<=r&&(s=Math.min(e-i,r-e),n<=s&&(t=h.body,n=s)))}),t}isEndListAppended(e){const t=this.endListFragments[e];return t!==void 0&&(t.buffered||Zt(t))}getState(e){const t=Tt(e),s=this.fragments[t];return s?s.buffered?Zt(s)?fe.PARTIAL:fe.OK:fe.APPENDING:fe.NOT_LOADED}isTimeBuffered(e,t,s){let i,r;for(let n=0;n=i&&t<=r)return!0;if(t<=i)return!1}return!1}onManifestLoading(){this.removeAllFragments()}onFragLoaded(e,t){if(t.frag.sn==="initSegment"||t.frag.bitrateTest)return;const s=t.frag,i=t.part?null:t,r=Tt(s);this.fragments[r]={body:s,appendedPTS:null,loaded:i,buffered:!1,range:Object.create(null)}}onBufferAppended(e,t){const{frag:s,part:i,timeRanges:r,type:n}=t;if(s.sn==="initSegment")return;const o=s.type;if(i){let l=this.activePartLists[o];l||(this.activePartLists[o]=l=[]),l.push(i)}this.timeRanges=r;const c=r[n];this.detectEvictedFragments(n,c,o,i)}onFragBuffered(e,t){this.detectPartialFragments(t)}hasFragment(e){const t=Tt(e);return!!this.fragments[t]}hasFragments(e){const{fragments:t}=this,s=Object.keys(t);if(!e)return s.length>0;for(let i=s.length;i--;){const r=t[s[i]];if((r==null?void 0:r.body.type)===e)return!0}return!1}hasParts(e){var t;return!!((t=this.activePartLists[e])!=null&&t.length)}removeFragmentsInRange(e,t,s,i,r){i&&!this.hasGaps||Object.keys(this.fragments).forEach(n=>{const o=this.fragments[n];if(!o)return;const c=o.body;c.type!==s||i&&!c.gap||c.starte&&(o.buffered||r)&&this.removeFragment(c)})}removeFragment(e){const t=Tt(e);e.clearElementaryStreamInfo();const s=this.activePartLists[e.type];if(s){const i=e.sn;this.activePartLists[e.type]=Er(s,r=>r.fragment.sn!==i)}delete this.fragments[t],e.endList&&delete this.endListFragments[e.type]}removeAllFragments(){var e;this.fragments=Object.create(null),this.endListFragments=Object.create(null),this.activePartLists=Object.create(null),this.hasGaps=!1;const t=(e=this.hls)==null||(e=e.latestLevelDetails)==null?void 0:e.partList;t&&t.forEach(s=>s.clearElementaryStreamInfo())}}function Zt(a){var e,t,s;return a.buffered&&!!(a.body.gap||(e=a.range.video)!=null&&e.partial||(t=a.range.audio)!=null&&t.partial||(s=a.range.audiovideo)!=null&&s.partial)}function Tt(a){return`${a.type}_${a.level}_${a.sn}`}function Er(a,e){return a.filter(t=>{const s=e(t);return s||t.clearElementaryStreamInfo(),s})}var ot={cbc:0,ctr:1};class cl{constructor(e,t,s){this.subtle=void 0,this.aesIV=void 0,this.aesMode=void 0,this.subtle=e,this.aesIV=t,this.aesMode=s}decrypt(e,t){switch(this.aesMode){case ot.cbc:return this.subtle.decrypt({name:"AES-CBC",iv:this.aesIV},t,e);case ot.ctr:return this.subtle.decrypt({name:"AES-CTR",counter:this.aesIV,length:64},t,e);default:throw new Error(`[AESCrypto] invalid aes mode ${this.aesMode}`)}}}function hl(a){const e=a.byteLength,t=e&&new DataView(a.buffer).getUint8(e-1);return t?a.slice(0,e-t):a}class dl{constructor(){this.rcon=[0,1,2,4,8,16,32,64,128,27,54],this.subMix=[new Uint32Array(256),new Uint32Array(256),new Uint32Array(256),new Uint32Array(256)],this.invSubMix=[new Uint32Array(256),new Uint32Array(256),new Uint32Array(256),new Uint32Array(256)],this.sBox=new Uint32Array(256),this.invSBox=new Uint32Array(256),this.key=new Uint32Array(0),this.ksRows=0,this.keySize=0,this.keySchedule=void 0,this.invKeySchedule=void 0,this.initTable()}uint8ArrayToUint32Array_(e){const t=new DataView(e),s=new Uint32Array(4);for(let i=0;i<4;i++)s[i]=t.getUint32(i*4);return s}initTable(){const e=this.sBox,t=this.invSBox,s=this.subMix,i=s[0],r=s[1],n=s[2],o=s[3],c=this.invSubMix,l=c[0],h=c[1],d=c[2],u=c[3],f=new Uint32Array(256);let g=0,y=0,p=0;for(p=0;p<256;p++)p<128?f[p]=p<<1:f[p]=p<<1^283;for(p=0;p<256;p++){let E=y^y<<1^y<<2^y<<3^y<<4;E=E>>>8^E&255^99,e[g]=E,t[E]=g;const T=f[g],S=f[T],v=f[S];let x=f[E]*257^E*16843008;i[g]=x<<24|x>>>8,r[g]=x<<16|x>>>16,n[g]=x<<8|x>>>24,o[g]=x,x=v*16843009^S*65537^T*257^g*16843008,l[E]=x<<24|x>>>8,h[E]=x<<16|x>>>16,d[E]=x<<8|x>>>24,u[E]=x,g?(g=T^f[f[f[v^T]]],y^=f[f[y]]):g=y=1}}expandKey(e){const t=this.uint8ArrayToUint32Array_(e);let s=!0,i=0;for(;i{const o=ArrayBuffer.isView(e)?e:new Uint8Array(e);this.softwareDecrypt(o,t,s,i);const c=this.flush();c?r(c.buffer):n(new Error("[softwareDecrypt] Failed to decrypt data"))}):this.webCryptoDecrypt(new Uint8Array(e),t,s,i)}softwareDecrypt(e,t,s,i){const{currentIV:r,currentResult:n,remainderData:o}=this;if(i!==ot.cbc||t.byteLength!==16)return re.warn("SoftwareDecrypt: can only handle AES-128-CBC"),null;this.logOnce("JS AES decrypt"),o&&(e=we(o,e),this.remainderData=null);const c=this.getValidChunk(e);if(!c.length)return null;r&&(s=r);let l=this.softwareDecrypter;l||(l=this.softwareDecrypter=new dl),l.expandKey(t);const h=n;return this.currentResult=l.decrypt(c.buffer,0,s),this.currentIV=c.slice(-16).buffer,h||null}webCryptoDecrypt(e,t,s,i){if(this.key!==t||!this.fastAesKey){if(!this.subtle)return Promise.resolve(this.onWebCryptoError(e,t,s,i));this.key=t,this.fastAesKey=new ul(this.subtle,t,i)}return this.fastAesKey.expandKey().then(r=>this.subtle?(this.logOnce("WebCrypto AES decrypt"),new cl(this.subtle,new Uint8Array(s),i).decrypt(e.buffer,r)):Promise.reject(new Error("web crypto not initialized"))).catch(r=>(re.warn(`[decrypter]: WebCrypto Error, disable WebCrypto API, ${r.name}: ${r.message}`),this.onWebCryptoError(e,t,s,i)))}onWebCryptoError(e,t,s,i){const r=this.enableSoftwareAES;if(r){this.useSoftware=!0,this.logEnabled=!0,this.softwareDecrypt(e,t,s,i);const n=this.flush();if(n)return n.buffer}throw new Error("WebCrypto"+(r?" and softwareDecrypt":"")+": failed to decrypt data")}getValidChunk(e){let t=e;const s=e.length-e.length%gl;return s!==e.length&&(t=e.slice(0,s),this.remainderData=e.slice(s)),t}logOnce(e){this.logEnabled&&(re.log(`[decrypter]: ${e}`),this.logEnabled=!1)}}const Tr=Math.pow(2,17);class ml{constructor(e){this.config=void 0,this.loader=null,this.partLoadTimeout=-1,this.config=e}destroy(){this.loader&&(this.loader.destroy(),this.loader=null)}abort(){this.loader&&this.loader.abort()}load(e,t){const s=e.url;if(!s)return Promise.reject(new Ze({type:Y.NETWORK_ERROR,details:R.FRAG_LOAD_ERROR,fatal:!1,frag:e,error:new Error(`Fragment does not have a ${s?"part list":"url"}`),networkDetails:null}));this.abort();const i=this.config,r=i.fLoader,n=i.loader;return new Promise((o,c)=>{if(this.loader&&this.loader.destroy(),e.gap)if(e.tagList.some(g=>g[0]==="GAP")){c(vr(e));return}else e.gap=!1;const l=this.loader=r?new r(i):new n(i),h=Sr(e);e.loader=l;const d=yr(i.fragLoadPolicy.default),u={loadPolicy:d,timeout:d.maxLoadTimeMs,maxRetry:0,retryDelay:0,maxRetryDelay:0,highWaterMark:e.sn==="initSegment"?1/0:Tr};e.stats=l.stats;const f={onSuccess:(g,y,p,E)=>{this.resetLoader(e,l);let T=g.data;p.resetIV&&e.decryptdata&&(e.decryptdata.iv=new Uint8Array(T.slice(0,16)),T=T.slice(16)),o({frag:e,part:null,payload:T,networkDetails:E})},onError:(g,y,p,E)=>{this.resetLoader(e,l),c(new Ze({type:Y.NETWORK_ERROR,details:R.FRAG_LOAD_ERROR,fatal:!1,frag:e,response:ie({url:s,data:void 0},g),error:new Error(`HTTP Error ${g.code} ${g.text}`),networkDetails:p,stats:E}))},onAbort:(g,y,p)=>{this.resetLoader(e,l),c(new Ze({type:Y.NETWORK_ERROR,details:R.INTERNAL_ABORTED,fatal:!1,frag:e,error:new Error("Aborted"),networkDetails:p,stats:g}))},onTimeout:(g,y,p)=>{this.resetLoader(e,l),c(new Ze({type:Y.NETWORK_ERROR,details:R.FRAG_LOAD_TIMEOUT,fatal:!1,frag:e,error:new Error(`Timeout after ${u.timeout}ms`),networkDetails:p,stats:g}))}};t&&(f.onProgress=(g,y,p,E)=>t({frag:e,part:null,payload:p,networkDetails:E})),l.load(h,u,f)})}loadPart(e,t,s){this.abort();const i=this.config,r=i.fLoader,n=i.loader;return new Promise((o,c)=>{if(this.loader&&this.loader.destroy(),e.gap||t.gap){c(vr(e,t));return}const l=this.loader=r?new r(i):new n(i),h=Sr(e,t);e.loader=l;const d=yr(i.fragLoadPolicy.default),u={loadPolicy:d,timeout:d.maxLoadTimeMs,maxRetry:0,retryDelay:0,maxRetryDelay:0,highWaterMark:Tr};t.stats=l.stats,l.load(h,u,{onSuccess:(f,g,y,p)=>{this.resetLoader(e,l),this.updateStatsFromPart(e,t);const E={frag:e,part:t,payload:f.data,networkDetails:p};s(E),o(E)},onError:(f,g,y,p)=>{this.resetLoader(e,l),c(new Ze({type:Y.NETWORK_ERROR,details:R.FRAG_LOAD_ERROR,fatal:!1,frag:e,part:t,response:ie({url:h.url,data:void 0},f),error:new Error(`HTTP Error ${f.code} ${f.text}`),networkDetails:y,stats:p}))},onAbort:(f,g,y)=>{e.stats.aborted=t.stats.aborted,this.resetLoader(e,l),c(new Ze({type:Y.NETWORK_ERROR,details:R.INTERNAL_ABORTED,fatal:!1,frag:e,part:t,error:new Error("Aborted"),networkDetails:y,stats:f}))},onTimeout:(f,g,y)=>{this.resetLoader(e,l),c(new Ze({type:Y.NETWORK_ERROR,details:R.FRAG_LOAD_TIMEOUT,fatal:!1,frag:e,part:t,error:new Error(`Timeout after ${u.timeout}ms`),networkDetails:y,stats:f}))}})})}updateStatsFromPart(e,t){const s=e.stats,i=t.stats,r=i.total;if(s.loaded+=i.loaded,r){const c=Math.round(e.duration/t.duration),l=Math.min(Math.round(s.loaded/r),c),d=(c-l)*Math.round(s.loaded/l);s.total=s.loaded+d}else s.total=Math.max(s.loaded,s.total);const n=s.loading,o=i.loading;n.start?n.first+=o.first-o.start:(n.start=o.start,n.first=o.first),n.end=o.end}resetLoader(e,t){e.loader=null,this.loader===t&&(self.clearTimeout(this.partLoadTimeout),this.loader=null),t.destroy()}}function Sr(a,e=null){const t=e||a,s={frag:a,part:e,responseType:"arraybuffer",url:t.url,headers:{},rangeStart:0,rangeEnd:0},i=t.byteRangeStartOffset,r=t.byteRangeEndOffset;if(B(i)&&B(r)){var n;let o=i,c=r;if(a.sn==="initSegment"&&pl((n=a.decryptdata)==null?void 0:n.method)){const l=r-i;l%16&&(c=r+(16-l%16)),i!==0&&(s.resetIV=!0,o=i-16)}s.rangeStart=o,s.rangeEnd=c}return s}function vr(a,e){const t=new Error(`GAP ${a.gap?"tag":"attribute"} found`),s={type:Y.MEDIA_ERROR,details:R.FRAG_GAP,fatal:!1,frag:a,error:t,networkDetails:null};return e&&(s.part=e),(e||a).stats.aborted=!0,new Ze(s)}function pl(a){return a==="AES-128"||a==="AES-256"}class Ze extends Error{constructor(e){super(e.error.message),this.data=void 0,this.data=e}}class Vn extends Oe{constructor(e,t){super(e,t),this._boundTick=void 0,this._tickTimer=null,this._tickInterval=null,this._tickCallCount=0,this._boundTick=this.tick.bind(this)}destroy(){this.onHandlerDestroying(),this.onHandlerDestroyed()}onHandlerDestroying(){this.clearNextTick(),this.clearInterval()}onHandlerDestroyed(){}hasInterval(){return!!this._tickInterval}hasNextTick(){return!!this._tickTimer}setInterval(e){return this._tickInterval?!1:(this._tickCallCount=0,this._tickInterval=self.setInterval(this._boundTick,e),!0)}clearInterval(){return this._tickInterval?(self.clearInterval(this._tickInterval),this._tickInterval=null,!0):!1}clearNextTick(){return this._tickTimer?(self.clearTimeout(this._tickTimer),this._tickTimer=null,!0):!1}tick(){this._tickCallCount++,this._tickCallCount===1&&(this.doTick(),this._tickCallCount>1&&this.tickImmediate(),this._tickCallCount=0)}tickImmediate(){this.clearNextTick(),this._tickTimer=self.setTimeout(this._boundTick,0)}doTick(){}}class ki{constructor(e,t,s,i=0,r=-1,n=!1){this.level=void 0,this.sn=void 0,this.part=void 0,this.id=void 0,this.size=void 0,this.partial=void 0,this.transmuxing=Jt(),this.buffering={audio:Jt(),video:Jt(),audiovideo:Jt()},this.level=e,this.sn=t,this.id=s,this.size=i,this.part=r,this.partial=n}}function Jt(){return{start:0,executeStart:0,executeEnd:0,end:0}}const xr={length:0,start:()=>0,end:()=>0};class X{static isBuffered(e,t){if(e){const s=X.getBuffered(e);for(let i=s.length;i--;)if(t>=s.start(i)&&t<=s.end(i))return!0}return!1}static bufferedRanges(e){if(e){const t=X.getBuffered(e);return X.timeRangesToArray(t)}return[]}static timeRangesToArray(e){const t=[];for(let s=0;s1&&e.sort((h,d)=>h.start-d.start||d.end-h.end);let i=-1,r=[];if(s)for(let h=0;h=e[h].start&&t<=e[h].end&&(i=h);const d=r.length;if(d){const u=r[d-1].end;e[h].start-uu&&(r[d-1].end=e[h].end):r.push(e[h])}else r.push(e[h])}else r=e;let n=0,o,c=t,l=t;for(let h=0;h=d&&t<=u&&(i=h),t+s>=d&&t{const i=s.substring(2,s.length-1),r=t==null?void 0:t[i];return r===void 0?(a.playlistParsingError||(a.playlistParsingError=new Error(`Missing preceding EXT-X-DEFINE tag for Variable Reference: "${i}"`)),s):r})}return e}function Ir(a,e,t){let s=a.variableList;s||(a.variableList=s={});let i,r;if("QUERYPARAM"in e){i=e.QUERYPARAM;try{const n=new self.URL(t).searchParams;if(n.has(i))r=n.get(i);else throw new Error(`"${i}" does not match any query parameter in URI: "${t}"`)}catch(n){a.playlistParsingError||(a.playlistParsingError=new Error(`EXT-X-DEFINE QUERYPARAM: ${n.message}`))}}else i=e.NAME,r=e.VALUE;i in s?a.playlistParsingError||(a.playlistParsingError=new Error(`EXT-X-DEFINE duplicate Variable Name declarations: "${i}"`)):s[i]=r||""}function yl(a,e,t){const s=e.IMPORT;if(t&&s in t){let i=a.variableList;i||(a.variableList=i={}),i[s]=t[s]}else a.playlistParsingError||(a.playlistParsingError=new Error(`EXT-X-DEFINE IMPORT attribute not found in Multivariant Playlist: "${s}"`))}const El=/^(\d+)x(\d+)$/,Lr=/(.+?)=(".*?"|.*?)(?:,|$)/g;class le{constructor(e,t){typeof e=="string"&&(e=le.parseAttrList(e,t)),ne(this,e)}get clientAttrs(){return Object.keys(this).filter(e=>e.substring(0,2)==="X-")}decimalInteger(e){const t=parseInt(this[e],10);return t>Number.MAX_SAFE_INTEGER?1/0:t}hexadecimalInteger(e){if(this[e]){let t=(this[e]||"0x").slice(2);t=(t.length&1?"0":"")+t;const s=new Uint8Array(t.length/2);for(let i=0;iNumber.MAX_SAFE_INTEGER?1/0:t}decimalFloatingPoint(e){return parseFloat(this[e])}optionalFloat(e,t){const s=this[e];return s?parseFloat(s):t}enumeratedString(e){return this[e]}enumeratedStringList(e,t){const s=this[e];return(s?s.split(/[ ,]+/):[]).reduce((i,r)=>(i[r.toLowerCase()]=!0,i),t)}bool(e){return this[e]==="YES"}decimalResolution(e){const t=El.exec(this[e]);if(t!==null)return{width:parseInt(t[1],10),height:parseInt(t[2],10)}}static parseAttrList(e,t){let s;const i={},r='"';for(Lr.lastIndex=0;(s=Lr.exec(e))!==null;){const n=s[1].trim();let o=s[2];const c=o.indexOf(r)===0&&o.lastIndexOf(r)===o.length-1;let l=!1;if(c)o=o.slice(1,-1);else switch(n){case"IV":case"SCTE35-CMD":case"SCTE35-IN":case"SCTE35-OUT":l=!0}if(t&&(c||l))o=ci(t,o);else if(!l&&!c)switch(n){case"CLOSED-CAPTIONS":if(o==="NONE")break;case"ALLOWED-CPC":case"CLASS":case"ASSOC-LANGUAGE":case"AUDIO":case"BYTERANGE":case"CHANNELS":case"CHARACTERISTICS":case"CODECS":case"DATA-ID":case"END-DATE":case"GROUP-ID":case"ID":case"IMPORT":case"INSTREAM-ID":case"KEYFORMAT":case"KEYFORMATVERSIONS":case"LANGUAGE":case"NAME":case"PATHWAY-ID":case"QUERYPARAM":case"RECENTLY-REMOVED-DATERANGES":case"SERVER-URI":case"STABLE-RENDITION-ID":case"STABLE-VARIANT-ID":case"START-DATE":case"SUBTITLES":case"SUPPLEMENTAL-CODECS":case"URI":case"VALUE":case"VIDEO":case"X-ASSET-LIST":case"X-ASSET-URI":re.warn(`${e}: attribute ${n} is missing quotes`)}i[n]=o}return i}}const Tl="com.apple.hls.interstitial";function Sl(a){return a!=="ID"&&a!=="CLASS"&&a!=="CUE"&&a!=="START-DATE"&&a!=="DURATION"&&a!=="END-DATE"&&a!=="END-ON-NEXT"}function vl(a){return a==="SCTE35-OUT"||a==="SCTE35-IN"||a==="SCTE35-CMD"}class Yn{constructor(e,t,s=0){var i;if(this.attr=void 0,this.tagAnchor=void 0,this.tagOrder=void 0,this._startDate=void 0,this._endDate=void 0,this._dateAtEnd=void 0,this._cue=void 0,this._badValueForSameId=void 0,this.tagAnchor=(t==null?void 0:t.tagAnchor)||null,this.tagOrder=(i=t==null?void 0:t.tagOrder)!=null?i:s,t){const r=t.attr;for(const n in r)if(Object.prototype.hasOwnProperty.call(e,n)&&e[n]!==r[n]){re.warn(`DATERANGE tag attribute: "${n}" does not match for tags with ID: "${e.ID}"`),this._badValueForSameId=n;break}e=ne(new le({}),r,e)}if(this.attr=e,t?(this._startDate=t._startDate,this._cue=t._cue,this._endDate=t._endDate,this._dateAtEnd=t._dateAtEnd):this._startDate=new Date(e["START-DATE"]),"END-DATE"in this.attr){const r=(t==null?void 0:t.endDate)||new Date(this.attr["END-DATE"]);B(r.getTime())&&(this._endDate=r)}}get id(){return this.attr.ID}get class(){return this.attr.CLASS}get cue(){const e=this._cue;return e===void 0?this._cue=this.attr.enumeratedStringList(this.attr.CUE?"CUE":"X-CUE",{pre:!1,post:!1,once:!1}):e}get startTime(){const{tagAnchor:e}=this;return e===null||e.programDateTime===null?(re.warn(`Expected tagAnchor Fragment with PDT set for DateRange "${this.id}": ${e}`),NaN):e.start+(this.startDate.getTime()-e.programDateTime)/1e3}get startDate(){return this._startDate}get endDate(){const e=this._endDate||this._dateAtEnd;if(e)return e;const t=this.duration;return t!==null?this._dateAtEnd=new Date(this._startDate.getTime()+t*1e3):null}get duration(){if("DURATION"in this.attr){const e=this.attr.decimalFloatingPoint("DURATION");if(B(e))return e}else if(this._endDate)return(this._endDate.getTime()-this._startDate.getTime())/1e3;return null}get plannedDuration(){return"PLANNED-DURATION"in this.attr?this.attr.decimalFloatingPoint("PLANNED-DURATION"):null}get endOnNext(){return this.attr.bool("END-ON-NEXT")}get isInterstitial(){return this.class===Tl}get isValid(){return!!this.id&&!this._badValueForSameId&&B(this.startDate.getTime())&&(this.duration===null||this.duration>=0)&&(!this.endOnNext||!!this.class)&&(!this.attr.CUE||!this.cue.pre&&!this.cue.post||this.cue.pre!==this.cue.post)&&(!this.isInterstitial||"X-ASSET-URI"in this.attr||"X-ASSET-LIST"in this.attr)}}const xl=10;class Al{constructor(e){this.PTSKnown=!1,this.alignedSliding=!1,this.averagetargetduration=void 0,this.endCC=0,this.endSN=0,this.fragments=void 0,this.fragmentHint=void 0,this.partList=null,this.dateRanges=void 0,this.dateRangeTagCount=0,this.live=!0,this.requestScheduled=-1,this.ageHeader=0,this.advancedDateTime=void 0,this.updated=!0,this.advanced=!0,this.misses=0,this.startCC=0,this.startSN=0,this.startTimeOffset=null,this.targetduration=0,this.totalduration=0,this.type=null,this.url=void 0,this.m3u8="",this.version=null,this.canBlockReload=!1,this.canSkipUntil=0,this.canSkipDateRanges=!1,this.skippedSegments=0,this.recentlyRemovedDateranges=void 0,this.partHoldBack=0,this.holdBack=0,this.partTarget=0,this.preloadHint=void 0,this.renditionReports=void 0,this.tuneInGoal=0,this.deltaUpdateFailed=void 0,this.driftStartTime=0,this.driftEndTime=0,this.driftStart=0,this.driftEnd=0,this.encryptedFragments=void 0,this.playlistParsingError=null,this.variableList=null,this.hasVariableRefs=!1,this.appliedTimelineOffset=void 0,this.fragments=[],this.encryptedFragments=[],this.dateRanges={},this.url=e}reloaded(e){if(!e){this.advanced=!0,this.updated=!0;return}const t=this.lastPartSn-e.lastPartSn,s=this.lastPartIndex-e.lastPartIndex;this.updated=this.endSN!==e.endSN||!!s||!!t||!this.live,this.advanced=this.endSN>e.endSN||t>0||t===0&&s>0,this.updated||this.advanced?this.misses=Math.floor(e.misses*.6):this.misses=e.misses+1}hasKey(e){return this.encryptedFragments.some(t=>{let s=t.decryptdata;return s||(t.setKeyFormat(e.keyFormat),s=t.decryptdata),!!s&&e.matches(s)})}get hasProgramDateTime(){return this.fragments.length?B(this.fragments[this.fragments.length-1].programDateTime):!1}get levelTargetDuration(){return this.averagetargetduration||this.targetduration||xl}get drift(){const e=this.driftEndTime-this.driftStartTime;return e>0?(this.driftEnd-this.driftStart)*1e3/e:1}get edge(){return this.partEnd||this.fragmentEnd}get partEnd(){var e;return(e=this.partList)!=null&&e.length?this.partList[this.partList.length-1].end:this.fragmentEnd}get fragmentEnd(){return this.fragments.length?this.fragments[this.fragments.length-1].end:0}get fragmentStart(){return this.fragments.length?this.fragments[0].start:0}get age(){return this.advancedDateTime?Math.max(Date.now()-this.advancedDateTime,0)/1e3:0}get lastPartIndex(){var e;return(e=this.partList)!=null&&e.length?this.partList[this.partList.length-1].index:-1}get maxPartIndex(){const e=this.partList;if(e){const t=this.lastPartIndex;if(t!==-1){for(let s=e.length;s--;)if(e[s].index>t)return e[s].index;return t}}return 0}get lastPartSn(){var e;return(e=this.partList)!=null&&e.length?this.partList[this.partList.length-1].fragment.sn:this.endSN}get expired(){if(this.live&&this.age&&this.misses<3){const e=this.partEnd-this.fragmentStart;return this.age>Math.max(e,this.totalduration)+this.levelTargetDuration}return!1}}function Is(a,e){return a.length===e.length?!a.some((t,s)=>t!==e[s]):!1}function Rr(a,e){return!a&&!e?!0:!a||!e?!1:Is(a,e)}function _t(a){return a==="AES-128"||a==="AES-256"||a==="AES-256-CTR"}function wi(a){switch(a){case"AES-128":case"AES-256":return ot.cbc;case"AES-256-CTR":return ot.ctr;default:throw new Error(`invalid full segment method ${a}`)}}function Oi(a){return Uint8Array.from(atob(a),e=>e.charCodeAt(0))}function hi(a){return Uint8Array.from(unescape(encodeURIComponent(a)),e=>e.charCodeAt(0))}function Il(a){const e=hi(a).subarray(0,16),t=new Uint8Array(16);return t.set(e,16-e.length),t}function Wn(a){const e=function(s,i,r){const n=s[i];s[i]=s[r],s[r]=n};e(a,0,3),e(a,1,2),e(a,4,5),e(a,6,7)}function qn(a){const e=a.split(":");let t=null;if(e[0]==="data"&&e.length===2){const s=e[1].split(";"),i=s[s.length-1].split(",");if(i.length===2){const r=i[0]==="base64",n=i[1];r?(s.splice(-1,1),t=Oi(n)):t=Il(n)}}return t}const Ls=typeof self<"u"?self:void 0;var ce={CLEARKEY:"org.w3.clearkey",FAIRPLAY:"com.apple.fps",PLAYREADY:"com.microsoft.playready",WIDEVINE:"com.widevine.alpha"},Ee={CLEARKEY:"org.w3.clearkey",FAIRPLAY:"com.apple.streamingkeydelivery",PLAYREADY:"com.microsoft.playready",WIDEVINE:"urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"};function us(a){switch(a){case Ee.FAIRPLAY:return ce.FAIRPLAY;case Ee.PLAYREADY:return ce.PLAYREADY;case Ee.WIDEVINE:return ce.WIDEVINE;case Ee.CLEARKEY:return ce.CLEARKEY}}function Bs(a){switch(a){case ce.FAIRPLAY:return Ee.FAIRPLAY;case ce.PLAYREADY:return Ee.PLAYREADY;case ce.WIDEVINE:return Ee.WIDEVINE;case ce.CLEARKEY:return Ee.CLEARKEY}}function Mt(a){const{drmSystems:e,widevineLicenseUrl:t}=a,s=e?[ce.FAIRPLAY,ce.WIDEVINE,ce.PLAYREADY,ce.CLEARKEY].filter(i=>!!e[i]):[];return!s[ce.WIDEVINE]&&t&&s.push(ce.WIDEVINE),s}const jn=function(a){return Ls!=null&&(a=Ls.navigator)!=null&&a.requestMediaKeySystemAccess?self.navigator.requestMediaKeySystemAccess.bind(self.navigator):null}();function Ll(a,e,t,s){let i;switch(a){case ce.FAIRPLAY:i=["cenc","sinf"];break;case ce.WIDEVINE:case ce.PLAYREADY:i=["cenc"];break;case ce.CLEARKEY:i=["cenc","keyids"];break;default:throw new Error(`Unknown key-system: ${a}`)}return Rl(i,e,t,s)}function Rl(a,e,t,s){return[{initDataTypes:a,persistentState:s.persistentState||"optional",distinctiveIdentifier:s.distinctiveIdentifier||"optional",sessionTypes:s.sessionTypes||[s.sessionType||"temporary"],audioCapabilities:e.map(r=>({contentType:`audio/mp4; codecs=${r}`,robustness:s.audioRobustness||"",encryptionScheme:s.audioEncryptionScheme||null})),videoCapabilities:t.map(r=>({contentType:`video/mp4; codecs=${r}`,robustness:s.videoRobustness||"",encryptionScheme:s.videoEncryptionScheme||null}))}]}function bl(a){var e;return!!a&&(a.sessionType==="persistent-license"||!!((e=a.sessionTypes)!=null&&e.some(t=>t==="persistent-license")))}function Xn(a){const e=new Uint16Array(a.buffer,a.byteOffset,a.byteLength/2),t=String.fromCharCode.apply(null,Array.from(e)),s=t.substring(t.indexOf("<"),t.length),n=new DOMParser().parseFromString(s,"text/xml").getElementsByTagName("KID")[0];if(n){const o=n.childNodes[0]?n.childNodes[0].nodeValue:n.getAttribute("VALUE");if(o){const c=Oi(o).subarray(0,16);return Wn(c),c}}return null}let St={};class nt{static clearKeyUriToKeyIdMap(){St={}}static setKeyIdForUri(e,t){St[e]=t}static addKeyIdForUri(e){const t=Object.keys(St).length%Number.MAX_SAFE_INTEGER,s=new Uint8Array(16);return new DataView(s.buffer,12,4).setUint32(0,t),St[e]=s,s}constructor(e,t,s,i=[1],r=null,n){this.uri=void 0,this.method=void 0,this.keyFormat=void 0,this.keyFormatVersions=void 0,this.encrypted=void 0,this.isCommonEncryption=void 0,this.iv=null,this.key=null,this.keyId=null,this.pssh=null,this.method=e,this.uri=t,this.keyFormat=s,this.keyFormatVersions=i,this.iv=r,this.encrypted=e?e!=="NONE":!1,this.isCommonEncryption=this.encrypted&&!_t(e),n!=null&&n.startsWith("0x")&&(this.keyId=new Uint8Array(An(n)))}matches(e){return e.uri===this.uri&&e.method===this.method&&e.encrypted===this.encrypted&&e.keyFormat===this.keyFormat&&Is(e.keyFormatVersions,this.keyFormatVersions)&&Rr(e.iv,this.iv)&&Rr(e.keyId,this.keyId)}isSupported(){if(this.method){if(_t(this.method)||this.method==="NONE")return!0;if(this.keyFormat==="identity")return this.method==="SAMPLE-AES";switch(this.keyFormat){case Ee.FAIRPLAY:case Ee.WIDEVINE:case Ee.PLAYREADY:case Ee.CLEARKEY:return["SAMPLE-AES","SAMPLE-AES-CENC","SAMPLE-AES-CTR"].indexOf(this.method)!==-1}}return!1}getDecryptData(e,t){if(!this.encrypted||!this.uri)return null;if(_t(this.method)){let r=this.iv;return r||(typeof e!="number"&&(re.warn(`missing IV for initialization segment with method="${this.method}" - compliance issue`),e=0),r=Dl(e)),new nt(this.method,this.uri,"identity",this.keyFormatVersions,r)}if(this.keyId){const r=St[this.uri];if(r&&!Is(this.keyId,r)&&nt.setKeyIdForUri(this.uri,this.keyId),this.pssh)return this}const s=qn(this.uri);if(s)switch(this.keyFormat){case Ee.WIDEVINE:if(this.pssh=s,!this.keyId){const r=ko(s.buffer);if(r.length){var i;const n=r[0];this.keyId=(i=n.kids)!=null&&i.length?n.kids[0]:null}}this.keyId||(this.keyId=br(t));break;case Ee.PLAYREADY:{const r=new Uint8Array([154,4,240,121,152,64,66,134,171,146,230,91,224,136,95,149]);this.pssh=Po(r,null,s),this.keyId=Xn(s);break}default:{let r=s.subarray(0,16);if(r.length!==16){const n=new Uint8Array(16);n.set(r,16-r.length),r=n}this.keyId=r;break}}if(!this.keyId||this.keyId.byteLength!==16){let r;r=_l(t),r||(r=br(t),r||(r=St[this.uri])),r&&(this.keyId=r,nt.setKeyIdForUri(this.uri,r))}return this}}function _l(a){const e=a==null?void 0:a[Ee.WIDEVINE];return e?e.keyId:null}function br(a){const e=a==null?void 0:a[Ee.PLAYREADY];if(e){const t=qn(e.uri);if(t)return Xn(t)}return null}function Dl(a){const e=new Uint8Array(16);for(let t=12;t<16;t++)e[t]=a>>8*(15-t)&255;return e}const _r=/#EXT-X-STREAM-INF:([^\r\n]*)(?:[\r\n](?:#[^\r\n]*)?)*([^\r\n]+)|#EXT-X-(SESSION-DATA|SESSION-KEY|DEFINE|CONTENT-STEERING|START):([^\r\n]*)[\r\n]+/g,Dr=/#EXT-X-MEDIA:(.*)/g,Cl=/^#EXT(?:INF|-X-TARGETDURATION):/m,$s=new RegExp([/#EXTINF:\s*(\d*(?:\.\d+)?)(?:,(.*)\s+)?/.source,/(?!#) *(\S[^\r\n]*)/.source,/#.*/.source].join("|"),"g"),Pl=new RegExp([/#EXT-X-(PROGRAM-DATE-TIME|BYTERANGE|DATERANGE|DEFINE|KEY|MAP|PART|PART-INF|PLAYLIST-TYPE|PRELOAD-HINT|RENDITION-REPORT|SERVER-CONTROL|SKIP|START):(.+)/.source,/#EXT-X-(BITRATE|DISCONTINUITY-SEQUENCE|MEDIA-SEQUENCE|TARGETDURATION|VERSION): *(\d+)/.source,/#EXT-X-(DISCONTINUITY|ENDLIST|GAP|INDEPENDENT-SEGMENTS)/.source,/(#)([^:]*):(.*)/.source,/(#)(.*)(?:.*)\r?\n?/.source].join("|"));class qe{static findGroup(e,t){for(let s=0;s0&&r.length({id:l.attrs.AUDIO,audioCodec:l.audioCodec})),SUBTITLES:n.map(l=>({id:l.attrs.SUBTITLES,textCodec:l.textCodec})),"CLOSED-CAPTIONS":[]};let c=0;for(Dr.lastIndex=0;(i=Dr.exec(e))!==null;){const l=new le(i[1],s),h=l.TYPE;if(h){const d=o[h],u=r[h]||[];r[h]=u;const f=l.LANGUAGE,g=l["ASSOC-LANGUAGE"],y=l.CHANNELS,p=l.CHARACTERISTICS,E=l["INSTREAM-ID"],T={attrs:l,bitrate:0,id:c++,groupId:l["GROUP-ID"]||"",name:l.NAME||f||"",type:h,default:l.bool("DEFAULT"),autoselect:l.bool("AUTOSELECT"),forced:l.bool("FORCED"),lang:f,url:l.URI?qe.resolve(l.URI,t):""};if(g&&(T.assocLang=g),y&&(T.channels=y),p&&(T.characteristics=p),E&&(T.instreamId=E),d!=null&&d.length){const S=qe.findGroup(d,T.groupId)||d[0];wr(T,S,"audioCodec"),wr(T,S,"textCodec")}u.push(T)}}return r}static parseLevelPlaylist(e,t,s,i,r,n){var o;const c={url:t},l=new Al(t),h=l.fragments,d=[];let u=null,f=0,g=0,y=0,p=0,E=0,T=null,S=new Fs(i,c),v,x,D,A=-1,_=!1,b=null,I;if($s.lastIndex=0,l.m3u8=e,l.hasVariableRefs=Ar(e),((o=$s.exec(e))==null?void 0:o[0])!=="#EXTM3U")return l.playlistParsingError=new Error("Missing format identifier #EXTM3U"),l;for(;(v=$s.exec(e))!==null;){_&&(_=!1,S=new Fs(i,c),S.playlistOffset=y,S.setStart(y),S.sn=f,S.cc=p,E&&(S.bitrate=E),S.level=s,u&&(S.initSegment=u,u.rawProgramDateTime&&(S.rawProgramDateTime=u.rawProgramDateTime,u.rawProgramDateTime=null),b&&(S.setByteRange(b),b=null)));const W=v[1];if(W){S.duration=parseFloat(W);const K=(" "+v[2]).slice(1);S.title=K||null,S.tagList.push(K?["INF",W,K]:["INF",W])}else if(v[3]){if(B(S.duration)){S.playlistOffset=y,S.setStart(y),D&&Fr(S,D,l),S.sn=f,S.level=s,S.cc=p,h.push(S);const K=(" "+v[3]).slice(1);S.relurl=ci(l,K),di(S,T,d),T=S,y+=S.duration,f++,g=0,_=!0}}else{if(v=v[0].match(Pl),!v){re.warn("No matches on slow regex match for level playlist!");continue}for(x=1;x0&&Mr(l,K,v),f=l.startSN=parseInt(w);break;case"SKIP":{l.skippedSegments&&ze(l,K,v);const $=new le(w,l),H=$.decimalInteger("SKIPPED-SEGMENTS");if(B(H)){l.skippedSegments+=H;for(let O=H;O--;)h.push(null);f+=H}const q=$.enumeratedString("RECENTLY-REMOVED-DATERANGES");q&&(l.recentlyRemovedDateranges=(l.recentlyRemovedDateranges||[]).concat(q.split(" ")));break}case"TARGETDURATION":l.targetduration!==0&&ze(l,K,v),l.targetduration=Math.max(parseInt(w),1);break;case"VERSION":l.version!==null&&ze(l,K,v),l.version=parseInt(w);break;case"INDEPENDENT-SEGMENTS":break;case"ENDLIST":l.live||ze(l,K,v),l.live=!1;break;case"#":(w||V)&&S.tagList.push(V?[w,V]:[w]);break;case"DISCONTINUITY":p++,S.tagList.push(["DIS"]);break;case"GAP":S.gap=!0,S.tagList.push([K]);break;case"BITRATE":S.tagList.push([K,w]),E=parseInt(w)*1e3,B(E)?S.bitrate=E:E=0;break;case"DATERANGE":{const $=new le(w,l),H=new Yn($,l.dateRanges[$.ID],l.dateRangeTagCount);l.dateRangeTagCount++,H.isValid||l.skippedSegments?l.dateRanges[H.id]=H:re.warn(`Ignoring invalid DATERANGE tag: "${w}"`),S.tagList.push(["EXT-X-DATERANGE",w]);break}case"DEFINE":{{const $=new le(w,l);"IMPORT"in $?yl(l,$,n):Ir(l,$,t)}break}case"DISCONTINUITY-SEQUENCE":l.startCC!==0?ze(l,K,v):h.length>0&&Mr(l,K,v),l.startCC=p=parseInt(w);break;case"KEY":{const $=Cr(w,t,l);if($.isSupported()){if($.method==="NONE"){D=void 0;break}D||(D={});const H=D[$.keyFormat];H!=null&&H.matches($)||(H&&(D=ne({},D)),D[$.keyFormat]=$)}else re.warn(`[Keys] Ignoring unsupported EXT-X-KEY tag: "${w}"`);break}case"START":l.startTimeOffset=Pr(w);break;case"MAP":{const $=new le(w,l);if(S.duration){const H=new Fs(i,c);Or(H,$,s,D),u=H,S.initSegment=u,u.rawProgramDateTime&&!S.rawProgramDateTime&&(S.rawProgramDateTime=u.rawProgramDateTime)}else{const H=S.byteRangeEndOffset;if(H){const q=S.byteRangeStartOffset;b=`${H-q}@${q}`}else b=null;Or(S,$,s,D),u=S,_=!0}u.cc=p;break}case"SERVER-CONTROL":{I&&ze(l,K,v),I=new le(w),l.canBlockReload=I.bool("CAN-BLOCK-RELOAD"),l.canSkipUntil=I.optionalFloat("CAN-SKIP-UNTIL",0),l.canSkipDateRanges=l.canSkipUntil>0&&I.bool("CAN-SKIP-DATERANGES"),l.partHoldBack=I.optionalFloat("PART-HOLD-BACK",0),l.holdBack=I.optionalFloat("HOLD-BACK",0);break}case"PART-INF":{l.partTarget&&ze(l,K,v);const $=new le(w);l.partTarget=$.decimalFloatingPoint("PART-TARGET");break}case"PART":{let $=l.partList;$||($=l.partList=[]);const H=g>0?$[$.length-1]:void 0,q=g++,O=new le(w,l),F=new yo(O,S,c,q,H);$.push(F),S.duration+=F.duration;break}case"PRELOAD-HINT":{const $=new le(w,l);l.preloadHint=$;break}case"RENDITION-REPORT":{const $=new le(w,l);l.renditionReports=l.renditionReports||[],l.renditionReports.push($);break}default:re.warn(`line parsed but not handled: ${v}`);break}}}T&&!T.relurl?(h.pop(),y-=T.duration,l.partList&&(l.fragmentHint=T)):l.partList&&(di(S,T,d),S.cc=p,l.fragmentHint=S,D&&Fr(S,D,l)),l.targetduration||(l.playlistParsingError=new Error("Missing Target Duration"));const P=h.length,M=h[0],G=h[P-1];if(y+=l.skippedSegments*l.targetduration,y>0&&P&&G){l.averagetargetduration=y/P;const W=G.sn;l.endSN=W!=="initSegment"?W:0,l.live||(G.endList=!0),A>0&&(wl(h,A),M&&d.unshift(M))}return l.fragmentHint&&(y+=l.fragmentHint.duration),l.totalduration=y,d.length&&l.dateRangeTagCount&&M&&zn(d,l),l.endCC=p,l}}function zn(a,e){let t=a.length;if(!t)if(e.hasProgramDateTime){const o=e.fragments[e.fragments.length-1];a.push(o),t++}else return;const s=a[t-1],i=e.live?1/0:e.totalduration,r=Object.keys(e.dateRanges);for(let o=r.length;o--;){const c=e.dateRanges[r[o]],l=c.startDate.getTime();c.tagAnchor=s.ref;for(let h=t;h--;){var n;if(((n=a[h])==null?void 0:n.sn)=o||s===0){var n;const c=(((n=t[s+1])==null?void 0:n.start)||i)-r.start;if(e<=o+c*1e3){const l=t[s].sn-a.startSN;if(l<0)return-1;const h=a.fragments;if(h.length>t.length){const u=(t[s+1]||h[h.length-1]).sn-a.startSN;for(let f=u;f>l;f--){const g=h[f].programDateTime;if(e>=g&&es);["video","audio","text"].forEach(s=>{const i=t.filter(r=>_i(r,s));i.length&&(e[`${s}Codec`]=i.map(r=>r.split("/")[0]).join(","),t=t.filter(r=>i.indexOf(r)===-1))}),e.unknownCodecs=t}function wr(a,e,t){const s=e[t];s&&(a[t]=s)}function wl(a,e){let t=a[e];for(let s=e;s--;){const i=a[s];if(!i)return;i.programDateTime=t.programDateTime-i.duration*1e3,t=i}}function di(a,e,t){a.rawProgramDateTime?t.push(a):e!=null&&e.programDateTime&&(a.programDateTime=e.endProgramDateTime)}function Or(a,e,t,s){a.relurl=e.URI,e.BYTERANGE&&a.setByteRange(e.BYTERANGE),a.level=t,a.sn="initSegment",s&&(a.levelkeys=s),a.initSegment=null}function Fr(a,e,t){a.levelkeys=e;const{encryptedFragments:s}=t;(!s.length||s[s.length-1].levelkeys!==e)&&Object.keys(e).some(i=>e[i].isCommonEncryption)&&s.push(a)}function ze(a,e,t){a.playlistParsingError=new Error(`#EXT-X-${e} must not appear more than once (${t[0]})`)}function Mr(a,e,t){a.playlistParsingError=new Error(`#EXT-X-${e} must appear before the first Media Segment (${t[0]})`)}function Us(a,e){const t=e.startPTS;if(B(t)){let s=0,i;e.sn>a.sn?(s=t-a.start,i=a):(s=a.start-t,i=e),i.duration!==s&&i.setDuration(s)}else e.sn>a.sn?a.cc===e.cc&&a.minEndPTS?e.setStart(a.start+(a.minEndPTS-a.start)):e.setStart(a.start+a.duration):e.setStart(Math.max(a.start-e.duration,0))}function Qn(a,e,t,s,i,r,n){s-t<=0&&(n.warn("Fragment should have a positive duration",e),s=t+e.duration,r=i+e.duration);let c=t,l=s;const h=e.startPTS,d=e.endPTS;if(B(h)){const E=Math.abs(h-t);a&&E>a.totalduration?n.warn(`media timestamps and playlist times differ by ${E}s for level ${e.level} ${a.url}`):B(e.deltaPTS)?e.deltaPTS=Math.max(E,e.deltaPTS):e.deltaPTS=E,c=Math.max(t,h),t=Math.min(t,h),i=e.startDTS!==void 0?Math.min(i,e.startDTS):i,l=Math.min(s,d),s=Math.max(s,d),r=e.endDTS!==void 0?Math.max(r,e.endDTS):r}const u=t-e.start;e.start!==0&&e.setStart(t),e.setDuration(s-e.start),e.startPTS=t,e.maxStartPTS=c,e.startDTS=i,e.endPTS=s,e.minEndPTS=l,e.endDTS=r;const f=e.sn;if(!a||fa.endSN)return 0;let g;const y=f-a.startSN,p=a.fragments;for(p[y]=e,g=y;g>0;g--)Us(p[g],p[g-1]);for(g=y;g=0;h--){const d=i[h].initSegment;if(d){s=d;break}}a.fragmentHint&&delete a.fragmentHint.endPTS;let r;Nl(a,e,(h,d,u,f)=>{if((!e.startCC||e.skippedSegments)&&d.cc!==h.cc){const g=h.cc-d.cc;for(let y=u;y{var d;h&&(!h.initSegment||h.initSegment.relurl===((d=s)==null?void 0:d.relurl))&&(h.initSegment=s)}),e.skippedSegments){if(e.deltaUpdateFailed=n.some(h=>!h),e.deltaUpdateFailed){t.warn("[level-helper] Previous playlist missing segments skipped in delta playlist");for(let h=e.skippedSegments;h--;)n.shift();e.startSN=n[0].sn}else{e.canSkipDateRanges&&(e.dateRanges=Fl(a.dateRanges,e,t));const h=a.fragments.filter(d=>d.rawProgramDateTime);if(a.hasProgramDateTime&&!e.hasProgramDateTime)for(let d=1;d{d.elementaryStreams=h.elementaryStreams,d.stats=h.stats}),r?Qn(e,r,r.startPTS,r.endPTS,r.startDTS,r.endDTS,t):Zn(a,e),n.length&&(e.totalduration=e.edge-n[0].start),e.driftStartTime=a.driftStartTime,e.driftStart=a.driftStart;const l=e.advancedDateTime;if(e.advanced&&l){const h=e.edge;e.driftStart||(e.driftStartTime=l,e.driftStart=h),e.driftEndTime=l,e.driftEnd=h}else e.driftEndTime=a.driftEndTime,e.driftEnd=a.driftEnd,e.advancedDateTime=a.advancedDateTime;e.requestScheduled===-1&&(e.requestScheduled=a.requestScheduled)}function Fl(a,e,t){const{dateRanges:s,recentlyRemovedDateranges:i}=e,r=ne({},a);i&&i.forEach(c=>{delete r[c]});const o=Object.keys(r).length;return o?(Object.keys(s).forEach(c=>{const l=r[c],h=new Yn(s[c].attr,l);h.isValid?(r[c]=h,l||(h.tagOrder+=o)):t.warn(`Ignoring invalid Playlist Delta Update DATERANGE tag: "${oe(s[c].attr)}"`)}),r):s}function Ml(a,e,t){if(a&&e){let s=0;for(let i=0,r=a.length;i<=r;i++){const n=a[i],o=e[i+s];n&&o&&n.index===o.index&&n.fragment.sn===o.fragment.sn?t(n,o):s--}}}function Nl(a,e,t){const s=e.skippedSegments,i=Math.max(a.startSN,e.startSN)-e.startSN,r=(a.fragmentHint?1:0)+(s?e.endSN:Math.min(a.endSN,e.endSN))-e.startSN,n=e.startSN-a.startSN,o=e.fragmentHint?e.fragments.concat(e.fragmentHint):e.fragments,c=a.fragmentHint?a.fragments.concat(a.fragmentHint):a.fragments;for(let l=i;l<=r;l++){const h=c[n+l];let d=o[l];if(s&&!d&&h&&(d=e.fragments[l]=h),h&&d){t(h,d,l,o);const u=h.relurl,f=d.relurl;if(u&&Bl(u,f)){e.playlistParsingError=Nr(`media sequence mismatch ${d.sn}:`,a,e,h,d);return}else if(h.cc!==d.cc){e.playlistParsingError=Nr(`discontinuity sequence mismatch (${h.cc}!=${d.cc})`,a,e,h,d);return}}}}function Nr(a,e,t,s,i){return new Error(`${a} ${i.url} + Time to underbuffer: ${ee.toFixed(3)} s`),i.abortRequests(),this.fragCurrent=this.partCurrent=null,Y>f){let X=this.findBestLevel(this.hls.levels[f].bitrate,f,Y,0,ee,1,1);X===-1&&(X=f),this.hls.nextLoadLevel=this.hls.nextAutoLevel=X,this.resetEstimator(this.hls.levels[X].bitrate)}}};p||$>K*2?j():this.timer=self.setInterval(j,K*1e3),n.trigger(m.FRAG_LOAD_EMERGENCY_ABORTED,{frag:i,part:r,stats:h})},this.hls=e,this.bwEstimator=this.initEstimator(),this.registerListeners()}resetEstimator(e){e&&(this.log(`setting initial bwe to ${e}`),this.hls.config.abrEwmaDefaultEstimate=e),this.firstSelection=-1,this.bwEstimator=this.initEstimator()}initEstimator(){const e=this.hls.config;return new Ka(e.abrEwmaSlowVoD,e.abrEwmaFastVoD,e.abrEwmaDefaultEstimate)}registerListeners(){const{hls:e}=this;e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.FRAG_LOADING,this.onFragLoading,this),e.on(m.FRAG_LOADED,this.onFragLoaded,this),e.on(m.FRAG_BUFFERED,this.onFragBuffered,this),e.on(m.LEVEL_SWITCHING,this.onLevelSwitching,this),e.on(m.LEVEL_LOADED,this.onLevelLoaded,this),e.on(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.on(m.MAX_AUTO_LEVEL_UPDATED,this.onMaxAutoLevelUpdated,this),e.on(m.ERROR,this.onError,this)}unregisterListeners(){const{hls:e}=this;e&&(e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.FRAG_LOADING,this.onFragLoading,this),e.off(m.FRAG_LOADED,this.onFragLoaded,this),e.off(m.FRAG_BUFFERED,this.onFragBuffered,this),e.off(m.LEVEL_SWITCHING,this.onLevelSwitching,this),e.off(m.LEVEL_LOADED,this.onLevelLoaded,this),e.off(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.off(m.MAX_AUTO_LEVEL_UPDATED,this.onMaxAutoLevelUpdated,this),e.off(m.ERROR,this.onError,this))}destroy(){this.unregisterListeners(),this.clearTimer(),this.hls=this._abandonRulesCheck=this.supportedCache=null,this.fragCurrent=this.partCurrent=null}onManifestLoading(e,t){this.lastLoadedFragLevel=-1,this.firstSelection=-1,this.lastLevelLoadSec=0,this.supportedCache={},this.fragCurrent=this.partCurrent=null,this.onLevelsUpdated(),this.clearTimer()}onLevelsUpdated(){this.lastLoadedFragLevel>-1&&this.fragCurrent&&(this.lastLoadedFragLevel=this.fragCurrent.level),this._nextAutoLevel=-1,this.onMaxAutoLevelUpdated(),this.codecTiers=null,this.audioTracksByGroup=null}onMaxAutoLevelUpdated(){this.firstSelection=-1,this.nextAutoLevelKey=""}onFragLoading(e,t){const s=t.frag;if(!this.ignoreFragment(s)){if(!s.bitrateTest){var i;this.fragCurrent=s,this.partCurrent=(i=t.part)!=null?i:null}this.clearTimer(),this.timer=self.setInterval(this._abandonRulesCheck,100)}}onLevelSwitching(e,t){this.clearTimer()}onError(e,t){if(!t.fatal)switch(t.details){case R.BUFFER_ADD_CODEC_ERROR:case R.BUFFER_APPEND_ERROR:this.lastLoadedFragLevel=-1,this.firstSelection=-1;break;case R.FRAG_LOAD_TIMEOUT:{const s=t.frag,{fragCurrent:i,partCurrent:r}=this;if(s&&i&&s.sn===i.sn&&s.level===i.level){const n=performance.now(),o=r?r.stats:s.stats,c=n-o.loading.start,l=o.loading.first?o.loading.first-o.loading.start:-1;if(o.loaded&&l>-1){const u=this.bwEstimator.getEstimateTTFB();this.bwEstimator.sample(c-Math.min(u,l),o.loaded)}else this.bwEstimator.sampleTTFB(c)}break}}}getTimeToLoadFrag(e,t,s,i){const r=e+s/t,n=i?e+this.lastLevelLoadSec:0;return r+n}onLevelLoaded(e,t){const s=this.hls.config,{loading:i}=t.stats,r=i.end-i.first;M(r)&&(this.lastLevelLoadSec=r/1e3),t.details.live?this.bwEstimator.update(s.abrEwmaSlowLive,s.abrEwmaFastLive):this.bwEstimator.update(s.abrEwmaSlowVoD,s.abrEwmaFastVoD),this.timer>-1&&this._abandonRulesCheck(t.levelInfo)}onFragLoaded(e,{frag:t,part:s}){const i=s?s.stats:t.stats;if(t.type===B.MAIN&&this.bwEstimator.sampleTTFB(i.loading.first-i.loading.start),!this.ignoreFragment(t)){if(this.clearTimer(),t.level===this._nextAutoLevel&&(this._nextAutoLevel=-1),this.firstSelection=-1,this.hls.config.abrMaxWithRealBitrate){const r=s?s.duration:t.duration,n=this.hls.levels[t.level],o=(n.loaded?n.loaded.bytes:0)+i.loaded,c=(n.loaded?n.loaded.duration:0)+r;n.loaded={bytes:o,duration:c},n.realBitrate=Math.round(8*o/c)}if(t.bitrateTest){const r={stats:i,frag:t,part:s,id:t.type};this.onFragBuffered(m.FRAG_BUFFERED,r),t.bitrateTest=!1}else this.lastLoadedFragLevel=t.level}}onFragBuffered(e,t){const{frag:s,part:i}=t,r=i!=null&&i.stats.loaded?i.stats:s.stats;if(r.aborted||this.ignoreFragment(s))return;const n=r.parsing.end-r.loading.start-Math.min(r.loading.first-r.loading.start,this.bwEstimator.getEstimateTTFB());this.bwEstimator.sample(n,r.loaded),r.bwEstimate=this.getBwEstimate(),s.bitrateTest?this.bitrateTestDelay=n/1e3:this.bitrateTestDelay=0}ignoreFragment(e){return e.type!==B.MAIN||e.sn==="initSegment"}clearTimer(){this.timer>-1&&(self.clearInterval(this.timer),this.timer=-1)}get firstAutoLevel(){const{maxAutoLevel:e,minAutoLevel:t}=this.hls,s=this.getBwEstimate(),i=this.hls.config.maxStarvationDelay,r=this.findBestLevel(s,t,e,0,i,1,1);if(r>-1)return r;const n=this.hls.firstLevel,o=Math.min(Math.max(n,t),e);return this.warn(`Could not find best starting auto level. Defaulting to first in playlist ${n} clamped to ${o}`),o}get forcedAutoLevel(){return this.nextAutoLevelKey?-1:this._nextAutoLevel}get nextAutoLevel(){const e=this.forcedAutoLevel,s=this.bwEstimator.canEstimate(),i=this.lastLoadedFragLevel>-1;if(e!==-1&&(!s||!i||this.nextAutoLevelKey===this.getAutoLevelKey()))return e;const r=s&&i?this.getNextABRAutoLevel():this.firstAutoLevel;if(e!==-1){const n=this.hls.levels;if(n.length>Math.max(e,r)&&n[e].loadError<=n[r].loadError)return e}return this._nextAutoLevel=r,this.nextAutoLevelKey=this.getAutoLevelKey(),r}getAutoLevelKey(){return`${this.getBwEstimate()}_${this.getStarvationDelay().toFixed(2)}`}getNextABRAutoLevel(){const{fragCurrent:e,partCurrent:t,hls:s}=this;if(s.levels.length<=1)return s.loadLevel;const{maxAutoLevel:i,config:r,minAutoLevel:n}=s,o=t?t.duration:e?e.duration:0,c=this.getBwEstimate(),l=this.getStarvationDelay();let h=r.abrBandWidthFactor,u=r.abrBandWidthUpFactor;if(l){const p=this.findBestLevel(c,n,i,l,0,h,u);if(p>=0)return this.rebufferNotice=-1,p}let d=o?Math.min(o,r.maxStarvationDelay):r.maxStarvationDelay;if(!l){const p=this.bitrateTestDelay;p&&(d=(o?Math.min(o,r.maxLoadingDelay):r.maxLoadingDelay)-p,this.info(`bitrate test took ${Math.round(1e3*p)}ms, set first fragment max fetchDuration to ${Math.round(1e3*d)} ms`),h=u=1)}const f=this.findBestLevel(c,n,i,l,d,h,u);if(this.rebufferNotice!==f&&(this.rebufferNotice=f,this.info(`${l?"rebuffering expected":"buffer is empty"}, optimal quality level ${f}`)),f>-1)return f;const g=s.levels[n],y=s.loadLevelObj;return y&&(g==null?void 0:g.bitrate)=t;k--){var $;const G=g[k],N=k>u;if(!G)continue;if(E.useMediaCapabilities&&!G.supportedResult&&!G.supportedPromise){const X=navigator.mediaCapabilities;typeof(X==null?void 0:X.decodingInfo)=="function"&&Ao(G,I,D,A,e,_)?(G.supportedPromise=Sn(G,I,X,this.supportedCache),G.supportedPromise.then(Z=>{if(!this.hls)return;G.supportedResult=Z;const ye=this.hls.levels,fe=ye.indexOf(G);Z.error?this.warn(`MediaCapabilities decodingInfo error: "${Z.error}" for level ${fe} ${ne(Z)}`):Z.supported?Z.decodingInfoResults.some(be=>be.smooth===!1||be.powerEfficient===!1)&&this.log(`MediaCapabilities decodingInfo for level ${fe} not smooth or powerEfficient: ${ne(Z)}`):(this.warn(`Unsupported MediaCapabilities decodingInfo result for level ${fe} ${ne(Z)}`),fe>-1&&ye.length>1&&(this.log(`Removing unsupported level ${fe}`),this.hls.removeLevel(fe),this.hls.loadLevel===-1&&(this.hls.nextLoadLevel=0)))}).catch(Z=>{this.warn(`Error handling MediaCapabilities decodingInfo: ${Z}`)})):G.supportedResult=En}if((x&&G.codecSet!==x||D&&G.videoRange!==D||N&&A>G.frameRate||!N&&A>0&&AX.smooth===!1))&&(!v||k!==P)){H.push(k);continue}const K=G.details,Y=(f?K==null?void 0:K.partTarget:K==null?void 0:K.averagetargetduration)||F;let w;N?w=o*e:w=n*e;const O=F&&i>=F*2&&r===0?G.averageBitrate:G.maxBitrate,j=this.getTimeToLoadFrag(U,w,O*Y,K===void 0);if(w>=O&&(k===h||G.loadError===0&&G.fragmentError===0)&&(j<=U||!M(j)||S&&!this.bitrateTestDelay||j${k} adjustedbw(${Math.round(w)})-bitrate=${Math.round(w-O)} ttfb:${U.toFixed(1)} avgDuration:${Y.toFixed(1)} maxFetchDuration:${l.toFixed(1)} fetchDuration:${j.toFixed(1)} firstSelection:${v} codecSet:${G.codecSet} videoRange:${G.videoRange} hls.loadLevel:${p}`)),v&&(this.firstSelection=k),k}}return-1}set nextAutoLevel(e){const t=this.deriveNextAutoLevel(e);this._nextAutoLevel!==t&&(this.nextAutoLevelKey="",this._nextAutoLevel=t)}deriveNextAutoLevel(e){const{maxAutoLevel:t,minAutoLevel:s}=this.hls;return Math.min(Math.max(e,s),t)}}const An={search:function(a,e){let t=0,s=a.length-1,i=null,r=null;for(;t<=s;){i=(t+s)/2|0,r=a[i];const n=e(r);if(n>0)t=i+1;else if(n<0)s=i-1;else return r}return null}};function Uo(a,e,t){if(e===null||!Array.isArray(a)||!a.length||!M(e))return null;const s=a[0].programDateTime;if(e<(s||0))return null;const i=a[a.length-1].endProgramDateTime;if(e>=(i||0))return null;for(let r=0;r0&&o<15e-7&&(t+=15e-7),r&&a.level!==r.level&&r.end<=a.end&&(r=e[2+a.sn-e[0].sn]||null)}else t===0&&e[0].start===0&&(r=e[0]);if(r&&((!a||a.level===r.level)&&sr(t,s,r)===0||$o(r,a,Math.min(i,s))))return r;const n=An.search(e,sr.bind(null,t,s));return n&&(n!==a||!r)?n:r}function $o(a,e,t){if(e&&e.start===0&&e.level0){const s=e.tagList.reduce((i,r)=>(r[0]==="INF"&&(i+=parseFloat(r[1])),i),t);return a.start<=s}return!1}function sr(a=0,e=0,t){if(t.start<=a&&t.start+t.duration>a)return 0;const s=Math.min(e,t.duration+(t.deltaPTS?t.deltaPTS:0));return t.start+t.duration-s<=a?1:t.start-s>a&&t.start?-1:0}function Go(a,e,t){const s=Math.min(e,t.duration+(t.deltaPTS?t.deltaPTS:0))*1e3;return(t.endProgramDateTime||0)-s>a}function In(a,e,t){if(a&&a.startCC<=e&&a.endCC>=e){let s=a.fragments;const{fragmentHint:i}=a;i&&(s=s.concat(i));let r;return An.search(s,n=>n.cce?-1:(r=n,n.end<=t?1:n.start>t?-1:0)),r||null}return null}function ds(a){switch(a.details){case R.FRAG_LOAD_TIMEOUT:case R.KEY_LOAD_TIMEOUT:case R.LEVEL_LOAD_TIMEOUT:case R.MANIFEST_LOAD_TIMEOUT:return!0}return!1}function Ln(a){return a.details.startsWith("key")}function Rn(a){return Ln(a)&&!!a.frag&&!a.frag.decryptdata}function ir(a,e){const t=ds(e);return a.default[`${t?"timeout":"error"}Retry`]}function Ei(a,e){const t=a.backoff==="linear"?1:Math.pow(2,e);return Math.min(t*a.retryDelayMs,a.maxRetryDelayMs)}function rr(a){return te(te({},a),{errorRetry:null,timeoutRetry:null})}function fs(a,e,t,s){if(!a)return!1;const i=s==null?void 0:s.code,r=e499)}function Zs(a){return a===0&&navigator.onLine===!1}var ge={DoNothing:0,SendAlternateToPenaltyBox:2,RemoveAlternatePermanently:3,RetryRequest:5},Ae={None:0,MoveAllAlternatesMatchingHost:1,MoveAllAlternatesMatchingHDCP:2,MoveAllAlternatesMatchingKey:4};class Vo extends Ce{constructor(e){super("error-controller",e.logger),this.hls=void 0,this.playlistError=0,this.hls=e,this.registerListeners()}registerListeners(){const e=this.hls;e.on(m.ERROR,this.onError,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.LEVEL_UPDATED,this.onLevelUpdated,this)}unregisterListeners(){const e=this.hls;e&&(e.off(m.ERROR,this.onError,this),e.off(m.ERROR,this.onErrorOut,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.LEVEL_UPDATED,this.onLevelUpdated,this))}destroy(){this.unregisterListeners(),this.hls=null}startLoad(e){}stopLoad(){this.playlistError=0}getVariantLevelIndex(e){return(e==null?void 0:e.type)===B.MAIN?e.level:this.getVariantIndex()}getVariantIndex(){var e;const t=this.hls,s=t.currentLevel;return(e=t.loadLevelObj)!=null&&e.details||s===-1?t.loadLevel:s}variantHasKey(e,t){if(e){var s;if((s=e.details)!=null&&s.hasKey(t))return!0;const i=e.audioGroups;if(i)return this.hls.allAudioTracks.filter(n=>i.indexOf(n.groupId)>=0).some(n=>{var o;return(o=n.details)==null?void 0:o.hasKey(t)})}return!1}onManifestLoading(){this.playlistError=0}onLevelUpdated(){this.playlistError=0}onError(e,t){var s;if(t.fatal)return;const i=this.hls,r=t.context;switch(t.details){case R.FRAG_LOAD_ERROR:case R.FRAG_LOAD_TIMEOUT:case R.KEY_LOAD_ERROR:case R.KEY_LOAD_TIMEOUT:t.errorAction=this.getFragRetryOrSwitchAction(t);return;case R.FRAG_PARSING_ERROR:if((s=t.frag)!=null&&s.gap){t.errorAction=Et();return}case R.FRAG_GAP:case R.FRAG_DECRYPT_ERROR:{t.errorAction=this.getFragRetryOrSwitchAction(t),t.errorAction.action=ge.SendAlternateToPenaltyBox;return}case R.LEVEL_EMPTY_ERROR:case R.LEVEL_PARSING_ERROR:{var n;const c=t.parent===B.MAIN?t.level:i.loadLevel;t.details===R.LEVEL_EMPTY_ERROR&&((n=t.context)!=null&&(n=n.levelDetails)!=null&&n.live)?t.errorAction=this.getPlaylistRetryOrSwitchAction(t,c):(t.levelRetry=!1,t.errorAction=this.getLevelSwitchAction(t,c))}return;case R.LEVEL_LOAD_ERROR:case R.LEVEL_LOAD_TIMEOUT:typeof(r==null?void 0:r.level)=="number"&&(t.errorAction=this.getPlaylistRetryOrSwitchAction(t,r.level));return;case R.AUDIO_TRACK_LOAD_ERROR:case R.AUDIO_TRACK_LOAD_TIMEOUT:case R.SUBTITLE_LOAD_ERROR:case R.SUBTITLE_TRACK_LOAD_TIMEOUT:if(r){const c=i.loadLevelObj;if(c&&(r.type===Q.AUDIO_TRACK&&c.hasAudioGroup(r.groupId)||r.type===Q.SUBTITLE_TRACK&&c.hasSubtitleGroup(r.groupId))){t.errorAction=this.getPlaylistRetryOrSwitchAction(t,i.loadLevel),t.errorAction.action=ge.SendAlternateToPenaltyBox,t.errorAction.flags=Ae.MoveAllAlternatesMatchingHost;return}}return;case R.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED:t.errorAction={action:ge.SendAlternateToPenaltyBox,flags:Ae.MoveAllAlternatesMatchingHDCP};return;case R.KEY_SYSTEM_SESSION_UPDATE_FAILED:case R.KEY_SYSTEM_STATUS_INTERNAL_ERROR:case R.KEY_SYSTEM_NO_SESSION:t.errorAction={action:ge.SendAlternateToPenaltyBox,flags:Ae.MoveAllAlternatesMatchingKey};return;case R.BUFFER_ADD_CODEC_ERROR:case R.REMUX_ALLOC_ERROR:case R.BUFFER_APPEND_ERROR:if(!t.errorAction){var o;t.errorAction=this.getLevelSwitchAction(t,(o=t.level)!=null?o:i.loadLevel)}return;case R.INTERNAL_EXCEPTION:case R.BUFFER_APPENDING_ERROR:case R.BUFFER_FULL_ERROR:case R.LEVEL_SWITCH_ERROR:case R.BUFFER_STALLED_ERROR:case R.BUFFER_SEEK_OVER_HOLE:case R.BUFFER_NUDGE_ON_STALL:t.errorAction=Et();return}t.type===V.KEY_SYSTEM_ERROR&&(t.levelRetry=!1,t.errorAction=Et())}getPlaylistRetryOrSwitchAction(e,t){const s=this.hls,i=ir(s.config.playlistLoadPolicy,e),r=this.playlistError++;if(fs(i,r,ds(e),e.response))return{action:ge.RetryRequest,flags:Ae.None,retryConfig:i,retryCount:r};const o=this.getLevelSwitchAction(e,t);return i&&(o.retryConfig=i,o.retryCount=r),o}getFragRetryOrSwitchAction(e){const t=this.hls,s=this.getVariantLevelIndex(e.frag),i=t.levels[s],{fragLoadPolicy:r,keyLoadPolicy:n}=t.config,o=ir(Ln(e)?n:r,e),c=t.levels.reduce((h,u)=>h+u.fragmentError,0);if(i&&(e.details!==R.FRAG_GAP&&i.fragmentError++,!Rn(e)&&fs(o,c,ds(e),e.response)))return{action:ge.RetryRequest,flags:Ae.None,retryConfig:o,retryCount:c};const l=this.getLevelSwitchAction(e,s);return o&&(l.retryConfig=o,l.retryCount=c),l}getLevelSwitchAction(e,t){const s=this.hls;t==null&&(t=s.loadLevel);const i=this.hls.levels[t];if(i){var r,n;const l=e.details;i.loadError++,l===R.BUFFER_APPEND_ERROR&&i.fragmentError++;let h=-1;const{levels:u,loadLevel:d,minAutoLevel:f,maxAutoLevel:g}=s;!s.autoLevelEnabled&&!s.config.preserveManualLevelOnError&&(s.loadLevel=-1);const y=(r=e.frag)==null?void 0:r.type,E=(y===B.AUDIO&&l===R.FRAG_PARSING_ERROR||e.sourceBufferName==="audio"&&(l===R.BUFFER_ADD_CODEC_ERROR||l===R.BUFFER_APPEND_ERROR))&&u.some(({audioCodec:D})=>i.audioCodec!==D),S=e.sourceBufferName==="video"&&(l===R.BUFFER_ADD_CODEC_ERROR||l===R.BUFFER_APPEND_ERROR)&&u.some(({codecSet:D,audioCodec:A})=>i.codecSet!==D&&i.audioCodec===A),{type:v,groupId:x}=(n=e.context)!=null?n:{};for(let D=u.length;D--;){const A=(D+d)%u.length;if(A!==d&&A>=f&&A<=g&&u[A].loadError===0){var o,c;const _=u[A];if(l===R.FRAG_GAP&&y===B.MAIN&&e.frag){const b=u[A].details;if(b){const I=lt(e.frag,b.fragments,e.frag.start);if(I!=null&&I.gap)continue}}else{if(v===Q.AUDIO_TRACK&&_.hasAudioGroup(x)||v===Q.SUBTITLE_TRACK&&_.hasSubtitleGroup(x))continue;if(y===B.AUDIO&&(o=i.audioGroups)!=null&&o.some(b=>_.hasAudioGroup(b))||y===B.SUBTITLE&&(c=i.subtitleGroups)!=null&&c.some(b=>_.hasSubtitleGroup(b))||E&&i.audioCodec===_.audioCodec||S&&i.codecSet===_.codecSet||!E&&i.codecSet!==_.codecSet)continue}h=A;break}}if(h>-1&&s.loadLevel!==h)return e.levelRetry=!0,this.playlistError=0,{action:ge.SendAlternateToPenaltyBox,flags:Ae.None,nextAutoLevel:h}}return{action:ge.SendAlternateToPenaltyBox,flags:Ae.MoveAllAlternatesMatchingHost}}onErrorOut(e,t){var s;switch((s=t.errorAction)==null?void 0:s.action){case ge.DoNothing:break;case ge.SendAlternateToPenaltyBox:this.sendAlternateToPenaltyBox(t),!t.errorAction.resolved&&t.details!==R.FRAG_GAP?t.fatal=!0:/MediaSource readyState: ended/.test(t.error.message)&&(this.warn(`MediaSource ended after "${t.sourceBufferName}" sourceBuffer append error. Attempting to recover from media error.`),this.hls.recoverMediaError());break}if(t.fatal){this.hls.stopLoad();return}}sendAlternateToPenaltyBox(e){const t=this.hls,s=e.errorAction;if(!s)return;const{flags:i}=s,r=s.nextAutoLevel;switch(i){case Ae.None:this.switchLevel(e,r);break;case Ae.MoveAllAlternatesMatchingHDCP:{const c=this.getVariantLevelIndex(e.frag),l=t.levels[c],h=l==null?void 0:l.attrs["HDCP-LEVEL"];if(s.hdcpLevel=h,h==="NONE")this.warn("HDCP policy resticted output with HDCP-LEVEL=NONE");else if(h){t.maxHdcpLevel=Qs[Qs.indexOf(h)-1],s.resolved=!0,this.warn(`Restricting playback to HDCP-LEVEL of "${t.maxHdcpLevel}" or lower`);break}}case Ae.MoveAllAlternatesMatchingKey:{const c=e.decryptdata;if(c){const l=this.hls.levels,h=l.length;for(let d=h;d--;)if(this.variantHasKey(l[d],c)){var n,o;this.log(`Banned key found in level ${d} (${l[d].bitrate}bps) or audio group "${(n=l[d].audioGroups)==null?void 0:n.join(",")}" (${(o=e.frag)==null?void 0:o.type} fragment) ${me(c.keyId||[])}`),l[d].fragmentError++,l[d].loadError++,this.log(`Removing level ${d} with key error (${e.error})`),this.hls.removeLevel(d)}const u=e.frag;if(this.hls.levels.length{const c=this.fragments[o];if(!c||n>=c.body.sn)return;if(!c.buffered&&(!c.loaded||r)){c.body.type===s&&this.removeFragment(c.body);return}const l=c.range[e];if(l){if(l.time.length===0){this.removeFragment(c.body);return}l.time.some(h=>{const u=!this.isTimeBuffered(h.startPTS,h.endPTS,t);return u&&this.removeFragment(c.body),u})}})}detectPartialFragments(e){const t=this.timeRanges;if(!t||e.frag.sn==="initSegment")return;const s=e.frag,i=ut(s),r=this.fragments[i];if(!r||r.buffered&&s.gap)return;const n=!s.relurl;Object.keys(t).forEach(o=>{const c=s.elementaryStreams[o];if(!c)return;const l=t[o],h=n||c.partial===!0;r.range[o]=this.getBufferedTimes(s,e.part,h,l)}),r.loaded=null,Object.keys(r.range).length?(this.bufferedEnd(r,s),Kt(r)||this.removeParts(s.sn-1,s.type)):this.removeFragment(r.body)}bufferedEnd(e,t){e.buffered=!0,(e.body.endList=t.endList||e.body.endList)&&(this.endListFragments[e.body.type]=e)}removeParts(e,t){const s=this.activePartLists[t];s&&(this.activePartLists[t]=nr(s,i=>i.fragment.sn>=e))}fragBuffered(e,t){const s=ut(e);let i=this.fragments[s];!i&&t&&(i=this.fragments[s]={body:e,appendedPTS:null,loaded:null,buffered:!1,range:Object.create(null)},e.gap&&(this.hasGaps=!0)),i&&(i.loaded=null,this.bufferedEnd(i,e))}getBufferedTimes(e,t,s,i){const r={time:[],partial:s},n=e.start,o=e.end,c=e.minEndPTS||o,l=e.maxStartPTS||n;for(let h=0;h=u&&c<=d){r.time.push({startPTS:Math.max(n,i.start(h)),endPTS:Math.min(o,i.end(h))});break}else if(nu){const f=Math.max(n,i.start(h)),g=Math.min(o,i.end(h));g>f&&(r.partial=!0,r.time.push({startPTS:f,endPTS:g}))}else if(o<=u)break}return r}getPartialFragment(e){let t=null,s,i,r,n=0;const{bufferPadding:o,fragments:c}=this;return Object.keys(c).forEach(l=>{const h=c[l];h&&Kt(h)&&(i=h.body.start-o,r=h.body.end+o,e>=i&&e<=r&&(s=Math.min(e-i,r-e),n<=s&&(t=h.body,n=s)))}),t}isEndListAppended(e){const t=this.endListFragments[e];return t!==void 0&&(t.buffered||Kt(t))}getState(e){const t=ut(e),s=this.fragments[t];return s?s.buffered?Kt(s)?ue.PARTIAL:ue.OK:ue.APPENDING:ue.NOT_LOADED}isTimeBuffered(e,t,s){let i,r;for(let n=0;n=i&&t<=r)return!0;if(t<=i)return!1}return!1}onManifestLoading(){this.removeAllFragments()}onFragLoaded(e,t){if(t.frag.sn==="initSegment"||t.frag.bitrateTest)return;const s=t.frag,i=t.part?null:t,r=ut(s);this.fragments[r]={body:s,appendedPTS:null,loaded:i,buffered:!1,range:Object.create(null)}}onBufferAppended(e,t){const{frag:s,part:i,timeRanges:r,type:n}=t;if(s.sn==="initSegment")return;const o=s.type;if(i){let l=this.activePartLists[o];l||(this.activePartLists[o]=l=[]),l.push(i)}this.timeRanges=r;const c=r[n];this.detectEvictedFragments(n,c,o,i)}onFragBuffered(e,t){this.detectPartialFragments(t)}hasFragment(e){const t=ut(e);return!!this.fragments[t]}hasFragments(e){const{fragments:t}=this,s=Object.keys(t);if(!e)return s.length>0;for(let i=s.length;i--;){const r=t[s[i]];if((r==null?void 0:r.body.type)===e)return!0}return!1}hasParts(e){var t;return!!((t=this.activePartLists[e])!=null&&t.length)}removeFragmentsInRange(e,t,s,i,r){i&&!this.hasGaps||Object.keys(this.fragments).forEach(n=>{const o=this.fragments[n];if(!o)return;const c=o.body;c.type!==s||i&&!c.gap||c.starte&&(o.buffered||r)&&this.removeFragment(c)})}removeFragment(e){const t=ut(e);e.clearElementaryStreamInfo();const s=this.activePartLists[e.type];if(s){const i=e.sn;this.activePartLists[e.type]=nr(s,r=>r.fragment.sn!==i)}delete this.fragments[t],e.endList&&delete this.endListFragments[e.type]}removeAllFragments(){var e;this.fragments=Object.create(null),this.endListFragments=Object.create(null),this.activePartLists=Object.create(null),this.hasGaps=!1;const t=(e=this.hls)==null||(e=e.latestLevelDetails)==null?void 0:e.partList;t&&t.forEach(s=>s.clearElementaryStreamInfo())}}function Kt(a){var e,t,s;return a.buffered&&!!(a.body.gap||(e=a.range.video)!=null&&e.partial||(t=a.range.audio)!=null&&t.partial||(s=a.range.audiovideo)!=null&&s.partial)}function ut(a){return`${a.type}_${a.level}_${a.sn}`}function nr(a,e){return a.filter(t=>{const s=e(t);return s||t.clearElementaryStreamInfo(),s})}var et={cbc:0,ctr:1};class Yo{constructor(e,t,s){this.subtle=void 0,this.aesIV=void 0,this.aesMode=void 0,this.subtle=e,this.aesIV=t,this.aesMode=s}decrypt(e,t){switch(this.aesMode){case et.cbc:return this.subtle.decrypt({name:"AES-CBC",iv:this.aesIV},t,e);case et.ctr:return this.subtle.decrypt({name:"AES-CTR",counter:this.aesIV,length:64},t,e);default:throw new Error(`[AESCrypto] invalid aes mode ${this.aesMode}`)}}}function Wo(a){const e=a.byteLength,t=e&&new DataView(a.buffer).getUint8(e-1);return t?a.slice(0,e-t):a}class qo{constructor(){this.rcon=[0,1,2,4,8,16,32,64,128,27,54],this.subMix=[new Uint32Array(256),new Uint32Array(256),new Uint32Array(256),new Uint32Array(256)],this.invSubMix=[new Uint32Array(256),new Uint32Array(256),new Uint32Array(256),new Uint32Array(256)],this.sBox=new Uint32Array(256),this.invSBox=new Uint32Array(256),this.key=new Uint32Array(0),this.ksRows=0,this.keySize=0,this.keySchedule=void 0,this.invKeySchedule=void 0,this.initTable()}uint8ArrayToUint32Array_(e){const t=new DataView(e),s=new Uint32Array(4);for(let i=0;i<4;i++)s[i]=t.getUint32(i*4);return s}initTable(){const e=this.sBox,t=this.invSBox,s=this.subMix,i=s[0],r=s[1],n=s[2],o=s[3],c=this.invSubMix,l=c[0],h=c[1],u=c[2],d=c[3],f=new Uint32Array(256);let g=0,y=0,p=0;for(p=0;p<256;p++)p<128?f[p]=p<<1:f[p]=p<<1^283;for(p=0;p<256;p++){let E=y^y<<1^y<<2^y<<3^y<<4;E=E>>>8^E&255^99,e[g]=E,t[E]=g;const T=f[g],S=f[T],v=f[S];let x=f[E]*257^E*16843008;i[g]=x<<24|x>>>8,r[g]=x<<16|x>>>16,n[g]=x<<8|x>>>24,o[g]=x,x=v*16843009^S*65537^T*257^g*16843008,l[E]=x<<24|x>>>8,h[E]=x<<16|x>>>16,u[E]=x<<8|x>>>24,d[E]=x,g?(g=T^f[f[f[v^T]]],y^=f[f[y]]):g=y=1}}expandKey(e){const t=this.uint8ArrayToUint32Array_(e);let s=!0,i=0;for(;i{const o=ArrayBuffer.isView(e)?e:new Uint8Array(e);this.softwareDecrypt(o,t,s,i);const c=this.flush();c?r(c.buffer):n(new Error("[softwareDecrypt] Failed to decrypt data"))}):this.webCryptoDecrypt(new Uint8Array(e),t,s,i)}softwareDecrypt(e,t,s,i){const{currentIV:r,currentResult:n,remainderData:o}=this;if(i!==et.cbc||t.byteLength!==16)return se.warn("SoftwareDecrypt: can only handle AES-128-CBC"),null;this.logOnce("JS AES decrypt"),o&&(e=De(o,e),this.remainderData=null);const c=this.getValidChunk(e);if(!c.length)return null;r&&(s=r);let l=this.softwareDecrypter;l||(l=this.softwareDecrypter=new qo),l.expandKey(t);const h=n;return this.currentResult=l.decrypt(c.buffer,0,s),this.currentIV=c.slice(-16).buffer,h||null}webCryptoDecrypt(e,t,s,i){if(this.key!==t||!this.fastAesKey){if(!this.subtle)return Promise.resolve(this.onWebCryptoError(e,t,s,i));this.key=t,this.fastAesKey=new jo(this.subtle,t,i)}return this.fastAesKey.expandKey().then(r=>this.subtle?(this.logOnce("WebCrypto AES decrypt"),new Yo(this.subtle,new Uint8Array(s),i).decrypt(e.buffer,r)):Promise.reject(new Error("web crypto not initialized"))).catch(r=>(se.warn(`[decrypter]: WebCrypto Error, disable WebCrypto API, ${r.name}: ${r.message}`),this.onWebCryptoError(e,t,s,i)))}onWebCryptoError(e,t,s,i){const r=this.enableSoftwareAES;if(r){this.useSoftware=!0,this.logEnabled=!0,this.softwareDecrypt(e,t,s,i);const n=this.flush();if(n)return n.buffer}throw new Error("WebCrypto"+(r?" and softwareDecrypt":"")+": failed to decrypt data")}getValidChunk(e){let t=e;const s=e.length-e.length%zo;return s!==e.length&&(t=e.slice(0,s),this.remainderData=e.slice(s)),t}logOnce(e){this.logEnabled&&(se.log(`[decrypter]: ${e}`),this.logEnabled=!1)}}const ar=Math.pow(2,17);class Qo{constructor(e){this.config=void 0,this.loader=null,this.partLoadTimeout=-1,this.config=e}destroy(){this.loader&&(this.loader.destroy(),this.loader=null)}abort(){this.loader&&this.loader.abort()}load(e,t){const s=e.url;if(!s)return Promise.reject(new We({type:V.NETWORK_ERROR,details:R.FRAG_LOAD_ERROR,fatal:!1,frag:e,error:new Error(`Fragment does not have a ${s?"part list":"url"}`),networkDetails:null}));this.abort();const i=this.config,r=i.fLoader,n=i.loader;return new Promise((o,c)=>{if(this.loader&&this.loader.destroy(),e.gap)if(e.tagList.some(g=>g[0]==="GAP")){c(lr(e));return}else e.gap=!1;const l=this.loader=r?new r(i):new n(i),h=or(e);e.loader=l;const u=rr(i.fragLoadPolicy.default),d={loadPolicy:u,timeout:u.maxLoadTimeMs,maxRetry:0,retryDelay:0,maxRetryDelay:0,highWaterMark:e.sn==="initSegment"?1/0:ar};e.stats=l.stats;const f={onSuccess:(g,y,p,E)=>{this.resetLoader(e,l);let T=g.data;p.resetIV&&e.decryptdata&&(e.decryptdata.iv=new Uint8Array(T.slice(0,16)),T=T.slice(16)),o({frag:e,part:null,payload:T,networkDetails:E})},onError:(g,y,p,E)=>{this.resetLoader(e,l),c(new We({type:V.NETWORK_ERROR,details:R.FRAG_LOAD_ERROR,fatal:!1,frag:e,response:te({url:s,data:void 0},g),error:new Error(`HTTP Error ${g.code} ${g.text}`),networkDetails:p,stats:E}))},onAbort:(g,y,p)=>{this.resetLoader(e,l),c(new We({type:V.NETWORK_ERROR,details:R.INTERNAL_ABORTED,fatal:!1,frag:e,error:new Error("Aborted"),networkDetails:p,stats:g}))},onTimeout:(g,y,p)=>{this.resetLoader(e,l),c(new We({type:V.NETWORK_ERROR,details:R.FRAG_LOAD_TIMEOUT,fatal:!1,frag:e,error:new Error(`Timeout after ${d.timeout}ms`),networkDetails:p,stats:g}))}};t&&(f.onProgress=(g,y,p,E)=>t({frag:e,part:null,payload:p,networkDetails:E})),l.load(h,d,f)})}loadPart(e,t,s){this.abort();const i=this.config,r=i.fLoader,n=i.loader;return new Promise((o,c)=>{if(this.loader&&this.loader.destroy(),e.gap||t.gap){c(lr(e,t));return}const l=this.loader=r?new r(i):new n(i),h=or(e,t);e.loader=l;const u=rr(i.fragLoadPolicy.default),d={loadPolicy:u,timeout:u.maxLoadTimeMs,maxRetry:0,retryDelay:0,maxRetryDelay:0,highWaterMark:ar};t.stats=l.stats,l.load(h,d,{onSuccess:(f,g,y,p)=>{this.resetLoader(e,l),this.updateStatsFromPart(e,t);const E={frag:e,part:t,payload:f.data,networkDetails:p};s(E),o(E)},onError:(f,g,y,p)=>{this.resetLoader(e,l),c(new We({type:V.NETWORK_ERROR,details:R.FRAG_LOAD_ERROR,fatal:!1,frag:e,part:t,response:te({url:h.url,data:void 0},f),error:new Error(`HTTP Error ${f.code} ${f.text}`),networkDetails:y,stats:p}))},onAbort:(f,g,y)=>{e.stats.aborted=t.stats.aborted,this.resetLoader(e,l),c(new We({type:V.NETWORK_ERROR,details:R.INTERNAL_ABORTED,fatal:!1,frag:e,part:t,error:new Error("Aborted"),networkDetails:y,stats:f}))},onTimeout:(f,g,y)=>{this.resetLoader(e,l),c(new We({type:V.NETWORK_ERROR,details:R.FRAG_LOAD_TIMEOUT,fatal:!1,frag:e,part:t,error:new Error(`Timeout after ${d.timeout}ms`),networkDetails:y,stats:f}))}})})}updateStatsFromPart(e,t){const s=e.stats,i=t.stats,r=i.total;if(s.loaded+=i.loaded,r){const c=Math.round(e.duration/t.duration),l=Math.min(Math.round(s.loaded/r),c),u=(c-l)*Math.round(s.loaded/l);s.total=s.loaded+u}else s.total=Math.max(s.loaded,s.total);const n=s.loading,o=i.loading;n.start?n.first+=o.first-o.start:(n.start=o.start,n.first=o.first),n.end=o.end}resetLoader(e,t){e.loader=null,this.loader===t&&(self.clearTimeout(this.partLoadTimeout),this.loader=null),t.destroy()}}function or(a,e=null){const t=e||a,s={frag:a,part:e,responseType:"arraybuffer",url:t.url,headers:{},rangeStart:0,rangeEnd:0},i=t.byteRangeStartOffset,r=t.byteRangeEndOffset;if(M(i)&&M(r)){var n;let o=i,c=r;if(a.sn==="initSegment"&&Zo((n=a.decryptdata)==null?void 0:n.method)){const l=r-i;l%16&&(c=r+(16-l%16)),i!==0&&(s.resetIV=!0,o=i-16)}s.rangeStart=o,s.rangeEnd=c}return s}function lr(a,e){const t=new Error(`GAP ${a.gap?"tag":"attribute"} found`),s={type:V.MEDIA_ERROR,details:R.FRAG_GAP,fatal:!1,frag:a,error:t,networkDetails:null};return e&&(s.part=e),(e||a).stats.aborted=!0,new We(s)}function Zo(a){return a==="AES-128"||a==="AES-256"}class We extends Error{constructor(e){super(e.error.message),this.data=void 0,this.data=e}}class bn extends Ce{constructor(e,t){super(e,t),this._boundTick=void 0,this._tickTimer=null,this._tickInterval=null,this._tickCallCount=0,this._boundTick=this.tick.bind(this)}destroy(){this.onHandlerDestroying(),this.onHandlerDestroyed()}onHandlerDestroying(){this.clearNextTick(),this.clearInterval()}onHandlerDestroyed(){}hasInterval(){return!!this._tickInterval}hasNextTick(){return!!this._tickTimer}setInterval(e){return this._tickInterval?!1:(this._tickCallCount=0,this._tickInterval=self.setInterval(this._boundTick,e),!0)}clearInterval(){return this._tickInterval?(self.clearInterval(this._tickInterval),this._tickInterval=null,!0):!1}clearNextTick(){return this._tickTimer?(self.clearTimeout(this._tickTimer),this._tickTimer=null,!0):!1}tick(){this._tickCallCount++,this._tickCallCount===1&&(this.doTick(),this._tickCallCount>1&&this.tickImmediate(),this._tickCallCount=0)}tickImmediate(){this.clearNextTick(),this._tickTimer=self.setTimeout(this._boundTick,0)}doTick(){}}class Si{constructor(e,t,s,i=0,r=-1,n=!1){this.level=void 0,this.sn=void 0,this.part=void 0,this.id=void 0,this.size=void 0,this.partial=void 0,this.transmuxing=Vt(),this.buffering={audio:Vt(),video:Vt(),audiovideo:Vt()},this.level=e,this.sn=t,this.id=s,this.size=i,this.part=r,this.partial=n}}function Vt(){return{start:0,executeStart:0,executeEnd:0,end:0}}const cr={length:0,start:()=>0,end:()=>0};class q{static isBuffered(e,t){if(e){const s=q.getBuffered(e);for(let i=s.length;i--;)if(t>=s.start(i)&&t<=s.end(i))return!0}return!1}static bufferedRanges(e){if(e){const t=q.getBuffered(e);return q.timeRangesToArray(t)}return[]}static timeRangesToArray(e){const t=[];for(let s=0;s1&&e.sort((h,u)=>h.start-u.start||u.end-h.end);let i=-1,r=[];if(s)for(let h=0;h=e[h].start&&t<=e[h].end&&(i=h);const u=r.length;if(u){const d=r[u-1].end;e[h].start-dd&&(r[u-1].end=e[h].end):r.push(e[h])}else r.push(e[h])}else r=e;let n=0,o,c=t,l=t;for(let h=0;h=u&&t<=d&&(i=h),t+s>=u&&t{const i=s.substring(2,s.length-1),r=t==null?void 0:t[i];return r===void 0?(a.playlistParsingError||(a.playlistParsingError=new Error(`Missing preceding EXT-X-DEFINE tag for Variable Reference: "${i}"`)),s):r})}return e}function ur(a,e,t){let s=a.variableList;s||(a.variableList=s={});let i,r;if("QUERYPARAM"in e){i=e.QUERYPARAM;try{const n=new self.URL(t).searchParams;if(n.has(i))r=n.get(i);else throw new Error(`"${i}" does not match any query parameter in URI: "${t}"`)}catch(n){a.playlistParsingError||(a.playlistParsingError=new Error(`EXT-X-DEFINE QUERYPARAM: ${n.message}`))}}else i=e.NAME,r=e.VALUE;i in s?a.playlistParsingError||(a.playlistParsingError=new Error(`EXT-X-DEFINE duplicate Variable Name declarations: "${i}"`)):s[i]=r||""}function Jo(a,e,t){const s=e.IMPORT;if(t&&s in t){let i=a.variableList;i||(a.variableList=i={}),i[s]=t[s]}else a.playlistParsingError||(a.playlistParsingError=new Error(`EXT-X-DEFINE IMPORT attribute not found in Multivariant Playlist: "${s}"`))}const el=/^(\d+)x(\d+)$/,dr=/(.+?)=(".*?"|.*?)(?:,|$)/g;class ae{constructor(e,t){typeof e=="string"&&(e=ae.parseAttrList(e,t)),ie(this,e)}get clientAttrs(){return Object.keys(this).filter(e=>e.substring(0,2)==="X-")}decimalInteger(e){const t=parseInt(this[e],10);return t>Number.MAX_SAFE_INTEGER?1/0:t}hexadecimalInteger(e){if(this[e]){let t=(this[e]||"0x").slice(2);t=(t.length&1?"0":"")+t;const s=new Uint8Array(t.length/2);for(let i=0;iNumber.MAX_SAFE_INTEGER?1/0:t}decimalFloatingPoint(e){return parseFloat(this[e])}optionalFloat(e,t){const s=this[e];return s?parseFloat(s):t}enumeratedString(e){return this[e]}enumeratedStringList(e,t){const s=this[e];return(s?s.split(/[ ,]+/):[]).reduce((i,r)=>(i[r.toLowerCase()]=!0,i),t)}bool(e){return this[e]==="YES"}decimalResolution(e){const t=el.exec(this[e]);if(t!==null)return{width:parseInt(t[1],10),height:parseInt(t[2],10)}}static parseAttrList(e,t){let s;const i={},r='"';for(dr.lastIndex=0;(s=dr.exec(e))!==null;){const n=s[1].trim();let o=s[2];const c=o.indexOf(r)===0&&o.lastIndexOf(r)===o.length-1;let l=!1;if(c)o=o.slice(1,-1);else switch(n){case"IV":case"SCTE35-CMD":case"SCTE35-IN":case"SCTE35-OUT":l=!0}if(t&&(c||l))o=Js(t,o);else if(!l&&!c)switch(n){case"CLOSED-CAPTIONS":if(o==="NONE")break;case"ALLOWED-CPC":case"CLASS":case"ASSOC-LANGUAGE":case"AUDIO":case"BYTERANGE":case"CHANNELS":case"CHARACTERISTICS":case"CODECS":case"DATA-ID":case"END-DATE":case"GROUP-ID":case"ID":case"IMPORT":case"INSTREAM-ID":case"KEYFORMAT":case"KEYFORMATVERSIONS":case"LANGUAGE":case"NAME":case"PATHWAY-ID":case"QUERYPARAM":case"RECENTLY-REMOVED-DATERANGES":case"SERVER-URI":case"STABLE-RENDITION-ID":case"STABLE-VARIANT-ID":case"START-DATE":case"SUBTITLES":case"SUPPLEMENTAL-CODECS":case"URI":case"VALUE":case"VIDEO":case"X-ASSET-LIST":case"X-ASSET-URI":se.warn(`${e}: attribute ${n} is missing quotes`)}i[n]=o}return i}}const tl="com.apple.hls.interstitial";function sl(a){return a!=="ID"&&a!=="CLASS"&&a!=="CUE"&&a!=="START-DATE"&&a!=="DURATION"&&a!=="END-DATE"&&a!=="END-ON-NEXT"}function il(a){return a==="SCTE35-OUT"||a==="SCTE35-IN"||a==="SCTE35-CMD"}class Dn{constructor(e,t,s=0){var i;if(this.attr=void 0,this.tagAnchor=void 0,this.tagOrder=void 0,this._startDate=void 0,this._endDate=void 0,this._dateAtEnd=void 0,this._cue=void 0,this._badValueForSameId=void 0,this.tagAnchor=(t==null?void 0:t.tagAnchor)||null,this.tagOrder=(i=t==null?void 0:t.tagOrder)!=null?i:s,t){const r=t.attr;for(const n in r)if(Object.prototype.hasOwnProperty.call(e,n)&&e[n]!==r[n]){se.warn(`DATERANGE tag attribute: "${n}" does not match for tags with ID: "${e.ID}"`),this._badValueForSameId=n;break}e=ie(new ae({}),r,e)}if(this.attr=e,t?(this._startDate=t._startDate,this._cue=t._cue,this._endDate=t._endDate,this._dateAtEnd=t._dateAtEnd):this._startDate=new Date(e["START-DATE"]),"END-DATE"in this.attr){const r=(t==null?void 0:t.endDate)||new Date(this.attr["END-DATE"]);M(r.getTime())&&(this._endDate=r)}}get id(){return this.attr.ID}get class(){return this.attr.CLASS}get cue(){const e=this._cue;return e===void 0?this._cue=this.attr.enumeratedStringList(this.attr.CUE?"CUE":"X-CUE",{pre:!1,post:!1,once:!1}):e}get startTime(){const{tagAnchor:e}=this;return e===null||e.programDateTime===null?(se.warn(`Expected tagAnchor Fragment with PDT set for DateRange "${this.id}": ${e}`),NaN):e.start+(this.startDate.getTime()-e.programDateTime)/1e3}get startDate(){return this._startDate}get endDate(){const e=this._endDate||this._dateAtEnd;if(e)return e;const t=this.duration;return t!==null?this._dateAtEnd=new Date(this._startDate.getTime()+t*1e3):null}get duration(){if("DURATION"in this.attr){const e=this.attr.decimalFloatingPoint("DURATION");if(M(e))return e}else if(this._endDate)return(this._endDate.getTime()-this._startDate.getTime())/1e3;return null}get plannedDuration(){return"PLANNED-DURATION"in this.attr?this.attr.decimalFloatingPoint("PLANNED-DURATION"):null}get endOnNext(){return this.attr.bool("END-ON-NEXT")}get isInterstitial(){return this.class===tl}get isValid(){return!!this.id&&!this._badValueForSameId&&M(this.startDate.getTime())&&(this.duration===null||this.duration>=0)&&(!this.endOnNext||!!this.class)&&(!this.attr.CUE||!this.cue.pre&&!this.cue.post||this.cue.pre!==this.cue.post)&&(!this.isInterstitial||"X-ASSET-URI"in this.attr||"X-ASSET-LIST"in this.attr)}}const rl=10;class nl{constructor(e){this.PTSKnown=!1,this.alignedSliding=!1,this.averagetargetduration=void 0,this.endCC=0,this.endSN=0,this.fragments=void 0,this.fragmentHint=void 0,this.partList=null,this.dateRanges=void 0,this.dateRangeTagCount=0,this.live=!0,this.requestScheduled=-1,this.ageHeader=0,this.advancedDateTime=void 0,this.updated=!0,this.advanced=!0,this.misses=0,this.startCC=0,this.startSN=0,this.startTimeOffset=null,this.targetduration=0,this.totalduration=0,this.type=null,this.url=void 0,this.m3u8="",this.version=null,this.canBlockReload=!1,this.canSkipUntil=0,this.canSkipDateRanges=!1,this.skippedSegments=0,this.recentlyRemovedDateranges=void 0,this.partHoldBack=0,this.holdBack=0,this.partTarget=0,this.preloadHint=void 0,this.renditionReports=void 0,this.tuneInGoal=0,this.deltaUpdateFailed=void 0,this.driftStartTime=0,this.driftEndTime=0,this.driftStart=0,this.driftEnd=0,this.encryptedFragments=void 0,this.playlistParsingError=null,this.variableList=null,this.hasVariableRefs=!1,this.appliedTimelineOffset=void 0,this.fragments=[],this.encryptedFragments=[],this.dateRanges={},this.url=e}reloaded(e){if(!e){this.advanced=!0,this.updated=!0;return}const t=this.lastPartSn-e.lastPartSn,s=this.lastPartIndex-e.lastPartIndex;this.updated=this.endSN!==e.endSN||!!s||!!t||!this.live,this.advanced=this.endSN>e.endSN||t>0||t===0&&s>0,this.updated||this.advanced?this.misses=Math.floor(e.misses*.6):this.misses=e.misses+1}hasKey(e){return this.encryptedFragments.some(t=>{let s=t.decryptdata;return s||(t.setKeyFormat(e.keyFormat),s=t.decryptdata),!!s&&e.matches(s)})}get hasProgramDateTime(){return this.fragments.length?M(this.fragments[this.fragments.length-1].programDateTime):!1}get levelTargetDuration(){return this.averagetargetduration||this.targetduration||rl}get drift(){const e=this.driftEndTime-this.driftStartTime;return e>0?(this.driftEnd-this.driftStart)*1e3/e:1}get edge(){return this.partEnd||this.fragmentEnd}get partEnd(){var e;return(e=this.partList)!=null&&e.length?this.partList[this.partList.length-1].end:this.fragmentEnd}get fragmentEnd(){return this.fragments.length?this.fragments[this.fragments.length-1].end:0}get fragmentStart(){return this.fragments.length?this.fragments[0].start:0}get age(){return this.advancedDateTime?Math.max(Date.now()-this.advancedDateTime,0)/1e3:0}get lastPartIndex(){var e;return(e=this.partList)!=null&&e.length?this.partList[this.partList.length-1].index:-1}get maxPartIndex(){const e=this.partList;if(e){const t=this.lastPartIndex;if(t!==-1){for(let s=e.length;s--;)if(e[s].index>t)return e[s].index;return t}}return 0}get lastPartSn(){var e;return(e=this.partList)!=null&&e.length?this.partList[this.partList.length-1].fragment.sn:this.endSN}get expired(){if(this.live&&this.age&&this.misses<3){const e=this.partEnd-this.fragmentStart;return this.age>Math.max(e,this.totalduration)+this.levelTargetDuration}return!1}}function gs(a,e){return a.length===e.length?!a.some((t,s)=>t!==e[s]):!1}function fr(a,e){return!a&&!e?!0:!a||!e?!1:gs(a,e)}function Tt(a){return a==="AES-128"||a==="AES-256"||a==="AES-256-CTR"}function vi(a){switch(a){case"AES-128":case"AES-256":return et.cbc;case"AES-256-CTR":return et.ctr;default:throw new Error(`invalid full segment method ${a}`)}}function xi(a){return Uint8Array.from(atob(a),e=>e.charCodeAt(0))}function ei(a){return Uint8Array.from(unescape(encodeURIComponent(a)),e=>e.charCodeAt(0))}function al(a){const e=ei(a).subarray(0,16),t=new Uint8Array(16);return t.set(e,16-e.length),t}function Cn(a){const e=function(s,i,r){const n=s[i];s[i]=s[r],s[r]=n};e(a,0,3),e(a,1,2),e(a,4,5),e(a,6,7)}function Pn(a){const e=a.split(":");let t=null;if(e[0]==="data"&&e.length===2){const s=e[1].split(";"),i=s[s.length-1].split(",");if(i.length===2){const r=i[0]==="base64",n=i[1];r?(s.splice(-1,1),t=xi(n)):t=al(n)}}return t}const ms=typeof self<"u"?self:void 0;var oe={CLEARKEY:"org.w3.clearkey",FAIRPLAY:"com.apple.fps",PLAYREADY:"com.microsoft.playready",WIDEVINE:"com.widevine.alpha"},pe={CLEARKEY:"org.w3.clearkey",FAIRPLAY:"com.apple.streamingkeydelivery",PLAYREADY:"com.microsoft.playready",WIDEVINE:"urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"};function ss(a){switch(a){case pe.FAIRPLAY:return oe.FAIRPLAY;case pe.PLAYREADY:return oe.PLAYREADY;case pe.WIDEVINE:return oe.WIDEVINE;case pe.CLEARKEY:return oe.CLEARKEY}}function _s(a){switch(a){case oe.FAIRPLAY:return pe.FAIRPLAY;case oe.PLAYREADY:return pe.PLAYREADY;case oe.WIDEVINE:return pe.WIDEVINE;case oe.CLEARKEY:return pe.CLEARKEY}}function _t(a){const{drmSystems:e,widevineLicenseUrl:t}=a,s=e?[oe.FAIRPLAY,oe.WIDEVINE,oe.PLAYREADY,oe.CLEARKEY].filter(i=>!!e[i]):[];return!s[oe.WIDEVINE]&&t&&s.push(oe.WIDEVINE),s}const kn=function(a){return ms!=null&&(a=ms.navigator)!=null&&a.requestMediaKeySystemAccess?self.navigator.requestMediaKeySystemAccess.bind(self.navigator):null}();function ol(a,e,t,s){let i;switch(a){case oe.FAIRPLAY:i=["cenc","sinf"];break;case oe.WIDEVINE:case oe.PLAYREADY:i=["cenc"];break;case oe.CLEARKEY:i=["cenc","keyids"];break;default:throw new Error(`Unknown key-system: ${a}`)}return ll(i,e,t,s)}function ll(a,e,t,s){return[{initDataTypes:a,persistentState:s.persistentState||"optional",distinctiveIdentifier:s.distinctiveIdentifier||"optional",sessionTypes:s.sessionTypes||[s.sessionType||"temporary"],audioCapabilities:e.map(r=>({contentType:`audio/mp4; codecs=${r}`,robustness:s.audioRobustness||"",encryptionScheme:s.audioEncryptionScheme||null})),videoCapabilities:t.map(r=>({contentType:`video/mp4; codecs=${r}`,robustness:s.videoRobustness||"",encryptionScheme:s.videoEncryptionScheme||null}))}]}function cl(a){var e;return!!a&&(a.sessionType==="persistent-license"||!!((e=a.sessionTypes)!=null&&e.some(t=>t==="persistent-license")))}function wn(a){const e=new Uint16Array(a.buffer,a.byteOffset,a.byteLength/2),t=String.fromCharCode.apply(null,Array.from(e)),s=t.substring(t.indexOf("<"),t.length),n=new DOMParser().parseFromString(s,"text/xml").getElementsByTagName("KID")[0];if(n){const o=n.childNodes[0]?n.childNodes[0].nodeValue:n.getAttribute("VALUE");if(o){const c=xi(o).subarray(0,16);return Cn(c),c}}return null}let dt={};class Ze{static clearKeyUriToKeyIdMap(){dt={}}static setKeyIdForUri(e,t){dt[e]=t}static addKeyIdForUri(e){const t=Object.keys(dt).length%Number.MAX_SAFE_INTEGER,s=new Uint8Array(16);return new DataView(s.buffer,12,4).setUint32(0,t),dt[e]=s,s}constructor(e,t,s,i=[1],r=null,n){this.uri=void 0,this.method=void 0,this.keyFormat=void 0,this.keyFormatVersions=void 0,this.encrypted=void 0,this.isCommonEncryption=void 0,this.iv=null,this.key=null,this.keyId=null,this.pssh=null,this.method=e,this.uri=t,this.keyFormat=s,this.keyFormatVersions=i,this.iv=r,this.encrypted=e?e!=="NONE":!1,this.isCommonEncryption=this.encrypted&&!Tt(e),n!=null&&n.startsWith("0x")&&(this.keyId=new Uint8Array(on(n)))}matches(e){return e.uri===this.uri&&e.method===this.method&&e.encrypted===this.encrypted&&e.keyFormat===this.keyFormat&&gs(e.keyFormatVersions,this.keyFormatVersions)&&fr(e.iv,this.iv)&&fr(e.keyId,this.keyId)}isSupported(){if(this.method){if(Tt(this.method)||this.method==="NONE")return!0;if(this.keyFormat==="identity")return this.method==="SAMPLE-AES";switch(this.keyFormat){case pe.FAIRPLAY:case pe.WIDEVINE:case pe.PLAYREADY:case pe.CLEARKEY:return["SAMPLE-AES","SAMPLE-AES-CENC","SAMPLE-AES-CTR"].indexOf(this.method)!==-1}}return!1}getDecryptData(e,t){if(!this.encrypted||!this.uri)return null;if(Tt(this.method)){let r=this.iv;return r||(typeof e!="number"&&(se.warn(`missing IV for initialization segment with method="${this.method}" - compliance issue`),e=0),r=ul(e)),new Ze(this.method,this.uri,"identity",this.keyFormatVersions,r)}if(this.keyId){const r=dt[this.uri];if(r&&!gs(this.keyId,r)&&Ze.setKeyIdForUri(this.uri,this.keyId),this.pssh)return this}const s=Pn(this.uri);if(s)switch(this.keyFormat){case pe.WIDEVINE:if(this.pssh=s,!this.keyId){const r=go(s.buffer);if(r.length){var i;const n=r[0];this.keyId=(i=n.kids)!=null&&i.length?n.kids[0]:null}}this.keyId||(this.keyId=gr(t));break;case pe.PLAYREADY:{const r=new Uint8Array([154,4,240,121,152,64,66,134,171,146,230,91,224,136,95,149]);this.pssh=fo(r,null,s),this.keyId=wn(s);break}default:{let r=s.subarray(0,16);if(r.length!==16){const n=new Uint8Array(16);n.set(r,16-r.length),r=n}this.keyId=r;break}}if(!this.keyId||this.keyId.byteLength!==16){let r;r=hl(t),r||(r=gr(t),r||(r=dt[this.uri])),r&&(this.keyId=r,Ze.setKeyIdForUri(this.uri,r))}return this}}function hl(a){const e=a==null?void 0:a[pe.WIDEVINE];return e?e.keyId:null}function gr(a){const e=a==null?void 0:a[pe.PLAYREADY];if(e){const t=Pn(e.uri);if(t)return wn(t)}return null}function ul(a){const e=new Uint8Array(16);for(let t=12;t<16;t++)e[t]=a>>8*(15-t)&255;return e}const mr=/#EXT-X-STREAM-INF:([^\r\n]*)(?:[\r\n](?:#[^\r\n]*)?)*([^\r\n]+)|#EXT-X-(SESSION-DATA|SESSION-KEY|DEFINE|CONTENT-STEERING|START):([^\r\n]*)[\r\n]+/g,pr=/#EXT-X-MEDIA:(.*)/g,dl=/^#EXT(?:INF|-X-TARGETDURATION):/m,Ds=new RegExp([/#EXTINF:\s*(\d*(?:\.\d+)?)(?:,(.*)\s+)?/.source,/(?!#) *(\S[^\r\n]*)/.source,/#.*/.source].join("|"),"g"),fl=new RegExp([/#EXT-X-(PROGRAM-DATE-TIME|BYTERANGE|DATERANGE|DEFINE|KEY|MAP|PART|PART-INF|PLAYLIST-TYPE|PRELOAD-HINT|RENDITION-REPORT|SERVER-CONTROL|SKIP|START):(.+)/.source,/#EXT-X-(BITRATE|DISCONTINUITY-SEQUENCE|MEDIA-SEQUENCE|TARGETDURATION|VERSION): *(\d+)/.source,/#EXT-X-(DISCONTINUITY|ENDLIST|GAP|INDEPENDENT-SEGMENTS)/.source,/(#)([^:]*):(.*)/.source,/(#)(.*)(?:.*)\r?\n?/.source].join("|"));class Ge{static findGroup(e,t){for(let s=0;s0&&r.length({id:l.attrs.AUDIO,audioCodec:l.audioCodec})),SUBTITLES:n.map(l=>({id:l.attrs.SUBTITLES,textCodec:l.textCodec})),"CLOSED-CAPTIONS":[]};let c=0;for(pr.lastIndex=0;(i=pr.exec(e))!==null;){const l=new ae(i[1],s),h=l.TYPE;if(h){const u=o[h],d=r[h]||[];r[h]=d;const f=l.LANGUAGE,g=l["ASSOC-LANGUAGE"],y=l.CHANNELS,p=l.CHARACTERISTICS,E=l["INSTREAM-ID"],T={attrs:l,bitrate:0,id:c++,groupId:l["GROUP-ID"]||"",name:l.NAME||f||"",type:h,default:l.bool("DEFAULT"),autoselect:l.bool("AUTOSELECT"),forced:l.bool("FORCED"),lang:f,url:l.URI?Ge.resolve(l.URI,t):""};if(g&&(T.assocLang=g),y&&(T.channels=y),p&&(T.characteristics=p),E&&(T.instreamId=E),u!=null&&u.length){const S=Ge.findGroup(u,T.groupId)||u[0];Sr(T,S,"audioCodec"),Sr(T,S,"textCodec")}d.push(T)}}return r}static parseLevelPlaylist(e,t,s,i,r,n){var o;const c={url:t},l=new nl(t),h=l.fragments,u=[];let d=null,f=0,g=0,y=0,p=0,E=0,T=null,S=new Ls(i,c),v,x,D,A=-1,_=!1,b=null,I;if(Ds.lastIndex=0,l.m3u8=e,l.hasVariableRefs=hr(e),((o=Ds.exec(e))==null?void 0:o[0])!=="#EXTM3U")return l.playlistParsingError=new Error("Missing format identifier #EXTM3U"),l;for(;(v=Ds.exec(e))!==null;){_&&(_=!1,S=new Ls(i,c),S.playlistOffset=y,S.setStart(y),S.sn=f,S.cc=p,E&&(S.bitrate=E),S.level=s,d&&(S.initSegment=d,d.rawProgramDateTime&&(S.rawProgramDateTime=d.rawProgramDateTime,d.rawProgramDateTime=null),b&&(S.setByteRange(b),b=null)));const H=v[1];if(H){S.duration=parseFloat(H);const $=(" "+v[2]).slice(1);S.title=$||null,S.tagList.push($?["INF",H,$]:["INF",H])}else if(v[3]){if(M(S.duration)){S.playlistOffset=y,S.setStart(y),D&&xr(S,D,l),S.sn=f,S.level=s,S.cc=p,h.push(S);const $=(" "+v[3]).slice(1);S.relurl=Js(l,$),ti(S,T,u),T=S,y+=S.duration,f++,g=0,_=!0}}else{if(v=v[0].match(fl),!v){se.warn("No matches on slow regex match for level playlist!");continue}for(x=1;x0&&Ar(l,$,v),f=l.startSN=parseInt(k);break;case"SKIP":{l.skippedSegments&&He(l,$,v);const N=new ae(k,l),K=N.decimalInteger("SKIPPED-SEGMENTS");if(M(K)){l.skippedSegments+=K;for(let w=K;w--;)h.push(null);f+=K}const Y=N.enumeratedString("RECENTLY-REMOVED-DATERANGES");Y&&(l.recentlyRemovedDateranges=(l.recentlyRemovedDateranges||[]).concat(Y.split(" ")));break}case"TARGETDURATION":l.targetduration!==0&&He(l,$,v),l.targetduration=Math.max(parseInt(k),1);break;case"VERSION":l.version!==null&&He(l,$,v),l.version=parseInt(k);break;case"INDEPENDENT-SEGMENTS":break;case"ENDLIST":l.live||He(l,$,v),l.live=!1;break;case"#":(k||G)&&S.tagList.push(G?[k,G]:[k]);break;case"DISCONTINUITY":p++,S.tagList.push(["DIS"]);break;case"GAP":S.gap=!0,S.tagList.push([$]);break;case"BITRATE":S.tagList.push([$,k]),E=parseInt(k)*1e3,M(E)?S.bitrate=E:E=0;break;case"DATERANGE":{const N=new ae(k,l),K=new Dn(N,l.dateRanges[N.ID],l.dateRangeTagCount);l.dateRangeTagCount++,K.isValid||l.skippedSegments?l.dateRanges[K.id]=K:se.warn(`Ignoring invalid DATERANGE tag: "${k}"`),S.tagList.push(["EXT-X-DATERANGE",k]);break}case"DEFINE":{{const N=new ae(k,l);"IMPORT"in N?Jo(l,N,n):ur(l,N,t)}break}case"DISCONTINUITY-SEQUENCE":l.startCC!==0?He(l,$,v):h.length>0&&Ar(l,$,v),l.startCC=p=parseInt(k);break;case"KEY":{const N=yr(k,t,l);if(N.isSupported()){if(N.method==="NONE"){D=void 0;break}D||(D={});const K=D[N.keyFormat];K!=null&&K.matches(N)||(K&&(D=ie({},D)),D[N.keyFormat]=N)}else se.warn(`[Keys] Ignoring unsupported EXT-X-KEY tag: "${k}"`);break}case"START":l.startTimeOffset=Er(k);break;case"MAP":{const N=new ae(k,l);if(S.duration){const K=new Ls(i,c);vr(K,N,s,D),d=K,S.initSegment=d,d.rawProgramDateTime&&!S.rawProgramDateTime&&(S.rawProgramDateTime=d.rawProgramDateTime)}else{const K=S.byteRangeEndOffset;if(K){const Y=S.byteRangeStartOffset;b=`${K-Y}@${Y}`}else b=null;vr(S,N,s,D),d=S,_=!0}d.cc=p;break}case"SERVER-CONTROL":{I&&He(l,$,v),I=new ae(k),l.canBlockReload=I.bool("CAN-BLOCK-RELOAD"),l.canSkipUntil=I.optionalFloat("CAN-SKIP-UNTIL",0),l.canSkipDateRanges=l.canSkipUntil>0&&I.bool("CAN-SKIP-DATERANGES"),l.partHoldBack=I.optionalFloat("PART-HOLD-BACK",0),l.holdBack=I.optionalFloat("HOLD-BACK",0);break}case"PART-INF":{l.partTarget&&He(l,$,v);const N=new ae(k);l.partTarget=N.decimalFloatingPoint("PART-TARGET");break}case"PART":{let N=l.partList;N||(N=l.partList=[]);const K=g>0?N[N.length-1]:void 0,Y=g++,w=new ae(k,l),O=new Za(w,S,c,Y,K);N.push(O),S.duration+=O.duration;break}case"PRELOAD-HINT":{const N=new ae(k,l);l.preloadHint=N;break}case"RENDITION-REPORT":{const N=new ae(k,l);l.renditionReports=l.renditionReports||[],l.renditionReports.push(N);break}default:se.warn(`line parsed but not handled: ${v}`);break}}}T&&!T.relurl?(h.pop(),y-=T.duration,l.partList&&(l.fragmentHint=T)):l.partList&&(ti(S,T,u),S.cc=p,l.fragmentHint=S,D&&xr(S,D,l)),l.targetduration||(l.playlistParsingError=new Error("Missing Target Duration"));const P=h.length,F=h[0],U=h[P-1];if(y+=l.skippedSegments*l.targetduration,y>0&&P&&U){l.averagetargetduration=y/P;const H=U.sn;l.endSN=H!=="initSegment"?H:0,l.live||(U.endList=!0),A>0&&(ml(h,A),F&&u.unshift(F))}return l.fragmentHint&&(y+=l.fragmentHint.duration),l.totalduration=y,u.length&&l.dateRangeTagCount&&F&&On(u,l),l.endCC=p,l}}function On(a,e){let t=a.length;if(!t)if(e.hasProgramDateTime){const o=e.fragments[e.fragments.length-1];a.push(o),t++}else return;const s=a[t-1],i=e.live?1/0:e.totalduration,r=Object.keys(e.dateRanges);for(let o=r.length;o--;){const c=e.dateRanges[r[o]],l=c.startDate.getTime();c.tagAnchor=s.ref;for(let h=t;h--;){var n;if(((n=a[h])==null?void 0:n.sn)=o||s===0){var n;const c=(((n=t[s+1])==null?void 0:n.start)||i)-r.start;if(e<=o+c*1e3){const l=t[s].sn-a.startSN;if(l<0)return-1;const h=a.fragments;if(h.length>t.length){const d=(t[s+1]||h[h.length-1]).sn-a.startSN;for(let f=d;f>l;f--){const g=h[f].programDateTime;if(e>=g&&es);["video","audio","text"].forEach(s=>{const i=t.filter(r=>pi(r,s));i.length&&(e[`${s}Codec`]=i.map(r=>r.split("/")[0]).join(","),t=t.filter(r=>i.indexOf(r)===-1))}),e.unknownCodecs=t}function Sr(a,e,t){const s=e[t];s&&(a[t]=s)}function ml(a,e){let t=a[e];for(let s=e;s--;){const i=a[s];if(!i)return;i.programDateTime=t.programDateTime-i.duration*1e3,t=i}}function ti(a,e,t){a.rawProgramDateTime?t.push(a):e!=null&&e.programDateTime&&(a.programDateTime=e.endProgramDateTime)}function vr(a,e,t,s){a.relurl=e.URI,e.BYTERANGE&&a.setByteRange(e.BYTERANGE),a.level=t,a.sn="initSegment",s&&(a.levelkeys=s),a.initSegment=null}function xr(a,e,t){a.levelkeys=e;const{encryptedFragments:s}=t;(!s.length||s[s.length-1].levelkeys!==e)&&Object.keys(e).some(i=>e[i].isCommonEncryption)&&s.push(a)}function He(a,e,t){a.playlistParsingError=new Error(`#EXT-X-${e} must not appear more than once (${t[0]})`)}function Ar(a,e,t){a.playlistParsingError=new Error(`#EXT-X-${e} must appear before the first Media Segment (${t[0]})`)}function Cs(a,e){const t=e.startPTS;if(M(t)){let s=0,i;e.sn>a.sn?(s=t-a.start,i=a):(s=a.start-t,i=e),i.duration!==s&&i.setDuration(s)}else e.sn>a.sn?a.cc===e.cc&&a.minEndPTS?e.setStart(a.start+(a.minEndPTS-a.start)):e.setStart(a.start+a.duration):e.setStart(Math.max(a.start-e.duration,0))}function Fn(a,e,t,s,i,r,n){s-t<=0&&(n.warn("Fragment should have a positive duration",e),s=t+e.duration,r=i+e.duration);let c=t,l=s;const h=e.startPTS,u=e.endPTS;if(M(h)){const E=Math.abs(h-t);a&&E>a.totalduration?n.warn(`media timestamps and playlist times differ by ${E}s for level ${e.level} ${a.url}`):M(e.deltaPTS)?e.deltaPTS=Math.max(E,e.deltaPTS):e.deltaPTS=E,c=Math.max(t,h),t=Math.min(t,h),i=e.startDTS!==void 0?Math.min(i,e.startDTS):i,l=Math.min(s,u),s=Math.max(s,u),r=e.endDTS!==void 0?Math.max(r,e.endDTS):r}const d=t-e.start;e.start!==0&&e.setStart(t),e.setDuration(s-e.start),e.startPTS=t,e.maxStartPTS=c,e.startDTS=i,e.endPTS=s,e.minEndPTS=l,e.endDTS=r;const f=e.sn;if(!a||fa.endSN)return 0;let g;const y=f-a.startSN,p=a.fragments;for(p[y]=e,g=y;g>0;g--)Cs(p[g],p[g-1]);for(g=y;g=0;h--){const u=i[h].initSegment;if(u){s=u;break}}a.fragmentHint&&delete a.fragmentHint.endPTS;let r;Tl(a,e,(h,u,d,f)=>{if((!e.startCC||e.skippedSegments)&&u.cc!==h.cc){const g=h.cc-u.cc;for(let y=d;y{var u;h&&(!h.initSegment||h.initSegment.relurl===((u=s)==null?void 0:u.relurl))&&(h.initSegment=s)}),e.skippedSegments){if(e.deltaUpdateFailed=n.some(h=>!h),e.deltaUpdateFailed){t.warn("[level-helper] Previous playlist missing segments skipped in delta playlist");for(let h=e.skippedSegments;h--;)n.shift();e.startSN=n[0].sn}else{e.canSkipDateRanges&&(e.dateRanges=yl(a.dateRanges,e,t));const h=a.fragments.filter(u=>u.rawProgramDateTime);if(a.hasProgramDateTime&&!e.hasProgramDateTime)for(let u=1;u{u.elementaryStreams=h.elementaryStreams,u.stats=h.stats}),r?Fn(e,r,r.startPTS,r.endPTS,r.startDTS,r.endDTS,t):Mn(a,e),n.length&&(e.totalduration=e.edge-n[0].start),e.driftStartTime=a.driftStartTime,e.driftStart=a.driftStart;const l=e.advancedDateTime;if(e.advanced&&l){const h=e.edge;e.driftStart||(e.driftStartTime=l,e.driftStart=h),e.driftEndTime=l,e.driftEnd=h}else e.driftEndTime=a.driftEndTime,e.driftEnd=a.driftEnd,e.advancedDateTime=a.advancedDateTime;e.requestScheduled===-1&&(e.requestScheduled=a.requestScheduled)}function yl(a,e,t){const{dateRanges:s,recentlyRemovedDateranges:i}=e,r=ie({},a);i&&i.forEach(c=>{delete r[c]});const o=Object.keys(r).length;return o?(Object.keys(s).forEach(c=>{const l=r[c],h=new Dn(s[c].attr,l);h.isValid?(r[c]=h,l||(h.tagOrder+=o)):t.warn(`Ignoring invalid Playlist Delta Update DATERANGE tag: "${ne(s[c].attr)}"`)}),r):s}function El(a,e,t){if(a&&e){let s=0;for(let i=0,r=a.length;i<=r;i++){const n=a[i],o=e[i+s];n&&o&&n.index===o.index&&n.fragment.sn===o.fragment.sn?t(n,o):s--}}}function Tl(a,e,t){const s=e.skippedSegments,i=Math.max(a.startSN,e.startSN)-e.startSN,r=(a.fragmentHint?1:0)+(s?e.endSN:Math.min(a.endSN,e.endSN))-e.startSN,n=e.startSN-a.startSN,o=e.fragmentHint?e.fragments.concat(e.fragmentHint):e.fragments,c=a.fragmentHint?a.fragments.concat(a.fragmentHint):a.fragments;for(let l=i;l<=r;l++){const h=c[n+l];let u=o[l];if(s&&!u&&h&&(u=e.fragments[l]=h),h&&u){t(h,u,l,o);const d=h.relurl,f=u.relurl;if(d&&Sl(d,f)){e.playlistParsingError=Ir(`media sequence mismatch ${u.sn}:`,a,e,h,u);return}else if(h.cc!==u.cc){e.playlistParsingError=Ir(`discontinuity sequence mismatch (${h.cc}!=${u.cc})`,a,e,h,u);return}}}}function Ir(a,e,t,s,i){return new Error(`${a} ${i.url} Playlist starting @${e.startSN} ${e.m3u8} Playlist starting @${t.startSN} -${t.m3u8}`)}function Zn(a,e,t=!0){const s=e.startSN+e.skippedSegments-a.startSN,i=a.fragments,r=s>=0;let n=0;if(r&&se){const r=s[s.length-1].duration*1e3;r{var s;(s=e.details)==null||s.fragments.forEach(i=>{i.level=t,i.initSegment&&(i.initSegment.level=t)})})}function Bl(a,e){return a!==e&&e?$r(a)!==$r(e):!1}function $r(a){return a.replace(/\?[^?]*$/,"")}function Nt(a,e){for(let s=0,i=a.length;sa.startCC)}function Ur(a,e){const t=a.start+e;a.startPTS=t,a.setStart(t),a.endPTS=t+a.duration}function ia(a,e){const t=e.fragments;for(let s=0,i=t.length;s{const{config:n,fragCurrent:o,media:c,mediaBuffer:l,state:h}=this,d=c?c.currentTime:0,u=X.bufferInfo(l||c,d,n.maxBufferHole),f=!u.len;if(this.log(`Media seeking to ${B(d)?d.toFixed(3):d}, state: ${h}, ${f?"out of":"in"} buffer`),this.state===C.ENDED)this.resetLoadingState();else if(o){const g=n.maxFragLookUpTolerance,y=o.start-g,p=o.start+o.duration+g;if(f||pu.end){const E=d>p;(dg&&(this.lastCurrentTime=d),!this.loadingParts){const y=Math.max(u.end,d),p=this.shouldLoadParts(this.getLevelDetails(),y);p&&(this.log(`LL-Part loading ON after seeking to ${d.toFixed(2)} with buffer @${y.toFixed(2)}`),this.loadingParts=p)}}this.hls.hasEnoughToStart||(this.log(`Setting ${f?"startPosition":"nextLoadPosition"} to ${d} for seek without enough to start`),this.nextLoadPosition=d,f&&(this.startPosition=d)),f&&this.state===C.IDLE&&this.tickImmediate()},this.onMediaEnded=()=>{this.log("setting startPosition to 0 because media ended"),this.startPosition=this.lastCurrentTime=0},this.playlistType=r,this.hls=e,this.fragmentLoader=new ml(e.config),this.keyLoader=s,this.fragmentTracker=t,this.config=e.config,this.decrypter=new Pi(e.config)}registerListeners(){const{hls:e}=this;e.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.on(m.ERROR,this.onError,this)}unregisterListeners(){const{hls:e}=this;e.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.off(m.ERROR,this.onError,this)}doTick(){this.onTickEnd()}onTickEnd(){}startLoad(e){}stopLoad(){if(this.state===C.STOPPED)return;this.fragmentLoader.abort(),this.keyLoader.abort(this.playlistType);const e=this.fragCurrent;e!=null&&e.loader&&(e.abortRequests(),this.fragmentTracker.removeFragment(e)),this.resetTransmuxer(),this.fragCurrent=null,this.fragPrevious=null,this.clearInterval(),this.clearNextTick(),this.state=C.STOPPED}get startPositionValue(){const{nextLoadPosition:e,startPosition:t}=this;return t===-1&&e?e:t}get bufferingEnabled(){return this.buffering}pauseBuffering(){this.buffering=!1}resumeBuffering(){this.buffering=!0}get inFlightFrag(){return{frag:this.fragCurrent,state:this.state}}_streamEnded(e,t){if(t.live||!this.media)return!1;const s=e.end||0,i=this.config.timelineOffset||0;if(s<=i)return!1;const r=e.buffered;this.config.maxBufferHole&&r&&r.length>1&&(e=X.bufferedInfo(r,e.start,0));const n=e.nextStart;if(n&&n>i&&n{const n=r.frag;if(this.fragContextChanged(n)){this.warn(`${n.type} sn: ${n.sn}${r.part?" part: "+r.part.index:""} of ${this.fragInfo(n,!1,r.part)}) was dropped during download.`),this.fragmentTracker.removeFragment(n);return}n.stats.chunkCount++,this._handleFragmentLoadProgress(r)};this._doFragLoad(e,t,s,i).then(r=>{if(!r)return;const n=this.state,o=r.frag;if(this.fragContextChanged(o)){(n===C.FRAG_LOADING||!this.fragCurrent&&n===C.PARSING)&&(this.fragmentTracker.removeFragment(o),this.state=C.IDLE);return}"payload"in r&&(this.log(`Loaded ${o.type} sn: ${o.sn} of ${this.playlistLabel()} ${o.level}`),this.hls.trigger(m.FRAG_LOADED,r)),this._handleFragmentLoadComplete(r)}).catch(r=>{this.state===C.STOPPED||this.state===C.ERROR||(this.warn(`Frag error: ${(r==null?void 0:r.message)||r}`),this.resetFragmentLoading(e))})}clearTrackerIfNeeded(e){var t;const{fragmentTracker:s}=this;if(s.getState(e)===fe.APPENDING){const r=e.type,n=this.getFwdBufferInfo(this.mediaBuffer,r),o=Math.max(e.duration,n?n.len:this.config.maxBufferLength),c=this.backtrackFragment;((c?e.sn-c.sn:0)===1||this.reduceMaxBufferLength(o,e.duration))&&s.removeFragment(e)}else((t=this.mediaBuffer)==null?void 0:t.buffered.length)===0?s.removeAllFragments():s.hasParts(e.type)&&(s.detectPartialFragments({frag:e,part:null,stats:e.stats,id:e.type}),s.getState(e)===fe.PARTIAL&&s.removeFragment(e))}checkLiveUpdate(e){if(e.updated&&!e.live){const t=e.fragments[e.fragments.length-1];this.fragmentTracker.detectPartialFragments({frag:t,part:null,stats:t.stats,id:t.type})}e.fragments[0]||(e.deltaUpdateFailed=!0)}waitForLive(e){const t=e.details;return(t==null?void 0:t.live)&&t.type!=="EVENT"&&(this.levelLastLoaded!==e||t.expired)}flushMainBuffer(e,t,s=null){if(!(e-t))return;const i={startOffset:e,endOffset:t,type:s};this.hls.trigger(m.BUFFER_FLUSHING,i)}_loadInitSegment(e,t){this._doFragLoad(e,t).then(s=>{const i=s==null?void 0:s.frag;if(!i||this.fragContextChanged(i)||!this.levels)throw new Error("init load aborted");return s}).then(s=>{const{hls:i}=this,{frag:r,payload:n}=s,o=r.decryptdata;if(n&&n.byteLength>0&&o!=null&&o.key&&o.iv&&_t(o.method)){const c=self.performance.now();return this.decrypter.decrypt(new Uint8Array(n),o.key.buffer,o.iv.buffer,wi(o.method)).catch(l=>{throw i.trigger(m.ERROR,{type:Y.MEDIA_ERROR,details:R.FRAG_DECRYPT_ERROR,fatal:!1,error:l,reason:l.message,frag:r}),l}).then(l=>{const h=self.performance.now();return i.trigger(m.FRAG_DECRYPTED,{frag:r,payload:l,stats:{tstart:c,tdecrypt:h}}),s.payload=l,this.completeInitSegmentLoad(s)})}return this.completeInitSegmentLoad(s)}).catch(s=>{this.state===C.STOPPED||this.state===C.ERROR||(this.warn(s),this.resetFragmentLoading(e))})}completeInitSegmentLoad(e){const{levels:t}=this;if(!t)throw new Error("init load aborted, missing levels");const s=e.frag.stats;this.state!==C.STOPPED&&(this.state=C.IDLE),e.frag.data=new Uint8Array(e.payload),s.parsing.start=s.buffering.start=self.performance.now(),s.parsing.end=s.buffering.end=self.performance.now(),this.tick()}unhandledEncryptionError(e,t){var s,i;const r=e.tracks;if(r&&!t.encrypted&&((s=r.audio)!=null&&s.encrypted||(i=r.video)!=null&&i.encrypted)&&(!this.config.emeEnabled||!this.keyLoader.emeController)){const n=this.media,o=new Error(`Encrypted track with no key in ${this.fragInfo(t)} (media ${n?"attached mediaKeys: "+n.mediaKeys:"detached"})`);return this.warn(o.message),!n||n.mediaKeys?!1:(this.hls.trigger(m.ERROR,{type:Y.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_NO_KEYS,fatal:!1,error:o,frag:t}),this.resetTransmuxer(),!0)}return!1}fragContextChanged(e){const{fragCurrent:t}=this;return!e||!t||e.sn!==t.sn||e.level!==t.level}fragBufferedComplete(e,t){const s=this.mediaBuffer?this.mediaBuffer:this.media;if(this.log(`Buffered ${e.type} sn: ${e.sn}${t?" part: "+t.index:""} of ${this.fragInfo(e,!1,t)} > buffer:${s?Gl.toString(X.getBuffered(s)):"(detached)"})`),de(e)){var i;if(e.type!==U.SUBTITLE){const n=e.elementaryStreams;if(!Object.keys(n).some(o=>!!n[o])){this.state=C.IDLE;return}}const r=(i=this.levels)==null?void 0:i[e.level];r!=null&&r.fragmentError&&(this.log(`Resetting level fragment error count of ${r.fragmentError} on frag buffered`),r.fragmentError=0)}this.state=C.IDLE}_handleFragmentLoadComplete(e){const{transmuxer:t}=this;if(!t)return;const{frag:s,part:i,partsLoaded:r}=e,n=!r||r.length===0||r.some(c=>!c),o=new ki(s.level,s.sn,s.stats.chunkCount+1,0,i?i.index:-1,!n);t.flush(o)}_handleFragmentLoadProgress(e){}_doFragLoad(e,t,s=null,i){var r;this.fragCurrent=e;const n=t.details;if(!this.levels||!n)throw new Error(`frag load aborted, missing level${n?"":" detail"}s`);let o=null;if(e.encrypted&&!((r=e.decryptdata)!=null&&r.key)){if(this.log(`Loading key for ${e.sn} of [${n.startSN}-${n.endSN}], ${this.playlistLabel()} ${e.level}`),this.state=C.KEY_LOADING,this.fragCurrent=e,o=this.keyLoader.load(e).then(u=>{if(!this.fragContextChanged(u.frag))return this.hls.trigger(m.KEY_LOADED,u),this.state===C.KEY_LOADING&&(this.state=C.IDLE),u}),this.hls.trigger(m.KEY_LOADING,{frag:e}),this.fragCurrent===null)return this.log("context changed in KEY_LOADING"),Promise.resolve(null)}else e.encrypted||(o=this.keyLoader.loadClear(e,n.encryptedFragments,this.startFragRequested),o&&this.log("[eme] blocking frag load until media-keys acquired"));const c=this.fragPrevious;if(de(e)&&(!c||e.sn!==c.sn)){const u=this.shouldLoadParts(t.details,e.end);u!==this.loadingParts&&(this.log(`LL-Part loading ${u?"ON":"OFF"} loading sn ${c==null?void 0:c.sn}->${e.sn}`),this.loadingParts=u)}if(s=Math.max(e.start,s||0),this.loadingParts&&de(e)){const u=n.partList;if(u&&i){s>n.fragmentEnd&&n.fragmentHint&&(e=n.fragmentHint);const f=this.getNextPart(u,e,s);if(f>-1){const g=u[f];e=this.fragCurrent=g.fragment,this.log(`Loading ${e.type} sn: ${e.sn} part: ${g.index} (${f}/${u.length-1}) of ${this.fragInfo(e,!1,g)}) cc: ${e.cc} [${n.startSN}-${n.endSN}], target: ${parseFloat(s.toFixed(3))}`),this.nextLoadPosition=g.start+g.duration,this.state=C.FRAG_LOADING;let y;return o?y=o.then(p=>!p||this.fragContextChanged(p.frag)?null:this.doFragPartsLoad(e,g,t,i)).catch(p=>this.handleFragLoadError(p)):y=this.doFragPartsLoad(e,g,t,i).catch(p=>this.handleFragLoadError(p)),this.hls.trigger(m.FRAG_LOADING,{frag:e,part:g,targetBufferTime:s}),this.fragCurrent===null?Promise.reject(new Error("frag load aborted, context changed in FRAG_LOADING parts")):y}else if(!e.url||this.loadedEndOfParts(u,s))return Promise.resolve(null)}}if(de(e)&&this.loadingParts){var l;this.log(`LL-Part loading OFF after next part miss @${s.toFixed(2)} Check buffer at sn: ${e.sn} loaded parts: ${(l=n.partList)==null?void 0:l.filter(u=>u.loaded).map(u=>`[${u.start}-${u.end}]`)}`),this.loadingParts=!1}else if(!e.url)return Promise.resolve(null);this.log(`Loading ${e.type} sn: ${e.sn} of ${this.fragInfo(e,!1)}) cc: ${e.cc} ${"["+n.startSN+"-"+n.endSN+"]"}, target: ${parseFloat(s.toFixed(3))}`),B(e.sn)&&!this.bitrateTest&&(this.nextLoadPosition=e.start+e.duration),this.state=C.FRAG_LOADING;const h=this.config.progressive&&e.type!==U.SUBTITLE;let d;return h&&o?d=o.then(u=>!u||this.fragContextChanged(u.frag)?null:this.fragmentLoader.load(e,i)).catch(u=>this.handleFragLoadError(u)):d=Promise.all([this.fragmentLoader.load(e,h?i:void 0),o]).then(([u])=>(!h&&i&&i(u),u)).catch(u=>this.handleFragLoadError(u)),this.hls.trigger(m.FRAG_LOADING,{frag:e,targetBufferTime:s}),this.fragCurrent===null?Promise.reject(new Error("frag load aborted, context changed in FRAG_LOADING")):d}doFragPartsLoad(e,t,s,i){return new Promise((r,n)=>{var o;const c=[],l=(o=s.details)==null?void 0:o.partList,h=d=>{this.fragmentLoader.loadPart(e,d,i).then(u=>{c[d.index]=u;const f=u.part;this.hls.trigger(m.FRAG_LOADED,u);const g=Br(s.details,e.sn,d.index+1)||ta(l,e.sn,d.index+1);if(g)h(g);else return r({frag:e,part:f,partsLoaded:c})}).catch(n)};h(t)})}handleFragLoadError(e){if("data"in e){const t=e.data;t.frag&&t.details===R.INTERNAL_ABORTED?this.handleFragLoadAborted(t.frag,t.part):t.frag&&t.type===Y.KEY_SYSTEM_ERROR?(t.frag.abortRequests(),this.resetStartWhenNotLoaded(),this.resetFragmentLoading(t.frag)):this.hls.trigger(m.ERROR,t)}else this.hls.trigger(m.ERROR,{type:Y.OTHER_ERROR,details:R.INTERNAL_EXCEPTION,err:e,error:e,fatal:!0});return null}_handleTransmuxerFlush(e){const t=this.getCurrentContext(e);if(!t||this.state!==C.PARSING){!this.fragCurrent&&this.state!==C.STOPPED&&this.state!==C.ERROR&&(this.state=C.IDLE);return}const{frag:s,part:i,level:r}=t,n=self.performance.now();s.stats.parsing.end=n,i&&(i.stats.parsing.end=n);const o=this.getLevelDetails(),l=o&&s.sn>o.endSN||this.shouldLoadParts(o,s.end);l!==this.loadingParts&&(this.log(`LL-Part loading ${l?"ON":"OFF"} after parsing segment ending @${s.end.toFixed(2)}`),this.loadingParts=l),this.updateLevelTiming(s,i,r,e.partial)}shouldLoadParts(e,t){if(this.config.lowLatencyMode){if(!e)return this.loadingParts;if(e.partList){var s;const r=e.partList[0];if(r.fragment.type===U.SUBTITLE)return!1;const n=r.end+(((s=e.fragmentHint)==null?void 0:s.duration)||0);if(t>=n){var i;if((this.hls.hasEnoughToStart?((i=this.media)==null?void 0:i.currentTime)||this.lastCurrentTime:this.getLoadPosition())>r.start-r.fragment.duration)return!0}}}return!1}getCurrentContext(e){const{levels:t,fragCurrent:s}=this,{level:i,sn:r,part:n}=e;if(!(t!=null&&t[i]))return this.warn(`Levels object was unset while buffering fragment ${r} of ${this.playlistLabel()} ${i}. The current chunk will not be buffered.`),null;const o=t[i],c=o.details,l=n>-1?Br(c,r,n):null,h=l?l.fragment:ea(c,r,s);return h?(s&&s!==h&&(h.stats=s.stats),{frag:h,part:l,level:o}):null}bufferFragmentData(e,t,s,i,r){if(this.state!==C.PARSING)return;const{data1:n,data2:o}=e;let c=n;if(o&&(c=we(n,o)),!c.length)return;const l=this.initPTS[t.cc],h=l?-l.baseTime/l.timescale:void 0,d={type:e.type,frag:t,part:s,chunkMeta:i,offset:h,parent:t.type,data:c};if(this.hls.trigger(m.BUFFER_APPENDING,d),e.dropped&&e.independent&&!s){if(r)return;this.flushBufferGap(t)}}flushBufferGap(e){const t=this.media;if(!t)return;if(!X.isBuffered(t,t.currentTime)){this.flushMainBuffer(0,e.start);return}const s=t.currentTime,i=X.bufferInfo(t,s,0),r=e.duration,n=Math.min(this.config.maxFragLookUpTolerance*2,r*.25),o=Math.max(Math.min(e.start-n,i.end-n),s+n);e.start-o>n&&this.flushMainBuffer(o,e.start)}getFwdBufferInfo(e,t){var s;const i=this.getLoadPosition();if(!B(i))return null;const n=this.lastCurrentTime>i||(s=this.media)!=null&&s.paused?0:this.config.maxBufferHole;return this.getFwdBufferInfoAtPos(e,i,t,n)}getFwdBufferInfoAtPos(e,t,s,i){const r=X.bufferInfo(e,t,i);if(r.len===0&&r.nextStart!==void 0){const n=this.fragmentTracker.getBufferedFrag(t,s);if(n&&(r.nextStart<=n.end||n.gap)){const o=Math.max(Math.min(r.nextStart,n.end)-t,i);return X.bufferInfo(e,t,o)}}return r}getMaxBufferLength(e){const{config:t}=this;let s;return e?s=Math.max(8*t.maxBufferSize/e,t.maxBufferLength):s=t.maxBufferLength,Math.min(s,t.maxMaxBufferLength)}exceedsMaxBuffer(e,t,s){const i=e.nextStart;if(i&&s.start>i){const r=e.buffered;if(r){let n=e.len;const o=e.bufferedIndex;for(let c=r.length-1;c>o;c--)r[c].start=t}}return!1}reduceMaxBufferLength(e,t){const s=this.config,i=Math.max(Math.min(e-t,s.maxBufferLength),t),r=Math.max(e-t*3,s.maxMaxBufferLength/2,i);return r>=i?(s.maxMaxBufferLength=r,this.warn(`Reduce max buffer length to ${r}s`),!0):!1}getAppendedFrag(e,t=U.MAIN){const s=this.fragmentTracker?this.fragmentTracker.getAppendedFrag(e,t):null;return s&&"fragment"in s?s.fragment:s}getNextFragment(e,t){const s=t.fragments,i=s.length;if(!i)return null;const{config:r}=this,n=t.fragmentStart,o=r.lowLatencyMode&&!!t.partList;let c=null;if(t.live){const d=r.initialLiveManifestSize;if(i=n?(p=f,E=f===u?"config":"next load start"):g!==null?(p=g,E="live edge"):(p=e,E="buffer pos"),p=r){const c=n.sn;return this.loopSn!==c&&(this.log(`buffer full after gaps in "${i}" playlist starting at sn: ${c}`),this.loopSn=c),null}}return this.loopSn=void 0,n}get primaryPrefetch(){if(Gr(this.config)){var e;if((e=this.hls.interstitialsManager)==null||(e=e.playingItem)==null?void 0:e.event)return!0}return!1}filterReplacedPrimary(e,t){if(!e)return e;if(Gr(this.config)&&e.type!==U.SUBTITLE){const s=this.hls.interstitialsManager,i=s==null?void 0:s.bufferingItem;if(i){const n=i.event;if(n){if(n.appendInPlace||Math.abs(e.start-i.start)>1||i.start===0)return null}else if(e.end<=i.start&&(t==null?void 0:t.live)===!1||e.start>i.end&&i.nextEvent&&(i.nextEvent.appendInPlace||e.start-i.end>1))return null}const r=s==null?void 0:s.playerQueue;if(r)for(let n=r.length;n--;){const o=r[n].interstitial;if(o.appendInPlace&&e.start>=o.startTime&&e.end<=o.resumeTime)return null}}return e}mapToInitFragWhenRequired(e){return e!=null&&e.initSegment&&!e.initSegment.data&&!this.bitrateTest?e.initSegment:e}getNextPart(e,t,s){let i=-1,r=!1,n=!0;for(let o=0,c=e.length;o-1&&ss.start)return!0}return!1}getInitialLiveFragment(e){const t=e.fragments,s=this.fragPrevious;let i=null;if(s){if(e.hasProgramDateTime&&(i=il(t,s.endProgramDateTime,this.config.maxFragLookUpTolerance),i&&this.log(`Live playlist, switching playlist, load frag with same PDT: ${s.programDateTime}`)),!i){const r=s.sn+1;if(r>=e.startSN&&r<=e.endSN){const n=t[r-e.startSN];s.cc===n.cc&&(i=n,this.log(`Live playlist, switching playlist, load frag with next SN: ${i.sn}`))}i||(i=Un(e,s.cc,s.end),i&&this.log(`Live playlist, switching playlist, load frag with same CC: ${i.sn}`))}}else{const r=this.hls.liveSyncPosition;r!==null&&(i=this.getFragmentAtPosition(r,this.bitrateTest?e.fragmentEnd:e.edge,e))}return i}getFragmentAtPosition(e,t,s){const{config:i}=this;let{fragPrevious:r}=this,{fragments:n,endSN:o}=s;const{fragmentHint:c}=s,{maxFragLookUpTolerance:l}=i,h=s.partList,d=!!(this.loadingParts&&h!=null&&h.length&&c);d&&!this.bitrateTest&&h[h.length-1].fragment.sn===c.sn&&(n=n.concat(c),o=c.sn);let u;if(et-l||(f=this.media)!=null&&f.paused||!this.startFragRequested?0:l;u=pt(r,n,e,y)}else u=n[n.length-1];if(u){const g=u.sn-s.startSN,y=this.fragmentTracker.getState(u);if((y===fe.OK||y===fe.PARTIAL&&u.gap)&&(r=u),r&&u.sn===r.sn&&(!d||h[0].fragment.sn>u.sn||!s.live)&&u.level===r.level){const E=n[g+1];u.sn${e.startSN} fragments: ${i}`),c}return r}waitForCdnTuneIn(e){return e.live&&e.canBlockReload&&e.partTarget&&e.tuneInGoal>Math.max(e.partHoldBack,e.partTarget*3)}setStartPosition(e,t){let s=this.startPosition;s=0&&(s=this.nextLoadPosition),s}handleFragLoadAborted(e,t){this.transmuxer&&e.type===this.playlistType&&de(e)&&e.stats.aborted&&(this.log(`Fragment ${e.sn}${t?" part "+t.index:""} of ${this.playlistLabel()} ${e.level} was aborted`),this.resetFragmentLoading(e))}resetFragmentLoading(e){(!this.fragCurrent||!this.fragContextChanged(e)&&this.state!==C.FRAG_LOADING_WAITING_RETRY)&&(this.state=C.IDLE)}onFragmentOrKeyLoadError(e,t){var s;if(t.chunkMeta&&!t.frag){const E=this.getCurrentContext(t.chunkMeta);E&&(t.frag=E.frag)}const i=t.frag;if(!i||i.type!==e||!this.levels)return;if(this.fragContextChanged(i)){var r;this.warn(`Frag load error must match current frag to retry ${i.url} > ${(r=this.fragCurrent)==null?void 0:r.url}`);return}const n=t.details===R.FRAG_GAP;n&&this.fragmentTracker.fragBuffered(i,!0);const o=t.errorAction;if(!o){this.state=C.ERROR;return}const{action:c,flags:l,retryCount:h=0,retryConfig:d}=o,u=!!d,f=u&&c===pe.RetryRequest,g=u&&!o.resolved&&l===Re.MoveAllAlternatesMatchingHost,y=(s=this.hls.latestLevelDetails)==null?void 0:s.live;if(!f&&g&&de(i)&&!i.endList&&y&&!Kn(t))this.resetFragmentErrors(e),this.treatAsGap(i),o.resolved=!0;else if((f||g)&&h=t||s&&!li(0))&&(s&&this.log("Connection restored (online)"),this.resetStartWhenNotLoaded(),this.state=C.IDLE)}reduceLengthAndFlushBuffer(e){if(this.state===C.PARSING||this.state===C.PARSED){const t=e.frag,s=e.parent,i=this.getFwdBufferInfo(this.mediaBuffer,s),r=i&&i.len>.5;r&&this.reduceMaxBufferLength(i.len,(t==null?void 0:t.duration)||10);const n=!r;return n&&this.warn(`Buffer full error while media.currentTime (${this.getLoadPosition()}) is not buffered, flush ${s} buffer`),t&&(this.fragmentTracker.removeFragment(t),this.nextLoadPosition=t.start),this.resetLoadingState(),n}return!1}resetFragmentErrors(e){e===U.AUDIO&&(this.fragCurrent=null),this.hls.hasEnoughToStart||(this.startFragRequested=!1),this.state!==C.STOPPED&&(this.state=C.IDLE)}afterBufferFlushed(e,t,s){if(!e)return;const i=X.getBuffered(e);this.fragmentTracker.detectEvictedFragments(t,i,s),this.state===C.ENDED&&this.resetLoadingState()}resetLoadingState(){this.log("Reset loading state"),this.fragCurrent=null,this.fragPrevious=null,this.state!==C.STOPPED&&(this.state=C.IDLE)}resetStartWhenNotLoaded(){if(!this.hls.hasEnoughToStart){this.startFragRequested=!1;const e=this.levelLastLoaded,t=e?e.details:null;t!=null&&t.live?(this.log("resetting startPosition for live start"),this.startPosition=-1,this.setStartPosition(t,t.fragmentStart),this.resetLoadingState()):this.nextLoadPosition=this.startPosition}}resetWhenMissingContext(e){this.log(`Loading context changed while buffering sn ${e.sn} of ${this.playlistLabel()} ${e.level===-1?"":e.level}. This chunk will not be buffered.`),this.removeUnbufferedFrags(),this.resetStartWhenNotLoaded(),this.resetLoadingState()}removeUnbufferedFrags(e=0){this.fragmentTracker.removeFragmentsInRange(e,1/0,this.playlistType,!1,!0)}updateLevelTiming(e,t,s,i){const r=s.details;if(!r){this.warn("level.details undefined");return}if(!Object.keys(e.elementaryStreams).reduce((c,l)=>{const h=e.elementaryStreams[l];if(h){const d=h.endPTS-h.startPTS;if(d<=0)return this.warn(`Could not parse fragment ${e.sn} ${l} duration reliably (${d})`),c||!1;const u=i?0:Qn(r,e,h.startPTS,h.endPTS,h.startDTS,h.endDTS,this);return this.hls.trigger(m.LEVEL_PTS_UPDATED,{details:r,level:s,drift:u,type:l,frag:e,start:h.startPTS,end:h.endPTS}),!0}return c},!1)){var o;const c=((o=this.transmuxer)==null?void 0:o.error)===null;if((s.fragmentError===0||c&&(s.fragmentError<2||e.endList))&&this.treatAsGap(e,s),c){const l=new Error(`Found no media in fragment ${e.sn} of ${this.playlistLabel()} ${e.level} resetting transmuxer to fallback to playlist timing`);if(this.warn(l.message),this.hls.trigger(m.ERROR,{type:Y.MEDIA_ERROR,details:R.FRAG_PARSING_ERROR,fatal:!1,error:l,frag:e,reason:`Found no media in msn ${e.sn} of ${this.playlistLabel()} "${s.url}"`}),!this.hls)return;this.resetTransmuxer()}}this.state=C.PARSED,this.log(`Parsed ${e.type} sn: ${e.sn}${t?" part: "+t.index:""} of ${this.fragInfo(e,!1,t)})`),this.hls.trigger(m.FRAG_PARSED,{frag:e,part:t})}playlistLabel(){return this.playlistType===U.MAIN?"level":"track"}fragInfo(e,t=!0,s){var i,r;return`${this.playlistLabel()} ${e.level} (${s?"part":"frag"}:[${((i=t&&!s?e.startPTS:(s||e).start)!=null?i:NaN).toFixed(3)}-${((r=t&&!s?e.endPTS:(s||e).end)!=null?r:NaN).toFixed(3)}]${s&&e.type==="main"?"INDEPENDENT="+(s.independent?"YES":"NO"):""}`}treatAsGap(e,t){t&&t.fragmentError++,e.gap=!0,this.fragmentTracker.removeFragment(e),this.fragmentTracker.fragBuffered(e,!0)}resetTransmuxer(){var e;(e=this.transmuxer)==null||e.reset()}recoverWorkerError(e){e.event==="demuxerWorker"&&(this.fragmentTracker.removeAllFragments(),this.transmuxer&&(this.transmuxer.destroy(),this.transmuxer=null),this.resetStartWhenNotLoaded(),this.resetLoadingState())}set state(e){const t=this._state;t!==e&&(this._state=e,this.log(`${t}->${e}`))}get state(){return this._state}}function Gr(a){return!!a.interstitialsController&&a.enableInterstitialPlayback!==!1}class na{constructor(){this.chunks=[],this.dataLength=0}push(e){this.chunks.push(e),this.dataLength+=e.length}flush(){const{chunks:e,dataLength:t}=this;let s;if(e.length)e.length===1?s=e[0]:s=Kl(e,t);else return new Uint8Array(0);return this.reset(),s}reset(){this.chunks.length=0,this.dataLength=0}}function Kl(a,e){const t=new Uint8Array(e);let s=0;for(let i=0;i0)return a.subarray(t,t+s)}function Xl(a,e,t,s){const i=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350],r=e[t+2],n=r>>2&15;if(n>12){const f=new Error(`invalid ADTS sampling index:${n}`);a.emit(m.ERROR,m.ERROR,{type:Y.MEDIA_ERROR,details:R.FRAG_PARSING_ERROR,fatal:!0,error:f,reason:f.message});return}const o=(r>>6&3)+1,c=e[t+3]>>6&3|(r&1)<<2,l="mp4a.40."+o,h=i[n];let d=n;(o===5||o===29)&&(d-=3);const u=[o<<3|(d&14)>>1,(d&1)<<7|c<<3];return re.log(`manifest codec:${s}, parsed codec:${l}, channels:${c}, rate:${h} (ADTS object type:${o} sampling index:${n})`),{config:u,samplerate:h,channelCount:c,codec:l,parsedCodec:l,manifestCodec:s}}function oa(a,e){return a[e]===255&&(a[e+1]&246)===240}function la(a,e){return a[e+1]&1?7:9}function Bi(a,e){return(a[e+3]&3)<<11|a[e+4]<<3|(a[e+5]&224)>>>5}function zl(a,e){return e+5=a.length)return!1;const s=Bi(a,e);if(s<=t)return!1;const i=e+s;return i===a.length||bs(a,i)}return!1}function ca(a,e,t,s,i){if(!a.samplerate){const r=Xl(e,t,s,i);if(!r)return;ne(a,r)}}function ha(a){return 1024*9e4/a}function Jl(a,e){const t=la(a,e);if(e+t<=a.length){const s=Bi(a,e)-t;if(s>0)return{headerLength:t,frameLength:s}}}function da(a,e,t,s,i){const r=ha(a.samplerate),n=s+i*r,o=Jl(e,t);let c;if(o){const{frameLength:d,headerLength:u}=o,f=u+d,g=Math.max(0,t+f-e.length);g?(c=new Uint8Array(f-u),c.set(e.subarray(t+u,e.length),0)):c=e.subarray(t+u,t+f);const y={unit:c,pts:n};return g||a.samples.push(y),{sample:y,length:f,missing:g}}const l=e.length-t;return c=new Uint8Array(l),c.set(e.subarray(t,e.length),0),{sample:{unit:c,pts:n},length:l,missing:-1}}function ec(a,e){return Ni(a,e)&&Cs(a,e+6)+10<=a.length-e}function tc(a){return a instanceof ArrayBuffer?a:a.byteOffset==0&&a.byteLength==a.buffer.byteLength?a.buffer:new Uint8Array(a).buffer}function Ks(a,e=0,t=1/0){return sc(a,e,t,Uint8Array)}function sc(a,e,t,s){const i=ic(a);let r=1;"BYTES_PER_ELEMENT"in s&&(r=s.BYTES_PER_ELEMENT);const n=rc(a)?a.byteOffset:0,o=(n+a.byteLength)/r,c=(n+e)/r,l=Math.floor(Math.max(0,Math.min(c,o))),h=Math.floor(Math.min(l+Math.max(t,0),o));return new s(i,l,h-l)}function ic(a){return a instanceof ArrayBuffer?a:a.buffer}function rc(a){return a&&a.buffer instanceof ArrayBuffer&&a.byteLength!==void 0&&a.byteOffset!==void 0}function nc(a){const e={key:a.type,description:"",data:"",mimeType:null,pictureType:null},t=3;if(a.size<2)return;if(a.data[0]!==t){console.log("Ignore frame with unrecognized character encoding");return}const s=a.data.subarray(1).indexOf(0);if(s===-1)return;const i=De(Ks(a.data,1,s)),r=a.data[2+s],n=a.data.subarray(3+s).indexOf(0);if(n===-1)return;const o=De(Ks(a.data,3+s,n));let c;return i==="-->"?c=De(Ks(a.data,4+s+n)):c=tc(a.data.subarray(4+s+n)),e.mimeType=i,e.pictureType=r,e.description=o,e.data=c,e}function ac(a){if(a.size<2)return;const e=De(a.data,!0),t=new Uint8Array(a.data.subarray(e.length+1));return{key:a.type,info:e,data:t.buffer}}function oc(a){if(a.size<2)return;if(a.type==="TXXX"){let t=1;const s=De(a.data.subarray(t),!0);t+=s.length+1;const i=De(a.data.subarray(t));return{key:a.type,info:s,data:i}}const e=De(a.data.subarray(1));return{key:a.type,info:"",data:e}}function lc(a){if(a.type==="WXXX"){if(a.size<2)return;let t=1;const s=De(a.data.subarray(t),!0);t+=s.length+1;const i=De(a.data.subarray(t));return{key:a.type,info:s,data:i}}const e=De(a.data);return{key:a.type,info:"",data:e}}function cc(a){return a.type==="PRIV"?ac(a):a.type[0]==="W"?lc(a):a.type==="APIC"?nc(a):oc(a)}function hc(a){const e=String.fromCharCode(a[0],a[1],a[2],a[3]),t=Cs(a,4),s=10;return{type:e,size:t,data:a.subarray(s,s+t)}}const es=10,dc=10;function ua(a){let e=0;const t=[];for(;Ni(a,e);){const s=Cs(a,e+6);a[e+5]>>6&1&&(e+=es),e+=es;const i=e+s;for(;e+dc0&&o.samples.push({pts:this.lastPTS,dts:this.lastPTS,data:s,type:_e.audioId3,duration:Number.POSITIVE_INFINITY});i{if(B(a))return a*90;const s=t?t.baseTime*9e4/t.timescale:0;return e*9e4+s};let ts=null;const gc=[32,64,96,128,160,192,224,256,288,320,352,384,416,448,32,48,56,64,80,96,112,128,160,192,224,256,320,384,32,40,48,56,64,80,96,112,128,160,192,224,256,320,32,48,56,64,80,96,112,128,144,160,176,192,224,256,8,16,24,32,40,48,56,64,80,96,112,128,144,160],mc=[44100,48e3,32e3,22050,24e3,16e3,11025,12e3,8e3],pc=[[0,72,144,12],[0,0,0,0],[0,72,144,12],[0,144,144,12]],yc=[0,1,1,4];function ga(a,e,t,s,i){if(t+24>e.length)return;const r=ma(e,t);if(r&&t+r.frameLength<=e.length){const n=r.samplesPerFrame*9e4/r.sampleRate,o=s+i*n,c={unit:e.subarray(t,t+r.frameLength),pts:o,dts:o};return a.config=[],a.channelCount=r.channelCount,a.samplerate=r.sampleRate,a.samples.push(c),{sample:c,length:r.frameLength,missing:0}}}function ma(a,e){const t=a[e+1]>>3&3,s=a[e+1]>>1&3,i=a[e+2]>>4&15,r=a[e+2]>>2&3;if(t!==1&&i!==0&&i!==15&&r!==3){const n=a[e+2]>>1&1,o=a[e+3]>>6,c=t===3?3-s:s===3?3:4,l=gc[c*14+i-1]*1e3,d=mc[(t===3?0:t===2?1:2)*3+r],u=o===3?1:2,f=pc[t][s],g=yc[s],y=f*8*g,p=Math.floor(f*l/d+n)*g;if(ts===null){const S=(navigator.userAgent||"").match(/Chrome\/(\d+)/i);ts=S?parseInt(S[1]):0}return!!ts&&ts<=87&&s===2&&l>=224e3&&o===0&&(a[e+3]=a[e+3]|128),{sampleRate:d,channelCount:u,frameLength:p,samplesPerFrame:y}}}function Gi(a,e){return a[e]===255&&(a[e+1]&224)===224&&(a[e+1]&6)!==0}function pa(a,e){return e+1{let t=0,s=5;e+=s;const i=new Uint32Array(1),r=new Uint32Array(1),n=new Uint8Array(1);for(;s>0;){n[0]=a[e];const o=Math.min(s,8),c=8-o;r[0]=4278190080>>>24+c<>c,t=t?t<e.length||e[t]!==11||e[t+1]!==119)return-1;const r=e[t+4]>>6;if(r>=3)return-1;const o=[48e3,44100,32e3][r],c=e[t+4]&63,h=[64,69,96,64,70,96,80,87,120,80,88,120,96,104,144,96,105,144,112,121,168,112,122,168,128,139,192,128,140,192,160,174,240,160,175,240,192,208,288,192,209,288,224,243,336,224,244,336,256,278,384,256,279,384,320,348,480,320,349,480,384,417,576,384,418,576,448,487,672,448,488,672,512,557,768,512,558,768,640,696,960,640,697,960,768,835,1152,768,836,1152,896,975,1344,896,976,1344,1024,1114,1536,1024,1115,1536,1152,1253,1728,1152,1254,1728,1280,1393,1920,1280,1394,1920][c*3+r]*2;if(t+h>e.length)return-1;const d=e[t+6]>>5;let u=0;d===2?u+=2:(d&1&&d!==1&&(u+=2),d&4&&(u+=2));const f=(e[t+6]<<8|e[t+7])>>12-u&1,y=[2,1,2,3,3,4,4,5][d]+f,p=e[t+5]>>3,E=e[t+5]&7,T=new Uint8Array([r<<6|p<<1|E>>2,(E&3)<<6|d<<3|f<<2|c>>4,c<<4&224]),S=1536/o*9e4,v=s+i*S,x=e.subarray(t,t+h);return a.config=T,a.channelCount=y,a.samplerate=o,a.samples.push({unit:x,pts:v}),h}class vc extends Ui{resetInitSegment(e,t,s,i){super.resetInitSegment(e,t,s,i),this._audioTrack={container:"audio/mpeg",type:"audio",id:2,pid:-1,sequenceNumber:0,segmentCodec:"mp3",samples:[],manifestCodec:t,duration:i,inputTimeScale:9e4,dropped:0}}static probe(e){if(!e)return!1;const t=Ht(e,0);let s=(t==null?void 0:t.length)||0;if(t&&e[s]===11&&e[s+1]===119&&$i(t)!==void 0&&Ea(e,s)<=16)return!1;for(let i=e.length;s{const n=Do(r);if(xc.test(n.schemeIdUri)){const o=Vr(n,t);let c=n.eventDuration===4294967295?Number.POSITIVE_INFINITY:n.eventDuration/n.timeScale;c<=.001&&(c=Number.POSITIVE_INFINITY);const l=n.payload;s.samples.push({data:l,len:l.byteLength,dts:o,pts:o,type:_e.emsg,duration:c})}else if(this.config.enableEmsgKLVMetadata&&n.schemeIdUri.startsWith("urn:misb:KLV:bin:1910.1")){const o=Vr(n,t);s.samples.push({data:n.payload,len:n.payload.byteLength,dts:o,pts:o,type:_e.misbklv,duration:Number.POSITIVE_INFINITY})}})}return s}demuxSampleAes(e,t,s){return Promise.reject(new Error("The MP4 demuxer does not support SAMPLE-AES decryption"))}destroy(){this.config=null,this.remainderData=null,this.videoTrack=this.audioTrack=this.id3Track=this.txtTrack=void 0}}function Vr(a,e){return B(a.presentationTime)?a.presentationTime/a.timeScale:e+a.presentationTimeDelta/a.timeScale}class Ic{constructor(e,t,s){this.keyData=void 0,this.decrypter=void 0,this.keyData=s,this.decrypter=new Pi(t,{removePKCS7Padding:!1})}decryptBuffer(e){return this.decrypter.decrypt(e,this.keyData.key.buffer,this.keyData.iv.buffer,ot.cbc)}decryptAacSample(e,t,s){const i=e[t].unit;if(i.length<=16)return;const r=i.subarray(16,i.length-i.length%16),n=r.buffer.slice(r.byteOffset,r.byteOffset+r.length);this.decryptBuffer(n).then(o=>{const c=new Uint8Array(o);i.set(c,16),this.decrypter.isSync()||this.decryptAacSamples(e,t+1,s)}).catch(s)}decryptAacSamples(e,t,s){for(;;t++){if(t>=e.length){s();return}if(!(e[t].unit.length<32)&&(this.decryptAacSample(e,t,s),!this.decrypter.isSync()))return}}getAvcEncryptedData(e){const t=Math.floor((e.length-48)/160)*16+16,s=new Int8Array(t);let i=0;for(let r=32;r{r.data=this.getAvcDecryptedUnit(n,c),this.decrypter.isSync()||this.decryptAvcSamples(e,t,s+1,i)}).catch(i)}decryptAvcSamples(e,t,s,i){if(e instanceof Uint8Array)throw new Error("Cannot decrypt samples of type Uint8Array");for(;;t++,s=0){if(t>=e.length){i();return}const r=e[t].units;for(;!(s>=r.length);s++){const n=r[s];if(!(n.data.length<=48||n.type!==1&&n.type!==5)&&(this.decryptAvcSample(e,t,s,i,n),!this.decrypter.isSync()))return}}}}class Sa{constructor(){this.VideoSample=null}createVideoSample(e,t,s){return{key:e,frame:!1,pts:t,dts:s,units:[],length:0}}getLastNalUnit(e){var t;let s=this.VideoSample,i;if((!s||s.units.length===0)&&(s=e[e.length-1]),(t=s)!=null&&t.units){const r=s.units;i=r[r.length-1]}return i}pushAccessUnit(e,t){if(e.units.length&&e.frame){if(e.pts===void 0){const s=t.samples,i=s.length;if(i){const r=s[i-1];e.pts=r.pts,e.dts=r.dts}else{t.dropped++;return}}t.samples.push(e)}}parseNALu(e,t,s){const i=t.byteLength;let r=e.naluState||0;const n=r,o=[];let c=0,l,h,d,u=-1,f=0;for(r===-1&&(u=0,f=this.getNALuType(t,0),r=0,c=1);c=0){const g={data:t.subarray(u,h),type:f};o.push(g)}else{const g=this.getLastNalUnit(e.samples);g&&(n&&c<=4-n&&g.state&&(g.data=g.data.subarray(0,g.data.byteLength-n)),h>0&&(g.data=we(g.data,t.subarray(0,h)),g.state=0))}c=0&&r>=0){const g={data:t.subarray(u,i),type:f,state:r};o.push(g)}if(o.length===0){const g=this.getLastNalUnit(e.samples);g&&(g.data=we(g.data,t))}return e.naluState=r,o}}class Bt{constructor(e){this.data=void 0,this.bytesAvailable=void 0,this.word=void 0,this.bitsAvailable=void 0,this.data=e,this.bytesAvailable=e.byteLength,this.word=0,this.bitsAvailable=0}loadWord(){const e=this.data,t=this.bytesAvailable,s=e.byteLength-t,i=new Uint8Array(4),r=Math.min(4,t);if(r===0)throw new Error("no bytes available");i.set(e.subarray(s,s+r)),this.word=new DataView(i.buffer).getUint32(0),this.bitsAvailable=r*8,this.bytesAvailable-=r}skipBits(e){let t;e=Math.min(e,this.bytesAvailable*8+this.bitsAvailable),this.bitsAvailable>e?(this.word<<=e,this.bitsAvailable-=e):(e-=this.bitsAvailable,t=e>>3,e-=t<<3,this.bytesAvailable-=t,this.loadWord(),this.word<<=e,this.bitsAvailable-=e)}readBits(e){let t=Math.min(this.bitsAvailable,e);const s=this.word>>>32-t;if(e>32&&re.error("Cannot read more than 32 bits at a time"),this.bitsAvailable-=t,this.bitsAvailable>0)this.word<<=t;else if(this.bytesAvailable>0)this.loadWord();else throw new Error("no bits available");return t=e-t,t>0&&this.bitsAvailable?s<>>e)return this.word<<=e,this.bitsAvailable-=e,e;return this.loadWord(),e+this.skipLZ()}skipUEG(){this.skipBits(1+this.skipLZ())}skipEG(){this.skipBits(1+this.skipLZ())}readUEG(){const e=this.skipLZ();return this.readBits(e+1)-1}readEG(){const e=this.readUEG();return 1&e?1+e>>>1:-1*(e>>>1)}readBoolean(){return this.readBits(1)===1}readUByte(){return this.readBits(8)}readUShort(){return this.readBits(16)}readUInt(){return this.readBits(32)}}class Lc extends Sa{parsePES(e,t,s,i){const r=this.parseNALu(e,s.data,i);let n=this.VideoSample,o,c=!1;s.data=null,n&&r.length&&!e.audFound&&(this.pushAccessUnit(n,e),n=this.VideoSample=this.createVideoSample(!1,s.pts,s.dts)),r.forEach(l=>{var h,d;switch(l.type){case 1:{let y=!1;o=!0;const p=l.data;if(c&&p.length>4){const E=this.readSliceType(p);(E===2||E===4||E===7||E===9)&&(y=!0)}if(y){var u;(u=n)!=null&&u.frame&&!n.key&&(this.pushAccessUnit(n,e),n=this.VideoSample=null)}n||(n=this.VideoSample=this.createVideoSample(!0,s.pts,s.dts)),n.frame=!0,n.key=y;break}case 5:o=!0,(h=n)!=null&&h.frame&&!n.key&&(this.pushAccessUnit(n,e),n=this.VideoSample=null),n||(n=this.VideoSample=this.createVideoSample(!0,s.pts,s.dts)),n.key=!0,n.frame=!0;break;case 6:{o=!0,bi(l.data,1,s.pts,t.samples);break}case 7:{var f,g;o=!0,c=!0;const y=l.data,p=this.readSPS(y);if(!e.sps||e.width!==p.width||e.height!==p.height||((f=e.pixelRatio)==null?void 0:f[0])!==p.pixelRatio[0]||((g=e.pixelRatio)==null?void 0:g[1])!==p.pixelRatio[1]){e.width=p.width,e.height=p.height,e.pixelRatio=p.pixelRatio,e.sps=[y];const E=y.subarray(1,4);let T="avc1.";for(let S=0;S<3;S++){let v=E[S].toString(16);v.length<2&&(v="0"+v),T+=v}e.codec=T}break}case 8:o=!0,e.pps=[l.data];break;case 9:o=!0,e.audFound=!0,(d=n)!=null&&d.frame&&(this.pushAccessUnit(n,e),n=null),n||(n=this.VideoSample=this.createVideoSample(!1,s.pts,s.dts));break;case 12:o=!0;break;default:o=!1;break}n&&o&&n.units.push(l)}),i&&n&&(this.pushAccessUnit(n,e),this.VideoSample=null)}getNALuType(e,t){return e[t]&31}readSliceType(e){const t=new Bt(e);return t.readUByte(),t.readUEG(),t.readUEG()}skipScalingList(e,t){let s=8,i=8,r;for(let n=0;n{var h,d;switch(l.type){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9:n||(n=this.VideoSample=this.createVideoSample(!1,s.pts,s.dts)),n.frame=!0,o=!0;break;case 16:case 17:case 18:case 21:if(o=!0,c){var u;(u=n)!=null&&u.frame&&!n.key&&(this.pushAccessUnit(n,e),n=this.VideoSample=null)}n||(n=this.VideoSample=this.createVideoSample(!0,s.pts,s.dts)),n.key=!0,n.frame=!0;break;case 19:case 20:o=!0,(h=n)!=null&&h.frame&&!n.key&&(this.pushAccessUnit(n,e),n=this.VideoSample=null),n||(n=this.VideoSample=this.createVideoSample(!0,s.pts,s.dts)),n.key=!0,n.frame=!0;break;case 39:o=!0,bi(l.data,2,s.pts,t.samples);break;case 32:o=!0,e.vps||(typeof e.params!="object"&&(e.params={}),e.params=ne(e.params,this.readVPS(l.data)),this.initVPS=l.data),e.vps=[l.data];break;case 33:if(o=!0,c=!0,e.vps!==void 0&&e.vps[0]!==this.initVPS&&e.sps!==void 0&&!this.matchSPS(e.sps[0],l.data)&&(this.initVPS=e.vps[0],e.sps=e.pps=void 0),!e.sps){const f=this.readSPS(l.data);e.width=f.width,e.height=f.height,e.pixelRatio=f.pixelRatio,e.codec=f.codecString,e.sps=[],typeof e.params!="object"&&(e.params={});for(const g in f.params)e.params[g]=f.params[g]}this.pushParameterSet(e.sps,l.data,e.vps),n||(n=this.VideoSample=this.createVideoSample(!0,s.pts,s.dts)),n.key=!0;break;case 34:if(o=!0,typeof e.params=="object"){if(!e.pps){e.pps=[];const f=this.readPPS(l.data);for(const g in f)e.params[g]=f[g]}this.pushParameterSet(e.pps,l.data,e.vps)}break;case 35:o=!0,e.audFound=!0,(d=n)!=null&&d.frame&&(this.pushAccessUnit(n,e),n=null),n||(n=this.VideoSample=this.createVideoSample(!1,s.pts,s.dts));break;default:o=!1;break}n&&o&&n.units.push(l)}),i&&n&&(this.pushAccessUnit(n,e),this.VideoSample=null)}pushParameterSet(e,t,s){(s&&s[0]===this.initVPS||!s&&!e.length)&&e.push(t)}getNALuType(e,t){return(e[t]&126)>>>1}ebsp2rbsp(e){const t=new Uint8Array(e.byteLength);let s=0;for(let i=0;i=2&&e[i]===3&&e[i-1]===0&&e[i-2]===0||(t[s]=e[i],s++);return new Uint8Array(t.buffer,0,s)}pushAccessUnit(e,t){super.pushAccessUnit(e,t),this.initVPS&&(this.initVPS=null)}readVPS(e){const t=new Bt(e);t.readUByte(),t.readUByte(),t.readBits(4),t.skipBits(2),t.readBits(6);const s=t.readBits(3),i=t.readBoolean();return{numTemporalLayers:s+1,temporalIdNested:i}}readSPS(e){const t=new Bt(this.ebsp2rbsp(e));t.readUByte(),t.readUByte(),t.readBits(4);const s=t.readBits(3);t.readBoolean();const i=t.readBits(2),r=t.readBoolean(),n=t.readBits(5),o=t.readUByte(),c=t.readUByte(),l=t.readUByte(),h=t.readUByte(),d=t.readUByte(),u=t.readUByte(),f=t.readUByte(),g=t.readUByte(),y=t.readUByte(),p=t.readUByte(),E=t.readUByte(),T=[],S=[];for(let te=0;te0)for(let te=s;te<8;te++)t.readBits(2);for(let te=0;te1&&t.readEG();for(let yt=0;yt0&&ht<16?(F=zi[ht-1],z=Xt[ht-1]):ht===255&&(F=t.readBits(16),z=t.readBits(16))}if(t.readBoolean()&&t.readBoolean(),t.readBoolean()&&(t.readBits(3),t.readBoolean(),t.readBoolean()&&(t.readUByte(),t.readUByte(),t.readUByte())),t.readBoolean()&&(t.readUEG(),t.readUEG()),t.readBoolean(),t.readBoolean(),t.readBoolean(),Se=t.readBoolean(),Se&&(t.skipUEG(),t.skipUEG(),t.skipUEG(),t.skipUEG()),t.readBoolean()&&(Q=t.readBits(32),ee=t.readBits(32),t.readBoolean()&&t.readUEG(),t.readBoolean())){const Xt=t.readBoolean(),Qi=t.readBoolean();let wt=!1;(Xt||Qi)&&(wt=t.readBoolean(),wt&&(t.readUByte(),t.readBits(5),t.readBoolean(),t.readBits(5)),t.readBits(4),t.readBits(4),wt&&t.readBits(4),t.readBits(5),t.readBits(5),t.readBits(5));for(let Zi=0;Zi<=s;Zi++){se=t.readBoolean();const so=se||t.readBoolean();let Ji=!1;so?t.readEG():Ji=t.readBoolean();const er=Ji?1:t.readUEG()+1;if(Xt)for(let Ot=0;Ot>te&1)<<31-te)>>>0;let ws=ks.toString(16);return n===1&&ws==="2"&&(ws="6"),{codecString:`hvc1.${lt}${n}.${ws}.${r?"H":"L"}${E}.B0`,params:{general_tier_flag:r,general_profile_idc:n,general_profile_space:i,general_profile_compatibility_flags:[o,c,l,h],general_constraint_indicator_flags:[d,u,f,g,y,p],general_level_idc:E,bit_depth:M+8,bit_depth_luma_minus8:M,bit_depth_chroma_minus8:G,min_spatial_segmentation_idc:O,chroma_format_idc:v,frame_rate:{fixed:se,fps:ee/Q}},width:Pe,height:$e,pixelRatio:[F,z]}}readPPS(e){const t=new Bt(this.ebsp2rbsp(e));t.readUByte(),t.readUByte(),t.skipUEG(),t.skipUEG(),t.skipBits(2),t.skipBits(3),t.skipBits(2),t.skipUEG(),t.skipUEG(),t.skipEG(),t.skipBits(2),t.readBoolean()&&t.skipUEG(),t.skipEG(),t.skipEG(),t.skipBits(4);const i=t.readBoolean(),r=t.readBoolean();let n=1;return r&&i?n=0:r?n=3:i&&(n=2),{parallelismType:n}}matchSPS(e,t){return String.fromCharCode.apply(null,e).substr(3)===String.fromCharCode.apply(null,t).substr(3)}}const ge=188;class rt{constructor(e,t,s,i){this.logger=void 0,this.observer=void 0,this.config=void 0,this.typeSupported=void 0,this.sampleAes=null,this.pmtParsed=!1,this.audioCodec=void 0,this.videoCodec=void 0,this._pmtId=-1,this._videoTrack=void 0,this._audioTrack=void 0,this._id3Track=void 0,this._txtTrack=void 0,this.aacOverFlow=null,this.remainderData=null,this.videoParser=void 0,this.observer=e,this.config=t,this.typeSupported=s,this.logger=i,this.videoParser=null}static probe(e,t){const s=rt.syncOffset(e);return s>0&&t.warn(`MPEG2-TS detected but first sync word found @ offset ${s}`),s!==-1}static syncOffset(e){const t=e.length;let s=Math.min(ge*5,t-ge)+1,i=0;for(;i1&&(n===0&&o>2||c+ge>s))return n}else{if(o)return-1;break}i++}return-1}static createTrack(e,t){return{container:e==="video"||e==="audio"?"video/mp2t":void 0,type:e,id:Rn[e],pid:-1,inputTimeScale:9e4,sequenceNumber:0,samples:[],dropped:0,duration:e==="audio"?t:void 0}}resetInitSegment(e,t,s,i){this.pmtParsed=!1,this._pmtId=-1,this._videoTrack=rt.createTrack("video"),this._videoTrack.duration=i,this._audioTrack=rt.createTrack("audio",i),this._id3Track=rt.createTrack("id3"),this._txtTrack=rt.createTrack("text"),this._audioTrack.segmentCodec="aac",this.videoParser=null,this.aacOverFlow=null,this.remainderData=null,this.audioCodec=t,this.videoCodec=s}resetTimeStamp(){}resetContiguity(){const{_audioTrack:e,_videoTrack:t,_id3Track:s}=this;e&&(e.pesData=null),t&&(t.pesData=null),s&&(s.pesData=null),this.aacOverFlow=null,this.remainderData=null}demux(e,t,s=!1,i=!1){s||(this.sampleAes=null);let r;const n=this._videoTrack,o=this._audioTrack,c=this._id3Track,l=this._txtTrack;let h=n.pid,d=n.pesData,u=o.pid,f=c.pid,g=o.pesData,y=c.pesData,p=null,E=this.pmtParsed,T=this._pmtId,S=e.length;if(this.remainderData&&(e=we(this.remainderData,e),S=e.length,this.remainderData=null),S>4;let P;if(I>1){if(P=A+5+e[A+4],P===A+ge)continue}else P=A+4;switch(b){case h:_&&(d&&(r=vt(d,this.logger))&&(this.readyVideoParser(n.segmentCodec),this.videoParser!==null&&this.videoParser.parsePES(n,l,r,!1)),d={data:[],size:0}),d&&(d.data.push(e.subarray(P,A+ge)),d.size+=A+ge-P);break;case u:if(_){if(g&&(r=vt(g,this.logger)))switch(o.segmentCodec){case"aac":this.parseAACPES(o,r);break;case"mp3":this.parseMPEGPES(o,r);break;case"ac3":this.parseAC3PES(o,r);break}g={data:[],size:0}}g&&(g.data.push(e.subarray(P,A+ge)),g.size+=A+ge-P);break;case f:_&&(y&&(r=vt(y,this.logger))&&this.parseID3PES(c,r),y={data:[],size:0}),y&&(y.data.push(e.subarray(P,A+ge)),y.size+=A+ge-P);break;case 0:_&&(P+=e[P]+1),T=this._pmtId=bc(e,P);break;case T:{_&&(P+=e[P]+1);const M=_c(e,P,this.typeSupported,s,this.observer,this.logger);h=M.videoPid,h>0&&(n.pid=h,n.segmentCodec=M.segmentVideoCodec),u=M.audioPid,u>0&&(o.pid=u,o.segmentCodec=M.segmentAudioCodec),f=M.id3Pid,f>0&&(c.pid=f),p!==null&&!E&&(this.logger.warn(`MPEG-TS PMT found at ${A} after unknown PID '${p}'. Backtracking to sync byte @${v} to parse all TS packets.`),p=null,A=v-188),E=this.pmtParsed=!0;break}case 17:case 8191:break;default:p=b;break}}else x++;x>0&&gi(this.observer,new Error(`Found ${x} TS packet/s that do not start with 0x47`),void 0,this.logger),n.pesData=d,o.pesData=g,c.pesData=y;const D={audioTrack:o,videoTrack:n,id3Track:c,textTrack:l};return i&&this.extractRemainingSamples(D),D}flush(){const{remainderData:e}=this;this.remainderData=null;let t;return e?t=this.demux(e,-1,!1,!0):t={videoTrack:this._videoTrack,audioTrack:this._audioTrack,id3Track:this._id3Track,textTrack:this._txtTrack},this.extractRemainingSamples(t),this.sampleAes?this.decrypt(t,this.sampleAes):t}extractRemainingSamples(e){const{audioTrack:t,videoTrack:s,id3Track:i,textTrack:r}=e,n=s.pesData,o=t.pesData,c=i.pesData;let l;if(n&&(l=vt(n,this.logger))?(this.readyVideoParser(s.segmentCodec),this.videoParser!==null&&(this.videoParser.parsePES(s,r,l,!0),s.pesData=null)):s.pesData=n,o&&(l=vt(o,this.logger))){switch(t.segmentCodec){case"aac":this.parseAACPES(t,l);break;case"mp3":this.parseMPEGPES(t,l);break;case"ac3":this.parseAC3PES(t,l);break}t.pesData=null}else o!=null&&o.size&&this.logger.log("last AAC PES packet truncated,might overlap between fragments"),t.pesData=o;c&&(l=vt(c,this.logger))?(this.parseID3PES(i,l),i.pesData=null):i.pesData=c}demuxSampleAes(e,t,s){const i=this.demux(e,s,!0,!this.config.progressive),r=this.sampleAes=new Ic(this.observer,this.config,t);return this.decrypt(i,r)}readyVideoParser(e){this.videoParser===null&&(e==="avc"?this.videoParser=new Lc:e==="hevc"&&(this.videoParser=new Rc))}decrypt(e,t){return new Promise(s=>{const{audioTrack:i,videoTrack:r}=e;i.samples&&i.segmentCodec==="aac"?t.decryptAacSamples(i.samples,0,()=>{r.samples?t.decryptAvcSamples(r.samples,0,0,()=>{s(e)}):s(e)}):r.samples&&t.decryptAvcSamples(r.samples,0,0,()=>{s(e)})})}destroy(){this.observer&&this.observer.removeAllListeners(),this.config=this.logger=this.observer=null,this.aacOverFlow=this.videoParser=this.remainderData=this.sampleAes=null,this._videoTrack=this._audioTrack=this._id3Track=this._txtTrack=void 0}parseAACPES(e,t){let s=0;const i=this.aacOverFlow;let r=t.data;if(i){this.aacOverFlow=null;const d=i.missing,u=i.sample.unit.byteLength;if(d===-1)r=we(i.sample.unit,r);else{const f=u-d;i.sample.unit.set(r.subarray(0,d),f),e.samples.push(i.sample),s=i.missing}}let n,o;for(n=s,o=r.length;n0;)o+=c}}parseID3PES(e,t){if(t.pts===void 0){this.logger.warn("[tsdemuxer]: ID3 PES unknown PTS");return}const s=ne({},t,{type:this._videoTrack?_e.emsg:_e.audioId3,duration:Number.POSITIVE_INFINITY});e.samples.push(s)}}function fi(a,e){return((a[e+1]&31)<<8)+a[e+2]}function bc(a,e){return(a[e+10]&31)<<8|a[e+11]}function _c(a,e,t,s,i,r){const n={audioPid:-1,videoPid:-1,id3Pid:-1,segmentVideoCodec:"avc",segmentAudioCodec:"aac"},o=(a[e+1]&15)<<8|a[e+2],c=e+3+o-4,l=(a[e+10]&15)<<8|a[e+11];for(e+=12+l;e0){let u=e+5,f=d;for(;f>2;){switch(a[u]){case 106:t.ac3!==!0?r.log("AC-3 audio found, not supported in this browser for now"):(n.audioPid=h,n.segmentAudioCodec="ac3");break}const y=a[u+1]+2;u+=y,f-=y}}break;case 194:case 135:return gi(i,new Error("Unsupported EC-3 in M2TS found"),void 0,r),n;case 36:n.videoPid===-1&&(n.videoPid=h,n.segmentVideoCodec="hevc",r.log("HEVC in M2TS found"));break}e+=d+5}return n}function gi(a,e,t,s){s.warn(`parsing error: ${e.message}`),a.emit(m.ERROR,m.ERROR,{type:Y.MEDIA_ERROR,details:R.FRAG_PARSING_ERROR,fatal:!1,levelRetry:t,error:e,reason:e.message})}function Vs(a,e){e.log(`${a} with AES-128-CBC encryption found in unencrypted stream`)}function vt(a,e){let t=0,s,i,r,n,o;const c=a.data;if(!a||a.size===0)return null;for(;c[0].length<19&&c.length>1;)c[0]=we(c[0],c[1]),c.splice(1,1);if(s=c[0],(s[0]<<16)+(s[1]<<8)+s[2]===1){if(i=(s[4]<<8)+s[5],i&&i>a.size-6)return null;const h=s[7];h&192&&(n=(s[9]&14)*536870912+(s[10]&255)*4194304+(s[11]&254)*16384+(s[12]&255)*128+(s[13]&254)/2,h&64?(o=(s[14]&14)*536870912+(s[15]&255)*4194304+(s[16]&254)*16384+(s[17]&255)*128+(s[18]&254)/2,n-o>60*9e4&&(e.warn(`${Math.round((n-o)/9e4)}s delta between PTS and DTS, align them`),n=o)):o=n),r=s[8];let d=r+9;if(a.size<=d)return null;a.size-=d;const u=new Uint8Array(a.size);for(let f=0,g=c.length;fy){d-=y;continue}else s=s.subarray(d),y-=d,d=0;u.set(s,t),t+=y}return i&&(i-=r+3),{data:u,pts:n,dts:o,len:i}}return null}class Dc{static getSilentFrame(e,t){switch(e){case"mp4a.40.2":if(t===1)return new Uint8Array([0,200,0,128,35,128]);if(t===2)return new Uint8Array([33,0,73,144,2,25,0,35,128]);if(t===3)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,142]);if(t===4)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,128,44,128,8,2,56]);if(t===5)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,130,48,4,153,0,33,144,2,56]);if(t===6)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,130,48,4,153,0,33,144,2,0,178,0,32,8,224]);break;default:if(t===1)return new Uint8Array([1,64,34,128,163,78,230,128,186,8,0,0,0,28,6,241,193,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94]);if(t===2)return new Uint8Array([1,64,34,128,163,94,230,128,186,8,0,0,0,0,149,0,6,241,161,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94]);if(t===3)return new Uint8Array([1,64,34,128,163,94,230,128,186,8,0,0,0,0,149,0,6,241,161,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94]);break}}}const tt=Math.pow(2,32)-1;class L{static init(){L.types={avc1:[],avcC:[],hvc1:[],hvcC:[],btrt:[],dinf:[],dref:[],esds:[],ftyp:[],hdlr:[],mdat:[],mdhd:[],mdia:[],mfhd:[],minf:[],moof:[],moov:[],mp4a:[],".mp3":[],dac3:[],"ac-3":[],mvex:[],mvhd:[],pasp:[],sdtp:[],stbl:[],stco:[],stsc:[],stsd:[],stsz:[],stts:[],tfdt:[],tfhd:[],traf:[],trak:[],trun:[],trex:[],tkhd:[],vmhd:[],smhd:[]};let e;for(e in L.types)L.types.hasOwnProperty(e)&&(L.types[e]=[e.charCodeAt(0),e.charCodeAt(1),e.charCodeAt(2),e.charCodeAt(3)]);const t=new Uint8Array([0,0,0,0,0,0,0,0,118,105,100,101,0,0,0,0,0,0,0,0,0,0,0,0,86,105,100,101,111,72,97,110,100,108,101,114,0]),s=new Uint8Array([0,0,0,0,0,0,0,0,115,111,117,110,0,0,0,0,0,0,0,0,0,0,0,0,83,111,117,110,100,72,97,110,100,108,101,114,0]);L.HDLR_TYPES={video:t,audio:s};const i=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,12,117,114,108,32,0,0,0,1]),r=new Uint8Array([0,0,0,0,0,0,0,0]);L.STTS=L.STSC=L.STCO=r,L.STSZ=new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0]),L.VMHD=new Uint8Array([0,0,0,1,0,0,0,0,0,0,0,0]),L.SMHD=new Uint8Array([0,0,0,0,0,0,0,0]),L.STSD=new Uint8Array([0,0,0,0,0,0,0,1]);const n=new Uint8Array([105,115,111,109]),o=new Uint8Array([97,118,99,49]),c=new Uint8Array([0,0,0,1]);L.FTYP=L.box(L.types.ftyp,n,c,n,o),L.DINF=L.box(L.types.dinf,L.box(L.types.dref,i))}static box(e,...t){let s=8,i=t.length;const r=i;for(;i--;)s+=t[i].byteLength;const n=new Uint8Array(s);for(n[0]=s>>24&255,n[1]=s>>16&255,n[2]=s>>8&255,n[3]=s&255,n.set(e,4),i=0,s=8;i>24&255,e>>16&255,e>>8&255,e&255,s>>24,s>>16&255,s>>8&255,s&255,i>>24,i>>16&255,i>>8&255,i&255,85,196,0,0]))}static mdia(e){return L.box(L.types.mdia,L.mdhd(e.timescale||0,e.duration||0),L.hdlr(e.type),L.minf(e))}static mfhd(e){return L.box(L.types.mfhd,new Uint8Array([0,0,0,0,e>>24,e>>16&255,e>>8&255,e&255]))}static minf(e){return e.type==="audio"?L.box(L.types.minf,L.box(L.types.smhd,L.SMHD),L.DINF,L.stbl(e)):L.box(L.types.minf,L.box(L.types.vmhd,L.VMHD),L.DINF,L.stbl(e))}static moof(e,t,s){return L.box(L.types.moof,L.mfhd(e),L.traf(s,t))}static moov(e){let t=e.length;const s=[];for(;t--;)s[t]=L.trak(e[t]);return L.box.apply(null,[L.types.moov,L.mvhd(e[0].timescale||0,e[0].duration||0)].concat(s).concat(L.mvex(e)))}static mvex(e){let t=e.length;const s=[];for(;t--;)s[t]=L.trex(e[t]);return L.box.apply(null,[L.types.mvex,...s])}static mvhd(e,t){t*=e;const s=Math.floor(t/(tt+1)),i=Math.floor(t%(tt+1)),r=new Uint8Array([1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,3,e>>24&255,e>>16&255,e>>8&255,e&255,s>>24,s>>16&255,s>>8&255,s&255,i>>24,i>>16&255,i>>8&255,i&255,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255]);return L.box(L.types.mvhd,r)}static sdtp(e){const t=e.samples||[],s=new Uint8Array(4+t.length);let i,r;for(i=0;i>>8&255),t.push(n&255),t=t.concat(Array.prototype.slice.call(r));for(i=0;i>>8&255),s.push(n&255),s=s.concat(Array.prototype.slice.call(r));const o=L.box(L.types.avcC,new Uint8Array([1,t[3],t[4],t[5],255,224|e.sps.length].concat(t).concat([e.pps.length]).concat(s))),c=e.width,l=e.height,h=e.pixelRatio[0],d=e.pixelRatio[1];return L.box(L.types.avc1,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,c>>8&255,c&255,l>>8&255,l&255,0,72,0,0,0,72,0,0,0,0,0,0,0,1,18,100,97,105,108,121,109,111,116,105,111,110,47,104,108,115,46,106,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,17,17]),o,L.box(L.types.btrt,new Uint8Array([0,28,156,128,0,45,198,192,0,45,198,192])),L.box(L.types.pasp,new Uint8Array([h>>24,h>>16&255,h>>8&255,h&255,d>>24,d>>16&255,d>>8&255,d&255])))}static esds(e){const t=e.config;return new Uint8Array([0,0,0,0,3,25,0,1,0,4,17,64,21,0,0,0,0,0,0,0,0,0,0,0,5,2,...t,6,1,2])}static audioStsd(e){const t=e.samplerate||0;return new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,e.channelCount||0,0,16,0,0,0,0,t>>8&255,t&255,0,0])}static mp4a(e){return L.box(L.types.mp4a,L.audioStsd(e),L.box(L.types.esds,L.esds(e)))}static mp3(e){return L.box(L.types[".mp3"],L.audioStsd(e))}static ac3(e){return L.box(L.types["ac-3"],L.audioStsd(e),L.box(L.types.dac3,e.config))}static stsd(e){const{segmentCodec:t}=e;if(e.type==="audio"){if(t==="aac")return L.box(L.types.stsd,L.STSD,L.mp4a(e));if(t==="ac3"&&e.config)return L.box(L.types.stsd,L.STSD,L.ac3(e));if(t==="mp3"&&e.codec==="mp3")return L.box(L.types.stsd,L.STSD,L.mp3(e))}else if(e.pps&&e.sps){if(t==="avc")return L.box(L.types.stsd,L.STSD,L.avc1(e));if(t==="hevc"&&e.vps)return L.box(L.types.stsd,L.STSD,L.hvc1(e))}else throw new Error("video track missing pps or sps");throw new Error(`unsupported ${e.type} segment codec (${t}/${e.codec})`)}static tkhd(e){const t=e.id,s=(e.duration||0)*(e.timescale||0),i=e.width||0,r=e.height||0,n=Math.floor(s/(tt+1)),o=Math.floor(s%(tt+1));return L.box(L.types.tkhd,new Uint8Array([1,0,0,7,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,3,t>>24&255,t>>16&255,t>>8&255,t&255,0,0,0,0,n>>24,n>>16&255,n>>8&255,n&255,o>>24,o>>16&255,o>>8&255,o&255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,i>>8&255,i&255,0,0,r>>8&255,r&255,0,0]))}static traf(e,t){const s=L.sdtp(e),i=e.id,r=Math.floor(t/(tt+1)),n=Math.floor(t%(tt+1));return L.box(L.types.traf,L.box(L.types.tfhd,new Uint8Array([0,0,0,0,i>>24,i>>16&255,i>>8&255,i&255])),L.box(L.types.tfdt,new Uint8Array([1,0,0,0,r>>24,r>>16&255,r>>8&255,r&255,n>>24,n>>16&255,n>>8&255,n&255])),L.trun(e,s.length+16+20+8+16+8+8),s)}static trak(e){return e.duration=e.duration||4294967295,L.box(L.types.trak,L.tkhd(e),L.mdia(e))}static trex(e){const t=e.id;return L.box(L.types.trex,new Uint8Array([0,0,0,0,t>>24,t>>16&255,t>>8&255,t&255,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1]))}static trun(e,t){const s=e.samples||[],i=s.length,r=12+16*i,n=new Uint8Array(r);let o,c,l,h,d,u;for(t+=8+r,n.set([e.type==="video"?1:0,0,15,1,i>>>24&255,i>>>16&255,i>>>8&255,i&255,t>>>24&255,t>>>16&255,t>>>8&255,t&255],0),o=0;o>>24&255,l>>>16&255,l>>>8&255,l&255,h>>>24&255,h>>>16&255,h>>>8&255,h&255,d.isLeading<<2|d.dependsOn,d.isDependedOn<<6|d.hasRedundancy<<4|d.paddingValue<<1|d.isNonSync,d.degradPrio&61440,d.degradPrio&15,u>>>24&255,u>>>16&255,u>>>8&255,u&255],12+16*o);return L.box(L.types.trun,n)}static initSegment(e){L.types||L.init();const t=L.moov(e);return we(L.FTYP,t)}static hvc1(e){const t=e.params,s=[e.vps,e.sps,e.pps],i=4,r=new Uint8Array([1,t.general_profile_space<<6|(t.general_tier_flag?32:0)|t.general_profile_idc,t.general_profile_compatibility_flags[0],t.general_profile_compatibility_flags[1],t.general_profile_compatibility_flags[2],t.general_profile_compatibility_flags[3],t.general_constraint_indicator_flags[0],t.general_constraint_indicator_flags[1],t.general_constraint_indicator_flags[2],t.general_constraint_indicator_flags[3],t.general_constraint_indicator_flags[4],t.general_constraint_indicator_flags[5],t.general_level_idc,240|t.min_spatial_segmentation_idc>>8,255&t.min_spatial_segmentation_idc,252|t.parallelismType,252|t.chroma_format_idc,248|t.bit_depth_luma_minus8,248|t.bit_depth_chroma_minus8,0,parseInt(t.frame_rate.fps),i-1|t.temporal_id_nested<<2|t.num_temporal_layers<<3|(t.frame_rate.fixed?64:0),s.length]);let n=r.length;for(let g=0;g>8,s[g][y].length&255]),n),n+=2,o.set(s[g][y],n),n+=s[g][y].length}const l=L.box(L.types.hvcC,o),h=e.width,d=e.height,u=e.pixelRatio[0],f=e.pixelRatio[1];return L.box(L.types.hvc1,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,h>>8&255,h&255,d>>8&255,d&255,0,72,0,0,0,72,0,0,0,0,0,0,0,1,18,100,97,105,108,121,109,111,116,105,111,110,47,104,108,115,46,106,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,17,17]),l,L.box(L.types.btrt,new Uint8Array([0,28,156,128,0,45,198,192,0,45,198,192])),L.box(L.types.pasp,new Uint8Array([u>>24,u>>16&255,u>>8&255,u&255,f>>24,f>>16&255,f>>8&255,f&255])))}}L.types=void 0;L.HDLR_TYPES=void 0;L.STTS=void 0;L.STSC=void 0;L.STCO=void 0;L.STSZ=void 0;L.VMHD=void 0;L.SMHD=void 0;L.STSD=void 0;L.FTYP=void 0;L.DINF=void 0;const va=9e4;function Ki(a,e,t=1,s=!1){const i=a*e*t;return s?Math.round(i):i}function Cc(a,e,t=1,s=!1){return Ki(a,e,1/t,s)}function Ft(a,e=!1){return Ki(a,1e3,1/va,e)}function Pc(a,e=1){return Ki(a,va,1/e)}function Hr(a){const{baseTime:e,timescale:t,trackId:s}=a;return`${e/t} (${e}/${t}) trackId: ${s}`}const kc=10*1e3,wc=1024,Oc=1152,Fc=1536;let xt=null,Hs=null;function Yr(a,e,t,s){return{duration:e,size:t,cts:s,flags:{isLeading:0,isDependedOn:0,hasRedundancy:0,degradPrio:0,dependsOn:a?2:1,isNonSync:a?0:1}}}class fs extends Oe{constructor(e,t,s,i){if(super("mp4-remuxer",i),this.observer=void 0,this.config=void 0,this.typeSupported=void 0,this.ISGenerated=!1,this._initPTS=null,this._initDTS=null,this.nextVideoTs=null,this.nextAudioTs=null,this.videoSampleDuration=null,this.isAudioContiguous=!1,this.isVideoContiguous=!1,this.videoTrackConfig=void 0,this.observer=e,this.config=t,this.typeSupported=s,this.ISGenerated=!1,xt===null){const n=(navigator.userAgent||"").match(/Chrome\/(\d+)/i);xt=n?parseInt(n[1]):0}if(Hs===null){const r=navigator.userAgent.match(/Safari\/(\d+)/i);Hs=r?parseInt(r[1]):0}}destroy(){this.config=this.videoTrackConfig=this._initPTS=this._initDTS=null}resetTimeStamp(e){const t=this._initPTS;(!t||!e||e.trackId!==t.trackId||e.baseTime!==t.baseTime||e.timescale!==t.timescale)&&this.log(`Reset initPTS: ${t&&Hr(t)} > ${e&&Hr(e)}`),this._initPTS=this._initDTS=e}resetNextTimestamp(){this.log("reset next timestamp"),this.isVideoContiguous=!1,this.isAudioContiguous=!1}resetInitSegment(){this.log("ISGenerated flag reset"),this.ISGenerated=!1,this.videoTrackConfig=void 0}getVideoStartPts(e){let t=!1;const s=e[0].pts,i=e.reduce((r,n)=>{let o=n.pts,c=o-r;return c<-4294967296&&(t=!0,o=be(o,s),c=o-r),c>0?r:o},s);return t&&this.debug("PTS rollover detected"),i}remux(e,t,s,i,r,n,o,c){let l,h,d,u,f,g,y=r,p=r;const E=e.pid>-1,T=t.pid>-1,S=t.samples.length,v=e.samples.length>0,x=o&&S>0||S>1;if((!E||v)&&(!T||x)||this.ISGenerated||o){if(this.ISGenerated){var A,_,b,I;const W=this.videoTrackConfig;(W&&(t.width!==W.width||t.height!==W.height||((A=t.pixelRatio)==null?void 0:A[0])!==((_=W.pixelRatio)==null?void 0:_[0])||((b=t.pixelRatio)==null?void 0:b[1])!==((I=W.pixelRatio)==null?void 0:I[1]))||!W&&x||this.nextAudioTs===null&&v)&&this.resetInitSegment()}this.ISGenerated||(d=this.generateIS(e,t,r,n));const P=this.isVideoContiguous;let M=-1,G;if(x&&(M=Mc(t.samples),!P&&this.config.forceKeyFrameOnDiscontinuity))if(g=!0,M>0){this.warn(`Dropped ${M} out of ${S} video samples due to a missing keyframe`);const W=this.getVideoStartPts(t.samples);t.samples=t.samples.slice(M),t.dropped+=M,p+=(t.samples[0].pts-W)/t.inputTimeScale,G=p}else M===-1&&(this.warn(`No keyframe found out of ${S} video samples`),g=!1);if(this.ISGenerated){if(v&&x){const W=this.getVideoStartPts(t.samples),w=(be(e.samples[0].pts,W)-W)/t.inputTimeScale;y+=Math.max(0,w),p+=Math.max(0,-w)}if(v){if(e.samplerate||(this.warn("regenerate InitSegment as audio detected"),d=this.generateIS(e,t,r,n)),h=this.remuxAudio(e,y,this.isAudioContiguous,n,T||x||c===U.AUDIO?p:void 0),x){const W=h?h.endPTS-h.startPTS:0;t.inputTimeScale||(this.warn("regenerate InitSegment as video detected"),d=this.generateIS(e,t,r,n)),l=this.remuxVideo(t,p,P,W)}}else x&&(l=this.remuxVideo(t,p,P,0));l&&(l.firstKeyFrame=M,l.independent=M!==-1,l.firstKeyFramePTS=G)}}return this.ISGenerated&&this._initPTS&&this._initDTS&&(s.samples.length&&(f=xa(s,r,this._initPTS,this._initDTS)),i.samples.length&&(u=Aa(i,r,this._initPTS))),{audio:h,video:l,initSegment:d,independent:g,text:u,id3:f}}computeInitPts(e,t,s,i){const r=Math.round(s*t);let n=be(e,r);if(n0?O-1:O].dts&&(T=!0)}T&&n.sort(function(O,F){const z=O.dts-F.dts,se=O.pts-F.pts;return z||se}),g=n[0].dts,y=n[n.length-1].dts;const v=y-g,x=v?Math.round(v/(c-1)):f||e.inputTimeScale/30;if(s){const O=g-S,F=O>x,z=O<-1;if((F||z)&&(F?this.warn(`${(e.segmentCodec||"").toUpperCase()}: ${Ft(O,!0)} ms (${O}dts) hole between fragments detected at ${t.toFixed(3)}`):this.warn(`${(e.segmentCodec||"").toUpperCase()}: ${Ft(-O,!0)} ms (${O}dts) overlapping between fragments detected at ${t.toFixed(3)}`),!z||S>=n[0].pts||xt)){g=S;const se=n[0].pts-O;if(F)n[0].dts=g,n[0].pts=se;else{let Q=!0;for(let ee=0;eese&&Q);ee++){const Se=n[ee].pts;if(n[ee].dts-=O,n[ee].pts-=O,ee0?F.dts-n[O-1].dts:x;if(Q=O>0?F.pts-n[O-1].pts:x,Se.stretchShortVideoTrack&&this.nextAudioTs!==null){const Pe=Math.floor(Se.maxBufferHole*r),$e=(i?p+i*r:this.nextAudioTs+h)-F.pts;$e>Pe?(f=$e-me,f<0?f=me:M=!0,this.log(`It is approximately ${$e/90} ms to the next segment; using duration ${f/90} ms for the last video frame.`)):f=me}else f=me}const ee=Math.round(F.pts-F.dts);G=Math.min(G,f),K=Math.max(K,f),W=Math.min(W,Q),w=Math.max(w,Q),o.push(Yr(F.key,f,se,ee))}if(o.length){if(xt){if(xt<70){const O=o[0].flags;O.dependsOn=2,O.isNonSync=0}}else if(Hs&&w-W0&&(i&&Math.abs(S-(E+T))<9e3||Math.abs(be(y[0].pts,S)-(E+T))<20*h),y.forEach(function(w){w.pts=be(w.pts,S)}),!s||E<0){const w=y.length;if(y=y.filter(V=>V.pts>=0),w!==y.length&&this.warn(`Removed ${y.length-w} of ${w} samples (initPTS ${T} / ${n})`),!y.length)return;r===0?E=0:i&&!g?E=Math.max(0,S-T):E=y[0].pts-T}if(e.segmentCodec==="aac"){const w=this.config.maxAudioFramesDrift;for(let V=0,$=E+T;V=w*h&&F0){A+=p;try{D=new Uint8Array(A)}catch(F){this.observer.emit(m.ERROR,m.ERROR,{type:Y.MUX_ERROR,details:R.REMUX_ALLOC_ERROR,fatal:!1,error:F,bytes:A,reason:`fail allocating audio mdat ${A}`});return}u||(new DataView(D.buffer).setUint32(0,A),D.set(L.types.mdat,4))}else return;D.set(H,p);const O=H.byteLength;p+=O,f.push(Yr(!0,l,O,0)),x=q}const b=f.length;if(!b)return;const I=f[f.length-1];E=x-T,this.nextAudioTs=E+c*I.duration;const P=u?new Uint8Array(0):L.moof(e.sequenceNumber++,v/c,ne({},e,{samples:f}));e.samples=[];const M=(v-T)/n,G=this.nextAudioTs/n,K={data1:P,data2:D,startPTS:M,endPTS:G,startDTS:M,endDTS:G,type:"audio",hasAudio:!0,hasVideo:!1,nb:b};return this.isAudioContiguous=!0,K}}function be(a,e){let t;if(e===null)return a;for(e4294967296;)a+=t;return a}function Mc(a){for(let e=0;en.pts-o.pts);const r=a.samples;return a.samples=[],{samples:r}}class Nc extends Oe{constructor(e,t,s,i){super("passthrough-remuxer",i),this.emitInitSegment=!1,this.audioCodec=void 0,this.videoCodec=void 0,this.initData=void 0,this.initPTS=null,this.initTracks=void 0,this.lastEndTime=null,this.isVideoContiguous=!1}destroy(){}resetTimeStamp(e){this.lastEndTime=null;const t=this.initPTS;t&&e&&t.baseTime===e.baseTime&&t.timescale===e.timescale||(this.initPTS=e)}resetNextTimestamp(){this.isVideoContiguous=!1,this.lastEndTime=null}resetInitSegment(e,t,s,i){this.audioCodec=t,this.videoCodec=s,this.generateInitSegment(e,i),this.emitInitSegment=!0}generateInitSegment(e,t){let{audioCodec:s,videoCodec:i}=this;if(!(e!=null&&e.byteLength)){this.initTracks=void 0,this.initData=void 0;return}const{audio:r,video:n}=this.initData=Dn(e);if(t)Io(e,t);else{const c=r||n;c!=null&&c.encrypted&&this.warn(`Init segment with encrypted track with has no key ("${c.codec}")!`)}r&&(s=Wr(r,ae.AUDIO,this)),n&&(i=Wr(n,ae.VIDEO,this));const o={};r&&n?o.audiovideo={container:"video/mp4",codec:s+","+i,supplemental:n.supplemental,encrypted:n.encrypted,initSegment:e,id:"main"}:r?o.audio={container:"audio/mp4",codec:s,encrypted:r.encrypted,initSegment:e,id:"audio"}:n?o.video={container:"video/mp4",codec:i,supplemental:n.supplemental,encrypted:n.encrypted,initSegment:e,id:"main"}:this.warn("initSegment does not contain moov or trak boxes."),this.initTracks=o}remux(e,t,s,i,r,n){var o,c;let{initPTS:l,lastEndTime:h}=this;const d={audio:void 0,video:void 0,text:i,id3:s,initSegment:void 0};B(h)||(h=this.lastEndTime=r||0);const u=t.samples;if(!u.length)return d;const f={initPTS:void 0,timescale:void 0,trackId:void 0};let g=this.initData;if((o=g)!=null&&o.length||(this.generateInitSegment(u),g=this.initData),!((c=g)!=null&&c.length))return this.warn("Failed to generate initSegment."),d;this.emitInitSegment&&(f.tracks=this.initTracks,this.emitInitSegment=!1);const y=Ro(u,g,this),p=g.audio?y[g.audio.id]:null,E=g.video?y[g.video.id]:null,T=ss(E,1/0),S=ss(p,1/0),v=ss(E,0,!0),x=ss(p,0,!0);let D=r,A=0;const _=p&&(!E||!l&&S0?this.lastEndTime=P:(this.warn("Duration parsed from mp4 should be greater than zero"),this.resetNextTimestamp());const M=!!g.audio,G=!!g.video;let W="";M&&(W+="audio"),G&&(W+="video");const K=(g.audio?g.audio.encrypted:!1)||(g.video?g.video.encrypted:!1),w={data1:u,startPTS:I,startDTS:I,endPTS:P,endDTS:P,type:W,hasAudio:M,hasVideo:G,nb:1,dropped:0,encrypted:K};d.audio=M&&!G?w:void 0,d.video=G?w:void 0;const V=E==null?void 0:E.sampleCount;if(V){const $=E.keyFrameIndex,H=$!==-1;w.nb=V,w.dropped=$===0||this.isVideoContiguous?0:H?$:V,w.independent=H,w.firstKeyFrame=$,H&&E.keyFrameStart&&(w.firstKeyFramePTS=(E.keyFrameStart-l.baseTime)/l.timescale),this.isVideoContiguous||(d.independent=H),this.isVideoContiguous||(this.isVideoContiguous=H),w.dropped&&this.warn(`fmp4 does not start with IDR: firstIDR ${$}/${V} dropped: ${w.dropped} start: ${w.firstKeyFramePTS||"NA"}`)}return d.initSegment=f,d.id3=xa(s,r,l,l),i.samples.length&&(d.text=Aa(i,r,l)),d}}function ss(a,e,t=!1){return(a==null?void 0:a.start)!==void 0?(a.start+(t?a.duration:0))/a.timescale:e}function Bc(a,e,t,s){if(a===null)return!0;const i=Math.max(s,1),r=e-a.baseTime/a.timescale;return Math.abs(r-t)>i}function Wr(a,e,t){const s=a.codec;return s&&s.length>4?s:e===ae.AUDIO?s==="ec-3"||s==="ac-3"||s==="alac"?s:s==="fLaC"||s==="Opus"?Ts(s,!1):(t.warn(`Unhandled audio codec "${s}" in mp4 MAP`),s||"mp4a"):(t.warn(`Unhandled video codec "${s}" in mp4 MAP`),s||"avc1")}let Je;try{Je=self.performance.now.bind(self.performance)}catch{Je=Date.now}const gs=[{demux:Ac,remux:Nc},{demux:rt,remux:fs},{demux:Tc,remux:fs},{demux:vc,remux:fs}];gs.splice(2,0,{demux:Sc,remux:fs});class qr{constructor(e,t,s,i,r,n){this.asyncResult=!1,this.logger=void 0,this.observer=void 0,this.typeSupported=void 0,this.config=void 0,this.id=void 0,this.demuxer=void 0,this.remuxer=void 0,this.decrypter=void 0,this.probe=void 0,this.decryptionPromise=null,this.transmuxConfig=void 0,this.currentTransmuxState=void 0,this.observer=e,this.typeSupported=t,this.config=s,this.id=r,this.logger=n}configure(e){this.transmuxConfig=e,this.decrypter&&this.decrypter.reset()}push(e,t,s,i){const r=s.transmuxing;r.executeStart=Je();let n=new Uint8Array(e);const{currentTransmuxState:o,transmuxConfig:c}=this;i&&(this.currentTransmuxState=i);const{contiguous:l,discontinuity:h,trackSwitch:d,accurateTimeOffset:u,timeOffset:f,initSegmentChange:g}=i||o,{audioCodec:y,videoCodec:p,defaultInitPts:E,duration:T,initSegmentData:S}=c,v=$c(n,t);if(v&&_t(v.method)){const _=this.getDecrypter(),b=wi(v.method);if(_.isSync()){let I=_.softwareDecrypt(n,v.key.buffer,v.iv.buffer,b);if(s.part>-1){const M=_.flush();I=M&&M.buffer}if(!I)return r.executeEnd=Je(),Ys(s);n=new Uint8Array(I)}else return this.asyncResult=!0,this.decryptionPromise=_.webCryptoDecrypt(n,v.key.buffer,v.iv.buffer,b).then(I=>{const P=this.push(I,null,s);return this.decryptionPromise=null,P}),this.decryptionPromise}const x=this.needsProbing(h,d);if(x){const _=this.configureTransmuxer(n);if(_)return this.logger.warn(`[transmuxer] ${_.message}`),this.observer.emit(m.ERROR,m.ERROR,{type:Y.MEDIA_ERROR,details:R.FRAG_PARSING_ERROR,fatal:!1,error:_,reason:_.message}),r.executeEnd=Je(),Ys(s)}(h||d||g||x)&&this.resetInitSegment(S,y,p,T,t),(h||g||x)&&this.resetInitialTimestamp(E),l||this.resetContiguity();const D=this.transmux(n,v,f,u,s);this.asyncResult=Yt(D);const A=this.currentTransmuxState;return A.contiguous=!0,A.discontinuity=!1,A.trackSwitch=!1,r.executeEnd=Je(),D}flush(e){const t=e.transmuxing;t.executeStart=Je();const{decrypter:s,currentTransmuxState:i,decryptionPromise:r}=this;if(r)return this.asyncResult=!0,r.then(()=>this.flush(e));const n=[],{timeOffset:o}=i;if(s){const d=s.flush();d&&n.push(this.push(d.buffer,null,e))}const{demuxer:c,remuxer:l}=this;if(!c||!l){t.executeEnd=Je();const d=[Ys(e)];return this.asyncResult?Promise.resolve(d):d}const h=c.flush(o);return Yt(h)?(this.asyncResult=!0,h.then(d=>(this.flushRemux(n,d,e),n))):(this.flushRemux(n,h,e),this.asyncResult?Promise.resolve(n):n)}flushRemux(e,t,s){const{audioTrack:i,videoTrack:r,id3Track:n,textTrack:o}=t,{accurateTimeOffset:c,timeOffset:l}=this.currentTransmuxState;this.logger.log(`[transmuxer.ts]: Flushed ${this.id} sn: ${s.sn}${s.part>-1?" part: "+s.part:""} of ${this.id===U.MAIN?"level":"track"} ${s.level}`);const h=this.remuxer.remux(i,r,n,o,l,c,!0,this.id);e.push({remuxResult:h,chunkMeta:s}),s.transmuxing.executeEnd=Je()}resetInitialTimestamp(e){const{demuxer:t,remuxer:s}=this;!t||!s||(t.resetTimeStamp(e),s.resetTimeStamp(e))}resetContiguity(){const{demuxer:e,remuxer:t}=this;!e||!t||(e.resetContiguity(),t.resetNextTimestamp())}resetInitSegment(e,t,s,i,r){const{demuxer:n,remuxer:o}=this;!n||!o||(n.resetInitSegment(e,t,s,i),o.resetInitSegment(e,t,s,r))}destroy(){this.demuxer&&(this.demuxer.destroy(),this.demuxer=void 0),this.remuxer&&(this.remuxer.destroy(),this.remuxer=void 0)}transmux(e,t,s,i,r){let n;return t&&t.method==="SAMPLE-AES"?n=this.transmuxSampleAes(e,t,s,i,r):n=this.transmuxUnencrypted(e,s,i,r),n}transmuxUnencrypted(e,t,s,i){const{audioTrack:r,videoTrack:n,id3Track:o,textTrack:c}=this.demuxer.demux(e,t,!1,!this.config.progressive);return{remuxResult:this.remuxer.remux(r,n,o,c,t,s,!1,this.id),chunkMeta:i}}transmuxSampleAes(e,t,s,i,r){return this.demuxer.demuxSampleAes(e,t,s).then(n=>({remuxResult:this.remuxer.remux(n.audioTrack,n.videoTrack,n.id3Track,n.textTrack,s,i,!1,this.id),chunkMeta:r}))}configureTransmuxer(e){const{config:t,observer:s,typeSupported:i}=this;let r;for(let d=0,u=gs.length;d0&&(e==null?void 0:e.key)!=null&&e.iv!==null&&e.method!=null&&(t=e),t}const Ys=a=>({remuxResult:{},chunkMeta:a});function Yt(a){return"then"in a&&a.then instanceof Function}class Uc{constructor(e,t,s,i,r){this.audioCodec=void 0,this.videoCodec=void 0,this.initSegmentData=void 0,this.duration=void 0,this.defaultInitPts=void 0,this.audioCodec=e,this.videoCodec=t,this.initSegmentData=s,this.duration=i,this.defaultInitPts=r||null}}class Gc{constructor(e,t,s,i,r,n){this.discontinuity=void 0,this.contiguous=void 0,this.accurateTimeOffset=void 0,this.trackSwitch=void 0,this.timeOffset=void 0,this.initSegmentChange=void 0,this.discontinuity=e,this.contiguous=t,this.accurateTimeOffset=s,this.trackSwitch=i,this.timeOffset=r,this.initSegmentChange=n}}let jr=0;class Ia{constructor(e,t,s,i){this.error=null,this.hls=void 0,this.id=void 0,this.instanceNo=jr++,this.observer=void 0,this.frag=null,this.part=null,this.useWorker=void 0,this.workerContext=null,this.transmuxer=null,this.onTransmuxComplete=void 0,this.onFlush=void 0,this.onWorkerMessage=c=>{const l=c.data,h=this.hls;if(!(!h||!(l!=null&&l.event)||l.instanceNo!==this.instanceNo))switch(l.event){case"init":{var d;const u=(d=this.workerContext)==null?void 0:d.objectURL;u&&self.URL.revokeObjectURL(u);break}case"transmuxComplete":{this.handleTransmuxComplete(l.data);break}case"flush":{this.onFlush(l.data);break}case"workerLog":{h.logger[l.data.logType]&&h.logger[l.data.logType](l.data.message);break}default:{l.data=l.data||{},l.data.frag=this.frag,l.data.part=this.part,l.data.id=this.id,h.trigger(l.event,l.data);break}}},this.onWorkerError=c=>{if(!this.hls)return;const l=new Error(`${c.message} (${c.filename}:${c.lineno})`);this.hls.config.enableWorker=!1,this.hls.logger.warn(`Error in "${this.id}" Web Worker, fallback to inline`),this.hls.trigger(m.ERROR,{type:Y.OTHER_ERROR,details:R.INTERNAL_EXCEPTION,fatal:!1,event:"demuxerWorker",error:l})};const r=e.config;this.hls=e,this.id=t,this.useWorker=!!r.enableWorker,this.onTransmuxComplete=s,this.onFlush=i;const n=(c,l)=>{l=l||{},l.frag=this.frag||void 0,c===m.ERROR&&(l=l,l.parent=this.id,l.part=this.part,this.error=l.error),this.hls.trigger(c,l)};this.observer=new Mi,this.observer.on(m.FRAG_DECRYPTED,n),this.observer.on(m.ERROR,n);const o=cr(r.preferManagedMediaSource);if(this.useWorker&&typeof Worker<"u"){const c=this.hls.logger;if(r.workerPath||Yl()){try{r.workerPath?(c.log(`loading Web Worker ${r.workerPath} for "${t}"`),this.workerContext=ql(r.workerPath)):(c.log(`injecting Web Worker for "${t}"`),this.workerContext=Wl());const{worker:h}=this.workerContext;h.addEventListener("message",this.onWorkerMessage),h.addEventListener("error",this.onWorkerError),h.postMessage({instanceNo:this.instanceNo,cmd:"init",typeSupported:o,id:t,config:oe(r)})}catch(h){c.warn(`Error setting up "${t}" Web Worker, fallback to inline`,h),this.terminateWorker(),this.error=null,this.transmuxer=new qr(this.observer,o,r,"",t,e.logger)}return}}this.transmuxer=new qr(this.observer,o,r,"",t,e.logger)}reset(){if(this.frag=null,this.part=null,this.workerContext){const e=this.instanceNo;this.instanceNo=jr++;const t=this.hls.config,s=cr(t.preferManagedMediaSource);this.workerContext.worker.postMessage({instanceNo:this.instanceNo,cmd:"reset",resetNo:e,typeSupported:s,id:this.id,config:oe(t)})}}terminateWorker(){if(this.workerContext){const{worker:e}=this.workerContext;this.workerContext=null,e.removeEventListener("message",this.onWorkerMessage),e.removeEventListener("error",this.onWorkerError),jl(this.hls.config.workerPath)}}destroy(){if(this.workerContext)this.terminateWorker(),this.onWorkerMessage=this.onWorkerError=null;else{const t=this.transmuxer;t&&(t.destroy(),this.transmuxer=null)}const e=this.observer;e&&e.removeAllListeners(),this.frag=null,this.part=null,this.observer=null,this.hls=null}push(e,t,s,i,r,n,o,c,l,h){var d,u;l.transmuxing.start=self.performance.now();const{instanceNo:f,transmuxer:g}=this,y=n?n.start:r.start,p=r.decryptdata,E=this.frag,T=!(E&&r.cc===E.cc),S=!(E&&l.level===E.level),v=E?l.sn-E.sn:-1,x=this.part?l.part-this.part.index:-1,D=v===0&&l.id>1&&l.id===(E==null?void 0:E.stats.chunkCount),A=!S&&(v===1||v===0&&(x===1||D&&x<=0)),_=self.performance.now();(S||v||r.stats.parsing.start===0)&&(r.stats.parsing.start=_),n&&(x||!A)&&(n.stats.parsing.start=_);const b=!(E&&((d=r.initSegment)==null?void 0:d.url)===((u=E.initSegment)==null?void 0:u.url)),I=new Gc(T,A,c,S,y,b);if(!A||T||b){this.hls.logger.log(`[transmuxer-interface]: Starting new transmux session for ${r.type} sn: ${l.sn}${l.part>-1?" part: "+l.part:""} ${this.id===U.MAIN?"level":"track"}: ${l.level} id: ${l.id} +${t.m3u8}`)}function Mn(a,e,t=!0){const s=e.startSN+e.skippedSegments-a.startSN,i=a.fragments,r=s>=0;let n=0;if(r&&se){const r=s[s.length-1].duration*1e3;r{var s;(s=e.details)==null||s.fragments.forEach(i=>{i.level=t,i.initSegment&&(i.initSegment.level=t)})})}function Sl(a,e){return a!==e&&e?Rr(a)!==Rr(e):!1}function Rr(a){return a.replace(/\?[^?]*$/,"")}function Dt(a,e){for(let s=0,i=a.length;sa.startCC)}function br(a,e){const t=a.start+e;a.startPTS=t,a.setStart(t),a.endPTS=t+a.duration}function Gn(a,e){const t=e.fragments;for(let s=0,i=t.length;s{const{config:n,fragCurrent:o,media:c,mediaBuffer:l,state:h}=this,u=c?c.currentTime:0,d=q.bufferInfo(l||c,u,n.maxBufferHole),f=!d.len;if(this.log(`Media seeking to ${M(u)?u.toFixed(3):u}, state: ${h}, ${f?"out of":"in"} buffer`),this.state===C.ENDED)this.resetLoadingState();else if(o){const g=n.maxFragLookUpTolerance,y=o.start-g,p=o.start+o.duration+g;if(f||pd.end){const E=u>p;(ug&&(this.lastCurrentTime=u),!this.loadingParts){const y=Math.max(d.end,u),p=this.shouldLoadParts(this.getLevelDetails(),y);p&&(this.log(`LL-Part loading ON after seeking to ${u.toFixed(2)} with buffer @${y.toFixed(2)}`),this.loadingParts=p)}}this.hls.hasEnoughToStart||(this.log(`Setting ${f?"startPosition":"nextLoadPosition"} to ${u} for seek without enough to start`),this.nextLoadPosition=u,f&&(this.startPosition=u)),f&&this.state===C.IDLE&&this.tickImmediate()},this.onMediaEnded=()=>{this.log("setting startPosition to 0 because media ended"),this.startPosition=this.lastCurrentTime=0},this.playlistType=r,this.hls=e,this.fragmentLoader=new Qo(e.config),this.keyLoader=s,this.fragmentTracker=t,this.config=e.config,this.decrypter=new Ti(e.config)}registerListeners(){const{hls:e}=this;e.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.on(m.ERROR,this.onError,this)}unregisterListeners(){const{hls:e}=this;e.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.off(m.ERROR,this.onError,this)}doTick(){this.onTickEnd()}onTickEnd(){}startLoad(e){}stopLoad(){if(this.state===C.STOPPED)return;this.fragmentLoader.abort(),this.keyLoader.abort(this.playlistType);const e=this.fragCurrent;e!=null&&e.loader&&(e.abortRequests(),this.fragmentTracker.removeFragment(e)),this.resetTransmuxer(),this.fragCurrent=null,this.fragPrevious=null,this.clearInterval(),this.clearNextTick(),this.state=C.STOPPED}get startPositionValue(){const{nextLoadPosition:e,startPosition:t}=this;return t===-1&&e?e:t}get bufferingEnabled(){return this.buffering}pauseBuffering(){this.buffering=!1}resumeBuffering(){this.buffering=!0}get inFlightFrag(){return{frag:this.fragCurrent,state:this.state}}_streamEnded(e,t){if(t.live||!this.media)return!1;const s=e.end||0,i=this.config.timelineOffset||0;if(s<=i)return!1;const r=e.buffered;this.config.maxBufferHole&&r&&r.length>1&&(e=q.bufferedInfo(r,e.start,0));const n=e.nextStart;if(n&&n>i&&n{const n=r.frag;if(this.fragContextChanged(n)){this.warn(`${n.type} sn: ${n.sn}${r.part?" part: "+r.part.index:""} of ${this.fragInfo(n,!1,r.part)}) was dropped during download.`),this.fragmentTracker.removeFragment(n);return}n.stats.chunkCount++,this._handleFragmentLoadProgress(r)};this._doFragLoad(e,t,s,i).then(r=>{if(!r)return;const n=this.state,o=r.frag;if(this.fragContextChanged(o)){(n===C.FRAG_LOADING||!this.fragCurrent&&n===C.PARSING)&&(this.fragmentTracker.removeFragment(o),this.state=C.IDLE);return}"payload"in r&&(this.log(`Loaded ${o.type} sn: ${o.sn} of ${this.playlistLabel()} ${o.level}`),this.hls.trigger(m.FRAG_LOADED,r)),this._handleFragmentLoadComplete(r)}).catch(r=>{this.state===C.STOPPED||this.state===C.ERROR||(this.warn(`Frag error: ${(r==null?void 0:r.message)||r}`),this.resetFragmentLoading(e))})}clearTrackerIfNeeded(e){var t;const{fragmentTracker:s}=this;if(s.getState(e)===ue.APPENDING){const r=e.type,n=this.getFwdBufferInfo(this.mediaBuffer,r),o=Math.max(e.duration,n?n.len:this.config.maxBufferLength),c=this.backtrackFragment;((c?e.sn-c.sn:0)===1||this.reduceMaxBufferLength(o,e.duration))&&s.removeFragment(e)}else((t=this.mediaBuffer)==null?void 0:t.buffered.length)===0?s.removeAllFragments():s.hasParts(e.type)&&(s.detectPartialFragments({frag:e,part:null,stats:e.stats,id:e.type}),s.getState(e)===ue.PARTIAL&&s.removeFragment(e))}checkLiveUpdate(e){if(e.updated&&!e.live){const t=e.fragments[e.fragments.length-1];this.fragmentTracker.detectPartialFragments({frag:t,part:null,stats:t.stats,id:t.type})}e.fragments[0]||(e.deltaUpdateFailed=!0)}waitForLive(e){const t=e.details;return(t==null?void 0:t.live)&&t.type!=="EVENT"&&(this.levelLastLoaded!==e||t.expired)}flushMainBuffer(e,t,s=null){if(!(e-t))return;const i={startOffset:e,endOffset:t,type:s};this.hls.trigger(m.BUFFER_FLUSHING,i)}_loadInitSegment(e,t){this._doFragLoad(e,t).then(s=>{const i=s==null?void 0:s.frag;if(!i||this.fragContextChanged(i)||!this.levels)throw new Error("init load aborted");return s}).then(s=>{const{hls:i}=this,{frag:r,payload:n}=s,o=r.decryptdata;if(n&&n.byteLength>0&&o!=null&&o.key&&o.iv&&Tt(o.method)){const c=self.performance.now();return this.decrypter.decrypt(new Uint8Array(n),o.key.buffer,o.iv.buffer,vi(o.method)).catch(l=>{throw i.trigger(m.ERROR,{type:V.MEDIA_ERROR,details:R.FRAG_DECRYPT_ERROR,fatal:!1,error:l,reason:l.message,frag:r}),l}).then(l=>{const h=self.performance.now();return i.trigger(m.FRAG_DECRYPTED,{frag:r,payload:l,stats:{tstart:c,tdecrypt:h}}),s.payload=l,this.completeInitSegmentLoad(s)})}return this.completeInitSegmentLoad(s)}).catch(s=>{this.state===C.STOPPED||this.state===C.ERROR||(this.warn(s),this.resetFragmentLoading(e))})}completeInitSegmentLoad(e){const{levels:t}=this;if(!t)throw new Error("init load aborted, missing levels");const s=e.frag.stats;this.state!==C.STOPPED&&(this.state=C.IDLE),e.frag.data=new Uint8Array(e.payload),s.parsing.start=s.buffering.start=self.performance.now(),s.parsing.end=s.buffering.end=self.performance.now(),this.tick()}unhandledEncryptionError(e,t){var s,i;const r=e.tracks;if(r&&!t.encrypted&&((s=r.audio)!=null&&s.encrypted||(i=r.video)!=null&&i.encrypted)&&(!this.config.emeEnabled||!this.keyLoader.emeController)){const n=this.media,o=new Error(`Encrypted track with no key in ${this.fragInfo(t)} (media ${n?"attached mediaKeys: "+n.mediaKeys:"detached"})`);return this.warn(o.message),!n||n.mediaKeys?!1:(this.hls.trigger(m.ERROR,{type:V.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_NO_KEYS,fatal:!1,error:o,frag:t}),this.resetTransmuxer(),!0)}return!1}fragContextChanged(e){const{fragCurrent:t}=this;return!e||!t||e.sn!==t.sn||e.level!==t.level}fragBufferedComplete(e,t){const s=this.mediaBuffer?this.mediaBuffer:this.media;if(this.log(`Buffered ${e.type} sn: ${e.sn}${t?" part: "+t.index:""} of ${this.fragInfo(e,!1,t)} > buffer:${s?Al.toString(q.getBuffered(s)):"(detached)"})`),ce(e)){var i;if(e.type!==B.SUBTITLE){const n=e.elementaryStreams;if(!Object.keys(n).some(o=>!!n[o])){this.state=C.IDLE;return}}const r=(i=this.levels)==null?void 0:i[e.level];r!=null&&r.fragmentError&&(this.log(`Resetting level fragment error count of ${r.fragmentError} on frag buffered`),r.fragmentError=0)}this.state=C.IDLE}_handleFragmentLoadComplete(e){const{transmuxer:t}=this;if(!t)return;const{frag:s,part:i,partsLoaded:r}=e,n=!r||r.length===0||r.some(c=>!c),o=new Si(s.level,s.sn,s.stats.chunkCount+1,0,i?i.index:-1,!n);t.flush(o)}_handleFragmentLoadProgress(e){}_doFragLoad(e,t,s=null,i){var r;this.fragCurrent=e;const n=t.details;if(!this.levels||!n)throw new Error(`frag load aborted, missing level${n?"":" detail"}s`);let o=null;if(e.encrypted&&!((r=e.decryptdata)!=null&&r.key)){if(this.log(`Loading key for ${e.sn} of [${n.startSN}-${n.endSN}], ${this.playlistLabel()} ${e.level}`),this.state=C.KEY_LOADING,this.fragCurrent=e,o=this.keyLoader.load(e).then(d=>{if(!this.fragContextChanged(d.frag))return this.hls.trigger(m.KEY_LOADED,d),this.state===C.KEY_LOADING&&(this.state=C.IDLE),d}),this.hls.trigger(m.KEY_LOADING,{frag:e}),this.fragCurrent===null)return this.log("context changed in KEY_LOADING"),Promise.resolve(null)}else e.encrypted||(o=this.keyLoader.loadClear(e,n.encryptedFragments,this.startFragRequested),o&&this.log("[eme] blocking frag load until media-keys acquired"));const c=this.fragPrevious;if(ce(e)&&(!c||e.sn!==c.sn)){const d=this.shouldLoadParts(t.details,e.end);d!==this.loadingParts&&(this.log(`LL-Part loading ${d?"ON":"OFF"} loading sn ${c==null?void 0:c.sn}->${e.sn}`),this.loadingParts=d)}if(s=Math.max(e.start,s||0),this.loadingParts&&ce(e)){const d=n.partList;if(d&&i){s>n.fragmentEnd&&n.fragmentHint&&(e=n.fragmentHint);const f=this.getNextPart(d,e,s);if(f>-1){const g=d[f];e=this.fragCurrent=g.fragment,this.log(`Loading ${e.type} sn: ${e.sn} part: ${g.index} (${f}/${d.length-1}) of ${this.fragInfo(e,!1,g)}) cc: ${e.cc} [${n.startSN}-${n.endSN}], target: ${parseFloat(s.toFixed(3))}`),this.nextLoadPosition=g.start+g.duration,this.state=C.FRAG_LOADING;let y;return o?y=o.then(p=>!p||this.fragContextChanged(p.frag)?null:this.doFragPartsLoad(e,g,t,i)).catch(p=>this.handleFragLoadError(p)):y=this.doFragPartsLoad(e,g,t,i).catch(p=>this.handleFragLoadError(p)),this.hls.trigger(m.FRAG_LOADING,{frag:e,part:g,targetBufferTime:s}),this.fragCurrent===null?Promise.reject(new Error("frag load aborted, context changed in FRAG_LOADING parts")):y}else if(!e.url||this.loadedEndOfParts(d,s))return Promise.resolve(null)}}if(ce(e)&&this.loadingParts){var l;this.log(`LL-Part loading OFF after next part miss @${s.toFixed(2)} Check buffer at sn: ${e.sn} loaded parts: ${(l=n.partList)==null?void 0:l.filter(d=>d.loaded).map(d=>`[${d.start}-${d.end}]`)}`),this.loadingParts=!1}else if(!e.url)return Promise.resolve(null);this.log(`Loading ${e.type} sn: ${e.sn} of ${this.fragInfo(e,!1)}) cc: ${e.cc} ${"["+n.startSN+"-"+n.endSN+"]"}, target: ${parseFloat(s.toFixed(3))}`),M(e.sn)&&!this.bitrateTest&&(this.nextLoadPosition=e.start+e.duration),this.state=C.FRAG_LOADING;const h=this.config.progressive&&e.type!==B.SUBTITLE;let u;return h&&o?u=o.then(d=>!d||this.fragContextChanged(d.frag)?null:this.fragmentLoader.load(e,i)).catch(d=>this.handleFragLoadError(d)):u=Promise.all([this.fragmentLoader.load(e,h?i:void 0),o]).then(([d])=>(!h&&i&&i(d),d)).catch(d=>this.handleFragLoadError(d)),this.hls.trigger(m.FRAG_LOADING,{frag:e,targetBufferTime:s}),this.fragCurrent===null?Promise.reject(new Error("frag load aborted, context changed in FRAG_LOADING")):u}doFragPartsLoad(e,t,s,i){return new Promise((r,n)=>{var o;const c=[],l=(o=s.details)==null?void 0:o.partList,h=u=>{this.fragmentLoader.loadPart(e,u,i).then(d=>{c[u.index]=d;const f=d.part;this.hls.trigger(m.FRAG_LOADED,d);const g=Lr(s.details,e.sn,u.index+1)||Un(l,e.sn,u.index+1);if(g)h(g);else return r({frag:e,part:f,partsLoaded:c})}).catch(n)};h(t)})}handleFragLoadError(e){if("data"in e){const t=e.data;t.frag&&t.details===R.INTERNAL_ABORTED?this.handleFragLoadAborted(t.frag,t.part):t.frag&&t.type===V.KEY_SYSTEM_ERROR?(t.frag.abortRequests(),this.resetStartWhenNotLoaded(),this.resetFragmentLoading(t.frag)):this.hls.trigger(m.ERROR,t)}else this.hls.trigger(m.ERROR,{type:V.OTHER_ERROR,details:R.INTERNAL_EXCEPTION,err:e,error:e,fatal:!0});return null}_handleTransmuxerFlush(e){const t=this.getCurrentContext(e);if(!t||this.state!==C.PARSING){!this.fragCurrent&&this.state!==C.STOPPED&&this.state!==C.ERROR&&(this.state=C.IDLE);return}const{frag:s,part:i,level:r}=t,n=self.performance.now();s.stats.parsing.end=n,i&&(i.stats.parsing.end=n);const o=this.getLevelDetails(),l=o&&s.sn>o.endSN||this.shouldLoadParts(o,s.end);l!==this.loadingParts&&(this.log(`LL-Part loading ${l?"ON":"OFF"} after parsing segment ending @${s.end.toFixed(2)}`),this.loadingParts=l),this.updateLevelTiming(s,i,r,e.partial)}shouldLoadParts(e,t){if(this.config.lowLatencyMode){if(!e)return this.loadingParts;if(e.partList){var s;const r=e.partList[0];if(r.fragment.type===B.SUBTITLE)return!1;const n=r.end+(((s=e.fragmentHint)==null?void 0:s.duration)||0);if(t>=n){var i;if((this.hls.hasEnoughToStart?((i=this.media)==null?void 0:i.currentTime)||this.lastCurrentTime:this.getLoadPosition())>r.start-r.fragment.duration)return!0}}}return!1}getCurrentContext(e){const{levels:t,fragCurrent:s}=this,{level:i,sn:r,part:n}=e;if(!(t!=null&&t[i]))return this.warn(`Levels object was unset while buffering fragment ${r} of ${this.playlistLabel()} ${i}. The current chunk will not be buffered.`),null;const o=t[i],c=o.details,l=n>-1?Lr(c,r,n):null,h=l?l.fragment:Bn(c,r,s);return h?(s&&s!==h&&(h.stats=s.stats),{frag:h,part:l,level:o}):null}bufferFragmentData(e,t,s,i,r){if(this.state!==C.PARSING)return;const{data1:n,data2:o}=e;let c=n;if(o&&(c=De(n,o)),!c.length)return;const l=this.initPTS[t.cc],h=l?-l.baseTime/l.timescale:void 0,u={type:e.type,frag:t,part:s,chunkMeta:i,offset:h,parent:t.type,data:c};if(this.hls.trigger(m.BUFFER_APPENDING,u),e.dropped&&e.independent&&!s){if(r)return;this.flushBufferGap(t)}}flushBufferGap(e){const t=this.media;if(!t)return;if(!q.isBuffered(t,t.currentTime)){this.flushMainBuffer(0,e.start);return}const s=t.currentTime,i=q.bufferInfo(t,s,0),r=e.duration,n=Math.min(this.config.maxFragLookUpTolerance*2,r*.25),o=Math.max(Math.min(e.start-n,i.end-n),s+n);e.start-o>n&&this.flushMainBuffer(o,e.start)}getFwdBufferInfo(e,t){var s;const i=this.getLoadPosition();if(!M(i))return null;const n=this.lastCurrentTime>i||(s=this.media)!=null&&s.paused?0:this.config.maxBufferHole;return this.getFwdBufferInfoAtPos(e,i,t,n)}getFwdBufferInfoAtPos(e,t,s,i){const r=q.bufferInfo(e,t,i);if(r.len===0&&r.nextStart!==void 0){const n=this.fragmentTracker.getBufferedFrag(t,s);if(n&&(r.nextStart<=n.end||n.gap)){const o=Math.max(Math.min(r.nextStart,n.end)-t,i);return q.bufferInfo(e,t,o)}}return r}getMaxBufferLength(e){const{config:t}=this;let s;return e?s=Math.max(8*t.maxBufferSize/e,t.maxBufferLength):s=t.maxBufferLength,Math.min(s,t.maxMaxBufferLength)}exceedsMaxBuffer(e,t,s){const i=e.nextStart;if(i&&s.start>i){const r=e.buffered;if(r){let n=e.len;const o=e.bufferedIndex;for(let c=r.length-1;c>o;c--)r[c].start=t}}return!1}reduceMaxBufferLength(e,t){const s=this.config,i=Math.max(Math.min(e-t,s.maxBufferLength),t),r=Math.max(e-t*3,s.maxMaxBufferLength/2,i);return r>=i?(s.maxMaxBufferLength=r,this.warn(`Reduce max buffer length to ${r}s`),!0):!1}getAppendedFrag(e,t=B.MAIN){const s=this.fragmentTracker?this.fragmentTracker.getAppendedFrag(e,t):null;return s&&"fragment"in s?s.fragment:s}getNextFragment(e,t){const s=t.fragments,i=s.length;if(!i)return null;const{config:r}=this,n=t.fragmentStart,o=r.lowLatencyMode&&!!t.partList;let c=null;if(t.live){const u=r.initialLiveManifestSize;if(i=n?(p=f,E=f===d?"config":"next load start"):g!==null?(p=g,E="live edge"):(p=e,E="buffer pos"),p=r){const c=n.sn;return this.loopSn!==c&&(this.log(`buffer full after gaps in "${i}" playlist starting at sn: ${c}`),this.loopSn=c),null}}return this.loopSn=void 0,n}get primaryPrefetch(){if(_r(this.config)){var e;if((e=this.hls.interstitialsManager)==null||(e=e.playingItem)==null?void 0:e.event)return!0}return!1}filterReplacedPrimary(e,t){if(!e)return e;if(_r(this.config)&&e.type!==B.SUBTITLE){const s=this.hls.interstitialsManager,i=s==null?void 0:s.bufferingItem;if(i){const n=i.event;if(n){if(n.appendInPlace||Math.abs(e.start-i.start)>1||i.start===0)return null}else if(e.end<=i.start&&(t==null?void 0:t.live)===!1||e.start>i.end&&i.nextEvent&&(i.nextEvent.appendInPlace||e.start-i.end>1))return null}const r=s==null?void 0:s.playerQueue;if(r)for(let n=r.length;n--;){const o=r[n].interstitial;if(o.appendInPlace&&e.start>=o.startTime&&e.end<=o.resumeTime)return null}}return e}mapToInitFragWhenRequired(e){return e!=null&&e.initSegment&&!e.initSegment.data&&!this.bitrateTest?e.initSegment:e}getNextPart(e,t,s){let i=-1,r=!1,n=!0;for(let o=0,c=e.length;o-1&&ss.start)return!0}return!1}getInitialLiveFragment(e){const t=e.fragments,s=this.fragPrevious;let i=null;if(s){if(e.hasProgramDateTime&&(i=Uo(t,s.endProgramDateTime,this.config.maxFragLookUpTolerance),i&&this.log(`Live playlist, switching playlist, load frag with same PDT: ${s.programDateTime}`)),!i){const r=s.sn+1;if(r>=e.startSN&&r<=e.endSN){const n=t[r-e.startSN];s.cc===n.cc&&(i=n,this.log(`Live playlist, switching playlist, load frag with next SN: ${i.sn}`))}i||(i=In(e,s.cc,s.end),i&&this.log(`Live playlist, switching playlist, load frag with same CC: ${i.sn}`))}}else{const r=this.hls.liveSyncPosition;r!==null&&(i=this.getFragmentAtPosition(r,this.bitrateTest?e.fragmentEnd:e.edge,e))}return i}getFragmentAtPosition(e,t,s){const{config:i}=this;let{fragPrevious:r}=this,{fragments:n,endSN:o}=s;const{fragmentHint:c}=s,{maxFragLookUpTolerance:l}=i,h=s.partList,u=!!(this.loadingParts&&h!=null&&h.length&&c);u&&!this.bitrateTest&&h[h.length-1].fragment.sn===c.sn&&(n=n.concat(c),o=c.sn);let d;if(et-l||(f=this.media)!=null&&f.paused||!this.startFragRequested?0:l;d=lt(r,n,e,y)}else d=n[n.length-1];if(d){const g=d.sn-s.startSN,y=this.fragmentTracker.getState(d);if((y===ue.OK||y===ue.PARTIAL&&d.gap)&&(r=d),r&&d.sn===r.sn&&(!u||h[0].fragment.sn>d.sn||!s.live)&&d.level===r.level){const E=n[g+1];d.sn${e.startSN} fragments: ${i}`),c}return r}waitForCdnTuneIn(e){return e.live&&e.canBlockReload&&e.partTarget&&e.tuneInGoal>Math.max(e.partHoldBack,e.partTarget*3)}setStartPosition(e,t){let s=this.startPosition;s=0&&(s=this.nextLoadPosition),s}handleFragLoadAborted(e,t){this.transmuxer&&e.type===this.playlistType&&ce(e)&&e.stats.aborted&&(this.log(`Fragment ${e.sn}${t?" part "+t.index:""} of ${this.playlistLabel()} ${e.level} was aborted`),this.resetFragmentLoading(e))}resetFragmentLoading(e){(!this.fragCurrent||!this.fragContextChanged(e)&&this.state!==C.FRAG_LOADING_WAITING_RETRY)&&(this.state=C.IDLE)}onFragmentOrKeyLoadError(e,t){var s;if(t.chunkMeta&&!t.frag){const E=this.getCurrentContext(t.chunkMeta);E&&(t.frag=E.frag)}const i=t.frag;if(!i||i.type!==e||!this.levels)return;if(this.fragContextChanged(i)){var r;this.warn(`Frag load error must match current frag to retry ${i.url} > ${(r=this.fragCurrent)==null?void 0:r.url}`);return}const n=t.details===R.FRAG_GAP;n&&this.fragmentTracker.fragBuffered(i,!0);const o=t.errorAction;if(!o){this.state=C.ERROR;return}const{action:c,flags:l,retryCount:h=0,retryConfig:u}=o,d=!!u,f=d&&c===ge.RetryRequest,g=d&&!o.resolved&&l===Ae.MoveAllAlternatesMatchingHost,y=(s=this.hls.latestLevelDetails)==null?void 0:s.live;if(!f&&g&&ce(i)&&!i.endList&&y&&!Rn(t))this.resetFragmentErrors(e),this.treatAsGap(i),o.resolved=!0;else if((f||g)&&h=t||s&&!Zs(0))&&(s&&this.log("Connection restored (online)"),this.resetStartWhenNotLoaded(),this.state=C.IDLE)}reduceLengthAndFlushBuffer(e){if(this.state===C.PARSING||this.state===C.PARSED){const t=e.frag,s=e.parent,i=this.getFwdBufferInfo(this.mediaBuffer,s),r=i&&i.len>.5;r&&this.reduceMaxBufferLength(i.len,(t==null?void 0:t.duration)||10);const n=!r;return n&&this.warn(`Buffer full error while media.currentTime (${this.getLoadPosition()}) is not buffered, flush ${s} buffer`),t&&(this.fragmentTracker.removeFragment(t),this.nextLoadPosition=t.start),this.resetLoadingState(),n}return!1}resetFragmentErrors(e){e===B.AUDIO&&(this.fragCurrent=null),this.hls.hasEnoughToStart||(this.startFragRequested=!1),this.state!==C.STOPPED&&(this.state=C.IDLE)}afterBufferFlushed(e,t,s){if(!e)return;const i=q.getBuffered(e);this.fragmentTracker.detectEvictedFragments(t,i,s),this.state===C.ENDED&&this.resetLoadingState()}resetLoadingState(){this.log("Reset loading state"),this.fragCurrent=null,this.fragPrevious=null,this.state!==C.STOPPED&&(this.state=C.IDLE)}resetStartWhenNotLoaded(){if(!this.hls.hasEnoughToStart){this.startFragRequested=!1;const e=this.levelLastLoaded,t=e?e.details:null;t!=null&&t.live?(this.log("resetting startPosition for live start"),this.startPosition=-1,this.setStartPosition(t,t.fragmentStart),this.resetLoadingState()):this.nextLoadPosition=this.startPosition}}resetWhenMissingContext(e){this.log(`Loading context changed while buffering sn ${e.sn} of ${this.playlistLabel()} ${e.level===-1?"":e.level}. This chunk will not be buffered.`),this.removeUnbufferedFrags(),this.resetStartWhenNotLoaded(),this.resetLoadingState()}removeUnbufferedFrags(e=0){this.fragmentTracker.removeFragmentsInRange(e,1/0,this.playlistType,!1,!0)}updateLevelTiming(e,t,s,i){const r=s.details;if(!r){this.warn("level.details undefined");return}if(!Object.keys(e.elementaryStreams).reduce((c,l)=>{const h=e.elementaryStreams[l];if(h){const u=h.endPTS-h.startPTS;if(u<=0)return this.warn(`Could not parse fragment ${e.sn} ${l} duration reliably (${u})`),c||!1;const d=i?0:Fn(r,e,h.startPTS,h.endPTS,h.startDTS,h.endDTS,this);return this.hls.trigger(m.LEVEL_PTS_UPDATED,{details:r,level:s,drift:d,type:l,frag:e,start:h.startPTS,end:h.endPTS}),!0}return c},!1)){var o;const c=((o=this.transmuxer)==null?void 0:o.error)===null;if((s.fragmentError===0||c&&(s.fragmentError<2||e.endList))&&this.treatAsGap(e,s),c){const l=new Error(`Found no media in fragment ${e.sn} of ${this.playlistLabel()} ${e.level} resetting transmuxer to fallback to playlist timing`);if(this.warn(l.message),this.hls.trigger(m.ERROR,{type:V.MEDIA_ERROR,details:R.FRAG_PARSING_ERROR,fatal:!1,error:l,frag:e,reason:`Found no media in msn ${e.sn} of ${this.playlistLabel()} "${s.url}"`}),!this.hls)return;this.resetTransmuxer()}}this.state=C.PARSED,this.log(`Parsed ${e.type} sn: ${e.sn}${t?" part: "+t.index:""} of ${this.fragInfo(e,!1,t)})`),this.hls.trigger(m.FRAG_PARSED,{frag:e,part:t})}playlistLabel(){return this.playlistType===B.MAIN?"level":"track"}fragInfo(e,t=!0,s){var i,r;return`${this.playlistLabel()} ${e.level} (${s?"part":"frag"}:[${((i=t&&!s?e.startPTS:(s||e).start)!=null?i:NaN).toFixed(3)}-${((r=t&&!s?e.endPTS:(s||e).end)!=null?r:NaN).toFixed(3)}]${s&&e.type==="main"?"INDEPENDENT="+(s.independent?"YES":"NO"):""}`}treatAsGap(e,t){t&&t.fragmentError++,e.gap=!0,this.fragmentTracker.removeFragment(e),this.fragmentTracker.fragBuffered(e,!0)}resetTransmuxer(){var e;(e=this.transmuxer)==null||e.reset()}recoverWorkerError(e){e.event==="demuxerWorker"&&(this.fragmentTracker.removeAllFragments(),this.transmuxer&&(this.transmuxer.destroy(),this.transmuxer=null),this.resetStartWhenNotLoaded(),this.resetLoadingState())}set state(e){const t=this._state;t!==e&&(this._state=e,this.log(`${t}->${e}`))}get state(){return this._state}}function _r(a){return!!a.interstitialsController&&a.enableInterstitialPlayback!==!1}class Vn{constructor(){this.chunks=[],this.dataLength=0}push(e){this.chunks.push(e),this.dataLength+=e.length}flush(){const{chunks:e,dataLength:t}=this;let s;if(e.length)e.length===1?s=e[0]:s=Il(e,t);else return new Uint8Array(0);return this.reset(),s}reset(){this.chunks.length=0,this.dataLength=0}}function Il(a,e){const t=new Uint8Array(e);let s=0;for(let i=0;i0)return a.subarray(t,t+s)}function Pl(a,e,t,s){const i=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350],r=e[t+2],n=r>>2&15;if(n>12){const f=new Error(`invalid ADTS sampling index:${n}`);a.emit(m.ERROR,m.ERROR,{type:V.MEDIA_ERROR,details:R.FRAG_PARSING_ERROR,fatal:!0,error:f,reason:f.message});return}const o=(r>>6&3)+1,c=e[t+3]>>6&3|(r&1)<<2,l="mp4a.40."+o,h=i[n];let u=n;(o===5||o===29)&&(u-=3);const d=[o<<3|(u&14)>>1,(u&1)<<7|c<<3];return se.log(`manifest codec:${s}, parsed codec:${l}, channels:${c}, rate:${h} (ADTS object type:${o} sampling index:${n})`),{config:d,samplerate:h,channelCount:c,codec:l,parsedCodec:l,manifestCodec:s}}function Yn(a,e){return a[e]===255&&(a[e+1]&246)===240}function Wn(a,e){return a[e+1]&1?7:9}function Ri(a,e){return(a[e+3]&3)<<11|a[e+4]<<3|(a[e+5]&224)>>>5}function kl(a,e){return e+5=a.length)return!1;const s=Ri(a,e);if(s<=t)return!1;const i=e+s;return i===a.length||ys(a,i)}return!1}function qn(a,e,t,s,i){if(!a.samplerate){const r=Pl(e,t,s,i);if(!r)return;ie(a,r)}}function jn(a){return 1024*9e4/a}function Fl(a,e){const t=Wn(a,e);if(e+t<=a.length){const s=Ri(a,e)-t;if(s>0)return{headerLength:t,frameLength:s}}}function Xn(a,e,t,s,i){const r=jn(a.samplerate),n=s+i*r,o=Fl(e,t);let c;if(o){const{frameLength:u,headerLength:d}=o,f=d+u,g=Math.max(0,t+f-e.length);g?(c=new Uint8Array(f-d),c.set(e.subarray(t+d,e.length),0)):c=e.subarray(t+d,t+f);const y={unit:c,pts:n};return g||a.samples.push(y),{sample:y,length:f,missing:g}}const l=e.length-t;return c=new Uint8Array(l),c.set(e.subarray(t,e.length),0),{sample:{unit:c,pts:n},length:l,missing:-1}}function Ml(a,e){return Li(a,e)&&Ss(a,e+6)+10<=a.length-e}function Nl(a){return a instanceof ArrayBuffer?a:a.byteOffset==0&&a.byteLength==a.buffer.byteLength?a.buffer:new Uint8Array(a).buffer}function ks(a,e=0,t=1/0){return Bl(a,e,t,Uint8Array)}function Bl(a,e,t,s){const i=Ul(a);let r=1;"BYTES_PER_ELEMENT"in s&&(r=s.BYTES_PER_ELEMENT);const n=$l(a)?a.byteOffset:0,o=(n+a.byteLength)/r,c=(n+e)/r,l=Math.floor(Math.max(0,Math.min(c,o))),h=Math.floor(Math.min(l+Math.max(t,0),o));return new s(i,l,h-l)}function Ul(a){return a instanceof ArrayBuffer?a:a.buffer}function $l(a){return a&&a.buffer instanceof ArrayBuffer&&a.byteLength!==void 0&&a.byteOffset!==void 0}function Gl(a){const e={key:a.type,description:"",data:"",mimeType:null,pictureType:null},t=3;if(a.size<2)return;if(a.data[0]!==t){console.log("Ignore frame with unrecognized character encoding");return}const s=a.data.subarray(1).indexOf(0);if(s===-1)return;const i=Re(ks(a.data,1,s)),r=a.data[2+s],n=a.data.subarray(3+s).indexOf(0);if(n===-1)return;const o=Re(ks(a.data,3+s,n));let c;return i==="-->"?c=Re(ks(a.data,4+s+n)):c=Nl(a.data.subarray(4+s+n)),e.mimeType=i,e.pictureType=r,e.description=o,e.data=c,e}function Kl(a){if(a.size<2)return;const e=Re(a.data,!0),t=new Uint8Array(a.data.subarray(e.length+1));return{key:a.type,info:e,data:t.buffer}}function Vl(a){if(a.size<2)return;if(a.type==="TXXX"){let t=1;const s=Re(a.data.subarray(t),!0);t+=s.length+1;const i=Re(a.data.subarray(t));return{key:a.type,info:s,data:i}}const e=Re(a.data.subarray(1));return{key:a.type,info:"",data:e}}function Hl(a){if(a.type==="WXXX"){if(a.size<2)return;let t=1;const s=Re(a.data.subarray(t),!0);t+=s.length+1;const i=Re(a.data.subarray(t));return{key:a.type,info:s,data:i}}const e=Re(a.data);return{key:a.type,info:"",data:e}}function Yl(a){return a.type==="PRIV"?Kl(a):a.type[0]==="W"?Hl(a):a.type==="APIC"?Gl(a):Vl(a)}function Wl(a){const e=String.fromCharCode(a[0],a[1],a[2],a[3]),t=Ss(a,4),s=10;return{type:e,size:t,data:a.subarray(s,s+t)}}const Ht=10,ql=10;function zn(a){let e=0;const t=[];for(;Li(a,e);){const s=Ss(a,e+6);a[e+5]>>6&1&&(e+=Ht),e+=Ht;const i=e+s;for(;e+ql0&&o.samples.push({pts:this.lastPTS,dts:this.lastPTS,data:s,type:Le.audioId3,duration:Number.POSITIVE_INFINITY});i{if(M(a))return a*90;const s=t?t.baseTime*9e4/t.timescale:0;return e*9e4+s};let Yt=null;const zl=[32,64,96,128,160,192,224,256,288,320,352,384,416,448,32,48,56,64,80,96,112,128,160,192,224,256,320,384,32,40,48,56,64,80,96,112,128,160,192,224,256,320,32,48,56,64,80,96,112,128,144,160,176,192,224,256,8,16,24,32,40,48,56,64,80,96,112,128,144,160],Ql=[44100,48e3,32e3,22050,24e3,16e3,11025,12e3,8e3],Zl=[[0,72,144,12],[0,0,0,0],[0,72,144,12],[0,144,144,12]],Jl=[0,1,1,4];function Zn(a,e,t,s,i){if(t+24>e.length)return;const r=Jn(e,t);if(r&&t+r.frameLength<=e.length){const n=r.samplesPerFrame*9e4/r.sampleRate,o=s+i*n,c={unit:e.subarray(t,t+r.frameLength),pts:o,dts:o};return a.config=[],a.channelCount=r.channelCount,a.samplerate=r.sampleRate,a.samples.push(c),{sample:c,length:r.frameLength,missing:0}}}function Jn(a,e){const t=a[e+1]>>3&3,s=a[e+1]>>1&3,i=a[e+2]>>4&15,r=a[e+2]>>2&3;if(t!==1&&i!==0&&i!==15&&r!==3){const n=a[e+2]>>1&1,o=a[e+3]>>6,c=t===3?3-s:s===3?3:4,l=zl[c*14+i-1]*1e3,u=Ql[(t===3?0:t===2?1:2)*3+r],d=o===3?1:2,f=Zl[t][s],g=Jl[s],y=f*8*g,p=Math.floor(f*l/u+n)*g;if(Yt===null){const S=(navigator.userAgent||"").match(/Chrome\/(\d+)/i);Yt=S?parseInt(S[1]):0}return!!Yt&&Yt<=87&&s===2&&l>=224e3&&o===0&&(a[e+3]=a[e+3]|128),{sampleRate:u,channelCount:d,frameLength:p,samplesPerFrame:y}}}function Di(a,e){return a[e]===255&&(a[e+1]&224)===224&&(a[e+1]&6)!==0}function ea(a,e){return e+1{let t=0,s=5;e+=s;const i=new Uint32Array(1),r=new Uint32Array(1),n=new Uint8Array(1);for(;s>0;){n[0]=a[e];const o=Math.min(s,8),c=8-o;r[0]=4278190080>>>24+c<>c,t=t?t<e.length||e[t]!==11||e[t+1]!==119)return-1;const r=e[t+4]>>6;if(r>=3)return-1;const o=[48e3,44100,32e3][r],c=e[t+4]&63,h=[64,69,96,64,70,96,80,87,120,80,88,120,96,104,144,96,105,144,112,121,168,112,122,168,128,139,192,128,140,192,160,174,240,160,175,240,192,208,288,192,209,288,224,243,336,224,244,336,256,278,384,256,279,384,320,348,480,320,349,480,384,417,576,384,418,576,448,487,672,448,488,672,512,557,768,512,558,768,640,696,960,640,697,960,768,835,1152,768,836,1152,896,975,1344,896,976,1344,1024,1114,1536,1024,1115,1536,1152,1253,1728,1152,1254,1728,1280,1393,1920,1280,1394,1920][c*3+r]*2;if(t+h>e.length)return-1;const u=e[t+6]>>5;let d=0;u===2?d+=2:(u&1&&u!==1&&(d+=2),u&4&&(d+=2));const f=(e[t+6]<<8|e[t+7])>>12-d&1,y=[2,1,2,3,3,4,4,5][u]+f,p=e[t+5]>>3,E=e[t+5]&7,T=new Uint8Array([r<<6|p<<1|E>>2,(E&3)<<6|u<<3|f<<2|c>>4,c<<4&224]),S=1536/o*9e4,v=s+i*S,x=e.subarray(t,t+h);return a.config=T,a.channelCount=y,a.samplerate=o,a.samples.push({unit:x,pts:v}),h}class ic extends _i{resetInitSegment(e,t,s,i){super.resetInitSegment(e,t,s,i),this._audioTrack={container:"audio/mpeg",type:"audio",id:2,pid:-1,sequenceNumber:0,segmentCodec:"mp3",samples:[],manifestCodec:t,duration:i,inputTimeScale:9e4,dropped:0}}static probe(e){if(!e)return!1;const t=Mt(e,0);let s=(t==null?void 0:t.length)||0;if(t&&e[s]===11&&e[s+1]===119&&bi(t)!==void 0&&sa(e,s)<=16)return!1;for(let i=e.length;s{const n=ho(r);if(rc.test(n.schemeIdUri)){const o=Cr(n,t);let c=n.eventDuration===4294967295?Number.POSITIVE_INFINITY:n.eventDuration/n.timeScale;c<=.001&&(c=Number.POSITIVE_INFINITY);const l=n.payload;s.samples.push({data:l,len:l.byteLength,dts:o,pts:o,type:Le.emsg,duration:c})}else if(this.config.enableEmsgKLVMetadata&&n.schemeIdUri.startsWith("urn:misb:KLV:bin:1910.1")){const o=Cr(n,t);s.samples.push({data:n.payload,len:n.payload.byteLength,dts:o,pts:o,type:Le.misbklv,duration:Number.POSITIVE_INFINITY})}})}return s}demuxSampleAes(e,t,s){return Promise.reject(new Error("The MP4 demuxer does not support SAMPLE-AES decryption"))}destroy(){this.config=null,this.remainderData=null,this.videoTrack=this.audioTrack=this.id3Track=this.txtTrack=void 0}}function Cr(a,e){return M(a.presentationTime)?a.presentationTime/a.timeScale:e+a.presentationTimeDelta/a.timeScale}class ac{constructor(e,t,s){this.keyData=void 0,this.decrypter=void 0,this.keyData=s,this.decrypter=new Ti(t,{removePKCS7Padding:!1})}decryptBuffer(e){return this.decrypter.decrypt(e,this.keyData.key.buffer,this.keyData.iv.buffer,et.cbc)}decryptAacSample(e,t,s){const i=e[t].unit;if(i.length<=16)return;const r=i.subarray(16,i.length-i.length%16),n=r.buffer.slice(r.byteOffset,r.byteOffset+r.length);this.decryptBuffer(n).then(o=>{const c=new Uint8Array(o);i.set(c,16),this.decrypter.isSync()||this.decryptAacSamples(e,t+1,s)}).catch(s)}decryptAacSamples(e,t,s){for(;;t++){if(t>=e.length){s();return}if(!(e[t].unit.length<32)&&(this.decryptAacSample(e,t,s),!this.decrypter.isSync()))return}}getAvcEncryptedData(e){const t=Math.floor((e.length-48)/160)*16+16,s=new Int8Array(t);let i=0;for(let r=32;r{r.data=this.getAvcDecryptedUnit(n,c),this.decrypter.isSync()||this.decryptAvcSamples(e,t,s+1,i)}).catch(i)}decryptAvcSamples(e,t,s,i){if(e instanceof Uint8Array)throw new Error("Cannot decrypt samples of type Uint8Array");for(;;t++,s=0){if(t>=e.length){i();return}const r=e[t].units;for(;!(s>=r.length);s++){const n=r[s];if(!(n.data.length<=48||n.type!==1&&n.type!==5)&&(this.decryptAvcSample(e,t,s,i,n),!this.decrypter.isSync()))return}}}}class ra{constructor(){this.VideoSample=null}createVideoSample(e,t,s){return{key:e,frame:!1,pts:t,dts:s,units:[],length:0}}getLastNalUnit(e){var t;let s=this.VideoSample,i;if((!s||s.units.length===0)&&(s=e[e.length-1]),(t=s)!=null&&t.units){const r=s.units;i=r[r.length-1]}return i}pushAccessUnit(e,t){if(e.units.length&&e.frame){if(e.pts===void 0){const s=t.samples,i=s.length;if(i){const r=s[i-1];e.pts=r.pts,e.dts=r.dts}else{t.dropped++;return}}t.samples.push(e)}}parseNALu(e,t,s){const i=t.byteLength;let r=e.naluState||0;const n=r,o=[];let c=0,l,h,u,d=-1,f=0;for(r===-1&&(d=0,f=this.getNALuType(t,0),r=0,c=1);c=0){const g={data:t.subarray(d,h),type:f};o.push(g)}else{const g=this.getLastNalUnit(e.samples);g&&(n&&c<=4-n&&g.state&&(g.data=g.data.subarray(0,g.data.byteLength-n)),h>0&&(g.data=De(g.data,t.subarray(0,h)),g.state=0))}c=0&&r>=0){const g={data:t.subarray(d,i),type:f,state:r};o.push(g)}if(o.length===0){const g=this.getLastNalUnit(e.samples);g&&(g.data=De(g.data,t))}return e.naluState=r,o}}class Ct{constructor(e){this.data=void 0,this.bytesAvailable=void 0,this.word=void 0,this.bitsAvailable=void 0,this.data=e,this.bytesAvailable=e.byteLength,this.word=0,this.bitsAvailable=0}loadWord(){const e=this.data,t=this.bytesAvailable,s=e.byteLength-t,i=new Uint8Array(4),r=Math.min(4,t);if(r===0)throw new Error("no bytes available");i.set(e.subarray(s,s+r)),this.word=new DataView(i.buffer).getUint32(0),this.bitsAvailable=r*8,this.bytesAvailable-=r}skipBits(e){let t;e=Math.min(e,this.bytesAvailable*8+this.bitsAvailable),this.bitsAvailable>e?(this.word<<=e,this.bitsAvailable-=e):(e-=this.bitsAvailable,t=e>>3,e-=t<<3,this.bytesAvailable-=t,this.loadWord(),this.word<<=e,this.bitsAvailable-=e)}readBits(e){let t=Math.min(this.bitsAvailable,e);const s=this.word>>>32-t;if(e>32&&se.error("Cannot read more than 32 bits at a time"),this.bitsAvailable-=t,this.bitsAvailable>0)this.word<<=t;else if(this.bytesAvailable>0)this.loadWord();else throw new Error("no bits available");return t=e-t,t>0&&this.bitsAvailable?s<>>e)return this.word<<=e,this.bitsAvailable-=e,e;return this.loadWord(),e+this.skipLZ()}skipUEG(){this.skipBits(1+this.skipLZ())}skipEG(){this.skipBits(1+this.skipLZ())}readUEG(){const e=this.skipLZ();return this.readBits(e+1)-1}readEG(){const e=this.readUEG();return 1&e?1+e>>>1:-1*(e>>>1)}readBoolean(){return this.readBits(1)===1}readUByte(){return this.readBits(8)}readUShort(){return this.readBits(16)}readUInt(){return this.readBits(32)}}class oc extends ra{parsePES(e,t,s,i){const r=this.parseNALu(e,s.data,i);let n=this.VideoSample,o,c=!1;s.data=null,n&&r.length&&!e.audFound&&(this.pushAccessUnit(n,e),n=this.VideoSample=this.createVideoSample(!1,s.pts,s.dts)),r.forEach(l=>{var h,u;switch(l.type){case 1:{let y=!1;o=!0;const p=l.data;if(c&&p.length>4){const E=this.readSliceType(p);(E===2||E===4||E===7||E===9)&&(y=!0)}if(y){var d;(d=n)!=null&&d.frame&&!n.key&&(this.pushAccessUnit(n,e),n=this.VideoSample=null)}n||(n=this.VideoSample=this.createVideoSample(!0,s.pts,s.dts)),n.frame=!0,n.key=y;break}case 5:o=!0,(h=n)!=null&&h.frame&&!n.key&&(this.pushAccessUnit(n,e),n=this.VideoSample=null),n||(n=this.VideoSample=this.createVideoSample(!0,s.pts,s.dts)),n.key=!0,n.frame=!0;break;case 6:{o=!0,mi(l.data,1,s.pts,t.samples);break}case 7:{var f,g;o=!0,c=!0;const y=l.data,p=this.readSPS(y);if(!e.sps||e.width!==p.width||e.height!==p.height||((f=e.pixelRatio)==null?void 0:f[0])!==p.pixelRatio[0]||((g=e.pixelRatio)==null?void 0:g[1])!==p.pixelRatio[1]){e.width=p.width,e.height=p.height,e.pixelRatio=p.pixelRatio,e.sps=[y];const E=y.subarray(1,4);let T="avc1.";for(let S=0;S<3;S++){let v=E[S].toString(16);v.length<2&&(v="0"+v),T+=v}e.codec=T}break}case 8:o=!0,e.pps=[l.data];break;case 9:o=!0,e.audFound=!0,(u=n)!=null&&u.frame&&(this.pushAccessUnit(n,e),n=null),n||(n=this.VideoSample=this.createVideoSample(!1,s.pts,s.dts));break;case 12:o=!0;break;default:o=!1;break}n&&o&&n.units.push(l)}),i&&n&&(this.pushAccessUnit(n,e),this.VideoSample=null)}getNALuType(e,t){return e[t]&31}readSliceType(e){const t=new Ct(e);return t.readUByte(),t.readUEG(),t.readUEG()}skipScalingList(e,t){let s=8,i=8,r;for(let n=0;n{var h,u;switch(l.type){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9:n||(n=this.VideoSample=this.createVideoSample(!1,s.pts,s.dts)),n.frame=!0,o=!0;break;case 16:case 17:case 18:case 21:if(o=!0,c){var d;(d=n)!=null&&d.frame&&!n.key&&(this.pushAccessUnit(n,e),n=this.VideoSample=null)}n||(n=this.VideoSample=this.createVideoSample(!0,s.pts,s.dts)),n.key=!0,n.frame=!0;break;case 19:case 20:o=!0,(h=n)!=null&&h.frame&&!n.key&&(this.pushAccessUnit(n,e),n=this.VideoSample=null),n||(n=this.VideoSample=this.createVideoSample(!0,s.pts,s.dts)),n.key=!0,n.frame=!0;break;case 39:o=!0,mi(l.data,2,s.pts,t.samples);break;case 32:o=!0,e.vps||(typeof e.params!="object"&&(e.params={}),e.params=ie(e.params,this.readVPS(l.data)),this.initVPS=l.data),e.vps=[l.data];break;case 33:if(o=!0,c=!0,e.vps!==void 0&&e.vps[0]!==this.initVPS&&e.sps!==void 0&&!this.matchSPS(e.sps[0],l.data)&&(this.initVPS=e.vps[0],e.sps=e.pps=void 0),!e.sps){const f=this.readSPS(l.data);e.width=f.width,e.height=f.height,e.pixelRatio=f.pixelRatio,e.codec=f.codecString,e.sps=[],typeof e.params!="object"&&(e.params={});for(const g in f.params)e.params[g]=f.params[g]}this.pushParameterSet(e.sps,l.data,e.vps),n||(n=this.VideoSample=this.createVideoSample(!0,s.pts,s.dts)),n.key=!0;break;case 34:if(o=!0,typeof e.params=="object"){if(!e.pps){e.pps=[];const f=this.readPPS(l.data);for(const g in f)e.params[g]=f[g]}this.pushParameterSet(e.pps,l.data,e.vps)}break;case 35:o=!0,e.audFound=!0,(u=n)!=null&&u.frame&&(this.pushAccessUnit(n,e),n=null),n||(n=this.VideoSample=this.createVideoSample(!1,s.pts,s.dts));break;default:o=!1;break}n&&o&&n.units.push(l)}),i&&n&&(this.pushAccessUnit(n,e),this.VideoSample=null)}pushParameterSet(e,t,s){(s&&s[0]===this.initVPS||!s&&!e.length)&&e.push(t)}getNALuType(e,t){return(e[t]&126)>>>1}ebsp2rbsp(e){const t=new Uint8Array(e.byteLength);let s=0;for(let i=0;i=2&&e[i]===3&&e[i-1]===0&&e[i-2]===0||(t[s]=e[i],s++);return new Uint8Array(t.buffer,0,s)}pushAccessUnit(e,t){super.pushAccessUnit(e,t),this.initVPS&&(this.initVPS=null)}readVPS(e){const t=new Ct(e);t.readUByte(),t.readUByte(),t.readBits(4),t.skipBits(2),t.readBits(6);const s=t.readBits(3),i=t.readBoolean();return{numTemporalLayers:s+1,temporalIdNested:i}}readSPS(e){const t=new Ct(this.ebsp2rbsp(e));t.readUByte(),t.readUByte(),t.readBits(4);const s=t.readBits(3);t.readBoolean();const i=t.readBits(2),r=t.readBoolean(),n=t.readBits(5),o=t.readUByte(),c=t.readUByte(),l=t.readUByte(),h=t.readUByte(),u=t.readUByte(),d=t.readUByte(),f=t.readUByte(),g=t.readUByte(),y=t.readUByte(),p=t.readUByte(),E=t.readUByte(),T=[],S=[];for(let J=0;J0)for(let J=s;J<8;J++)t.readBits(2);for(let J=0;J1&&t.readEG();for(let ct=0;ct0&&it<16?(O=Ni[it-1],j=Ut[it-1]):it===255&&(O=t.readBits(16),j=t.readBits(16))}if(t.readBoolean()&&t.readBoolean(),t.readBoolean()&&(t.readBits(3),t.readBoolean(),t.readBoolean()&&(t.readUByte(),t.readUByte(),t.readUByte())),t.readBoolean()&&(t.readUEG(),t.readUEG()),t.readBoolean(),t.readBoolean(),t.readBoolean(),ye=t.readBoolean(),ye&&(t.skipUEG(),t.skipUEG(),t.skipUEG(),t.skipUEG()),t.readBoolean()&&(X=t.readBits(32),Z=t.readBits(32),t.readBoolean()&&t.readUEG(),t.readBoolean())){const Ut=t.readBoolean(),Bi=t.readBoolean();let It=!1;(Ut||Bi)&&(It=t.readBoolean(),It&&(t.readUByte(),t.readBits(5),t.readBoolean(),t.readBits(5)),t.readBits(4),t.readBits(4),It&&t.readBits(4),t.readBits(5),t.readBits(5),t.readBits(5));for(let Ui=0;Ui<=s;Ui++){ee=t.readBoolean();const Ba=ee||t.readBoolean();let $i=!1;Ba?t.readEG():$i=t.readBoolean();const Gi=$i?1:t.readUEG()+1;if(Ut)for(let Lt=0;Lt>J&1)<<31-J)>>>0;let As=xs.toString(16);return n===1&&As==="2"&&(As="6"),{codecString:`hvc1.${tt}${n}.${As}.${r?"H":"L"}${E}.B0`,params:{general_tier_flag:r,general_profile_idc:n,general_profile_space:i,general_profile_compatibility_flags:[o,c,l,h],general_constraint_indicator_flags:[u,d,f,g,y,p],general_level_idc:E,bit_depth:F+8,bit_depth_luma_minus8:F,bit_depth_chroma_minus8:U,min_spatial_segmentation_idc:w,chroma_format_idc:v,frame_rate:{fixed:ee,fps:Z/X}},width:be,height:Oe,pixelRatio:[O,j]}}readPPS(e){const t=new Ct(this.ebsp2rbsp(e));t.readUByte(),t.readUByte(),t.skipUEG(),t.skipUEG(),t.skipBits(2),t.skipBits(3),t.skipBits(2),t.skipUEG(),t.skipUEG(),t.skipEG(),t.skipBits(2),t.readBoolean()&&t.skipUEG(),t.skipEG(),t.skipEG(),t.skipBits(4);const i=t.readBoolean(),r=t.readBoolean();let n=1;return r&&i?n=0:r?n=3:i&&(n=2),{parallelismType:n}}matchSPS(e,t){return String.fromCharCode.apply(null,e).substr(3)===String.fromCharCode.apply(null,t).substr(3)}}const de=188;class Qe{constructor(e,t,s,i){this.logger=void 0,this.observer=void 0,this.config=void 0,this.typeSupported=void 0,this.sampleAes=null,this.pmtParsed=!1,this.audioCodec=void 0,this.videoCodec=void 0,this._pmtId=-1,this._videoTrack=void 0,this._audioTrack=void 0,this._id3Track=void 0,this._txtTrack=void 0,this.aacOverFlow=null,this.remainderData=null,this.videoParser=void 0,this.observer=e,this.config=t,this.typeSupported=s,this.logger=i,this.videoParser=null}static probe(e,t){const s=Qe.syncOffset(e);return s>0&&t.warn(`MPEG2-TS detected but first sync word found @ offset ${s}`),s!==-1}static syncOffset(e){const t=e.length;let s=Math.min(de*5,t-de)+1,i=0;for(;i1&&(n===0&&o>2||c+de>s))return n}else{if(o)return-1;break}i++}return-1}static createTrack(e,t){return{container:e==="video"||e==="audio"?"video/mp2t":void 0,type:e,id:hn[e],pid:-1,inputTimeScale:9e4,sequenceNumber:0,samples:[],dropped:0,duration:e==="audio"?t:void 0}}resetInitSegment(e,t,s,i){this.pmtParsed=!1,this._pmtId=-1,this._videoTrack=Qe.createTrack("video"),this._videoTrack.duration=i,this._audioTrack=Qe.createTrack("audio",i),this._id3Track=Qe.createTrack("id3"),this._txtTrack=Qe.createTrack("text"),this._audioTrack.segmentCodec="aac",this.videoParser=null,this.aacOverFlow=null,this.remainderData=null,this.audioCodec=t,this.videoCodec=s}resetTimeStamp(){}resetContiguity(){const{_audioTrack:e,_videoTrack:t,_id3Track:s}=this;e&&(e.pesData=null),t&&(t.pesData=null),s&&(s.pesData=null),this.aacOverFlow=null,this.remainderData=null}demux(e,t,s=!1,i=!1){s||(this.sampleAes=null);let r;const n=this._videoTrack,o=this._audioTrack,c=this._id3Track,l=this._txtTrack;let h=n.pid,u=n.pesData,d=o.pid,f=c.pid,g=o.pesData,y=c.pesData,p=null,E=this.pmtParsed,T=this._pmtId,S=e.length;if(this.remainderData&&(e=De(this.remainderData,e),S=e.length,this.remainderData=null),S>4;let P;if(I>1){if(P=A+5+e[A+4],P===A+de)continue}else P=A+4;switch(b){case h:_&&(u&&(r=ft(u,this.logger))&&(this.readyVideoParser(n.segmentCodec),this.videoParser!==null&&this.videoParser.parsePES(n,l,r,!1)),u={data:[],size:0}),u&&(u.data.push(e.subarray(P,A+de)),u.size+=A+de-P);break;case d:if(_){if(g&&(r=ft(g,this.logger)))switch(o.segmentCodec){case"aac":this.parseAACPES(o,r);break;case"mp3":this.parseMPEGPES(o,r);break;case"ac3":this.parseAC3PES(o,r);break}g={data:[],size:0}}g&&(g.data.push(e.subarray(P,A+de)),g.size+=A+de-P);break;case f:_&&(y&&(r=ft(y,this.logger))&&this.parseID3PES(c,r),y={data:[],size:0}),y&&(y.data.push(e.subarray(P,A+de)),y.size+=A+de-P);break;case 0:_&&(P+=e[P]+1),T=this._pmtId=cc(e,P);break;case T:{_&&(P+=e[P]+1);const F=hc(e,P,this.typeSupported,s,this.observer,this.logger);h=F.videoPid,h>0&&(n.pid=h,n.segmentCodec=F.segmentVideoCodec),d=F.audioPid,d>0&&(o.pid=d,o.segmentCodec=F.segmentAudioCodec),f=F.id3Pid,f>0&&(c.pid=f),p!==null&&!E&&(this.logger.warn(`MPEG-TS PMT found at ${A} after unknown PID '${p}'. Backtracking to sync byte @${v} to parse all TS packets.`),p=null,A=v-188),E=this.pmtParsed=!0;break}case 17:case 8191:break;default:p=b;break}}else x++;x>0&&ri(this.observer,new Error(`Found ${x} TS packet/s that do not start with 0x47`),void 0,this.logger),n.pesData=u,o.pesData=g,c.pesData=y;const D={audioTrack:o,videoTrack:n,id3Track:c,textTrack:l};return i&&this.extractRemainingSamples(D),D}flush(){const{remainderData:e}=this;this.remainderData=null;let t;return e?t=this.demux(e,-1,!1,!0):t={videoTrack:this._videoTrack,audioTrack:this._audioTrack,id3Track:this._id3Track,textTrack:this._txtTrack},this.extractRemainingSamples(t),this.sampleAes?this.decrypt(t,this.sampleAes):t}extractRemainingSamples(e){const{audioTrack:t,videoTrack:s,id3Track:i,textTrack:r}=e,n=s.pesData,o=t.pesData,c=i.pesData;let l;if(n&&(l=ft(n,this.logger))?(this.readyVideoParser(s.segmentCodec),this.videoParser!==null&&(this.videoParser.parsePES(s,r,l,!0),s.pesData=null)):s.pesData=n,o&&(l=ft(o,this.logger))){switch(t.segmentCodec){case"aac":this.parseAACPES(t,l);break;case"mp3":this.parseMPEGPES(t,l);break;case"ac3":this.parseAC3PES(t,l);break}t.pesData=null}else o!=null&&o.size&&this.logger.log("last AAC PES packet truncated,might overlap between fragments"),t.pesData=o;c&&(l=ft(c,this.logger))?(this.parseID3PES(i,l),i.pesData=null):i.pesData=c}demuxSampleAes(e,t,s){const i=this.demux(e,s,!0,!this.config.progressive),r=this.sampleAes=new ac(this.observer,this.config,t);return this.decrypt(i,r)}readyVideoParser(e){this.videoParser===null&&(e==="avc"?this.videoParser=new oc:e==="hevc"&&(this.videoParser=new lc))}decrypt(e,t){return new Promise(s=>{const{audioTrack:i,videoTrack:r}=e;i.samples&&i.segmentCodec==="aac"?t.decryptAacSamples(i.samples,0,()=>{r.samples?t.decryptAvcSamples(r.samples,0,0,()=>{s(e)}):s(e)}):r.samples&&t.decryptAvcSamples(r.samples,0,0,()=>{s(e)})})}destroy(){this.observer&&this.observer.removeAllListeners(),this.config=this.logger=this.observer=null,this.aacOverFlow=this.videoParser=this.remainderData=this.sampleAes=null,this._videoTrack=this._audioTrack=this._id3Track=this._txtTrack=void 0}parseAACPES(e,t){let s=0;const i=this.aacOverFlow;let r=t.data;if(i){this.aacOverFlow=null;const u=i.missing,d=i.sample.unit.byteLength;if(u===-1)r=De(i.sample.unit,r);else{const f=d-u;i.sample.unit.set(r.subarray(0,u),f),e.samples.push(i.sample),s=i.missing}}let n,o;for(n=s,o=r.length;n0;)o+=c}}parseID3PES(e,t){if(t.pts===void 0){this.logger.warn("[tsdemuxer]: ID3 PES unknown PTS");return}const s=ie({},t,{type:this._videoTrack?Le.emsg:Le.audioId3,duration:Number.POSITIVE_INFINITY});e.samples.push(s)}}function ii(a,e){return((a[e+1]&31)<<8)+a[e+2]}function cc(a,e){return(a[e+10]&31)<<8|a[e+11]}function hc(a,e,t,s,i,r){const n={audioPid:-1,videoPid:-1,id3Pid:-1,segmentVideoCodec:"avc",segmentAudioCodec:"aac"},o=(a[e+1]&15)<<8|a[e+2],c=e+3+o-4,l=(a[e+10]&15)<<8|a[e+11];for(e+=12+l;e0){let d=e+5,f=u;for(;f>2;){switch(a[d]){case 106:t.ac3!==!0?r.log("AC-3 audio found, not supported in this browser for now"):(n.audioPid=h,n.segmentAudioCodec="ac3");break}const y=a[d+1]+2;d+=y,f-=y}}break;case 194:case 135:return ri(i,new Error("Unsupported EC-3 in M2TS found"),void 0,r),n;case 36:n.videoPid===-1&&(n.videoPid=h,n.segmentVideoCodec="hevc",r.log("HEVC in M2TS found"));break}e+=u+5}return n}function ri(a,e,t,s){s.warn(`parsing error: ${e.message}`),a.emit(m.ERROR,m.ERROR,{type:V.MEDIA_ERROR,details:R.FRAG_PARSING_ERROR,fatal:!1,levelRetry:t,error:e,reason:e.message})}function ws(a,e){e.log(`${a} with AES-128-CBC encryption found in unencrypted stream`)}function ft(a,e){let t=0,s,i,r,n,o;const c=a.data;if(!a||a.size===0)return null;for(;c[0].length<19&&c.length>1;)c[0]=De(c[0],c[1]),c.splice(1,1);if(s=c[0],(s[0]<<16)+(s[1]<<8)+s[2]===1){if(i=(s[4]<<8)+s[5],i&&i>a.size-6)return null;const h=s[7];h&192&&(n=(s[9]&14)*536870912+(s[10]&255)*4194304+(s[11]&254)*16384+(s[12]&255)*128+(s[13]&254)/2,h&64?(o=(s[14]&14)*536870912+(s[15]&255)*4194304+(s[16]&254)*16384+(s[17]&255)*128+(s[18]&254)/2,n-o>60*9e4&&(e.warn(`${Math.round((n-o)/9e4)}s delta between PTS and DTS, align them`),n=o)):o=n),r=s[8];let u=r+9;if(a.size<=u)return null;a.size-=u;const d=new Uint8Array(a.size);for(let f=0,g=c.length;fy){u-=y;continue}else s=s.subarray(u),y-=u,u=0;d.set(s,t),t+=y}return i&&(i-=r+3),{data:d,pts:n,dts:o,len:i}}return null}class uc{static getSilentFrame(e,t){switch(e){case"mp4a.40.2":if(t===1)return new Uint8Array([0,200,0,128,35,128]);if(t===2)return new Uint8Array([33,0,73,144,2,25,0,35,128]);if(t===3)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,142]);if(t===4)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,128,44,128,8,2,56]);if(t===5)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,130,48,4,153,0,33,144,2,56]);if(t===6)return new Uint8Array([0,200,0,128,32,132,1,38,64,8,100,0,130,48,4,153,0,33,144,2,0,178,0,32,8,224]);break;default:if(t===1)return new Uint8Array([1,64,34,128,163,78,230,128,186,8,0,0,0,28,6,241,193,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94]);if(t===2)return new Uint8Array([1,64,34,128,163,94,230,128,186,8,0,0,0,0,149,0,6,241,161,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94]);if(t===3)return new Uint8Array([1,64,34,128,163,94,230,128,186,8,0,0,0,0,149,0,6,241,161,10,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,94]);break}}}const je=Math.pow(2,32)-1;class L{static init(){L.types={avc1:[],avcC:[],hvc1:[],hvcC:[],btrt:[],dinf:[],dref:[],esds:[],ftyp:[],hdlr:[],mdat:[],mdhd:[],mdia:[],mfhd:[],minf:[],moof:[],moov:[],mp4a:[],".mp3":[],dac3:[],"ac-3":[],mvex:[],mvhd:[],pasp:[],sdtp:[],stbl:[],stco:[],stsc:[],stsd:[],stsz:[],stts:[],tfdt:[],tfhd:[],traf:[],trak:[],trun:[],trex:[],tkhd:[],vmhd:[],smhd:[]};let e;for(e in L.types)L.types.hasOwnProperty(e)&&(L.types[e]=[e.charCodeAt(0),e.charCodeAt(1),e.charCodeAt(2),e.charCodeAt(3)]);const t=new Uint8Array([0,0,0,0,0,0,0,0,118,105,100,101,0,0,0,0,0,0,0,0,0,0,0,0,86,105,100,101,111,72,97,110,100,108,101,114,0]),s=new Uint8Array([0,0,0,0,0,0,0,0,115,111,117,110,0,0,0,0,0,0,0,0,0,0,0,0,83,111,117,110,100,72,97,110,100,108,101,114,0]);L.HDLR_TYPES={video:t,audio:s};const i=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,12,117,114,108,32,0,0,0,1]),r=new Uint8Array([0,0,0,0,0,0,0,0]);L.STTS=L.STSC=L.STCO=r,L.STSZ=new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0]),L.VMHD=new Uint8Array([0,0,0,1,0,0,0,0,0,0,0,0]),L.SMHD=new Uint8Array([0,0,0,0,0,0,0,0]),L.STSD=new Uint8Array([0,0,0,0,0,0,0,1]);const n=new Uint8Array([105,115,111,109]),o=new Uint8Array([97,118,99,49]),c=new Uint8Array([0,0,0,1]);L.FTYP=L.box(L.types.ftyp,n,c,n,o),L.DINF=L.box(L.types.dinf,L.box(L.types.dref,i))}static box(e,...t){let s=8,i=t.length;const r=i;for(;i--;)s+=t[i].byteLength;const n=new Uint8Array(s);for(n[0]=s>>24&255,n[1]=s>>16&255,n[2]=s>>8&255,n[3]=s&255,n.set(e,4),i=0,s=8;i>24&255,e>>16&255,e>>8&255,e&255,s>>24,s>>16&255,s>>8&255,s&255,i>>24,i>>16&255,i>>8&255,i&255,85,196,0,0]))}static mdia(e){return L.box(L.types.mdia,L.mdhd(e.timescale||0,e.duration||0),L.hdlr(e.type),L.minf(e))}static mfhd(e){return L.box(L.types.mfhd,new Uint8Array([0,0,0,0,e>>24,e>>16&255,e>>8&255,e&255]))}static minf(e){return e.type==="audio"?L.box(L.types.minf,L.box(L.types.smhd,L.SMHD),L.DINF,L.stbl(e)):L.box(L.types.minf,L.box(L.types.vmhd,L.VMHD),L.DINF,L.stbl(e))}static moof(e,t,s){return L.box(L.types.moof,L.mfhd(e),L.traf(s,t))}static moov(e){let t=e.length;const s=[];for(;t--;)s[t]=L.trak(e[t]);return L.box.apply(null,[L.types.moov,L.mvhd(e[0].timescale||0,e[0].duration||0)].concat(s).concat(L.mvex(e)))}static mvex(e){let t=e.length;const s=[];for(;t--;)s[t]=L.trex(e[t]);return L.box.apply(null,[L.types.mvex,...s])}static mvhd(e,t){t*=e;const s=Math.floor(t/(je+1)),i=Math.floor(t%(je+1)),r=new Uint8Array([1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,3,e>>24&255,e>>16&255,e>>8&255,e&255,s>>24,s>>16&255,s>>8&255,s&255,i>>24,i>>16&255,i>>8&255,i&255,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255]);return L.box(L.types.mvhd,r)}static sdtp(e){const t=e.samples||[],s=new Uint8Array(4+t.length);let i,r;for(i=0;i>>8&255),t.push(n&255),t=t.concat(Array.prototype.slice.call(r));for(i=0;i>>8&255),s.push(n&255),s=s.concat(Array.prototype.slice.call(r));const o=L.box(L.types.avcC,new Uint8Array([1,t[3],t[4],t[5],255,224|e.sps.length].concat(t).concat([e.pps.length]).concat(s))),c=e.width,l=e.height,h=e.pixelRatio[0],u=e.pixelRatio[1];return L.box(L.types.avc1,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,c>>8&255,c&255,l>>8&255,l&255,0,72,0,0,0,72,0,0,0,0,0,0,0,1,18,100,97,105,108,121,109,111,116,105,111,110,47,104,108,115,46,106,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,17,17]),o,L.box(L.types.btrt,new Uint8Array([0,28,156,128,0,45,198,192,0,45,198,192])),L.box(L.types.pasp,new Uint8Array([h>>24,h>>16&255,h>>8&255,h&255,u>>24,u>>16&255,u>>8&255,u&255])))}static esds(e){const t=e.config;return new Uint8Array([0,0,0,0,3,25,0,1,0,4,17,64,21,0,0,0,0,0,0,0,0,0,0,0,5,2,...t,6,1,2])}static audioStsd(e){const t=e.samplerate||0;return new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,e.channelCount||0,0,16,0,0,0,0,t>>8&255,t&255,0,0])}static mp4a(e){return L.box(L.types.mp4a,L.audioStsd(e),L.box(L.types.esds,L.esds(e)))}static mp3(e){return L.box(L.types[".mp3"],L.audioStsd(e))}static ac3(e){return L.box(L.types["ac-3"],L.audioStsd(e),L.box(L.types.dac3,e.config))}static stsd(e){const{segmentCodec:t}=e;if(e.type==="audio"){if(t==="aac")return L.box(L.types.stsd,L.STSD,L.mp4a(e));if(t==="ac3"&&e.config)return L.box(L.types.stsd,L.STSD,L.ac3(e));if(t==="mp3"&&e.codec==="mp3")return L.box(L.types.stsd,L.STSD,L.mp3(e))}else if(e.pps&&e.sps){if(t==="avc")return L.box(L.types.stsd,L.STSD,L.avc1(e));if(t==="hevc"&&e.vps)return L.box(L.types.stsd,L.STSD,L.hvc1(e))}else throw new Error("video track missing pps or sps");throw new Error(`unsupported ${e.type} segment codec (${t}/${e.codec})`)}static tkhd(e){const t=e.id,s=(e.duration||0)*(e.timescale||0),i=e.width||0,r=e.height||0,n=Math.floor(s/(je+1)),o=Math.floor(s%(je+1));return L.box(L.types.tkhd,new Uint8Array([1,0,0,7,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,3,t>>24&255,t>>16&255,t>>8&255,t&255,0,0,0,0,n>>24,n>>16&255,n>>8&255,n&255,o>>24,o>>16&255,o>>8&255,o&255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,i>>8&255,i&255,0,0,r>>8&255,r&255,0,0]))}static traf(e,t){const s=L.sdtp(e),i=e.id,r=Math.floor(t/(je+1)),n=Math.floor(t%(je+1));return L.box(L.types.traf,L.box(L.types.tfhd,new Uint8Array([0,0,0,0,i>>24,i>>16&255,i>>8&255,i&255])),L.box(L.types.tfdt,new Uint8Array([1,0,0,0,r>>24,r>>16&255,r>>8&255,r&255,n>>24,n>>16&255,n>>8&255,n&255])),L.trun(e,s.length+16+20+8+16+8+8),s)}static trak(e){return e.duration=e.duration||4294967295,L.box(L.types.trak,L.tkhd(e),L.mdia(e))}static trex(e){const t=e.id;return L.box(L.types.trex,new Uint8Array([0,0,0,0,t>>24,t>>16&255,t>>8&255,t&255,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1]))}static trun(e,t){const s=e.samples||[],i=s.length,r=12+16*i,n=new Uint8Array(r);let o,c,l,h,u,d;for(t+=8+r,n.set([e.type==="video"?1:0,0,15,1,i>>>24&255,i>>>16&255,i>>>8&255,i&255,t>>>24&255,t>>>16&255,t>>>8&255,t&255],0),o=0;o>>24&255,l>>>16&255,l>>>8&255,l&255,h>>>24&255,h>>>16&255,h>>>8&255,h&255,u.isLeading<<2|u.dependsOn,u.isDependedOn<<6|u.hasRedundancy<<4|u.paddingValue<<1|u.isNonSync,u.degradPrio&61440,u.degradPrio&15,d>>>24&255,d>>>16&255,d>>>8&255,d&255],12+16*o);return L.box(L.types.trun,n)}static initSegment(e){L.types||L.init();const t=L.moov(e);return De(L.FTYP,t)}static hvc1(e){const t=e.params,s=[e.vps,e.sps,e.pps],i=4,r=new Uint8Array([1,t.general_profile_space<<6|(t.general_tier_flag?32:0)|t.general_profile_idc,t.general_profile_compatibility_flags[0],t.general_profile_compatibility_flags[1],t.general_profile_compatibility_flags[2],t.general_profile_compatibility_flags[3],t.general_constraint_indicator_flags[0],t.general_constraint_indicator_flags[1],t.general_constraint_indicator_flags[2],t.general_constraint_indicator_flags[3],t.general_constraint_indicator_flags[4],t.general_constraint_indicator_flags[5],t.general_level_idc,240|t.min_spatial_segmentation_idc>>8,255&t.min_spatial_segmentation_idc,252|t.parallelismType,252|t.chroma_format_idc,248|t.bit_depth_luma_minus8,248|t.bit_depth_chroma_minus8,0,parseInt(t.frame_rate.fps),i-1|t.temporal_id_nested<<2|t.num_temporal_layers<<3|(t.frame_rate.fixed?64:0),s.length]);let n=r.length;for(let g=0;g>8,s[g][y].length&255]),n),n+=2,o.set(s[g][y],n),n+=s[g][y].length}const l=L.box(L.types.hvcC,o),h=e.width,u=e.height,d=e.pixelRatio[0],f=e.pixelRatio[1];return L.box(L.types.hvc1,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,h>>8&255,h&255,u>>8&255,u&255,0,72,0,0,0,72,0,0,0,0,0,0,0,1,18,100,97,105,108,121,109,111,116,105,111,110,47,104,108,115,46,106,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,17,17]),l,L.box(L.types.btrt,new Uint8Array([0,28,156,128,0,45,198,192,0,45,198,192])),L.box(L.types.pasp,new Uint8Array([d>>24,d>>16&255,d>>8&255,d&255,f>>24,f>>16&255,f>>8&255,f&255])))}}L.types=void 0;L.HDLR_TYPES=void 0;L.STTS=void 0;L.STSC=void 0;L.STCO=void 0;L.STSZ=void 0;L.VMHD=void 0;L.SMHD=void 0;L.STSD=void 0;L.FTYP=void 0;L.DINF=void 0;const na=9e4;function Ci(a,e,t=1,s=!1){const i=a*e*t;return s?Math.round(i):i}function dc(a,e,t=1,s=!1){return Ci(a,e,1/t,s)}function bt(a,e=!1){return Ci(a,1e3,1/na,e)}function fc(a,e=1){return Ci(a,na,1/e)}function Pr(a){const{baseTime:e,timescale:t,trackId:s}=a;return`${e/t} (${e}/${t}) trackId: ${s}`}const gc=10*1e3,mc=1024,pc=1152,yc=1536;let gt=null,Os=null;function kr(a,e,t,s){return{duration:e,size:t,cts:s,flags:{isLeading:0,isDependedOn:0,hasRedundancy:0,degradPrio:0,dependsOn:a?2:1,isNonSync:a?0:1}}}class is extends Ce{constructor(e,t,s,i){if(super("mp4-remuxer",i),this.observer=void 0,this.config=void 0,this.typeSupported=void 0,this.ISGenerated=!1,this._initPTS=null,this._initDTS=null,this.nextVideoTs=null,this.nextAudioTs=null,this.videoSampleDuration=null,this.isAudioContiguous=!1,this.isVideoContiguous=!1,this.videoTrackConfig=void 0,this.observer=e,this.config=t,this.typeSupported=s,this.ISGenerated=!1,gt===null){const n=(navigator.userAgent||"").match(/Chrome\/(\d+)/i);gt=n?parseInt(n[1]):0}if(Os===null){const r=navigator.userAgent.match(/Safari\/(\d+)/i);Os=r?parseInt(r[1]):0}}destroy(){this.config=this.videoTrackConfig=this._initPTS=this._initDTS=null}resetTimeStamp(e){const t=this._initPTS;(!t||!e||e.trackId!==t.trackId||e.baseTime!==t.baseTime||e.timescale!==t.timescale)&&this.log(`Reset initPTS: ${t&&Pr(t)} > ${e&&Pr(e)}`),this._initPTS=this._initDTS=e}resetNextTimestamp(){this.log("reset next timestamp"),this.isVideoContiguous=!1,this.isAudioContiguous=!1}resetInitSegment(){this.log("ISGenerated flag reset"),this.ISGenerated=!1,this.videoTrackConfig=void 0}getVideoStartPts(e){let t=!1;const s=e[0].pts,i=e.reduce((r,n)=>{let o=n.pts,c=o-r;return c<-4294967296&&(t=!0,o=Ie(o,s),c=o-r),c>0?r:o},s);return t&&this.debug("PTS rollover detected"),i}remux(e,t,s,i,r,n,o,c){let l,h,u,d,f,g,y=r,p=r;const E=e.pid>-1,T=t.pid>-1,S=t.samples.length,v=e.samples.length>0,x=o&&S>0||S>1;if((!E||v)&&(!T||x)||this.ISGenerated||o){if(this.ISGenerated){var A,_,b,I;const H=this.videoTrackConfig;(H&&(t.width!==H.width||t.height!==H.height||((A=t.pixelRatio)==null?void 0:A[0])!==((_=H.pixelRatio)==null?void 0:_[0])||((b=t.pixelRatio)==null?void 0:b[1])!==((I=H.pixelRatio)==null?void 0:I[1]))||!H&&x||this.nextAudioTs===null&&v)&&this.resetInitSegment()}this.ISGenerated||(u=this.generateIS(e,t,r,n));const P=this.isVideoContiguous;let F=-1,U;if(x&&(F=Ec(t.samples),!P&&this.config.forceKeyFrameOnDiscontinuity))if(g=!0,F>0){this.warn(`Dropped ${F} out of ${S} video samples due to a missing keyframe`);const H=this.getVideoStartPts(t.samples);t.samples=t.samples.slice(F),t.dropped+=F,p+=(t.samples[0].pts-H)/t.inputTimeScale,U=p}else F===-1&&(this.warn(`No keyframe found out of ${S} video samples`),g=!1);if(this.ISGenerated){if(v&&x){const H=this.getVideoStartPts(t.samples),k=(Ie(e.samples[0].pts,H)-H)/t.inputTimeScale;y+=Math.max(0,k),p+=Math.max(0,-k)}if(v){if(e.samplerate||(this.warn("regenerate InitSegment as audio detected"),u=this.generateIS(e,t,r,n)),h=this.remuxAudio(e,y,this.isAudioContiguous,n,T||x||c===B.AUDIO?p:void 0),x){const H=h?h.endPTS-h.startPTS:0;t.inputTimeScale||(this.warn("regenerate InitSegment as video detected"),u=this.generateIS(e,t,r,n)),l=this.remuxVideo(t,p,P,H)}}else x&&(l=this.remuxVideo(t,p,P,0));l&&(l.firstKeyFrame=F,l.independent=F!==-1,l.firstKeyFramePTS=U)}}return this.ISGenerated&&this._initPTS&&this._initDTS&&(s.samples.length&&(f=aa(s,r,this._initPTS,this._initDTS)),i.samples.length&&(d=oa(i,r,this._initPTS))),{audio:h,video:l,initSegment:u,independent:g,text:d,id3:f}}computeInitPts(e,t,s,i){const r=Math.round(s*t);let n=Ie(e,r);if(n0?w-1:w].dts&&(T=!0)}T&&n.sort(function(w,O){const j=w.dts-O.dts,ee=w.pts-O.pts;return j||ee}),g=n[0].dts,y=n[n.length-1].dts;const v=y-g,x=v?Math.round(v/(c-1)):f||e.inputTimeScale/30;if(s){const w=g-S,O=w>x,j=w<-1;if((O||j)&&(O?this.warn(`${(e.segmentCodec||"").toUpperCase()}: ${bt(w,!0)} ms (${w}dts) hole between fragments detected at ${t.toFixed(3)}`):this.warn(`${(e.segmentCodec||"").toUpperCase()}: ${bt(-w,!0)} ms (${w}dts) overlapping between fragments detected at ${t.toFixed(3)}`),!j||S>=n[0].pts||gt)){g=S;const ee=n[0].pts-w;if(O)n[0].dts=g,n[0].pts=ee;else{let X=!0;for(let Z=0;Zee&&X);Z++){const ye=n[Z].pts;if(n[Z].dts-=w,n[Z].pts-=w,Z0?O.dts-n[w-1].dts:x;if(X=w>0?O.pts-n[w-1].pts:x,ye.stretchShortVideoTrack&&this.nextAudioTs!==null){const be=Math.floor(ye.maxBufferHole*r),Oe=(i?p+i*r:this.nextAudioTs+h)-O.pts;Oe>be?(f=Oe-fe,f<0?f=fe:F=!0,this.log(`It is approximately ${Oe/90} ms to the next segment; using duration ${f/90} ms for the last video frame.`)):f=fe}else f=fe}const Z=Math.round(O.pts-O.dts);U=Math.min(U,f),$=Math.max($,f),H=Math.min(H,X),k=Math.max(k,X),o.push(kr(O.key,f,ee,Z))}if(o.length){if(gt){if(gt<70){const w=o[0].flags;w.dependsOn=2,w.isNonSync=0}}else if(Os&&k-H<$-U&&x/$<.025&&o[0].cts===0){this.warn("Found irregular gaps in sample duration. Using PTS instead of DTS to determine MP4 sample duration.");let w=g;for(let O=0,j=o.length;O0&&(i&&Math.abs(S-(E+T))<9e3||Math.abs(Ie(y[0].pts,S)-(E+T))<20*h),y.forEach(function(k){k.pts=Ie(k.pts,S)}),!s||E<0){const k=y.length;if(y=y.filter(G=>G.pts>=0),k!==y.length&&this.warn(`Removed ${y.length-k} of ${k} samples (initPTS ${T} / ${n})`),!y.length)return;r===0?E=0:i&&!g?E=Math.max(0,S-T):E=y[0].pts-T}if(e.segmentCodec==="aac"){const k=this.config.maxAudioFramesDrift;for(let G=0,N=E+T;G=k*h&&O0){A+=p;try{D=new Uint8Array(A)}catch(O){this.observer.emit(m.ERROR,m.ERROR,{type:V.MUX_ERROR,details:R.REMUX_ALLOC_ERROR,fatal:!1,error:O,bytes:A,reason:`fail allocating audio mdat ${A}`});return}d||(new DataView(D.buffer).setUint32(0,A),D.set(L.types.mdat,4))}else return;D.set(K,p);const w=K.byteLength;p+=w,f.push(kr(!0,l,w,0)),x=Y}const b=f.length;if(!b)return;const I=f[f.length-1];E=x-T,this.nextAudioTs=E+c*I.duration;const P=d?new Uint8Array(0):L.moof(e.sequenceNumber++,v/c,ie({},e,{samples:f}));e.samples=[];const F=(v-T)/n,U=this.nextAudioTs/n,$={data1:P,data2:D,startPTS:F,endPTS:U,startDTS:F,endDTS:U,type:"audio",hasAudio:!0,hasVideo:!1,nb:b};return this.isAudioContiguous=!0,$}}function Ie(a,e){let t;if(e===null)return a;for(e4294967296;)a+=t;return a}function Ec(a){for(let e=0;en.pts-o.pts);const r=a.samples;return a.samples=[],{samples:r}}class Tc extends Ce{constructor(e,t,s,i){super("passthrough-remuxer",i),this.emitInitSegment=!1,this.audioCodec=void 0,this.videoCodec=void 0,this.initData=void 0,this.initPTS=null,this.initTracks=void 0,this.lastEndTime=null,this.isVideoContiguous=!1}destroy(){}resetTimeStamp(e){this.lastEndTime=null;const t=this.initPTS;t&&e&&t.baseTime===e.baseTime&&t.timescale===e.timescale||(this.initPTS=e)}resetNextTimestamp(){this.isVideoContiguous=!1,this.lastEndTime=null}resetInitSegment(e,t,s,i){this.audioCodec=t,this.videoCodec=s,this.generateInitSegment(e,i),this.emitInitSegment=!0}generateInitSegment(e,t){let{audioCodec:s,videoCodec:i}=this;if(!(e!=null&&e.byteLength)){this.initTracks=void 0,this.initData=void 0;return}const{audio:r,video:n}=this.initData=fn(e);if(t)no(e,t);else{const c=r||n;c!=null&&c.encrypted&&this.warn(`Init segment with encrypted track with has no key ("${c.codec}")!`)}r&&(s=wr(r,re.AUDIO,this)),n&&(i=wr(n,re.VIDEO,this));const o={};r&&n?o.audiovideo={container:"video/mp4",codec:s+","+i,supplemental:n.supplemental,encrypted:n.encrypted,initSegment:e,id:"main"}:r?o.audio={container:"audio/mp4",codec:s,encrypted:r.encrypted,initSegment:e,id:"audio"}:n?o.video={container:"video/mp4",codec:i,supplemental:n.supplemental,encrypted:n.encrypted,initSegment:e,id:"main"}:this.warn("initSegment does not contain moov or trak boxes."),this.initTracks=o}remux(e,t,s,i,r,n){var o,c;let{initPTS:l,lastEndTime:h}=this;const u={audio:void 0,video:void 0,text:i,id3:s,initSegment:void 0};M(h)||(h=this.lastEndTime=r||0);const d=t.samples;if(!d.length)return u;const f={initPTS:void 0,timescale:void 0,trackId:void 0};let g=this.initData;if((o=g)!=null&&o.length||(this.generateInitSegment(d),g=this.initData),!((c=g)!=null&&c.length))return this.warn("Failed to generate initSegment."),u;this.emitInitSegment&&(f.tracks=this.initTracks,this.emitInitSegment=!1);const y=oo(d,g,this),p=g.audio?y[g.audio.id]:null,E=g.video?y[g.video.id]:null,T=Wt(E,1/0),S=Wt(p,1/0),v=Wt(E,0,!0),x=Wt(p,0,!0);let D=r,A=0;const _=p&&(!E||!l&&S0?this.lastEndTime=P:(this.warn("Duration parsed from mp4 should be greater than zero"),this.resetNextTimestamp());const F=!!g.audio,U=!!g.video;let H="";F&&(H+="audio"),U&&(H+="video");const $=(g.audio?g.audio.encrypted:!1)||(g.video?g.video.encrypted:!1),k={data1:d,startPTS:I,startDTS:I,endPTS:P,endDTS:P,type:H,hasAudio:F,hasVideo:U,nb:1,dropped:0,encrypted:$};u.audio=F&&!U?k:void 0,u.video=U?k:void 0;const G=E==null?void 0:E.sampleCount;if(G){const N=E.keyFrameIndex,K=N!==-1;k.nb=G,k.dropped=N===0||this.isVideoContiguous?0:K?N:G,k.independent=K,k.firstKeyFrame=N,K&&E.keyFrameStart&&(k.firstKeyFramePTS=(E.keyFrameStart-l.baseTime)/l.timescale),this.isVideoContiguous||(u.independent=K),this.isVideoContiguous||(this.isVideoContiguous=K),k.dropped&&this.warn(`fmp4 does not start with IDR: firstIDR ${N}/${G} dropped: ${k.dropped} start: ${k.firstKeyFramePTS||"NA"}`)}return u.initSegment=f,u.id3=aa(s,r,l,l),i.samples.length&&(u.text=oa(i,r,l)),u}}function Wt(a,e,t=!1){return(a==null?void 0:a.start)!==void 0?(a.start+(t?a.duration:0))/a.timescale:e}function Sc(a,e,t,s){if(a===null)return!0;const i=Math.max(s,1),r=e-a.baseTime/a.timescale;return Math.abs(r-t)>i}function wr(a,e,t){const s=a.codec;return s&&s.length>4?s:e===re.AUDIO?s==="ec-3"||s==="ac-3"||s==="alac"?s:s==="fLaC"||s==="Opus"?cs(s,!1):(t.warn(`Unhandled audio codec "${s}" in mp4 MAP`),s||"mp4a"):(t.warn(`Unhandled video codec "${s}" in mp4 MAP`),s||"avc1")}let qe;try{qe=self.performance.now.bind(self.performance)}catch{qe=Date.now}const rs=[{demux:nc,remux:Tc},{demux:Qe,remux:is},{demux:tc,remux:is},{demux:ic,remux:is}];rs.splice(2,0,{demux:sc,remux:is});class Or{constructor(e,t,s,i,r,n){this.asyncResult=!1,this.logger=void 0,this.observer=void 0,this.typeSupported=void 0,this.config=void 0,this.id=void 0,this.demuxer=void 0,this.remuxer=void 0,this.decrypter=void 0,this.probe=void 0,this.decryptionPromise=null,this.transmuxConfig=void 0,this.currentTransmuxState=void 0,this.observer=e,this.typeSupported=t,this.config=s,this.id=r,this.logger=n}configure(e){this.transmuxConfig=e,this.decrypter&&this.decrypter.reset()}push(e,t,s,i){const r=s.transmuxing;r.executeStart=qe();let n=new Uint8Array(e);const{currentTransmuxState:o,transmuxConfig:c}=this;i&&(this.currentTransmuxState=i);const{contiguous:l,discontinuity:h,trackSwitch:u,accurateTimeOffset:d,timeOffset:f,initSegmentChange:g}=i||o,{audioCodec:y,videoCodec:p,defaultInitPts:E,duration:T,initSegmentData:S}=c,v=vc(n,t);if(v&&Tt(v.method)){const _=this.getDecrypter(),b=vi(v.method);if(_.isSync()){let I=_.softwareDecrypt(n,v.key.buffer,v.iv.buffer,b);if(s.part>-1){const F=_.flush();I=F&&F.buffer}if(!I)return r.executeEnd=qe(),Fs(s);n=new Uint8Array(I)}else return this.asyncResult=!0,this.decryptionPromise=_.webCryptoDecrypt(n,v.key.buffer,v.iv.buffer,b).then(I=>{const P=this.push(I,null,s);return this.decryptionPromise=null,P}),this.decryptionPromise}const x=this.needsProbing(h,u);if(x){const _=this.configureTransmuxer(n);if(_)return this.logger.warn(`[transmuxer] ${_.message}`),this.observer.emit(m.ERROR,m.ERROR,{type:V.MEDIA_ERROR,details:R.FRAG_PARSING_ERROR,fatal:!1,error:_,reason:_.message}),r.executeEnd=qe(),Fs(s)}(h||u||g||x)&&this.resetInitSegment(S,y,p,T,t),(h||g||x)&&this.resetInitialTimestamp(E),l||this.resetContiguity();const D=this.transmux(n,v,f,d,s);this.asyncResult=Nt(D);const A=this.currentTransmuxState;return A.contiguous=!0,A.discontinuity=!1,A.trackSwitch=!1,r.executeEnd=qe(),D}flush(e){const t=e.transmuxing;t.executeStart=qe();const{decrypter:s,currentTransmuxState:i,decryptionPromise:r}=this;if(r)return this.asyncResult=!0,r.then(()=>this.flush(e));const n=[],{timeOffset:o}=i;if(s){const u=s.flush();u&&n.push(this.push(u.buffer,null,e))}const{demuxer:c,remuxer:l}=this;if(!c||!l){t.executeEnd=qe();const u=[Fs(e)];return this.asyncResult?Promise.resolve(u):u}const h=c.flush(o);return Nt(h)?(this.asyncResult=!0,h.then(u=>(this.flushRemux(n,u,e),n))):(this.flushRemux(n,h,e),this.asyncResult?Promise.resolve(n):n)}flushRemux(e,t,s){const{audioTrack:i,videoTrack:r,id3Track:n,textTrack:o}=t,{accurateTimeOffset:c,timeOffset:l}=this.currentTransmuxState;this.logger.log(`[transmuxer.ts]: Flushed ${this.id} sn: ${s.sn}${s.part>-1?" part: "+s.part:""} of ${this.id===B.MAIN?"level":"track"} ${s.level}`);const h=this.remuxer.remux(i,r,n,o,l,c,!0,this.id);e.push({remuxResult:h,chunkMeta:s}),s.transmuxing.executeEnd=qe()}resetInitialTimestamp(e){const{demuxer:t,remuxer:s}=this;!t||!s||(t.resetTimeStamp(e),s.resetTimeStamp(e))}resetContiguity(){const{demuxer:e,remuxer:t}=this;!e||!t||(e.resetContiguity(),t.resetNextTimestamp())}resetInitSegment(e,t,s,i,r){const{demuxer:n,remuxer:o}=this;!n||!o||(n.resetInitSegment(e,t,s,i),o.resetInitSegment(e,t,s,r))}destroy(){this.demuxer&&(this.demuxer.destroy(),this.demuxer=void 0),this.remuxer&&(this.remuxer.destroy(),this.remuxer=void 0)}transmux(e,t,s,i,r){let n;return t&&t.method==="SAMPLE-AES"?n=this.transmuxSampleAes(e,t,s,i,r):n=this.transmuxUnencrypted(e,s,i,r),n}transmuxUnencrypted(e,t,s,i){const{audioTrack:r,videoTrack:n,id3Track:o,textTrack:c}=this.demuxer.demux(e,t,!1,!this.config.progressive);return{remuxResult:this.remuxer.remux(r,n,o,c,t,s,!1,this.id),chunkMeta:i}}transmuxSampleAes(e,t,s,i,r){return this.demuxer.demuxSampleAes(e,t,s).then(n=>({remuxResult:this.remuxer.remux(n.audioTrack,n.videoTrack,n.id3Track,n.textTrack,s,i,!1,this.id),chunkMeta:r}))}configureTransmuxer(e){const{config:t,observer:s,typeSupported:i}=this;let r;for(let u=0,d=rs.length;u0&&(e==null?void 0:e.key)!=null&&e.iv!==null&&e.method!=null&&(t=e),t}const Fs=a=>({remuxResult:{},chunkMeta:a});function Nt(a){return"then"in a&&a.then instanceof Function}class xc{constructor(e,t,s,i,r){this.audioCodec=void 0,this.videoCodec=void 0,this.initSegmentData=void 0,this.duration=void 0,this.defaultInitPts=void 0,this.audioCodec=e,this.videoCodec=t,this.initSegmentData=s,this.duration=i,this.defaultInitPts=r||null}}class Ac{constructor(e,t,s,i,r,n){this.discontinuity=void 0,this.contiguous=void 0,this.accurateTimeOffset=void 0,this.trackSwitch=void 0,this.timeOffset=void 0,this.initSegmentChange=void 0,this.discontinuity=e,this.contiguous=t,this.accurateTimeOffset=s,this.trackSwitch=i,this.timeOffset=r,this.initSegmentChange=n}}let Fr=0;class la{constructor(e,t,s,i){this.error=null,this.hls=void 0,this.id=void 0,this.instanceNo=Fr++,this.observer=void 0,this.frag=null,this.part=null,this.useWorker=void 0,this.workerContext=null,this.transmuxer=null,this.onTransmuxComplete=void 0,this.onFlush=void 0,this.onWorkerMessage=c=>{const l=c.data,h=this.hls;if(!(!h||!(l!=null&&l.event)||l.instanceNo!==this.instanceNo))switch(l.event){case"init":{var u;const d=(u=this.workerContext)==null?void 0:u.objectURL;d&&self.URL.revokeObjectURL(d);break}case"transmuxComplete":{this.handleTransmuxComplete(l.data);break}case"flush":{this.onFlush(l.data);break}case"workerLog":{h.logger[l.data.logType]&&h.logger[l.data.logType](l.data.message);break}default:{l.data=l.data||{},l.data.frag=this.frag,l.data.part=this.part,l.data.id=this.id,h.trigger(l.event,l.data);break}}},this.onWorkerError=c=>{if(!this.hls)return;const l=new Error(`${c.message} (${c.filename}:${c.lineno})`);this.hls.config.enableWorker=!1,this.hls.logger.warn(`Error in "${this.id}" Web Worker, fallback to inline`),this.hls.trigger(m.ERROR,{type:V.OTHER_ERROR,details:R.INTERNAL_EXCEPTION,fatal:!1,event:"demuxerWorker",error:l})};const r=e.config;this.hls=e,this.id=t,this.useWorker=!!r.enableWorker,this.onTransmuxComplete=s,this.onFlush=i;const n=(c,l)=>{l=l||{},l.frag=this.frag||void 0,c===m.ERROR&&(l=l,l.parent=this.id,l.part=this.part,this.error=l.error),this.hls.trigger(c,l)};this.observer=new Ii,this.observer.on(m.FRAG_DECRYPTED,n),this.observer.on(m.ERROR,n);const o=zi(r.preferManagedMediaSource);if(this.useWorker&&typeof Worker<"u"){const c=this.hls.logger;if(r.workerPath||bl()){try{r.workerPath?(c.log(`loading Web Worker ${r.workerPath} for "${t}"`),this.workerContext=Dl(r.workerPath)):(c.log(`injecting Web Worker for "${t}"`),this.workerContext=_l());const{worker:h}=this.workerContext;h.addEventListener("message",this.onWorkerMessage),h.addEventListener("error",this.onWorkerError),h.postMessage({instanceNo:this.instanceNo,cmd:"init",typeSupported:o,id:t,config:ne(r)})}catch(h){c.warn(`Error setting up "${t}" Web Worker, fallback to inline`,h),this.terminateWorker(),this.error=null,this.transmuxer=new Or(this.observer,o,r,"",t,e.logger)}return}}this.transmuxer=new Or(this.observer,o,r,"",t,e.logger)}reset(){if(this.frag=null,this.part=null,this.workerContext){const e=this.instanceNo;this.instanceNo=Fr++;const t=this.hls.config,s=zi(t.preferManagedMediaSource);this.workerContext.worker.postMessage({instanceNo:this.instanceNo,cmd:"reset",resetNo:e,typeSupported:s,id:this.id,config:ne(t)})}}terminateWorker(){if(this.workerContext){const{worker:e}=this.workerContext;this.workerContext=null,e.removeEventListener("message",this.onWorkerMessage),e.removeEventListener("error",this.onWorkerError),Cl(this.hls.config.workerPath)}}destroy(){if(this.workerContext)this.terminateWorker(),this.onWorkerMessage=this.onWorkerError=null;else{const t=this.transmuxer;t&&(t.destroy(),this.transmuxer=null)}const e=this.observer;e&&e.removeAllListeners(),this.frag=null,this.part=null,this.observer=null,this.hls=null}push(e,t,s,i,r,n,o,c,l,h){var u,d;l.transmuxing.start=self.performance.now();const{instanceNo:f,transmuxer:g}=this,y=n?n.start:r.start,p=r.decryptdata,E=this.frag,T=!(E&&r.cc===E.cc),S=!(E&&l.level===E.level),v=E?l.sn-E.sn:-1,x=this.part?l.part-this.part.index:-1,D=v===0&&l.id>1&&l.id===(E==null?void 0:E.stats.chunkCount),A=!S&&(v===1||v===0&&(x===1||D&&x<=0)),_=self.performance.now();(S||v||r.stats.parsing.start===0)&&(r.stats.parsing.start=_),n&&(x||!A)&&(n.stats.parsing.start=_);const b=!(E&&((u=r.initSegment)==null?void 0:u.url)===((d=E.initSegment)==null?void 0:d.url)),I=new Ac(T,A,c,S,y,b);if(!A||T||b){this.hls.logger.log(`[transmuxer-interface]: Starting new transmux session for ${r.type} sn: ${l.sn}${l.part>-1?" part: "+l.part:""} ${this.id===B.MAIN?"level":"track"}: ${l.level} id: ${l.id} discontinuity: ${T} trackSwitch: ${S} contiguous: ${A} accurateTimeOffset: ${c} timeOffset: ${y} - initSegmentChange: ${b}`);const P=new Uc(s,i,t,o,h);this.configureTransmuxer(P)}if(this.frag=r,this.part=n,this.workerContext)this.workerContext.worker.postMessage({instanceNo:f,cmd:"demux",data:e,decryptdata:p,chunkMeta:l,state:I},e instanceof ArrayBuffer?[e]:[]);else if(g){const P=g.push(e,p,l,I);Yt(P)?P.then(M=>{this.handleTransmuxComplete(M)}).catch(M=>{this.transmuxerError(M,l,"transmuxer-interface push error")}):this.handleTransmuxComplete(P)}}flush(e){e.transmuxing.start=self.performance.now();const{instanceNo:t,transmuxer:s}=this;if(this.workerContext)this.workerContext.worker.postMessage({instanceNo:t,cmd:"flush",chunkMeta:e});else if(s){const i=s.flush(e);Yt(i)?i.then(r=>{this.handleFlushResult(r,e)}).catch(r=>{this.transmuxerError(r,e,"transmuxer-interface flush error")}):this.handleFlushResult(i,e)}}transmuxerError(e,t,s){this.hls&&(this.error=e,this.hls.trigger(m.ERROR,{type:Y.MEDIA_ERROR,details:R.FRAG_PARSING_ERROR,chunkMeta:t,frag:this.frag||void 0,part:this.part||void 0,fatal:!1,error:e,err:e,reason:s}))}handleFlushResult(e,t){e.forEach(s=>{this.handleTransmuxComplete(s)}),this.onFlush(t)}configureTransmuxer(e){const{instanceNo:t,transmuxer:s}=this;this.workerContext?this.workerContext.worker.postMessage({instanceNo:t,cmd:"configure",config:e}):s&&s.configure(e)}handleTransmuxComplete(e){e.chunkMeta.transmuxing.end=self.performance.now(),this.onTransmuxComplete(e)}}const Xr=100;class Kc extends Fi{constructor(e,t,s){super(e,t,s,"audio-stream-controller",U.AUDIO),this.mainAnchor=null,this.mainFragLoading=null,this.audioOnly=!1,this.bufferedTrack=null,this.switchingTrack=null,this.trackId=-1,this.waitingData=null,this.mainDetails=null,this.flushing=!1,this.bufferFlushed=!1,this.cachedTrackLoadedData=null,this.registerListeners()}onHandlerDestroying(){this.unregisterListeners(),super.onHandlerDestroying(),this.resetItem()}resetItem(){this.mainDetails=this.mainAnchor=this.mainFragLoading=this.bufferedTrack=this.switchingTrack=this.waitingData=this.cachedTrackLoadedData=null}registerListeners(){super.registerListeners();const{hls:e}=this;e.on(m.LEVEL_LOADED,this.onLevelLoaded,this),e.on(m.AUDIO_TRACKS_UPDATED,this.onAudioTracksUpdated,this),e.on(m.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),e.on(m.AUDIO_TRACK_LOADED,this.onAudioTrackLoaded,this),e.on(m.BUFFER_RESET,this.onBufferReset,this),e.on(m.BUFFER_CREATED,this.onBufferCreated,this),e.on(m.BUFFER_FLUSHING,this.onBufferFlushing,this),e.on(m.BUFFER_FLUSHED,this.onBufferFlushed,this),e.on(m.INIT_PTS_FOUND,this.onInitPtsFound,this),e.on(m.FRAG_LOADING,this.onFragLoading,this),e.on(m.FRAG_BUFFERED,this.onFragBuffered,this)}unregisterListeners(){const{hls:e}=this;e&&(super.unregisterListeners(),e.off(m.LEVEL_LOADED,this.onLevelLoaded,this),e.off(m.AUDIO_TRACKS_UPDATED,this.onAudioTracksUpdated,this),e.off(m.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),e.off(m.AUDIO_TRACK_LOADED,this.onAudioTrackLoaded,this),e.off(m.BUFFER_RESET,this.onBufferReset,this),e.off(m.BUFFER_CREATED,this.onBufferCreated,this),e.off(m.BUFFER_FLUSHING,this.onBufferFlushing,this),e.off(m.BUFFER_FLUSHED,this.onBufferFlushed,this),e.off(m.INIT_PTS_FOUND,this.onInitPtsFound,this),e.off(m.FRAG_LOADING,this.onFragLoading,this),e.off(m.FRAG_BUFFERED,this.onFragBuffered,this))}onInitPtsFound(e,{frag:t,id:s,initPTS:i,timescale:r,trackId:n}){if(s===U.MAIN){const o=t.cc,c=this.fragCurrent;if(this.initPTS[o]={baseTime:i,timescale:r,trackId:n},this.log(`InitPTS for cc: ${o} found from main: ${i/r} (${i}/${r}) trackId: ${n}`),this.mainAnchor=t,this.state===C.WAITING_INIT_PTS){const l=this.waitingData;(!l&&!this.loadingParts||l&&l.frag.cc!==o)&&this.syncWithAnchor(t,l==null?void 0:l.frag)}else!this.hls.hasEnoughToStart&&c&&c.cc!==o?(c.abortRequests(),this.syncWithAnchor(t,c)):this.state===C.IDLE&&this.tick()}}getLoadPosition(){return!this.startFragRequested&&this.nextLoadPosition>=0?this.nextLoadPosition:super.getLoadPosition()}syncWithAnchor(e,t){var s;const i=((s=this.mainFragLoading)==null?void 0:s.frag)||null;if(t&&(i==null?void 0:i.cc)===t.cc)return;const r=(i||e).cc,n=this.getLevelDetails(),o=this.getLoadPosition(),c=Un(n,r,o);c&&(this.log(`Syncing with main frag at ${c.start} cc ${c.cc}`),this.startFragRequested=!1,this.nextLoadPosition=c.start,this.resetLoadingState(),this.state===C.IDLE&&this.doTickIdle())}startLoad(e,t){if(!this.levels){this.startPosition=e,this.state=C.STOPPED;return}const s=this.lastCurrentTime;this.stopLoad(),this.setInterval(Xr),s>0&&e===-1?(this.log(`Override startPosition with lastCurrentTime @${s.toFixed(3)}`),e=s,this.state=C.IDLE):this.state=C.WAITING_TRACK,this.nextLoadPosition=this.lastCurrentTime=e+this.timelineOffset,this.startPosition=t?-1:e,this.tick()}doTick(){switch(this.state){case C.IDLE:this.doTickIdle();break;case C.WAITING_TRACK:{const{levels:e,trackId:t}=this,s=e==null?void 0:e[t],i=s==null?void 0:s.details;if(i&&!this.waitForLive(s)){if(this.waitForCdnTuneIn(i))break;this.state=C.WAITING_INIT_PTS}break}case C.FRAG_LOADING_WAITING_RETRY:{this.checkRetryDate();break}case C.WAITING_INIT_PTS:{const e=this.waitingData;if(e){const{frag:t,part:s,cache:i,complete:r}=e,n=this.mainAnchor;if(this.initPTS[t.cc]!==void 0){this.waitingData=null,this.state=C.FRAG_LOADING;const o=i.flush().buffer,c={frag:t,part:s,payload:o,networkDetails:null};this._handleFragmentLoadProgress(c),r&&super._handleFragmentLoadComplete(c)}else n&&n.cc!==e.frag.cc&&this.syncWithAnchor(n,e.frag)}else this.state=C.IDLE}}this.onTickEnd()}resetLoadingState(){const e=this.waitingData;e&&(this.fragmentTracker.removeFragment(e.frag),this.waitingData=null),super.resetLoadingState()}onTickEnd(){const{media:e}=this;e!=null&&e.readyState&&(this.lastCurrentTime=e.currentTime)}doTickIdle(){var e;const{hls:t,levels:s,media:i,trackId:r}=this,n=t.config;if(!this.buffering||!i&&!this.primaryPrefetch&&(this.startFragRequested||!n.startFragPrefetch)||!(s!=null&&s[r]))return;const o=s[r],c=o.details;if(!c||this.waitForLive(o)||this.waitForCdnTuneIn(c)){this.state=C.WAITING_TRACK,this.startFragRequested=!1;return}const l=this.mediaBuffer?this.mediaBuffer:this.media;this.bufferFlushed&&l&&(this.bufferFlushed=!1,this.afterBufferFlushed(l,ae.AUDIO,U.AUDIO));const h=this.getFwdBufferInfo(l,U.AUDIO);if(h===null)return;if(!this.switchingTrack&&this._streamEnded(h,c)){t.trigger(m.BUFFER_EOS,{type:"audio"}),this.state=C.ENDED;return}const d=h.len,u=t.maxBufferLength,f=c.fragments,g=f[0].start,y=this.getLoadPosition(),p=this.flushing?y:h.end;if(this.switchingTrack&&i){const S=y;c.PTSKnown&&Sg||h.nextStart)&&(this.log("Alt audio track ahead of main track, seek to start of alt audio track"),i.currentTime=g+.05)}if(d>=u&&!this.switchingTrack&&pT.end){const v=this.fragmentTracker.getFragAtPos(p,U.MAIN);v&&v.end>T.end&&(T=v,this.mainFragLoading={frag:v,targetBufferTime:null})}if(E.start>T.end)return}this.loadFragment(E,o,p)}onMediaDetaching(e,t){this.bufferFlushed=this.flushing=!1,super.onMediaDetaching(e,t)}onAudioTracksUpdated(e,{audioTracks:t}){this.resetTransmuxer(),this.levels=t.map(s=>new Kt(s))}onAudioTrackSwitching(e,t){const s=!!t.url;this.trackId=t.id;const{fragCurrent:i}=this;i&&(i.abortRequests(),this.removeUnbufferedFrags(i.start)),this.resetLoadingState(),s?(this.switchingTrack=t,this.flushAudioIfNeeded(t),this.state!==C.STOPPED&&(this.setInterval(Xr),this.state=C.IDLE,this.tick())):(this.resetTransmuxer(),this.switchingTrack=null,this.bufferedTrack=t,this.clearInterval())}onManifestLoading(){super.onManifestLoading(),this.bufferFlushed=this.flushing=this.audioOnly=!1,this.resetItem(),this.trackId=-1}onLevelLoaded(e,t){this.mainDetails=t.details;const s=this.cachedTrackLoadedData;s&&(this.cachedTrackLoadedData=null,this.onAudioTrackLoaded(m.AUDIO_TRACK_LOADED,s))}onAudioTrackLoaded(e,t){var s;const{levels:i}=this,{details:r,id:n,groupId:o,track:c}=t;if(!i){this.warn(`Audio tracks reset while loading track ${n} "${c.name}" of "${o}"`);return}const l=this.mainDetails;if(!l||r.endCC>l.endCC||l.expired){this.cachedTrackLoadedData=t,this.state!==C.STOPPED&&(this.state=C.WAITING_TRACK);return}this.cachedTrackLoadedData=null,this.log(`Audio track ${n} "${c.name}" of "${o}" loaded [${r.startSN},${r.endSN}]${r.lastPartSn?`[part-${r.lastPartSn}-${r.lastPartIndex}]`:""},duration:${r.totalduration}`);const h=i[n];let d=0;if(r.live||(s=h.details)!=null&&s.live){if(this.checkLiveUpdate(r),r.deltaUpdateFailed)return;if(h.details){var u;d=this.alignPlaylists(r,h.details,(u=this.levelLastLoaded)==null?void 0:u.details)}r.alignedSliding||(ra(r,l),r.alignedSliding||Rs(r,l),d=r.fragmentStart)}h.details=r,this.levelLastLoaded=h,this.startFragRequested||this.setStartPosition(l,d),this.hls.trigger(m.AUDIO_TRACK_UPDATED,{details:r,id:n,groupId:t.groupId}),this.state===C.WAITING_TRACK&&!this.waitForCdnTuneIn(r)&&(this.state=C.IDLE),this.tick()}_handleFragmentLoadProgress(e){var t;const s=e.frag,{part:i,payload:r}=e,{config:n,trackId:o,levels:c}=this;if(!c){this.warn(`Audio tracks were reset while fragment load was in progress. Fragment ${s.sn} of level ${s.level} will not be buffered`);return}const l=c[o];if(!l){this.warn("Audio track is undefined on fragment load progress");return}const h=l.details;if(!h){this.warn("Audio track details undefined on fragment load progress"),this.removeUnbufferedFrags(s.start);return}const d=n.defaultAudioCodec||l.audioCodec||"mp4a.40.2";let u=this.transmuxer;u||(u=this.transmuxer=new Ia(this.hls,U.AUDIO,this._handleTransmuxComplete.bind(this),this._handleTransmuxerFlush.bind(this)));const f=this.initPTS[s.cc],g=(t=s.initSegment)==null?void 0:t.data;if(f!==void 0){const p=i?i.index:-1,E=p!==-1,T=new ki(s.level,s.sn,s.stats.chunkCount,r.byteLength,p,E);u.push(r,g,d,"",s,i,h.totalduration,!1,T,f)}else{this.log(`Unknown video PTS for cc ${s.cc}, waiting for video PTS before demuxing audio frag ${s.sn} of [${h.startSN} ,${h.endSN}],track ${o}`);const{cache:y}=this.waitingData=this.waitingData||{frag:s,part:i,cache:new na,complete:!1};y.push(new Uint8Array(r)),this.state!==C.STOPPED&&(this.state=C.WAITING_INIT_PTS)}}_handleFragmentLoadComplete(e){if(this.waitingData){this.waitingData.complete=!0;return}super._handleFragmentLoadComplete(e)}onBufferReset(){this.mediaBuffer=null}onBufferCreated(e,t){this.bufferFlushed=this.flushing=!1;const s=t.tracks.audio;s&&(this.mediaBuffer=s.buffer||null)}onFragLoading(e,t){!this.audioOnly&&t.frag.type===U.MAIN&&de(t.frag)&&(this.mainFragLoading=t,this.state===C.IDLE&&this.tick())}onFragBuffered(e,t){const{frag:s,part:i}=t;if(s.type!==U.AUDIO){!this.audioOnly&&s.type===U.MAIN&&!s.elementaryStreams.video&&!s.elementaryStreams.audiovideo&&(this.audioOnly=!0,this.mainFragLoading=null);return}if(this.fragContextChanged(s)){this.warn(`Fragment ${s.sn}${i?" p: "+i.index:""} of level ${s.level} finished buffering, but was aborted. state: ${this.state}, audioSwitch: ${this.switchingTrack?this.switchingTrack.name:"false"}`);return}if(de(s)){this.fragPrevious=s;const r=this.switchingTrack;r&&(this.bufferedTrack=r,this.switchingTrack=null,this.hls.trigger(m.AUDIO_TRACK_SWITCHED,ie({},r)))}this.fragBufferedComplete(s,i),this.media&&this.tick()}onError(e,t){var s;if(t.fatal){this.state=C.ERROR;return}switch(t.details){case R.FRAG_GAP:case R.FRAG_PARSING_ERROR:case R.FRAG_DECRYPT_ERROR:case R.FRAG_LOAD_ERROR:case R.FRAG_LOAD_TIMEOUT:case R.KEY_LOAD_ERROR:case R.KEY_LOAD_TIMEOUT:this.onFragmentOrKeyLoadError(U.AUDIO,t);break;case R.AUDIO_TRACK_LOAD_ERROR:case R.AUDIO_TRACK_LOAD_TIMEOUT:case R.LEVEL_PARSING_ERROR:!t.levelRetry&&this.state===C.WAITING_TRACK&&((s=t.context)==null?void 0:s.type)===J.AUDIO_TRACK&&(this.state=C.IDLE);break;case R.BUFFER_ADD_CODEC_ERROR:case R.BUFFER_APPEND_ERROR:if(t.parent!=="audio")return;this.reduceLengthAndFlushBuffer(t)||this.resetLoadingState();break;case R.BUFFER_FULL_ERROR:if(t.parent!=="audio")return;this.reduceLengthAndFlushBuffer(t)&&(this.bufferedTrack=null,super.flushMainBuffer(0,Number.POSITIVE_INFINITY,"audio"));break;case R.INTERNAL_EXCEPTION:this.recoverWorkerError(t);break}}onBufferFlushing(e,{type:t}){t!==ae.VIDEO&&(this.flushing=!0)}onBufferFlushed(e,{type:t}){if(t!==ae.VIDEO){this.flushing=!1,this.bufferFlushed=!0,this.state===C.ENDED&&(this.state=C.IDLE);const s=this.mediaBuffer||this.media;s&&(this.afterBufferFlushed(s,t,U.AUDIO),this.tick())}}_handleTransmuxComplete(e){var t;const s="audio",{hls:i}=this,{remuxResult:r,chunkMeta:n}=e,o=this.getCurrentContext(n);if(!o){this.resetWhenMissingContext(n);return}const{frag:c,part:l,level:h}=o,{details:d}=h,{audio:u,text:f,id3:g,initSegment:y}=r;if(this.fragContextChanged(c)||!d){this.fragmentTracker.removeFragment(c);return}if(this.state=C.PARSING,this.switchingTrack&&u&&this.completeAudioSwitch(this.switchingTrack),y!=null&&y.tracks){const p=c.initSegment||c;if(this.unhandledEncryptionError(y,c))return;this._bufferInitSegment(h,y.tracks,p,n),i.trigger(m.FRAG_PARSING_INIT_SEGMENT,{frag:p,id:s,tracks:y.tracks})}if(u){const{startPTS:p,endPTS:E,startDTS:T,endDTS:S}=u;l&&(l.elementaryStreams[ae.AUDIO]={startPTS:p,endPTS:E,startDTS:T,endDTS:S}),c.setElementaryStreamInfo(ae.AUDIO,p,E,T,S),this.bufferFragmentData(u,c,l,n)}if(g!=null&&(t=g.samples)!=null&&t.length){const p=ne({id:s,frag:c,details:d},g);i.trigger(m.FRAG_PARSING_METADATA,p)}if(f){const p=ne({id:s,frag:c,details:d},f);i.trigger(m.FRAG_PARSING_USERDATA,p)}}_bufferInitSegment(e,t,s,i){if(this.state!==C.PARSING||(t.video&&delete t.video,t.audiovideo&&delete t.audiovideo,!t.audio))return;const r=t.audio;r.id=U.AUDIO;const n=e.audioCodec;this.log(`Init audio buffer, container:${r.container}, codecs[level/parsed]=[${n}/${r.codec}]`),n&&n.split(",").length===1&&(r.levelCodec=n),this.hls.trigger(m.BUFFER_CODECS,t);const o=r.initSegment;if(o!=null&&o.byteLength){const c={type:"audio",frag:s,part:null,chunkMeta:i,parent:s.type,data:o};this.hls.trigger(m.BUFFER_APPENDING,c)}this.tickImmediate()}loadFragment(e,t,s){const i=this.fragmentTracker.getState(e);if(this.switchingTrack||i===fe.NOT_LOADED||i===fe.PARTIAL){var r;if(!de(e))this._loadInitSegment(e,t);else if((r=t.details)!=null&&r.live&&!this.initPTS[e.cc]){this.log(`Waiting for video PTS in continuity counter ${e.cc} of live stream before loading audio fragment ${e.sn} of level ${this.trackId}`),this.state=C.WAITING_INIT_PTS;const n=this.mainDetails;n&&n.fragmentStart!==t.details.fragmentStart&&Rs(t.details,n)}else super.loadFragment(e,t,s)}else this.clearTrackerIfNeeded(e)}flushAudioIfNeeded(e){if(this.media&&this.bufferedTrack){const{name:t,lang:s,assocLang:i,characteristics:r,audioCodec:n,channels:o}=this.bufferedTrack;gt({name:t,lang:s,assocLang:i,characteristics:r,audioCodec:n,channels:o},e,ft)||(vs(e.url,this.hls)?(this.log("Switching audio track : flushing all audio"),super.flushMainBuffer(0,Number.POSITIVE_INFINITY,"audio"),this.bufferedTrack=null):this.bufferedTrack=e)}}completeAudioSwitch(e){const{hls:t}=this;this.flushAudioIfNeeded(e),this.bufferedTrack=e,this.switchingTrack=null,t.trigger(m.AUDIO_TRACK_SWITCHED,ie({},e))}}class Vi extends Oe{constructor(e,t){super(t,e.logger),this.hls=void 0,this.canLoad=!1,this.timer=-1,this.hls=e}destroy(){this.clearTimer(),this.hls=this.log=this.warn=null}clearTimer(){this.timer!==-1&&(self.clearTimeout(this.timer),this.timer=-1)}startLoad(){this.canLoad=!0,this.loadPlaylist()}stopLoad(){this.canLoad=!1,this.clearTimer()}switchParams(e,t,s){const i=t==null?void 0:t.renditionReports;if(i){let r=-1;for(let n=0;n=0&&h>t.partTarget&&(c+=1)}const l=s&&hr(s);return new dr(o,c>=0?c:void 0,l)}}}loadPlaylist(e){this.clearTimer()}loadingPlaylist(e,t){this.clearTimer()}shouldLoadPlaylist(e){return this.canLoad&&!!e&&!!e.url&&(!e.details||e.details.live)}getUrlWithDirectives(e,t){if(t)try{return t.addDirectives(e)}catch(s){this.warn(`Could not construct new URL with HLS Delivery Directives: ${s}`)}return e}playlistLoaded(e,t,s){const{details:i,stats:r}=t,n=self.performance.now(),o=r.loading.first?Math.max(0,n-r.loading.first):0;i.advancedDateTime=Date.now()-o;const c=this.hls.config.timelineOffset;if(c!==i.appliedTimelineOffset){const h=Math.max(c||0,0);i.appliedTimelineOffset=h,i.fragments.forEach(d=>{d.setStart(d.playlistOffset+h)})}if(i.live||s!=null&&s.live){const h="levelInfo"in t?t.levelInfo:t.track;if(i.reloaded(s),s&&i.fragments.length>0){Ol(s,i,this);const T=i.playlistParsingError;if(T){this.warn(T);const S=this.hls;if(!S.config.ignorePlaylistParsingErrors){var l;const{networkDetails:v}=t;S.trigger(m.ERROR,{type:Y.NETWORK_ERROR,details:R.LEVEL_PARSING_ERROR,fatal:!1,url:i.url,error:T,reason:T.message,level:t.level||void 0,parent:(l=i.fragments[0])==null?void 0:l.type,networkDetails:v,stats:r});return}i.playlistParsingError=null}}i.requestScheduled===-1&&(i.requestScheduled=r.loading.start);const d=this.hls.mainForwardBufferInfo,u=d?d.end-d.len:0,f=(i.edge-u)*1e3,g=Jn(i,f);if(i.requestScheduled+g0){if(b>i.targetduration*3)this.log(`Playlist last advanced ${_.toFixed(2)}s ago. Omitting segment and part directives.`),p=void 0,E=void 0;else if(s!=null&&s.tuneInGoal&&b-i.partTarget>s.tuneInGoal)this.warn(`CDN Tune-in goal increased from: ${s.tuneInGoal} to: ${I} with playlist age: ${i.age}`),I=0;else{const P=Math.floor(I/i.targetduration);if(p+=P,E!==void 0){const M=Math.round(I%i.targetduration/i.partTarget);E+=M}this.log(`CDN Tune-in age: ${i.ageHeader}s last advanced ${_.toFixed(2)}s goal: ${I} skip sn ${P} to part ${E}`)}i.tuneInGoal=I}if(y=this.getDeliveryDirectives(i,t.deliveryDirectives,p,E),T||!A){i.requestScheduled=n,this.loadingPlaylist(h,y);return}}else(i.canBlockReload||i.canSkipUntil)&&(y=this.getDeliveryDirectives(i,t.deliveryDirectives,p,E));y&&p!==void 0&&i.canBlockReload&&(i.requestScheduled=r.loading.first+Math.max(g-o*2,g/2)),this.scheduleLoading(h,y,i)}else this.clearTimer()}scheduleLoading(e,t,s){const i=s||e.details;if(!i){this.loadingPlaylist(e,t);return}const r=self.performance.now(),n=i.requestScheduled;if(r>=n){this.loadingPlaylist(e,t);return}const o=n-r;this.log(`reload live playlist ${e.name||e.bitrate+"bps"} in ${Math.round(o)} ms`),this.clearTimer(),this.timer=self.setTimeout(()=>this.loadingPlaylist(e,t),o)}getDeliveryDirectives(e,t,s,i){let r=hr(e);return t!=null&&t.skip&&e.deltaUpdateFailed&&(s=t.msn,i=t.part,r=ds.No),new dr(s,i,r)}checkRetry(e){const t=e.details,s=xs(e),i=e.errorAction,{action:r,retryCount:n=0,retryConfig:o}=i||{},c=!!i&&!!o&&(r===pe.RetryRequest||!i.resolved&&r===pe.SendAlternateToPenaltyBox);if(c){var l;if(n>=o.maxNumRetry)return!1;if(s&&(l=e.context)!=null&&l.deliveryDirectives)this.warn(`Retrying playlist loading ${n+1}/${o.maxNumRetry} after "${t}" without delivery-directives`),this.loadPlaylist();else{const h=Ci(o,n);this.clearTimer(),this.timer=self.setTimeout(()=>this.loadPlaylist(),h),this.warn(`Retrying playlist loading ${n+1}/${o.maxNumRetry} after "${t}" in ${h}ms`)}e.levelRetry=!0,i.resolved=!0}return c}}function La(a,e){if(a.length!==e.length)return!1;for(let t=0;ta[i]!==e[i])}function mi(a,e){return e.label.toLowerCase()===a.name.toLowerCase()&&(!e.language||e.language.toLowerCase()===(a.lang||"").toLowerCase())}class Vc extends Vi{constructor(e){super(e,"audio-track-controller"),this.tracks=[],this.groupIds=null,this.tracksInGroup=[],this.trackId=-1,this.currentTrack=null,this.selectDefaultTrack=!0,this.registerListeners()}registerListeners(){const{hls:e}=this;e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.MANIFEST_PARSED,this.onManifestParsed,this),e.on(m.LEVEL_LOADING,this.onLevelLoading,this),e.on(m.LEVEL_SWITCHING,this.onLevelSwitching,this),e.on(m.AUDIO_TRACK_LOADED,this.onAudioTrackLoaded,this),e.on(m.ERROR,this.onError,this)}unregisterListeners(){const{hls:e}=this;e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.MANIFEST_PARSED,this.onManifestParsed,this),e.off(m.LEVEL_LOADING,this.onLevelLoading,this),e.off(m.LEVEL_SWITCHING,this.onLevelSwitching,this),e.off(m.AUDIO_TRACK_LOADED,this.onAudioTrackLoaded,this),e.off(m.ERROR,this.onError,this)}destroy(){this.unregisterListeners(),this.tracks.length=0,this.tracksInGroup.length=0,this.currentTrack=null,super.destroy()}onManifestLoading(){this.tracks=[],this.tracksInGroup=[],this.groupIds=null,this.currentTrack=null,this.trackId=-1,this.selectDefaultTrack=!0}onManifestParsed(e,t){this.tracks=t.audioTracks||[]}onAudioTrackLoaded(e,t){const{id:s,groupId:i,details:r}=t,n=this.tracksInGroup[s];if(!n||n.groupId!==i){this.warn(`Audio track with id:${s} and group:${i} not found in active group ${n==null?void 0:n.groupId}`);return}const o=n.details;n.details=t.details,this.log(`Audio track ${s} "${n.name}" lang:${n.lang} group:${i} loaded [${r.startSN}-${r.endSN}]`),s===this.trackId&&this.playlistLoaded(s,t,o)}onLevelLoading(e,t){this.switchLevel(t.level)}onLevelSwitching(e,t){this.switchLevel(t.level)}switchLevel(e){const t=this.hls.levels[e];if(!t)return;const s=t.audioGroups||null,i=this.groupIds;let r=this.currentTrack;if(!s||(i==null?void 0:i.length)!==(s==null?void 0:s.length)||s!=null&&s.some(o=>(i==null?void 0:i.indexOf(o))===-1)){this.groupIds=s,this.trackId=-1,this.currentTrack=null;const o=this.tracks.filter(u=>!s||s.indexOf(u.groupId)!==-1);if(o.length)this.selectDefaultTrack&&!o.some(u=>u.default)&&(this.selectDefaultTrack=!1),o.forEach((u,f)=>{u.id=f});else if(!r&&!this.tracksInGroup.length)return;this.tracksInGroup=o;const c=this.hls.config.audioPreference;if(!r&&c){const u=We(c,o,ft);if(u>-1)r=o[u];else{const f=We(c,this.tracks);r=this.tracks[f]}}let l=this.findTrackId(r);l===-1&&r&&(l=this.findTrackId(null));const h={audioTracks:o};this.log(`Updating audio tracks, ${o.length} track(s) found in group(s): ${s==null?void 0:s.join(",")}`),this.hls.trigger(m.AUDIO_TRACKS_UPDATED,h);const d=this.trackId;if(l!==-1&&d===-1)this.setAudioTrack(l);else if(o.length&&d===-1){var n;const u=new Error(`No audio track selected for current audio group-ID(s): ${(n=this.groupIds)==null?void 0:n.join(",")} track count: ${o.length}`);this.warn(u.message),this.hls.trigger(m.ERROR,{type:Y.MEDIA_ERROR,details:R.AUDIO_TRACK_LOAD_ERROR,fatal:!0,error:u})}}}onError(e,t){t.fatal||!t.context||t.context.type===J.AUDIO_TRACK&&t.context.id===this.trackId&&(!this.groupIds||this.groupIds.indexOf(t.context.groupId)!==-1)&&this.checkRetry(t)}get allAudioTracks(){return this.tracks}get audioTracks(){return this.tracksInGroup}get audioTrack(){return this.trackId}set audioTrack(e){this.selectDefaultTrack=!1,this.setAudioTrack(e)}setAudioOption(e){const t=this.hls;if(t.config.audioPreference=e,e){const s=this.allAudioTracks;if(this.selectDefaultTrack=!1,s.length){const i=this.currentTrack;if(i&>(e,i,ft))return i;const r=We(e,this.tracksInGroup,ft);if(r>-1){const n=this.tracksInGroup[r];return this.setAudioTrack(r),n}else if(i){let n=t.loadLevel;n===-1&&(n=t.firstAutoLevel);const o=tl(e,t.levels,s,n,ft);if(o===-1)return null;t.nextLoadLevel=o}if(e.channels||e.audioCodec){const n=We(e,s);if(n>-1)return s[n]}}}return null}setAudioTrack(e){const t=this.tracksInGroup;if(e<0||e>=t.length){this.warn(`Invalid audio track id: ${e}`);return}this.selectDefaultTrack=!1;const s=this.currentTrack,i=t[e],r=i.details&&!i.details.live;if(e===this.trackId&&i===s&&r||(this.log(`Switching to audio-track ${e} "${i.name}" lang:${i.lang} group:${i.groupId} channels:${i.channels}`),this.trackId=e,this.currentTrack=i,this.hls.trigger(m.AUDIO_TRACK_SWITCHING,ie({},i)),r))return;const n=this.switchParams(i.url,s==null?void 0:s.details,i.details);this.loadPlaylist(n)}findTrackId(e){const t=this.tracksInGroup;for(let s=0;s{const s={label:"async-blocker",execute:t,onStart:()=>{},onComplete:()=>{},onError:()=>{}};this.append(s,e)})}prependBlocker(e){return new Promise(t=>{if(this.queues){const s={label:"async-blocker-prepend",execute:t,onStart:()=>{},onComplete:()=>{},onError:()=>{}};this.queues[e].unshift(s)}})}removeBlockers(){this.queues!==null&&[this.queues.video,this.queues.audio,this.queues.audiovideo].forEach(e=>{var t;const s=(t=e[0])==null?void 0:t.label;(s==="async-blocker"||s==="async-blocker-prepend")&&(e[0].execute(),e.splice(0,1))})}unblockAudio(e){if(this.queues===null)return;this.queues.audio[0]===e&&this.shiftAndExecuteNext("audio")}executeNext(e){if(this.queues===null||this.tracks===null)return;const t=this.queues[e];if(t.length){const i=t[0];try{i.execute()}catch(r){var s;if(i.onError(r),this.queues===null||this.tracks===null)return;const n=(s=this.tracks[e])==null?void 0:s.buffer;n!=null&&n.updating||this.shiftAndExecuteNext(e)}}}shiftAndExecuteNext(e){this.queues!==null&&(this.queues[e].shift(),this.executeNext(e))}current(e){var t;return((t=this.queues)==null?void 0:t[e][0])||null}toString(){const{queues:e,tracks:t}=this;return e===null||t===null?"":` + initSegmentChange: ${b}`);const P=new xc(s,i,t,o,h);this.configureTransmuxer(P)}if(this.frag=r,this.part=n,this.workerContext)this.workerContext.worker.postMessage({instanceNo:f,cmd:"demux",data:e,decryptdata:p,chunkMeta:l,state:I},e instanceof ArrayBuffer?[e]:[]);else if(g){const P=g.push(e,p,l,I);Nt(P)?P.then(F=>{this.handleTransmuxComplete(F)}).catch(F=>{this.transmuxerError(F,l,"transmuxer-interface push error")}):this.handleTransmuxComplete(P)}}flush(e){e.transmuxing.start=self.performance.now();const{instanceNo:t,transmuxer:s}=this;if(this.workerContext)this.workerContext.worker.postMessage({instanceNo:t,cmd:"flush",chunkMeta:e});else if(s){const i=s.flush(e);Nt(i)?i.then(r=>{this.handleFlushResult(r,e)}).catch(r=>{this.transmuxerError(r,e,"transmuxer-interface flush error")}):this.handleFlushResult(i,e)}}transmuxerError(e,t,s){this.hls&&(this.error=e,this.hls.trigger(m.ERROR,{type:V.MEDIA_ERROR,details:R.FRAG_PARSING_ERROR,chunkMeta:t,frag:this.frag||void 0,part:this.part||void 0,fatal:!1,error:e,err:e,reason:s}))}handleFlushResult(e,t){e.forEach(s=>{this.handleTransmuxComplete(s)}),this.onFlush(t)}configureTransmuxer(e){const{instanceNo:t,transmuxer:s}=this;this.workerContext?this.workerContext.worker.postMessage({instanceNo:t,cmd:"configure",config:e}):s&&s.configure(e)}handleTransmuxComplete(e){e.chunkMeta.transmuxing.end=self.performance.now(),this.onTransmuxComplete(e)}}const Mr=100;class Ic extends Ai{constructor(e,t,s){super(e,t,s,"audio-stream-controller",B.AUDIO),this.mainAnchor=null,this.mainFragLoading=null,this.audioOnly=!1,this.bufferedTrack=null,this.switchingTrack=null,this.trackId=-1,this.waitingData=null,this.mainDetails=null,this.flushing=!1,this.bufferFlushed=!1,this.cachedTrackLoadedData=null,this.registerListeners()}onHandlerDestroying(){this.unregisterListeners(),super.onHandlerDestroying(),this.resetItem()}resetItem(){this.mainDetails=this.mainAnchor=this.mainFragLoading=this.bufferedTrack=this.switchingTrack=this.waitingData=this.cachedTrackLoadedData=null}registerListeners(){super.registerListeners();const{hls:e}=this;e.on(m.LEVEL_LOADED,this.onLevelLoaded,this),e.on(m.AUDIO_TRACKS_UPDATED,this.onAudioTracksUpdated,this),e.on(m.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),e.on(m.AUDIO_TRACK_LOADED,this.onAudioTrackLoaded,this),e.on(m.BUFFER_RESET,this.onBufferReset,this),e.on(m.BUFFER_CREATED,this.onBufferCreated,this),e.on(m.BUFFER_FLUSHING,this.onBufferFlushing,this),e.on(m.BUFFER_FLUSHED,this.onBufferFlushed,this),e.on(m.INIT_PTS_FOUND,this.onInitPtsFound,this),e.on(m.FRAG_LOADING,this.onFragLoading,this),e.on(m.FRAG_BUFFERED,this.onFragBuffered,this)}unregisterListeners(){const{hls:e}=this;e&&(super.unregisterListeners(),e.off(m.LEVEL_LOADED,this.onLevelLoaded,this),e.off(m.AUDIO_TRACKS_UPDATED,this.onAudioTracksUpdated,this),e.off(m.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),e.off(m.AUDIO_TRACK_LOADED,this.onAudioTrackLoaded,this),e.off(m.BUFFER_RESET,this.onBufferReset,this),e.off(m.BUFFER_CREATED,this.onBufferCreated,this),e.off(m.BUFFER_FLUSHING,this.onBufferFlushing,this),e.off(m.BUFFER_FLUSHED,this.onBufferFlushed,this),e.off(m.INIT_PTS_FOUND,this.onInitPtsFound,this),e.off(m.FRAG_LOADING,this.onFragLoading,this),e.off(m.FRAG_BUFFERED,this.onFragBuffered,this))}onInitPtsFound(e,{frag:t,id:s,initPTS:i,timescale:r,trackId:n}){if(s===B.MAIN){const o=t.cc,c=this.fragCurrent;if(this.initPTS[o]={baseTime:i,timescale:r,trackId:n},this.log(`InitPTS for cc: ${o} found from main: ${i/r} (${i}/${r}) trackId: ${n}`),this.mainAnchor=t,this.state===C.WAITING_INIT_PTS){const l=this.waitingData;(!l&&!this.loadingParts||l&&l.frag.cc!==o)&&this.syncWithAnchor(t,l==null?void 0:l.frag)}else!this.hls.hasEnoughToStart&&c&&c.cc!==o?(c.abortRequests(),this.syncWithAnchor(t,c)):this.state===C.IDLE&&this.tick()}}getLoadPosition(){return!this.startFragRequested&&this.nextLoadPosition>=0?this.nextLoadPosition:super.getLoadPosition()}syncWithAnchor(e,t){var s;const i=((s=this.mainFragLoading)==null?void 0:s.frag)||null;if(t&&(i==null?void 0:i.cc)===t.cc)return;const r=(i||e).cc,n=this.getLevelDetails(),o=this.getLoadPosition(),c=In(n,r,o);c&&(this.log(`Syncing with main frag at ${c.start} cc ${c.cc}`),this.startFragRequested=!1,this.nextLoadPosition=c.start,this.resetLoadingState(),this.state===C.IDLE&&this.doTickIdle())}startLoad(e,t){if(!this.levels){this.startPosition=e,this.state=C.STOPPED;return}const s=this.lastCurrentTime;this.stopLoad(),this.setInterval(Mr),s>0&&e===-1?(this.log(`Override startPosition with lastCurrentTime @${s.toFixed(3)}`),e=s,this.state=C.IDLE):this.state=C.WAITING_TRACK,this.nextLoadPosition=this.lastCurrentTime=e+this.timelineOffset,this.startPosition=t?-1:e,this.tick()}doTick(){switch(this.state){case C.IDLE:this.doTickIdle();break;case C.WAITING_TRACK:{const{levels:e,trackId:t}=this,s=e==null?void 0:e[t],i=s==null?void 0:s.details;if(i&&!this.waitForLive(s)){if(this.waitForCdnTuneIn(i))break;this.state=C.WAITING_INIT_PTS}break}case C.FRAG_LOADING_WAITING_RETRY:{this.checkRetryDate();break}case C.WAITING_INIT_PTS:{const e=this.waitingData;if(e){const{frag:t,part:s,cache:i,complete:r}=e,n=this.mainAnchor;if(this.initPTS[t.cc]!==void 0){this.waitingData=null,this.state=C.FRAG_LOADING;const o=i.flush().buffer,c={frag:t,part:s,payload:o,networkDetails:null};this._handleFragmentLoadProgress(c),r&&super._handleFragmentLoadComplete(c)}else n&&n.cc!==e.frag.cc&&this.syncWithAnchor(n,e.frag)}else this.state=C.IDLE}}this.onTickEnd()}resetLoadingState(){const e=this.waitingData;e&&(this.fragmentTracker.removeFragment(e.frag),this.waitingData=null),super.resetLoadingState()}onTickEnd(){const{media:e}=this;e!=null&&e.readyState&&(this.lastCurrentTime=e.currentTime)}doTickIdle(){var e;const{hls:t,levels:s,media:i,trackId:r}=this,n=t.config;if(!this.buffering||!i&&!this.primaryPrefetch&&(this.startFragRequested||!n.startFragPrefetch)||!(s!=null&&s[r]))return;const o=s[r],c=o.details;if(!c||this.waitForLive(o)||this.waitForCdnTuneIn(c)){this.state=C.WAITING_TRACK,this.startFragRequested=!1;return}const l=this.mediaBuffer?this.mediaBuffer:this.media;this.bufferFlushed&&l&&(this.bufferFlushed=!1,this.afterBufferFlushed(l,re.AUDIO,B.AUDIO));const h=this.getFwdBufferInfo(l,B.AUDIO);if(h===null)return;if(!this.switchingTrack&&this._streamEnded(h,c)){t.trigger(m.BUFFER_EOS,{type:"audio"}),this.state=C.ENDED;return}const u=h.len,d=t.maxBufferLength,f=c.fragments,g=f[0].start,y=this.getLoadPosition(),p=this.flushing?y:h.end;if(this.switchingTrack&&i){const S=y;c.PTSKnown&&Sg||h.nextStart)&&(this.log("Alt audio track ahead of main track, seek to start of alt audio track"),i.currentTime=g+.05)}if(u>=d&&!this.switchingTrack&&pT.end){const v=this.fragmentTracker.getFragAtPos(p,B.MAIN);v&&v.end>T.end&&(T=v,this.mainFragLoading={frag:v,targetBufferTime:null})}if(E.start>T.end)return}this.loadFragment(E,o,p)}onMediaDetaching(e,t){this.bufferFlushed=this.flushing=!1,super.onMediaDetaching(e,t)}onAudioTracksUpdated(e,{audioTracks:t}){this.resetTransmuxer(),this.levels=t.map(s=>new Ot(s))}onAudioTrackSwitching(e,t){const s=!!t.url;this.trackId=t.id;const{fragCurrent:i}=this;i&&(i.abortRequests(),this.removeUnbufferedFrags(i.start)),this.resetLoadingState(),s?(this.switchingTrack=t,this.flushAudioIfNeeded(t),this.state!==C.STOPPED&&(this.setInterval(Mr),this.state=C.IDLE,this.tick())):(this.resetTransmuxer(),this.switchingTrack=null,this.bufferedTrack=t,this.clearInterval())}onManifestLoading(){super.onManifestLoading(),this.bufferFlushed=this.flushing=this.audioOnly=!1,this.resetItem(),this.trackId=-1}onLevelLoaded(e,t){this.mainDetails=t.details;const s=this.cachedTrackLoadedData;s&&(this.cachedTrackLoadedData=null,this.onAudioTrackLoaded(m.AUDIO_TRACK_LOADED,s))}onAudioTrackLoaded(e,t){var s;const{levels:i}=this,{details:r,id:n,groupId:o,track:c}=t;if(!i){this.warn(`Audio tracks reset while loading track ${n} "${c.name}" of "${o}"`);return}const l=this.mainDetails;if(!l||r.endCC>l.endCC||l.expired){this.cachedTrackLoadedData=t,this.state!==C.STOPPED&&(this.state=C.WAITING_TRACK);return}this.cachedTrackLoadedData=null,this.log(`Audio track ${n} "${c.name}" of "${o}" loaded [${r.startSN},${r.endSN}]${r.lastPartSn?`[part-${r.lastPartSn}-${r.lastPartIndex}]`:""},duration:${r.totalduration}`);const h=i[n];let u=0;if(r.live||(s=h.details)!=null&&s.live){if(this.checkLiveUpdate(r),r.deltaUpdateFailed)return;if(h.details){var d;u=this.alignPlaylists(r,h.details,(d=this.levelLastLoaded)==null?void 0:d.details)}r.alignedSliding||(Kn(r,l),r.alignedSliding||ps(r,l),u=r.fragmentStart)}h.details=r,this.levelLastLoaded=h,this.startFragRequested||this.setStartPosition(l,u),this.hls.trigger(m.AUDIO_TRACK_UPDATED,{details:r,id:n,groupId:t.groupId}),this.state===C.WAITING_TRACK&&!this.waitForCdnTuneIn(r)&&(this.state=C.IDLE),this.tick()}_handleFragmentLoadProgress(e){var t;const s=e.frag,{part:i,payload:r}=e,{config:n,trackId:o,levels:c}=this;if(!c){this.warn(`Audio tracks were reset while fragment load was in progress. Fragment ${s.sn} of level ${s.level} will not be buffered`);return}const l=c[o];if(!l){this.warn("Audio track is undefined on fragment load progress");return}const h=l.details;if(!h){this.warn("Audio track details undefined on fragment load progress"),this.removeUnbufferedFrags(s.start);return}const u=n.defaultAudioCodec||l.audioCodec||"mp4a.40.2";let d=this.transmuxer;d||(d=this.transmuxer=new la(this.hls,B.AUDIO,this._handleTransmuxComplete.bind(this),this._handleTransmuxerFlush.bind(this)));const f=this.initPTS[s.cc],g=(t=s.initSegment)==null?void 0:t.data;if(f!==void 0){const p=i?i.index:-1,E=p!==-1,T=new Si(s.level,s.sn,s.stats.chunkCount,r.byteLength,p,E);d.push(r,g,u,"",s,i,h.totalduration,!1,T,f)}else{this.log(`Unknown video PTS for cc ${s.cc}, waiting for video PTS before demuxing audio frag ${s.sn} of [${h.startSN} ,${h.endSN}],track ${o}`);const{cache:y}=this.waitingData=this.waitingData||{frag:s,part:i,cache:new Vn,complete:!1};y.push(new Uint8Array(r)),this.state!==C.STOPPED&&(this.state=C.WAITING_INIT_PTS)}}_handleFragmentLoadComplete(e){if(this.waitingData){this.waitingData.complete=!0;return}super._handleFragmentLoadComplete(e)}onBufferReset(){this.mediaBuffer=null}onBufferCreated(e,t){this.bufferFlushed=this.flushing=!1;const s=t.tracks.audio;s&&(this.mediaBuffer=s.buffer||null)}onFragLoading(e,t){!this.audioOnly&&t.frag.type===B.MAIN&&ce(t.frag)&&(this.mainFragLoading=t,this.state===C.IDLE&&this.tick())}onFragBuffered(e,t){const{frag:s,part:i}=t;if(s.type!==B.AUDIO){!this.audioOnly&&s.type===B.MAIN&&!s.elementaryStreams.video&&!s.elementaryStreams.audiovideo&&(this.audioOnly=!0,this.mainFragLoading=null);return}if(this.fragContextChanged(s)){this.warn(`Fragment ${s.sn}${i?" p: "+i.index:""} of level ${s.level} finished buffering, but was aborted. state: ${this.state}, audioSwitch: ${this.switchingTrack?this.switchingTrack.name:"false"}`);return}if(ce(s)){this.fragPrevious=s;const r=this.switchingTrack;r&&(this.bufferedTrack=r,this.switchingTrack=null,this.hls.trigger(m.AUDIO_TRACK_SWITCHED,te({},r)))}this.fragBufferedComplete(s,i),this.media&&this.tick()}onError(e,t){var s;if(t.fatal){this.state=C.ERROR;return}switch(t.details){case R.FRAG_GAP:case R.FRAG_PARSING_ERROR:case R.FRAG_DECRYPT_ERROR:case R.FRAG_LOAD_ERROR:case R.FRAG_LOAD_TIMEOUT:case R.KEY_LOAD_ERROR:case R.KEY_LOAD_TIMEOUT:this.onFragmentOrKeyLoadError(B.AUDIO,t);break;case R.AUDIO_TRACK_LOAD_ERROR:case R.AUDIO_TRACK_LOAD_TIMEOUT:case R.LEVEL_PARSING_ERROR:!t.levelRetry&&this.state===C.WAITING_TRACK&&((s=t.context)==null?void 0:s.type)===Q.AUDIO_TRACK&&(this.state=C.IDLE);break;case R.BUFFER_ADD_CODEC_ERROR:case R.BUFFER_APPEND_ERROR:if(t.parent!=="audio")return;this.reduceLengthAndFlushBuffer(t)||this.resetLoadingState();break;case R.BUFFER_FULL_ERROR:if(t.parent!=="audio")return;this.reduceLengthAndFlushBuffer(t)&&(this.bufferedTrack=null,super.flushMainBuffer(0,Number.POSITIVE_INFINITY,"audio"));break;case R.INTERNAL_EXCEPTION:this.recoverWorkerError(t);break}}onBufferFlushing(e,{type:t}){t!==re.VIDEO&&(this.flushing=!0)}onBufferFlushed(e,{type:t}){if(t!==re.VIDEO){this.flushing=!1,this.bufferFlushed=!0,this.state===C.ENDED&&(this.state=C.IDLE);const s=this.mediaBuffer||this.media;s&&(this.afterBufferFlushed(s,t,B.AUDIO),this.tick())}}_handleTransmuxComplete(e){var t;const s="audio",{hls:i}=this,{remuxResult:r,chunkMeta:n}=e,o=this.getCurrentContext(n);if(!o){this.resetWhenMissingContext(n);return}const{frag:c,part:l,level:h}=o,{details:u}=h,{audio:d,text:f,id3:g,initSegment:y}=r;if(this.fragContextChanged(c)||!u){this.fragmentTracker.removeFragment(c);return}if(this.state=C.PARSING,this.switchingTrack&&d&&this.completeAudioSwitch(this.switchingTrack),y!=null&&y.tracks){const p=c.initSegment||c;if(this.unhandledEncryptionError(y,c))return;this._bufferInitSegment(h,y.tracks,p,n),i.trigger(m.FRAG_PARSING_INIT_SEGMENT,{frag:p,id:s,tracks:y.tracks})}if(d){const{startPTS:p,endPTS:E,startDTS:T,endDTS:S}=d;l&&(l.elementaryStreams[re.AUDIO]={startPTS:p,endPTS:E,startDTS:T,endDTS:S}),c.setElementaryStreamInfo(re.AUDIO,p,E,T,S),this.bufferFragmentData(d,c,l,n)}if(g!=null&&(t=g.samples)!=null&&t.length){const p=ie({id:s,frag:c,details:u},g);i.trigger(m.FRAG_PARSING_METADATA,p)}if(f){const p=ie({id:s,frag:c,details:u},f);i.trigger(m.FRAG_PARSING_USERDATA,p)}}_bufferInitSegment(e,t,s,i){if(this.state!==C.PARSING||(t.video&&delete t.video,t.audiovideo&&delete t.audiovideo,!t.audio))return;const r=t.audio;r.id=B.AUDIO;const n=e.audioCodec;this.log(`Init audio buffer, container:${r.container}, codecs[level/parsed]=[${n}/${r.codec}]`),n&&n.split(",").length===1&&(r.levelCodec=n),this.hls.trigger(m.BUFFER_CODECS,t);const o=r.initSegment;if(o!=null&&o.byteLength){const c={type:"audio",frag:s,part:null,chunkMeta:i,parent:s.type,data:o};this.hls.trigger(m.BUFFER_APPENDING,c)}this.tickImmediate()}loadFragment(e,t,s){const i=this.fragmentTracker.getState(e);if(this.switchingTrack||i===ue.NOT_LOADED||i===ue.PARTIAL){var r;if(!ce(e))this._loadInitSegment(e,t);else if((r=t.details)!=null&&r.live&&!this.initPTS[e.cc]){this.log(`Waiting for video PTS in continuity counter ${e.cc} of live stream before loading audio fragment ${e.sn} of level ${this.trackId}`),this.state=C.WAITING_INIT_PTS;const n=this.mainDetails;n&&n.fragmentStart!==t.details.fragmentStart&&ps(t.details,n)}else super.loadFragment(e,t,s)}else this.clearTrackerIfNeeded(e)}flushAudioIfNeeded(e){if(this.media&&this.bufferedTrack){const{name:t,lang:s,assocLang:i,characteristics:r,audioCodec:n,channels:o}=this.bufferedTrack;ot({name:t,lang:s,assocLang:i,characteristics:r,audioCodec:n,channels:o},e,at)||(us(e.url,this.hls)?(this.log("Switching audio track : flushing all audio"),super.flushMainBuffer(0,Number.POSITIVE_INFINITY,"audio"),this.bufferedTrack=null):this.bufferedTrack=e)}}completeAudioSwitch(e){const{hls:t}=this;this.flushAudioIfNeeded(e),this.bufferedTrack=e,this.switchingTrack=null,t.trigger(m.AUDIO_TRACK_SWITCHED,te({},e))}}class Pi extends Ce{constructor(e,t){super(t,e.logger),this.hls=void 0,this.canLoad=!1,this.timer=-1,this.hls=e}destroy(){this.clearTimer(),this.hls=this.log=this.warn=null}clearTimer(){this.timer!==-1&&(self.clearTimeout(this.timer),this.timer=-1)}startLoad(){this.canLoad=!0,this.loadPlaylist()}stopLoad(){this.canLoad=!1,this.clearTimer()}switchParams(e,t,s){const i=t==null?void 0:t.renditionReports;if(i){let r=-1;for(let n=0;n=0&&h>t.partTarget&&(c+=1)}const l=s&&Qi(s);return new Zi(o,c>=0?c:void 0,l)}}}loadPlaylist(e){this.clearTimer()}loadingPlaylist(e,t){this.clearTimer()}shouldLoadPlaylist(e){return this.canLoad&&!!e&&!!e.url&&(!e.details||e.details.live)}getUrlWithDirectives(e,t){if(t)try{return t.addDirectives(e)}catch(s){this.warn(`Could not construct new URL with HLS Delivery Directives: ${s}`)}return e}playlistLoaded(e,t,s){const{details:i,stats:r}=t,n=self.performance.now(),o=r.loading.first?Math.max(0,n-r.loading.first):0;i.advancedDateTime=Date.now()-o;const c=this.hls.config.timelineOffset;if(c!==i.appliedTimelineOffset){const h=Math.max(c||0,0);i.appliedTimelineOffset=h,i.fragments.forEach(u=>{u.setStart(u.playlistOffset+h)})}if(i.live||s!=null&&s.live){const h="levelInfo"in t?t.levelInfo:t.track;if(i.reloaded(s),s&&i.fragments.length>0){pl(s,i,this);const T=i.playlistParsingError;if(T){this.warn(T);const S=this.hls;if(!S.config.ignorePlaylistParsingErrors){var l;const{networkDetails:v}=t;S.trigger(m.ERROR,{type:V.NETWORK_ERROR,details:R.LEVEL_PARSING_ERROR,fatal:!1,url:i.url,error:T,reason:T.message,level:t.level||void 0,parent:(l=i.fragments[0])==null?void 0:l.type,networkDetails:v,stats:r});return}i.playlistParsingError=null}}i.requestScheduled===-1&&(i.requestScheduled=r.loading.start);const u=this.hls.mainForwardBufferInfo,d=u?u.end-u.len:0,f=(i.edge-d)*1e3,g=Nn(i,f);if(i.requestScheduled+g0){if(b>i.targetduration*3)this.log(`Playlist last advanced ${_.toFixed(2)}s ago. Omitting segment and part directives.`),p=void 0,E=void 0;else if(s!=null&&s.tuneInGoal&&b-i.partTarget>s.tuneInGoal)this.warn(`CDN Tune-in goal increased from: ${s.tuneInGoal} to: ${I} with playlist age: ${i.age}`),I=0;else{const P=Math.floor(I/i.targetduration);if(p+=P,E!==void 0){const F=Math.round(I%i.targetduration/i.partTarget);E+=F}this.log(`CDN Tune-in age: ${i.ageHeader}s last advanced ${_.toFixed(2)}s goal: ${I} skip sn ${P} to part ${E}`)}i.tuneInGoal=I}if(y=this.getDeliveryDirectives(i,t.deliveryDirectives,p,E),T||!A){i.requestScheduled=n,this.loadingPlaylist(h,y);return}}else(i.canBlockReload||i.canSkipUntil)&&(y=this.getDeliveryDirectives(i,t.deliveryDirectives,p,E));y&&p!==void 0&&i.canBlockReload&&(i.requestScheduled=r.loading.first+Math.max(g-o*2,g/2)),this.scheduleLoading(h,y,i)}else this.clearTimer()}scheduleLoading(e,t,s){const i=s||e.details;if(!i){this.loadingPlaylist(e,t);return}const r=self.performance.now(),n=i.requestScheduled;if(r>=n){this.loadingPlaylist(e,t);return}const o=n-r;this.log(`reload live playlist ${e.name||e.bitrate+"bps"} in ${Math.round(o)} ms`),this.clearTimer(),this.timer=self.setTimeout(()=>this.loadingPlaylist(e,t),o)}getDeliveryDirectives(e,t,s,i){let r=Qi(e);return t!=null&&t.skip&&e.deltaUpdateFailed&&(s=t.msn,i=t.part,r=ts.No),new Zi(s,i,r)}checkRetry(e){const t=e.details,s=ds(e),i=e.errorAction,{action:r,retryCount:n=0,retryConfig:o}=i||{},c=!!i&&!!o&&(r===ge.RetryRequest||!i.resolved&&r===ge.SendAlternateToPenaltyBox);if(c){var l;if(n>=o.maxNumRetry)return!1;if(s&&(l=e.context)!=null&&l.deliveryDirectives)this.warn(`Retrying playlist loading ${n+1}/${o.maxNumRetry} after "${t}" without delivery-directives`),this.loadPlaylist();else{const h=Ei(o,n);this.clearTimer(),this.timer=self.setTimeout(()=>this.loadPlaylist(),h),this.warn(`Retrying playlist loading ${n+1}/${o.maxNumRetry} after "${t}" in ${h}ms`)}e.levelRetry=!0,i.resolved=!0}return c}}function ca(a,e){if(a.length!==e.length)return!1;for(let t=0;ta[i]!==e[i])}function ni(a,e){return e.label.toLowerCase()===a.name.toLowerCase()&&(!e.language||e.language.toLowerCase()===(a.lang||"").toLowerCase())}class Lc extends Pi{constructor(e){super(e,"audio-track-controller"),this.tracks=[],this.groupIds=null,this.tracksInGroup=[],this.trackId=-1,this.currentTrack=null,this.selectDefaultTrack=!0,this.registerListeners()}registerListeners(){const{hls:e}=this;e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.MANIFEST_PARSED,this.onManifestParsed,this),e.on(m.LEVEL_LOADING,this.onLevelLoading,this),e.on(m.LEVEL_SWITCHING,this.onLevelSwitching,this),e.on(m.AUDIO_TRACK_LOADED,this.onAudioTrackLoaded,this),e.on(m.ERROR,this.onError,this)}unregisterListeners(){const{hls:e}=this;e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.MANIFEST_PARSED,this.onManifestParsed,this),e.off(m.LEVEL_LOADING,this.onLevelLoading,this),e.off(m.LEVEL_SWITCHING,this.onLevelSwitching,this),e.off(m.AUDIO_TRACK_LOADED,this.onAudioTrackLoaded,this),e.off(m.ERROR,this.onError,this)}destroy(){this.unregisterListeners(),this.tracks.length=0,this.tracksInGroup.length=0,this.currentTrack=null,super.destroy()}onManifestLoading(){this.tracks=[],this.tracksInGroup=[],this.groupIds=null,this.currentTrack=null,this.trackId=-1,this.selectDefaultTrack=!0}onManifestParsed(e,t){this.tracks=t.audioTracks||[]}onAudioTrackLoaded(e,t){const{id:s,groupId:i,details:r}=t,n=this.tracksInGroup[s];if(!n||n.groupId!==i){this.warn(`Audio track with id:${s} and group:${i} not found in active group ${n==null?void 0:n.groupId}`);return}const o=n.details;n.details=t.details,this.log(`Audio track ${s} "${n.name}" lang:${n.lang} group:${i} loaded [${r.startSN}-${r.endSN}]`),s===this.trackId&&this.playlistLoaded(s,t,o)}onLevelLoading(e,t){this.switchLevel(t.level)}onLevelSwitching(e,t){this.switchLevel(t.level)}switchLevel(e){const t=this.hls.levels[e];if(!t)return;const s=t.audioGroups||null,i=this.groupIds;let r=this.currentTrack;if(!s||(i==null?void 0:i.length)!==(s==null?void 0:s.length)||s!=null&&s.some(o=>(i==null?void 0:i.indexOf(o))===-1)){this.groupIds=s,this.trackId=-1,this.currentTrack=null;const o=this.tracks.filter(d=>!s||s.indexOf(d.groupId)!==-1);if(o.length)this.selectDefaultTrack&&!o.some(d=>d.default)&&(this.selectDefaultTrack=!1),o.forEach((d,f)=>{d.id=f});else if(!r&&!this.tracksInGroup.length)return;this.tracksInGroup=o;const c=this.hls.config.audioPreference;if(!r&&c){const d=$e(c,o,at);if(d>-1)r=o[d];else{const f=$e(c,this.tracks);r=this.tracks[f]}}let l=this.findTrackId(r);l===-1&&r&&(l=this.findTrackId(null));const h={audioTracks:o};this.log(`Updating audio tracks, ${o.length} track(s) found in group(s): ${s==null?void 0:s.join(",")}`),this.hls.trigger(m.AUDIO_TRACKS_UPDATED,h);const u=this.trackId;if(l!==-1&&u===-1)this.setAudioTrack(l);else if(o.length&&u===-1){var n;const d=new Error(`No audio track selected for current audio group-ID(s): ${(n=this.groupIds)==null?void 0:n.join(",")} track count: ${o.length}`);this.warn(d.message),this.hls.trigger(m.ERROR,{type:V.MEDIA_ERROR,details:R.AUDIO_TRACK_LOAD_ERROR,fatal:!0,error:d})}}}onError(e,t){t.fatal||!t.context||t.context.type===Q.AUDIO_TRACK&&t.context.id===this.trackId&&(!this.groupIds||this.groupIds.indexOf(t.context.groupId)!==-1)&&this.checkRetry(t)}get allAudioTracks(){return this.tracks}get audioTracks(){return this.tracksInGroup}get audioTrack(){return this.trackId}set audioTrack(e){this.selectDefaultTrack=!1,this.setAudioTrack(e)}setAudioOption(e){const t=this.hls;if(t.config.audioPreference=e,e){const s=this.allAudioTracks;if(this.selectDefaultTrack=!1,s.length){const i=this.currentTrack;if(i&&ot(e,i,at))return i;const r=$e(e,this.tracksInGroup,at);if(r>-1){const n=this.tracksInGroup[r];return this.setAudioTrack(r),n}else if(i){let n=t.loadLevel;n===-1&&(n=t.firstAutoLevel);const o=No(e,t.levels,s,n,at);if(o===-1)return null;t.nextLoadLevel=o}if(e.channels||e.audioCodec){const n=$e(e,s);if(n>-1)return s[n]}}}return null}setAudioTrack(e){const t=this.tracksInGroup;if(e<0||e>=t.length){this.warn(`Invalid audio track id: ${e}`);return}this.selectDefaultTrack=!1;const s=this.currentTrack,i=t[e],r=i.details&&!i.details.live;if(e===this.trackId&&i===s&&r||(this.log(`Switching to audio-track ${e} "${i.name}" lang:${i.lang} group:${i.groupId} channels:${i.channels}`),this.trackId=e,this.currentTrack=i,this.hls.trigger(m.AUDIO_TRACK_SWITCHING,te({},i)),r))return;const n=this.switchParams(i.url,s==null?void 0:s.details,i.details);this.loadPlaylist(n)}findTrackId(e){const t=this.tracksInGroup;for(let s=0;s{const s={label:"async-blocker",execute:t,onStart:()=>{},onComplete:()=>{},onError:()=>{}};this.append(s,e)})}prependBlocker(e){return new Promise(t=>{if(this.queues){const s={label:"async-blocker-prepend",execute:t,onStart:()=>{},onComplete:()=>{},onError:()=>{}};this.queues[e].unshift(s)}})}removeBlockers(){this.queues!==null&&[this.queues.video,this.queues.audio,this.queues.audiovideo].forEach(e=>{var t;const s=(t=e[0])==null?void 0:t.label;(s==="async-blocker"||s==="async-blocker-prepend")&&(e[0].execute(),e.splice(0,1))})}unblockAudio(e){if(this.queues===null)return;this.queues.audio[0]===e&&this.shiftAndExecuteNext("audio")}executeNext(e){if(this.queues===null||this.tracks===null)return;const t=this.queues[e];if(t.length){const i=t[0];try{i.execute()}catch(r){var s;if(i.onError(r),this.queues===null||this.tracks===null)return;const n=(s=this.tracks[e])==null?void 0:s.buffer;n!=null&&n.updating||this.shiftAndExecuteNext(e)}}}shiftAndExecuteNext(e){this.queues!==null&&(this.queues[e].shift(),this.executeNext(e))}current(e){var t;return((t=this.queues)==null?void 0:t[e][0])||null}toString(){const{queues:e,tracks:t}=this;return e===null||t===null?"":` ${this.list("video")} ${this.list("audio")} -${this.list("audiovideo")}}`}list(e){var t,s;return(t=this.queues)!=null&&t[e]||(s=this.tracks)!=null&&s[e]?`${e}: (${this.listSbInfo(e)}) ${this.listOps(e)}`:""}listSbInfo(e){var t;const s=(t=this.tracks)==null?void 0:t[e],i=s==null?void 0:s.buffer;return i?`SourceBuffer${i.updating?" updating":""}${s.ended?" ended":""}${s.ending?" ending":""}`:"none"}listOps(e){var t;return((t=this.queues)==null?void 0:t[e].map(s=>s.label).join(", "))||""}}const zr=/(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\.[^.,]+)+/,Ra="HlsJsTrackRemovedError";class Yc extends Error{constructor(e){super(e),this.name=Ra}}class Wc extends Oe{constructor(e,t){super("buffer-controller",e.logger),this.hls=void 0,this.fragmentTracker=void 0,this.details=null,this._objectUrl=null,this.operationQueue=null,this.bufferCodecEventsTotal=0,this.media=null,this.mediaSource=null,this.lastMpegAudioChunk=null,this.blockedAudioAppend=null,this.lastVideoAppendEnd=0,this.appendSource=void 0,this.transferData=void 0,this.overrides=void 0,this.appendErrors={audio:0,video:0,audiovideo:0},this.tracks={},this.sourceBuffers=[[null,null],[null,null]],this._onEndStreaming=s=>{var i;this.hls&&((i=this.mediaSource)==null?void 0:i.readyState)==="open"&&this.hls.pauseBuffering()},this._onStartStreaming=s=>{this.hls&&this.hls.resumeBuffering()},this._onMediaSourceOpen=s=>{const{media:i,mediaSource:r}=this;s&&this.log("Media source opened"),!(!i||!r)&&(r.removeEventListener("sourceopen",this._onMediaSourceOpen),i.removeEventListener("emptied",this._onMediaEmptied),this.updateDuration(),this.hls.trigger(m.MEDIA_ATTACHED,{media:i,mediaSource:r}),this.mediaSource!==null&&this.checkPendingTracks())},this._onMediaSourceClose=()=>{this.log("Media source closed")},this._onMediaSourceEnded=()=>{this.log("Media source ended")},this._onMediaEmptied=()=>{const{mediaSrc:s,_objectUrl:i}=this;s!==i&&this.error(`Media element src was set while attaching MediaSource (${i} > ${s})`)},this.hls=e,this.fragmentTracker=t,this.appendSource=go(at(e.config.preferManagedMediaSource)),this.initTracks(),this.registerListeners()}hasSourceTypes(){return Object.keys(this.tracks).length>0}destroy(){this.unregisterListeners(),this.details=null,this.lastMpegAudioChunk=this.blockedAudioAppend=null,this.transferData=this.overrides=void 0,this.operationQueue&&(this.operationQueue.destroy(),this.operationQueue=null),this.hls=this.fragmentTracker=null,this._onMediaSourceOpen=this._onMediaSourceClose=null,this._onMediaSourceEnded=null,this._onStartStreaming=this._onEndStreaming=null}registerListeners(){const{hls:e}=this;e.on(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.MANIFEST_PARSED,this.onManifestParsed,this),e.on(m.BUFFER_RESET,this.onBufferReset,this),e.on(m.BUFFER_APPENDING,this.onBufferAppending,this),e.on(m.BUFFER_CODECS,this.onBufferCodecs,this),e.on(m.BUFFER_EOS,this.onBufferEos,this),e.on(m.BUFFER_FLUSHING,this.onBufferFlushing,this),e.on(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.on(m.FRAG_PARSED,this.onFragParsed,this),e.on(m.FRAG_CHANGED,this.onFragChanged,this),e.on(m.ERROR,this.onError,this)}unregisterListeners(){const{hls:e}=this;e.off(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.MANIFEST_PARSED,this.onManifestParsed,this),e.off(m.BUFFER_RESET,this.onBufferReset,this),e.off(m.BUFFER_APPENDING,this.onBufferAppending,this),e.off(m.BUFFER_CODECS,this.onBufferCodecs,this),e.off(m.BUFFER_EOS,this.onBufferEos,this),e.off(m.BUFFER_FLUSHING,this.onBufferFlushing,this),e.off(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.off(m.FRAG_PARSED,this.onFragParsed,this),e.off(m.FRAG_CHANGED,this.onFragChanged,this),e.off(m.ERROR,this.onError,this)}transferMedia(){const{media:e,mediaSource:t}=this;if(!e)return null;const s={};if(this.operationQueue){const r=this.isUpdating();r||this.operationQueue.removeBlockers();const n=this.isQueued();(r||n)&&this.warn(`Transfering MediaSource with${n?" operations in queue":""}${r?" updating SourceBuffer(s)":""} ${this.operationQueue}`),this.operationQueue.destroy()}const i=this.transferData;return!this.sourceBufferCount&&i&&i.mediaSource===t?ne(s,i.tracks):this.sourceBuffers.forEach(r=>{const[n]=r;n&&(s[n]=ne({},this.tracks[n]),this.removeBuffer(n)),r[0]=r[1]=null}),{media:e,mediaSource:t,tracks:s}}initTracks(){const e={};this.sourceBuffers=[[null,null],[null,null]],this.tracks=e,this.resetQueue(),this.resetAppendErrors(),this.lastMpegAudioChunk=this.blockedAudioAppend=null,this.lastVideoAppendEnd=0}onManifestLoading(){this.bufferCodecEventsTotal=0,this.details=null}onManifestParsed(e,t){var s;let i=2;(t.audio&&!t.video||!t.altAudio)&&(i=1),this.bufferCodecEventsTotal=i,this.log(`${i} bufferCodec event(s) expected.`),(s=this.transferData)!=null&&s.mediaSource&&this.sourceBufferCount&&i&&this.bufferCreated()}onMediaAttaching(e,t){const s=this.media=t.media;this.transferData=this.overrides=void 0;const i=at(this.appendSource);if(i){const r=!!t.mediaSource;(r||t.overrides)&&(this.transferData=t,this.overrides=t.overrides);const n=this.mediaSource=t.mediaSource||new i;if(this.assignMediaSource(n),r)this._objectUrl=s.src,this.attachTransferred();else{const o=this._objectUrl=self.URL.createObjectURL(n);if(this.appendSource)try{s.removeAttribute("src");const c=self.ManagedMediaSource;s.disableRemotePlayback=s.disableRemotePlayback||c&&n instanceof c,Qr(s),qc(s,o),s.load()}catch{s.src=o}else s.src=o}s.addEventListener("emptied",this._onMediaEmptied)}}assignMediaSource(e){var t,s;this.log(`${((t=this.transferData)==null?void 0:t.mediaSource)===e?"transferred":"created"} media source: ${(s=e.constructor)==null?void 0:s.name}`),e.addEventListener("sourceopen",this._onMediaSourceOpen),e.addEventListener("sourceended",this._onMediaSourceEnded),e.addEventListener("sourceclose",this._onMediaSourceClose),this.appendSource&&(e.addEventListener("startstreaming",this._onStartStreaming),e.addEventListener("endstreaming",this._onEndStreaming))}attachTransferred(){const e=this.media,t=this.transferData;if(!t||!e)return;const s=this.tracks,i=t.tracks,r=i?Object.keys(i):null,n=r?r.length:0,o=()=>{Promise.resolve().then(()=>{this.media&&this.mediaSourceOpenOrEnded&&this._onMediaSourceOpen()})};if(i&&r&&n){if(!this.tracksReady){this.hls.config.startFragPrefetch=!0,this.log("attachTransferred: waiting for SourceBuffer track info");return}if(this.log(`attachTransferred: (bufferCodecEventsTotal ${this.bufferCodecEventsTotal}) -required tracks: ${oe(s,(c,l)=>c==="initSegment"?void 0:l)}; -transfer tracks: ${oe(i,(c,l)=>c==="initSegment"?void 0:l)}}`),!xn(i,s)){t.mediaSource=null,t.tracks=void 0;const c=e.currentTime,l=this.details,h=Math.max(c,(l==null?void 0:l.fragments[0].start)||0);if(h-c>1){this.log(`attachTransferred: waiting for playback to reach new tracks start time ${c} -> ${h}`);return}this.warn(`attachTransferred: resetting MediaSource for incompatible tracks ("${Object.keys(i)}"->"${Object.keys(s)}") start time: ${h} currentTime: ${c}`),this.onMediaDetaching(m.MEDIA_DETACHING,{}),this.onMediaAttaching(m.MEDIA_ATTACHING,t),e.currentTime=h;return}this.transferData=void 0,r.forEach(c=>{const l=c,h=i[l];if(h){const d=h.buffer;if(d){const u=this.fragmentTracker,f=h.id;if(u.hasFragments(f)||u.hasParts(f)){const p=X.getBuffered(d);u.detectEvictedFragments(l,p,f,null,!0)}const g=Ws(l),y=[l,d];this.sourceBuffers[g]=y,d.updating&&this.operationQueue&&this.operationQueue.prependBlocker(l),this.trackSourceBuffer(l,h)}}}),o(),this.bufferCreated()}else this.log("attachTransferred: MediaSource w/o SourceBuffers"),o()}get mediaSourceOpenOrEnded(){var e;const t=(e=this.mediaSource)==null?void 0:e.readyState;return t==="open"||t==="ended"}onMediaDetaching(e,t){const s=!!t.transferMedia;this.transferData=this.overrides=void 0;const{media:i,mediaSource:r,_objectUrl:n}=this;if(r){if(this.log(`media source ${s?"transferring":"detaching"}`),s)this.sourceBuffers.forEach(([o])=>{o&&this.removeBuffer(o)}),this.resetQueue();else{if(this.mediaSourceOpenOrEnded){const o=r.readyState==="open";try{const c=r.sourceBuffers;for(let l=c.length;l--;)o&&c[l].abort(),r.removeSourceBuffer(c[l]);o&&r.endOfStream()}catch(c){this.warn(`onMediaDetaching: ${c.message} while calling endOfStream`)}}this.sourceBufferCount&&this.onBufferReset()}r.removeEventListener("sourceopen",this._onMediaSourceOpen),r.removeEventListener("sourceended",this._onMediaSourceEnded),r.removeEventListener("sourceclose",this._onMediaSourceClose),this.appendSource&&(r.removeEventListener("startstreaming",this._onStartStreaming),r.removeEventListener("endstreaming",this._onEndStreaming)),this.mediaSource=null,this._objectUrl=null}i&&(i.removeEventListener("emptied",this._onMediaEmptied),s||(n&&self.URL.revokeObjectURL(n),this.mediaSrc===n?(i.removeAttribute("src"),this.appendSource&&Qr(i),i.load()):this.warn("media|source.src was changed by a third party - skip cleanup")),this.media=null),this.hls.trigger(m.MEDIA_DETACHED,t)}onBufferReset(){this.sourceBuffers.forEach(([e])=>{e&&this.resetBuffer(e)}),this.initTracks()}resetBuffer(e){var t;const s=(t=this.tracks[e])==null?void 0:t.buffer;if(this.removeBuffer(e),s)try{var i;(i=this.mediaSource)!=null&&i.sourceBuffers.length&&this.mediaSource.removeSourceBuffer(s)}catch(r){this.warn(`onBufferReset ${e}`,r)}delete this.tracks[e]}removeBuffer(e){this.removeBufferListeners(e),this.sourceBuffers[Ws(e)]=[null,null];const t=this.tracks[e];t&&(t.buffer=void 0)}resetQueue(){this.operationQueue&&this.operationQueue.destroy(),this.operationQueue=new Hc(this.tracks)}onBufferCodecs(e,t){var s;const i=this.tracks,r=Object.keys(t);this.log(`BUFFER_CODECS: "${r}" (current SB count ${this.sourceBufferCount})`);const n="audiovideo"in t&&(i.audio||i.video)||i.audiovideo&&("audio"in t||"video"in t),o=!n&&this.sourceBufferCount&&this.media&&r.some(c=>!i[c]);if(n||o){this.warn(`Unsupported transition between "${Object.keys(i)}" and "${r}" SourceBuffers`);return}r.forEach(c=>{var l,h;const d=t[c],{id:u,codec:f,levelCodec:g,container:y,metadata:p,supplemental:E}=d;let T=i[c];const S=(l=this.transferData)==null||(l=l.tracks)==null?void 0:l[c],v=S!=null&&S.buffer?S:T,x=(v==null?void 0:v.pendingCodec)||(v==null?void 0:v.codec),D=v==null?void 0:v.levelCodec;T||(T=i[c]={buffer:void 0,listeners:[],codec:f,supplemental:E,container:y,levelCodec:g,metadata:p,id:u});const A=hs(x,D),_=A==null?void 0:A.replace(zr,"$1");let b=hs(f,g);const I=(h=b)==null?void 0:h.replace(zr,"$1");b&&A&&_!==I&&(c.slice(0,5)==="audio"&&(b=Ts(b,this.appendSource)),this.log(`switching codec ${x} to ${b}`),b!==(T.pendingCodec||T.codec)&&(T.pendingCodec=b),T.container=y,this.appendChangeType(c,y,b))}),(this.tracksReady||this.sourceBufferCount)&&(t.tracks=this.sourceBufferTracks),!this.sourceBufferCount&&(this.bufferCodecEventsTotal>1&&!this.tracks.video&&!t.video&&((s=t.audio)==null?void 0:s.id)==="main"&&(this.log("Main audio-only"),this.bufferCodecEventsTotal=1),this.mediaSourceOpenOrEnded&&this.checkPendingTracks())}get sourceBufferTracks(){return Object.keys(this.tracks).reduce((e,t)=>{const s=this.tracks[t];return e[t]={id:s.id,container:s.container,codec:s.codec,levelCodec:s.levelCodec},e},{})}appendChangeType(e,t,s){const i=`${t};codecs=${s}`,r={label:`change-type=${i}`,execute:()=>{const n=this.tracks[e];if(n){const o=n.buffer;o!=null&&o.changeType&&(this.log(`changing ${e} sourceBuffer type to ${i}`),o.changeType(i),n.codec=s,n.container=t)}this.shiftAndExecuteNext(e)},onStart:()=>{},onComplete:()=>{},onError:n=>{this.warn(`Failed to change ${e} SourceBuffer type`,n)}};this.append(r,e,this.isPending(this.tracks[e]))}blockAudio(e){var t;const s=e.start,i=s+e.duration*.05;if(((t=this.fragmentTracker.getAppendedFrag(s,U.MAIN))==null?void 0:t.gap)===!0)return;const n={label:"block-audio",execute:()=>{var o;const c=this.tracks.video;(this.lastVideoAppendEnd>i||c!=null&&c.buffer&&X.isBuffered(c.buffer,i)||((o=this.fragmentTracker.getAppendedFrag(i,U.MAIN))==null?void 0:o.gap)===!0)&&(this.blockedAudioAppend=null,this.shiftAndExecuteNext("audio"))},onStart:()=>{},onComplete:()=>{},onError:o=>{this.warn("Error executing block-audio operation",o)}};this.blockedAudioAppend={op:n,frag:e},this.append(n,"audio",!0)}unblockAudio(){const{blockedAudioAppend:e,operationQueue:t}=this;e&&t&&(this.blockedAudioAppend=null,t.unblockAudio(e.op))}onBufferAppending(e,t){const{tracks:s}=this,{data:i,type:r,parent:n,frag:o,part:c,chunkMeta:l,offset:h}=t,d=l.buffering[r],{sn:u,cc:f}=o,g=self.performance.now();d.start=g;const y=o.stats.buffering,p=c?c.stats.buffering:null;y.start===0&&(y.start=g),p&&p.start===0&&(p.start=g);const E=s.audio;let T=!1;r==="audio"&&(E==null?void 0:E.container)==="audio/mpeg"&&(T=!this.lastMpegAudioChunk||l.id===1||this.lastMpegAudioChunk.sn!==l.sn,this.lastMpegAudioChunk=l);const S=s.video,v=S==null?void 0:S.buffer;if(v&&u!=="initSegment"){const A=c||o,_=this.blockedAudioAppend;if(r==="audio"&&n!=="main"&&!this.blockedAudioAppend&&!(S.ending||S.ended)){const I=A.start+A.duration*.05,P=v.buffered,M=this.currentOp("video");!P.length&&!M?this.blockAudio(A):!M&&!X.isBuffered(v,I)&&this.lastVideoAppendEndI||b{var A;d.executeStart=self.performance.now();const _=(A=this.tracks[r])==null?void 0:A.buffer;_&&(T?this.updateTimestampOffset(_,x,.1,r,u,f):h!==void 0&&B(h)&&this.updateTimestampOffset(_,h,1e-6,r,u,f)),this.appendExecutor(i,r)},onStart:()=>{},onComplete:()=>{const A=self.performance.now();d.executeEnd=d.end=A,y.first===0&&(y.first=A),p&&p.first===0&&(p.first=A);const _={};this.sourceBuffers.forEach(([b,I])=>{b&&(_[b]=X.getBuffered(I))}),this.appendErrors[r]=0,r==="audio"||r==="video"?this.appendErrors.audiovideo=0:(this.appendErrors.audio=0,this.appendErrors.video=0),this.hls.trigger(m.BUFFER_APPENDED,{type:r,frag:o,part:c,chunkMeta:l,parent:o.type,timeRanges:_})},onError:A=>{var _;const b={type:Y.MEDIA_ERROR,parent:o.type,details:R.BUFFER_APPEND_ERROR,sourceBufferName:r,frag:o,part:c,chunkMeta:l,error:A,err:A,fatal:!1},I=(_=this.media)==null?void 0:_.error;if(A.code===DOMException.QUOTA_EXCEEDED_ERR||A.name=="QuotaExceededError"||"quota"in A)b.details=R.BUFFER_FULL_ERROR;else if(A.code===DOMException.INVALID_STATE_ERR&&this.mediaSourceOpenOrEnded&&!I)b.errorAction=bt(!0);else if(A.name===Ra&&this.sourceBufferCount===0)b.errorAction=bt(!0);else{const P=++this.appendErrors[r];this.warn(`Failed ${P}/${this.hls.config.appendErrorMaxRetry} times to append segment in "${r}" sourceBuffer (${I||"no media error"})`),(P>=this.hls.config.appendErrorMaxRetry||I)&&(b.fatal=!0)}this.hls.trigger(m.ERROR,b)}};this.log(`queuing "${r}" append sn: ${u}${c?" p: "+c.index:""} of ${o.type===U.MAIN?"level":"track"} ${o.level} cc: ${f}`),this.append(D,r,this.isPending(this.tracks[r]))}getFlushOp(e,t,s){return this.log(`queuing "${e}" remove ${t}-${s}`),{label:"remove",execute:()=>{this.removeExecutor(e,t,s)},onStart:()=>{},onComplete:()=>{this.hls.trigger(m.BUFFER_FLUSHED,{type:e})},onError:i=>{this.warn(`Failed to remove ${t}-${s} from "${e}" SourceBuffer`,i)}}}onBufferFlushing(e,t){const{type:s,startOffset:i,endOffset:r}=t;s?this.append(this.getFlushOp(s,i,r),s):this.sourceBuffers.forEach(([n])=>{n&&this.append(this.getFlushOp(n,i,r),n)})}onFragParsed(e,t){const{frag:s,part:i}=t,r=[],n=i?i.elementaryStreams:s.elementaryStreams;n[ae.AUDIOVIDEO]?r.push("audiovideo"):(n[ae.AUDIO]&&r.push("audio"),n[ae.VIDEO]&&r.push("video"));const o=()=>{const c=self.performance.now();s.stats.buffering.end=c,i&&(i.stats.buffering.end=c);const l=i?i.stats:s.stats;this.hls.trigger(m.FRAG_BUFFERED,{frag:s,part:i,stats:l,id:s.type})};r.length===0&&this.warn(`Fragments must have at least one ElementaryStreamType set. type: ${s.type} level: ${s.level} sn: ${s.sn}`),this.blockBuffers(o,r).catch(c=>{this.warn(`Fragment buffered callback ${c}`),this.stepOperationQueue(this.sourceBufferTypes)})}onFragChanged(e,t){this.trimBuffers()}get bufferedToEnd(){return this.sourceBufferCount>0&&!this.sourceBuffers.some(([e])=>{if(e){const t=this.tracks[e];if(t)return!t.ended||t.ending}return!1})}onBufferEos(e,t){var s;this.sourceBuffers.forEach(([n])=>{if(n){const o=this.tracks[n];(!t.type||t.type===n)&&(o.ending=!0,o.ended||(o.ended=!0,this.log(`${n} buffer reached EOS`)))}});const i=((s=this.overrides)==null?void 0:s.endOfStream)!==!1;this.sourceBufferCount>0&&!this.sourceBuffers.some(([n])=>{var o;return n&&!((o=this.tracks[n])!=null&&o.ended)})?i?(this.log("Queueing EOS"),this.blockUntilOpen(()=>{this.tracksEnded();const{mediaSource:n}=this;if(!n||n.readyState!=="open"){n&&this.log(`Could not call mediaSource.endOfStream(). mediaSource.readyState: ${n.readyState}`);return}this.log("Calling mediaSource.endOfStream()"),n.endOfStream(),this.hls.trigger(m.BUFFERED_TO_END,void 0)})):(this.tracksEnded(),this.hls.trigger(m.BUFFERED_TO_END,void 0)):t.type==="video"&&this.unblockAudio()}tracksEnded(){this.sourceBuffers.forEach(([e])=>{if(e!==null){const t=this.tracks[e];t&&(t.ending=!1)}})}onLevelUpdated(e,{details:t}){t.fragments.length&&(this.details=t,this.updateDuration())}updateDuration(){this.blockUntilOpen(()=>{const e=this.getDurationAndRange();e&&this.updateMediaSource(e)})}onError(e,t){if(t.details===R.BUFFER_APPEND_ERROR&&t.frag){var s;const i=(s=t.errorAction)==null?void 0:s.nextAutoLevel;B(i)&&i!==t.frag.level&&this.resetAppendErrors()}}resetAppendErrors(){this.appendErrors={audio:0,video:0,audiovideo:0}}trimBuffers(){const{hls:e,details:t,media:s}=this;if(!s||t===null||!this.sourceBufferCount)return;const i=e.config,r=s.currentTime,n=t.levelTargetDuration,o=t.live&&i.liveBackBufferLength!==null?i.liveBackBufferLength:i.backBufferLength;if(B(o)&&o>=0){const l=Math.max(o,n),h=Math.floor(r/n)*n-l;this.flushBackBuffer(r,n,h)}const c=i.frontBufferFlushThreshold;if(B(c)&&c>0){const l=Math.max(i.maxBufferLength,c),h=Math.max(l,n),d=Math.floor(r/n)*n+h;this.flushFrontBuffer(r,n,d)}}flushBackBuffer(e,t,s){this.sourceBuffers.forEach(([i,r])=>{if(r){const o=X.getBuffered(r);if(o.length>0&&s>o.start(0)){var n;this.hls.trigger(m.BACK_BUFFER_REACHED,{bufferEnd:s});const c=this.tracks[i];if((n=this.details)!=null&&n.live)this.hls.trigger(m.LIVE_BACK_BUFFER_REACHED,{bufferEnd:s});else if(c!=null&&c.ended){this.log(`Cannot flush ${i} back buffer while SourceBuffer is in ended state`);return}this.hls.trigger(m.BUFFER_FLUSHING,{startOffset:0,endOffset:s,type:i})}}})}flushFrontBuffer(e,t,s){this.sourceBuffers.forEach(([i,r])=>{if(r){const n=X.getBuffered(r),o=n.length;if(o<2)return;const c=n.start(o-1),l=n.end(o-1);if(s>c||e>=c&&e<=l)return;this.hls.trigger(m.BUFFER_FLUSHING,{startOffset:c,endOffset:1/0,type:i})}})}getDurationAndRange(){var e;const{details:t,mediaSource:s}=this;if(!t||!this.media||(s==null?void 0:s.readyState)!=="open")return null;const i=t.edge;if(t.live&&this.hls.config.liveDurationInfinity){if(t.fragments.length&&s.setLiveSeekableRange){const l=Math.max(0,t.fragmentStart),h=Math.max(l,i);return{duration:1/0,start:l,end:h}}return{duration:1/0}}const r=(e=this.overrides)==null?void 0:e.duration;if(r)return B(r)?{duration:r}:null;const n=this.media.duration,o=B(s.duration)?s.duration:0;return i>o&&i>n||!B(n)?{duration:i}:null}updateMediaSource({duration:e,start:t,end:s}){const i=this.mediaSource;!this.media||!i||i.readyState!=="open"||(i.duration!==e&&(B(e)&&this.log(`Updating MediaSource duration to ${e.toFixed(3)}`),i.duration=e),t!==void 0&&s!==void 0&&(this.log(`MediaSource duration is set to ${i.duration}. Setting seekable range to ${t}-${s}.`),i.setLiveSeekableRange(t,s)))}get tracksReady(){const e=this.pendingTrackCount;return e>0&&(e>=this.bufferCodecEventsTotal||this.isPending(this.tracks.audiovideo))}checkPendingTracks(){const{bufferCodecEventsTotal:e,pendingTrackCount:t,tracks:s}=this;if(this.log(`checkPendingTracks (pending: ${t} codec events expected: ${e}) ${oe(s)}`),this.tracksReady){var i;const r=(i=this.transferData)==null?void 0:i.tracks;r&&Object.keys(r).length?this.attachTransferred():this.createSourceBuffers()}}bufferCreated(){if(this.sourceBufferCount){const e={};this.sourceBuffers.forEach(([t,s])=>{if(t){const i=this.tracks[t];e[t]={buffer:s,container:i.container,codec:i.codec,supplemental:i.supplemental,levelCodec:i.levelCodec,id:i.id,metadata:i.metadata}}}),this.hls.trigger(m.BUFFER_CREATED,{tracks:e}),this.log(`SourceBuffers created. Running queue: ${this.operationQueue}`),this.sourceBuffers.forEach(([t])=>{this.executeNext(t)})}else{const e=new Error("could not create source buffer for media codec(s)");this.hls.trigger(m.ERROR,{type:Y.MEDIA_ERROR,details:R.BUFFER_INCOMPATIBLE_CODECS_ERROR,fatal:!0,error:e,reason:e.message})}}createSourceBuffers(){const{tracks:e,sourceBuffers:t,mediaSource:s}=this;if(!s)throw new Error("createSourceBuffers called when mediaSource was null");for(const r in e){const n=r,o=e[n];if(this.isPending(o)){const c=this.getTrackCodec(o,n),l=`${o.container};codecs=${c}`;o.codec=c,this.log(`creating sourceBuffer(${l})${this.currentOp(n)?" Queued":""} ${oe(o)}`);try{const h=s.addSourceBuffer(l),d=Ws(n),u=[n,h];t[d]=u,o.buffer=h}catch(h){var i;this.error(`error while trying to add sourceBuffer: ${h.message}`),this.shiftAndExecuteNext(n),(i=this.operationQueue)==null||i.removeBlockers(),delete this.tracks[n],this.hls.trigger(m.ERROR,{type:Y.MEDIA_ERROR,details:R.BUFFER_ADD_CODEC_ERROR,fatal:!1,error:h,sourceBufferName:n,mimeType:l,parent:o.id});return}this.trackSourceBuffer(n,o)}}this.bufferCreated()}getTrackCodec(e,t){const s=e.supplemental;let i=e.codec;s&&(t==="video"||t==="audiovideo")&&Ut(s,"video")&&(i=Mo(i,s));const r=hs(i,e.levelCodec);return r?t.slice(0,5)==="audio"?Ts(r,this.appendSource):r:""}trackSourceBuffer(e,t){const s=t.buffer;if(!s)return;const i=this.getTrackCodec(t,e);this.tracks[e]={buffer:s,codec:i,container:t.container,levelCodec:t.levelCodec,supplemental:t.supplemental,metadata:t.metadata,id:t.id,listeners:[]},this.removeBufferListeners(e),this.addBufferListener(e,"updatestart",this.onSBUpdateStart),this.addBufferListener(e,"updateend",this.onSBUpdateEnd),this.addBufferListener(e,"error",this.onSBUpdateError),this.appendSource&&this.addBufferListener(e,"bufferedchange",(r,n)=>{const o=n.removedRanges;o!=null&&o.length&&this.hls.trigger(m.BUFFER_FLUSHED,{type:r})})}get mediaSrc(){var e,t;const s=((e=this.media)==null||(t=e.querySelector)==null?void 0:t.call(e,"source"))||this.media;return s==null?void 0:s.src}onSBUpdateStart(e){const t=this.currentOp(e);t&&t.onStart()}onSBUpdateEnd(e){var t;if(((t=this.mediaSource)==null?void 0:t.readyState)==="closed"){this.resetBuffer(e);return}const s=this.currentOp(e);s&&(s.onComplete(),this.shiftAndExecuteNext(e))}onSBUpdateError(e,t){var s;const i=new Error(`${e} SourceBuffer error. MediaSource readyState: ${(s=this.mediaSource)==null?void 0:s.readyState}`);this.error(`${i}`,t),this.hls.trigger(m.ERROR,{type:Y.MEDIA_ERROR,details:R.BUFFER_APPENDING_ERROR,sourceBufferName:e,error:i,fatal:!1});const r=this.currentOp(e);r&&r.onError(i)}updateTimestampOffset(e,t,s,i,r,n){const o=t-e.timestampOffset;Math.abs(o)>=s&&(this.log(`Updating ${i} SourceBuffer timestampOffset to ${t} (sn: ${r} cc: ${n})`),e.timestampOffset=t)}removeExecutor(e,t,s){const{media:i,mediaSource:r}=this,n=this.tracks[e],o=n==null?void 0:n.buffer;if(!i||!r||!o){this.warn(`Attempting to remove from the ${e} SourceBuffer, but it does not exist`),this.shiftAndExecuteNext(e);return}const c=B(i.duration)?i.duration:1/0,l=B(r.duration)?r.duration:1/0,h=Math.max(0,t),d=Math.min(s,c,l);d>h&&(!n.ending||n.ended)?(n.ended=!1,this.log(`Removing [${h},${d}] from the ${e} SourceBuffer`),o.remove(h,d)):this.shiftAndExecuteNext(e)}appendExecutor(e,t){const s=this.tracks[t],i=s==null?void 0:s.buffer;if(!i)throw new Yc(`Attempting to append to the ${t} SourceBuffer, but it does not exist`);s.ending=!1,s.ended=!1,i.appendBuffer(e)}blockUntilOpen(e){if(this.isUpdating()||this.isQueued())this.blockBuffers(e).catch(t=>{this.warn(`SourceBuffer blocked callback ${t}`),this.stepOperationQueue(this.sourceBufferTypes)});else try{e()}catch(t){this.warn(`Callback run without blocking ${this.operationQueue} ${t}`)}}isUpdating(){return this.sourceBuffers.some(([e,t])=>e&&t.updating)}isQueued(){return this.sourceBuffers.some(([e])=>e&&!!this.currentOp(e))}isPending(e){return!!e&&!e.buffer}blockBuffers(e,t=this.sourceBufferTypes){if(!t.length)return this.log("Blocking operation requested, but no SourceBuffers exist"),Promise.resolve().then(e);const{operationQueue:s}=this,i=t.map(n=>this.appendBlocker(n));return t.length>1&&!!this.blockedAudioAppend&&this.unblockAudio(),Promise.all(i).then(n=>{s===this.operationQueue&&(e(),this.stepOperationQueue(this.sourceBufferTypes))})}stepOperationQueue(e){e.forEach(t=>{var s;const i=(s=this.tracks[t])==null?void 0:s.buffer;!i||i.updating||this.shiftAndExecuteNext(t)})}append(e,t,s){this.operationQueue&&this.operationQueue.append(e,t,s)}appendBlocker(e){if(this.operationQueue)return this.operationQueue.appendBlocker(e)}currentOp(e){return this.operationQueue?this.operationQueue.current(e):null}executeNext(e){e&&this.operationQueue&&this.operationQueue.executeNext(e)}shiftAndExecuteNext(e){this.operationQueue&&this.operationQueue.shiftAndExecuteNext(e)}get pendingTrackCount(){return Object.keys(this.tracks).reduce((e,t)=>e+(this.isPending(this.tracks[t])?1:0),0)}get sourceBufferCount(){return this.sourceBuffers.reduce((e,[t])=>e+(t?1:0),0)}get sourceBufferTypes(){return this.sourceBuffers.map(([e])=>e).filter(e=>!!e)}addBufferListener(e,t,s){const i=this.tracks[e];if(!i)return;const r=i.buffer;if(!r)return;const n=s.bind(this,e);i.listeners.push({event:t,listener:n}),r.addEventListener(t,n)}removeBufferListeners(e){const t=this.tracks[e];if(!t)return;const s=t.buffer;s&&(t.listeners.forEach(i=>{s.removeEventListener(i.event,i.listener)}),t.listeners.length=0)}}function Qr(a){const e=a.querySelectorAll("source");[].slice.call(e).forEach(t=>{a.removeChild(t)})}function qc(a,e){const t=self.document.createElement("source");t.type="video/mp4",t.src=e,a.appendChild(t)}function Ws(a){return a==="audio"?1:0}class Hi{constructor(e){this.hls=void 0,this.autoLevelCapping=void 0,this.firstLevel=void 0,this.media=void 0,this.restrictedLevels=void 0,this.timer=void 0,this.clientRect=void 0,this.streamController=void 0,this.hls=e,this.autoLevelCapping=Number.POSITIVE_INFINITY,this.firstLevel=-1,this.media=null,this.restrictedLevels=[],this.timer=void 0,this.clientRect=null,this.registerListeners()}setStreamController(e){this.streamController=e}destroy(){this.hls&&this.unregisterListener(),this.timer&&this.stopCapping(),this.media=null,this.clientRect=null,this.hls=this.streamController=null}registerListeners(){const{hls:e}=this;e.on(m.FPS_DROP_LEVEL_CAPPING,this.onFpsDropLevelCapping,this),e.on(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(m.MANIFEST_PARSED,this.onManifestParsed,this),e.on(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.on(m.BUFFER_CODECS,this.onBufferCodecs,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this)}unregisterListener(){const{hls:e}=this;e.off(m.FPS_DROP_LEVEL_CAPPING,this.onFpsDropLevelCapping,this),e.off(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(m.MANIFEST_PARSED,this.onManifestParsed,this),e.off(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.off(m.BUFFER_CODECS,this.onBufferCodecs,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this)}onFpsDropLevelCapping(e,t){const s=this.hls.levels[t.droppedLevel];this.isLevelAllowed(s)&&this.restrictedLevels.push({bitrate:s.bitrate,height:s.height,width:s.width})}onMediaAttaching(e,t){this.media=t.media instanceof HTMLVideoElement?t.media:null,this.clientRect=null,this.timer&&this.hls.levels.length&&this.detectPlayerSize()}onManifestParsed(e,t){const s=this.hls;this.restrictedLevels=[],this.firstLevel=t.firstLevel,s.config.capLevelToPlayerSize&&t.video&&this.startCapping()}onLevelsUpdated(e,t){this.timer&&B(this.autoLevelCapping)&&this.detectPlayerSize()}onBufferCodecs(e,t){this.hls.config.capLevelToPlayerSize&&t.video&&this.startCapping()}onMediaDetaching(){this.stopCapping(),this.media=null}detectPlayerSize(){if(this.media){if(this.mediaHeight<=0||this.mediaWidth<=0){this.clientRect=null;return}const e=this.hls.levels;if(e.length){const t=this.hls,s=this.getMaxLevel(e.length-1);s!==this.autoLevelCapping&&t.logger.log(`Setting autoLevelCapping to ${s}: ${e[s].height}p@${e[s].bitrate} for media ${this.mediaWidth}x${this.mediaHeight}`),t.autoLevelCapping=s,t.autoLevelEnabled&&t.autoLevelCapping>this.autoLevelCapping&&this.streamController&&this.streamController.nextLevelSwitch(),this.autoLevelCapping=t.autoLevelCapping}}}getMaxLevel(e){const t=this.hls.levels;if(!t.length)return-1;const s=t.filter((i,r)=>this.isLevelAllowed(i)&&r<=e);return this.clientRect=null,Hi.getMaxLevelByMediaSize(s,this.mediaWidth,this.mediaHeight)}startCapping(){this.timer||(this.autoLevelCapping=Number.POSITIVE_INFINITY,self.clearInterval(this.timer),this.timer=self.setInterval(this.detectPlayerSize.bind(this),1e3),this.detectPlayerSize())}stopCapping(){this.restrictedLevels=[],this.firstLevel=-1,this.autoLevelCapping=Number.POSITIVE_INFINITY,this.timer&&(self.clearInterval(this.timer),this.timer=void 0)}getDimensions(){if(this.clientRect)return this.clientRect;const e=this.media,t={width:0,height:0};if(e){const s=e.getBoundingClientRect();t.width=s.width,t.height=s.height,!t.width&&!t.height&&(t.width=s.right-s.left||e.width||0,t.height=s.bottom-s.top||e.height||0)}return this.clientRect=t,t}get mediaWidth(){return this.getDimensions().width*this.contentScaleFactor}get mediaHeight(){return this.getDimensions().height*this.contentScaleFactor}get contentScaleFactor(){let e=1;if(!this.hls.config.ignoreDevicePixelRatio)try{e=self.devicePixelRatio}catch{}return Math.min(e,this.hls.config.maxDevicePixelRatio)}isLevelAllowed(e){return!this.restrictedLevels.some(s=>e.bitrate===s.bitrate&&e.width===s.width&&e.height===s.height)}static getMaxLevelByMediaSize(e,t,s){if(!(e!=null&&e.length))return-1;const i=(o,c)=>c?o.width!==c.width||o.height!==c.height:!0;let r=e.length-1;const n=Math.max(t,s);for(let o=0;o=n||c.height>=n)&&i(c,e[o+1])){r=o;break}}return r}}const jc={MANIFEST:"m",AUDIO:"a",VIDEO:"v",MUXED:"av",INIT:"i",CAPTION:"c",TIMED_TEXT:"tt",KEY:"k",OTHER:"o"},Ae=jc,Xc={HLS:"h"},zc=Xc;class je{constructor(e,t){Array.isArray(e)&&(e=e.map(s=>s instanceof je?s:new je(s))),this.value=e,this.params=t}}const Qc="Dict";function Zc(a){return Array.isArray(a)?JSON.stringify(a):a instanceof Map?"Map{}":a instanceof Set?"Set{}":typeof a=="object"?JSON.stringify(a):String(a)}function Jc(a,e,t,s){return new Error(`failed to ${a} "${Zc(e)}" as ${t}`,{cause:s})}function Xe(a,e,t){return Jc("serialize",a,e,t)}class ba{constructor(e){this.description=e}}const Zr="Bare Item",eh="Boolean";function th(a){if(typeof a!="boolean")throw Xe(a,eh);return a?"?1":"?0"}function sh(a){return btoa(String.fromCharCode(...a))}const ih="Byte Sequence";function rh(a){if(ArrayBuffer.isView(a)===!1)throw Xe(a,ih);return`:${sh(a)}:`}const nh="Integer";function ah(a){return a<-999999999999999||99999999999999912)throw Xe(a,lh);const t=e.toString();return t.includes(".")?t:`${t}.0`}const hh="String",dh=/[\x00-\x1f\x7f]+/;function uh(a){if(dh.test(a))throw Xe(a,hh);return`"${a.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}function fh(a){return a.description||a.toString().slice(7,-1)}const gh="Token";function Jr(a){const e=fh(a);if(/^([a-zA-Z*])([!#$%&'*+\-.^_`|~\w:/]*)$/.test(e)===!1)throw Xe(e,gh);return e}function pi(a){switch(typeof a){case"number":if(!B(a))throw Xe(a,Zr);return Number.isInteger(a)?_a(a):ch(a);case"string":return uh(a);case"symbol":return Jr(a);case"boolean":return th(a);case"object":if(a instanceof Date)return oh(a);if(a instanceof Uint8Array)return rh(a);if(a instanceof ba)return Jr(a);default:throw Xe(a,Zr)}}const mh="Key";function yi(a){if(/^[a-z*][a-z0-9\-_.*]*$/.test(a)===!1)throw Xe(a,mh);return a}function Yi(a){return a==null?"":Object.entries(a).map(([e,t])=>t===!0?`;${yi(e)}`:`;${yi(e)}=${pi(t)}`).join("")}function Ca(a){return a instanceof je?`${pi(a.value)}${Yi(a.params)}`:pi(a)}function ph(a){return`(${a.value.map(Ca).join(" ")})${Yi(a.params)}`}function yh(a,e={whitespace:!0}){if(typeof a!="object"||a==null)throw Xe(a,Qc);const t=a instanceof Map?a.entries():Object.entries(a),s=e!=null&&e.whitespace?" ":"";return Array.from(t).map(([i,r])=>{r instanceof je||(r=new je(r));let n=yi(i);return r.value===!0?n+=Yi(r.params):(n+="=",Array.isArray(r.value)?n+=ph(r):n+=Ca(r)),n}).join(`,${s}`)}function Pa(a,e){return yh(a,e)}const Ge="CMCD-Object",he="CMCD-Request",dt="CMCD-Session",st="CMCD-Status",Eh={br:Ge,ab:Ge,d:Ge,ot:Ge,tb:Ge,tpb:Ge,lb:Ge,tab:Ge,lab:Ge,url:Ge,pb:he,bl:he,tbl:he,dl:he,ltc:he,mtp:he,nor:he,nrr:he,rc:he,sn:he,sta:he,su:he,ttfb:he,ttfbb:he,ttlb:he,cmsdd:he,cmsds:he,smrt:he,df:he,cs:he,ts:he,cid:dt,pr:dt,sf:dt,sid:dt,st:dt,v:dt,msd:dt,bs:st,bsd:st,cdn:st,rtp:st,bg:st,pt:st,ec:st,e:st},Th={REQUEST:he};function Sh(a){return Object.keys(a).reduce((e,t)=>{var s;return(s=a[t])===null||s===void 0||s.forEach(i=>e[i]=t),e},{})}function vh(a,e){const t={};if(!a)return t;const s=Object.keys(a),i=e?Sh(e):{};return s.reduce((r,n)=>{var o;const c=Eh[n]||i[n]||Th.REQUEST,l=(o=r[c])!==null&&o!==void 0?o:r[c]={};return l[n]=a[n],r},t)}function xh(a){return["ot","sf","st","e","sta"].includes(a)}function Ah(a){return typeof a=="number"?B(a):a!=null&&a!==""&&a!==!1}const ka="event";function Ih(a,e){const t=new URL(a),s=new URL(e);if(t.origin!==s.origin)return a;const i=t.pathname.split("/").slice(1),r=s.pathname.split("/").slice(1,-1);for(;i[0]===r[0];)i.shift(),r.shift();for(;r.length;)r.shift(),i.unshift("..");return i.join("/")+t.search+t.hash}const ms=a=>Math.round(a),Ei=(a,e)=>Array.isArray(a)?a.map(t=>Ei(t,e)):a instanceof je&&typeof a.value=="string"?new je(Ei(a.value,e),a.params):(e.baseUrl&&(a=Ih(a,e.baseUrl)),e.version===1?encodeURIComponent(a):a),is=a=>ms(a/100)*100,Lh=(a,e)=>{let t=a;return e.version>=2&&(a instanceof je&&typeof a.value=="string"?t=new je([a]):typeof a=="string"&&(t=[a])),Ei(t,e)},Rh={br:ms,d:ms,bl:is,dl:is,mtp:is,nor:Lh,rtp:is,tb:ms},wa="request",Oa="response",Wi=["ab","bg","bl","br","bs","bsd","cdn","cid","cs","df","ec","lab","lb","ltc","msd","mtp","pb","pr","pt","sf","sid","sn","st","sta","tab","tb","tbl","tpb","ts","v"],bh=["e"],_h=/^[a-zA-Z0-9-.]+-[a-zA-Z0-9-.]+$/;function Ps(a){return _h.test(a)}function Dh(a){return Wi.includes(a)||bh.includes(a)||Ps(a)}const Fa=["d","dl","nor","ot","rtp","su"];function Ch(a){return Wi.includes(a)||Fa.includes(a)||Ps(a)}const Ph=["cmsdd","cmsds","rc","smrt","ttfb","ttfbb","ttlb","url"];function kh(a){return Wi.includes(a)||Fa.includes(a)||Ph.includes(a)||Ps(a)}const wh=["bl","br","bs","cid","d","dl","mtp","nor","nrr","ot","pr","rtp","sf","sid","st","su","tb","v"];function Oh(a){return wh.includes(a)||Ps(a)}const Fh={[Oa]:kh,[ka]:Dh,[wa]:Ch};function Ma(a,e={}){const t={};if(a==null||typeof a!="object")return t;const s=e.version||a.v||1,i=e.reportingMode||wa,r=s===1?Oh:Fh[i];let n=Object.keys(a).filter(r);const o=e.filter;typeof o=="function"&&(n=n.filter(o));const c=i===Oa||i===ka;c&&!n.includes("ts")&&n.push("ts"),s>1&&!n.includes("v")&&n.push("v");const l=ne({},Rh,e.formatters),h={version:s,reportingMode:i,baseUrl:e.baseUrl};return n.sort().forEach(d=>{let u=a[d];const f=l[d];if(typeof f=="function"&&(u=f(u,h)),d==="v"){if(s===1)return;u=s}d=="pr"&&u===1||(c&&d==="ts"&&!B(u)&&(u=Date.now()),Ah(u)&&(xh(d)&&typeof u=="string"&&(u=new ba(u)),t[d]=u))}),t}function Mh(a,e={}){const t={};if(!a)return t;const s=Ma(a,e),i=vh(s,e==null?void 0:e.customHeaderMap);return Object.entries(i).reduce((r,[n,o])=>{const c=Pa(o,{whitespace:!1});return c&&(r[n]=c),r},t)}function Nh(a,e,t){return ne(a,Mh(e,t))}const Bh="CMCD";function $h(a,e={}){return a?Pa(Ma(a,e),{whitespace:!1}):""}function Uh(a,e={}){if(!a)return"";const t=$h(a,e);return encodeURIComponent(t)}function Gh(a,e={}){if(!a)return"";const t=Uh(a,e);return`${Bh}=${t}`}const en=/CMCD=[^&#]+/;function Kh(a,e,t){const s=Gh(e,t);if(!s)return a;if(en.test(a))return a.replace(en,s);const i=a.includes("?")?"&":"?";return`${a}${i}${s}`}class Vh{constructor(e){this.hls=void 0,this.config=void 0,this.media=void 0,this.sid=void 0,this.cid=void 0,this.useHeaders=!1,this.includeKeys=void 0,this.initialized=!1,this.starved=!1,this.buffering=!0,this.audioBuffer=void 0,this.videoBuffer=void 0,this.onWaiting=()=>{this.initialized&&(this.starved=!0),this.buffering=!0},this.onPlaying=()=>{this.initialized||(this.initialized=!0),this.buffering=!1},this.applyPlaylistData=i=>{try{this.apply(i,{ot:Ae.MANIFEST,su:!this.initialized})}catch(r){this.hls.logger.warn("Could not generate manifest CMCD data.",r)}},this.applyFragmentData=i=>{try{const{frag:r,part:n}=i,o=this.hls.levels[r.level],c=this.getObjectType(r),l={d:(n||r).duration*1e3,ot:c};(c===Ae.VIDEO||c===Ae.AUDIO||c==Ae.MUXED)&&(l.br=o.bitrate/1e3,l.tb=this.getTopBandwidth(c)/1e3,l.bl=this.getBufferLength(c));const h=n?this.getNextPart(n):this.getNextFrag(r);h!=null&&h.url&&h.url!==r.url&&(l.nor=h.url),this.apply(i,l)}catch(r){this.hls.logger.warn("Could not generate segment CMCD data.",r)}},this.hls=e;const t=this.config=e.config,{cmcd:s}=t;s!=null&&(t.pLoader=this.createPlaylistLoader(),t.fLoader=this.createFragmentLoader(),this.sid=s.sessionId||e.sessionId,this.cid=s.contentId,this.useHeaders=s.useHeaders===!0,this.includeKeys=s.includeKeys,this.registerListeners())}registerListeners(){const e=this.hls;e.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(m.MEDIA_DETACHED,this.onMediaDetached,this),e.on(m.BUFFER_CREATED,this.onBufferCreated,this)}unregisterListeners(){const e=this.hls;e.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(m.MEDIA_DETACHED,this.onMediaDetached,this),e.off(m.BUFFER_CREATED,this.onBufferCreated,this)}destroy(){this.unregisterListeners(),this.onMediaDetached(),this.hls=this.config=this.audioBuffer=this.videoBuffer=null,this.onWaiting=this.onPlaying=this.media=null}onMediaAttached(e,t){this.media=t.media,this.media.addEventListener("waiting",this.onWaiting),this.media.addEventListener("playing",this.onPlaying)}onMediaDetached(){this.media&&(this.media.removeEventListener("waiting",this.onWaiting),this.media.removeEventListener("playing",this.onPlaying),this.media=null)}onBufferCreated(e,t){var s,i;this.audioBuffer=(s=t.tracks.audio)==null?void 0:s.buffer,this.videoBuffer=(i=t.tracks.video)==null?void 0:i.buffer}createData(){var e;return{v:1,sf:zc.HLS,sid:this.sid,cid:this.cid,pr:(e=this.media)==null?void 0:e.playbackRate,mtp:this.hls.bandwidthEstimate/1e3}}apply(e,t={}){ne(t,this.createData());const s=t.ot===Ae.INIT||t.ot===Ae.VIDEO||t.ot===Ae.MUXED;this.starved&&s&&(t.bs=!0,t.su=!0,this.starved=!1),t.su==null&&(t.su=this.buffering);const{includeKeys:i}=this;i&&(t=Object.keys(t).reduce((n,o)=>(i.includes(o)&&(n[o]=t[o]),n),{}));const r={baseUrl:e.url};this.useHeaders?(e.headers||(e.headers={}),Nh(e.headers,t,r)):e.url=Kh(e.url,t,r)}getNextFrag(e){var t;const s=(t=this.hls.levels[e.level])==null?void 0:t.details;if(s){const i=e.sn-s.startSN;return s.fragments[i+1]}}getNextPart(e){var t;const{index:s,fragment:i}=e,r=(t=this.hls.levels[i.level])==null||(t=t.details)==null?void 0:t.partList;if(r){const{sn:n}=i;for(let o=r.length-1;o>=0;o--){const c=r[o];if(c.index===s&&c.fragment.sn===n)return r[o+1]}}}getObjectType(e){const{type:t}=e;if(t==="subtitle")return Ae.TIMED_TEXT;if(e.sn==="initSegment")return Ae.INIT;if(t==="audio")return Ae.AUDIO;if(t==="main")return this.hls.audioTracks.length?Ae.VIDEO:Ae.MUXED}getTopBandwidth(e){let t=0,s;const i=this.hls;if(e===Ae.AUDIO)s=i.audioTracks;else{const r=i.maxAutoLevel,n=r>-1?r+1:i.levels.length;s=i.levels.slice(0,n)}return s.forEach(r=>{r.bitrate>t&&(t=r.bitrate)}),t>0?t:NaN}getBufferLength(e){const t=this.media,s=e===Ae.AUDIO?this.audioBuffer:this.videoBuffer;return!s||!t?NaN:X.bufferInfo(s,t.currentTime,this.config.maxBufferHole).len*1e3}createPlaylistLoader(){const{pLoader:e}=this.config,t=this.applyPlaylistData,s=e||this.config.loader;return class{constructor(r){this.loader=void 0,this.loader=new s(r)}get stats(){return this.loader.stats}get context(){return this.loader.context}destroy(){this.loader.destroy()}abort(){this.loader.abort()}load(r,n,o){t(r),this.loader.load(r,n,o)}}}createFragmentLoader(){const{fLoader:e}=this.config,t=this.applyFragmentData,s=e||this.config.loader;return class{constructor(r){this.loader=void 0,this.loader=new s(r)}get stats(){return this.loader.stats}get context(){return this.loader.context}destroy(){this.loader.destroy()}abort(){this.loader.abort()}load(r,n,o){t(r),this.loader.load(r,n,o)}}}}const Hh=3e5;class Yh extends Oe{constructor(e){super("content-steering",e.logger),this.hls=void 0,this.loader=null,this.uri=null,this.pathwayId=".",this._pathwayPriority=null,this.timeToLoad=300,this.reloadTimer=-1,this.updated=0,this.started=!1,this.enabled=!0,this.levels=null,this.audioTracks=null,this.subtitleTracks=null,this.penalizedPathways={},this.hls=e,this.registerListeners()}registerListeners(){const e=this.hls;e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.on(m.MANIFEST_PARSED,this.onManifestParsed,this),e.on(m.ERROR,this.onError,this)}unregisterListeners(){const e=this.hls;e&&(e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.off(m.MANIFEST_PARSED,this.onManifestParsed,this),e.off(m.ERROR,this.onError,this))}pathways(){return(this.levels||[]).reduce((e,t)=>(e.indexOf(t.pathwayId)===-1&&e.push(t.pathwayId),e),[])}get pathwayPriority(){return this._pathwayPriority}set pathwayPriority(e){this.updatePathwayPriority(e)}startLoad(){if(this.started=!0,this.clearTimeout(),this.enabled&&this.uri){if(this.updated){const e=this.timeToLoad*1e3-(performance.now()-this.updated);if(e>0){this.scheduleRefresh(this.uri,e);return}}this.loadSteeringManifest(this.uri)}}stopLoad(){this.started=!1,this.loader&&(this.loader.destroy(),this.loader=null),this.clearTimeout()}clearTimeout(){this.reloadTimer!==-1&&(self.clearTimeout(this.reloadTimer),this.reloadTimer=-1)}destroy(){this.unregisterListeners(),this.stopLoad(),this.hls=null,this.levels=this.audioTracks=this.subtitleTracks=null}removeLevel(e){const t=this.levels;t&&(this.levels=t.filter(s=>s!==e))}onManifestLoading(){this.stopLoad(),this.enabled=!0,this.timeToLoad=300,this.updated=0,this.uri=null,this.pathwayId=".",this.levels=this.audioTracks=this.subtitleTracks=null}onManifestLoaded(e,t){const{contentSteering:s}=t;s!==null&&(this.pathwayId=s.pathwayId,this.uri=s.uri,this.started&&this.startLoad())}onManifestParsed(e,t){this.audioTracks=t.audioTracks,this.subtitleTracks=t.subtitleTracks}onError(e,t){const{errorAction:s}=t;if((s==null?void 0:s.action)===pe.SendAlternateToPenaltyBox&&s.flags===Re.MoveAllAlternatesMatchingHost){const i=this.levels;let r=this._pathwayPriority,n=this.pathwayId;if(t.context){const{groupId:o,pathwayId:c,type:l}=t.context;o&&i?n=this.getPathwayForGroupId(o,l,n):c&&(n=c)}n in this.penalizedPathways||(this.penalizedPathways[n]=performance.now()),!r&&i&&(r=this.pathways()),r&&r.length>1&&(this.updatePathwayPriority(r),s.resolved=this.pathwayId!==n),t.details===R.BUFFER_APPEND_ERROR&&!t.fatal?s.resolved=!0:s.resolved||this.warn(`Could not resolve ${t.details} ("${t.error.message}") with content-steering for Pathway: ${n} levels: ${i&&i.length} priorities: ${oe(r)} penalized: ${oe(this.penalizedPathways)}`)}}filterParsedLevels(e){this.levels=e;let t=this.getLevelsForPathway(this.pathwayId);if(t.length===0){const s=e[0].pathwayId;this.log(`No levels found in Pathway ${this.pathwayId}. Setting initial Pathway to "${s}"`),t=this.getLevelsForPathway(s),this.pathwayId=s}return t.length!==e.length&&this.log(`Found ${t.length}/${e.length} levels in Pathway "${this.pathwayId}"`),t}getLevelsForPathway(e){return this.levels===null?[]:this.levels.filter(t=>e===t.pathwayId)}updatePathwayPriority(e){this._pathwayPriority=e;let t;const s=this.penalizedPathways,i=performance.now();Object.keys(s).forEach(r=>{i-s[r]>Hh&&delete s[r]});for(let r=0;r0){this.log(`Setting Pathway to "${n}"`),this.pathwayId=n,sa(t),this.hls.trigger(m.LEVELS_UPDATED,{levels:t});const l=this.hls.levels[o];c&&l&&this.levels&&(l.attrs["STABLE-VARIANT-ID"]!==c.attrs["STABLE-VARIANT-ID"]&&l.bitrate!==c.bitrate&&this.log(`Unstable Pathways change from bitrate ${c.bitrate} to ${l.bitrate}`),this.hls.nextLoadLevel=o);break}}}getPathwayForGroupId(e,t,s){const i=this.getLevelsForPathway(s).concat(this.levels||[]);for(let r=0;r{const{ID:n,"BASE-ID":o,"URI-REPLACEMENT":c}=r;if(t.some(h=>h.pathwayId===n))return;const l=this.getLevelsForPathway(o).map(h=>{const d=new le(h.attrs);d["PATHWAY-ID"]=n;const u=d.AUDIO&&`${d.AUDIO}_clone_${n}`,f=d.SUBTITLES&&`${d.SUBTITLES}_clone_${n}`;u&&(s[d.AUDIO]=u,d.AUDIO=u),f&&(i[d.SUBTITLES]=f,d.SUBTITLES=f);const g=Na(h.uri,d["STABLE-VARIANT-ID"],"PER-VARIANT-URIS",c),y=new Kt({attrs:d,audioCodec:h.audioCodec,bitrate:h.bitrate,height:h.height,name:h.name,url:g,videoCodec:h.videoCodec,width:h.width});if(h.audioGroups)for(let p=1;p{this.log(`Loaded steering manifest: "${i}"`);const g=h.data;if((g==null?void 0:g.VERSION)!==1){this.log(`Steering VERSION ${g.VERSION} not supported!`);return}this.updated=performance.now(),this.timeToLoad=g.TTL;const{"RELOAD-URI":y,"PATHWAY-CLONES":p,"PATHWAY-PRIORITY":E}=g;if(y)try{this.uri=new self.URL(y,i).href}catch{this.enabled=!1,this.log(`Failed to parse Steering Manifest RELOAD-URI: ${y}`);return}this.scheduleRefresh(this.uri||u.url),p&&this.clonePathways(p);const T={steeringManifest:g,url:i.toString()};this.hls.trigger(m.STEERING_MANIFEST_LOADED,T),E&&this.updatePathwayPriority(E)},onError:(h,d,u,f)=>{if(this.log(`Error loading steering manifest: ${h.code} ${h.text} (${d.url})`),this.stopLoad(),h.code===410){this.enabled=!1,this.log(`Steering manifest ${d.url} no longer available`);return}let g=this.timeToLoad*1e3;if(h.code===429){const y=this.loader;if(typeof(y==null?void 0:y.getResponseHeader)=="function"){const p=y.getResponseHeader("Retry-After");p&&(g=parseFloat(p)*1e3)}this.log(`Steering manifest ${d.url} rate limited`);return}this.scheduleRefresh(this.uri||d.url,g)},onTimeout:(h,d,u)=>{this.log(`Timeout loading steering manifest (${d.url})`),this.scheduleRefresh(this.uri||d.url)}};this.log(`Requesting steering manifest: ${i}`),this.loader.load(r,c,l)}scheduleRefresh(e,t=this.timeToLoad*1e3){this.clearTimeout(),this.reloadTimer=self.setTimeout(()=>{var s;const i=(s=this.hls)==null?void 0:s.media;if(i&&!i.ended){this.loadSteeringManifest(e);return}this.scheduleRefresh(e,this.timeToLoad*1e3)},t)}}function tn(a,e,t,s){a&&Object.keys(e).forEach(i=>{const r=a.filter(n=>n.groupId===i).map(n=>{const o=ne({},n);return o.details=void 0,o.attrs=new le(o.attrs),o.url=o.attrs.URI=Na(n.url,n.attrs["STABLE-RENDITION-ID"],"PER-RENDITION-URIS",t),o.groupId=o.attrs["GROUP-ID"]=e[i],o.attrs["PATHWAY-ID"]=s,o});a.push(...r)})}function Na(a,e,t,s){const{HOST:i,PARAMS:r,[t]:n}=s;let o;e&&(o=n==null?void 0:n[e],o&&(a=o));const c=new self.URL(a);return i&&!o&&(c.host=i),r&&Object.keys(r).sort().forEach(l=>{l&&c.searchParams.set(l,r[l])}),c.href}class Dt extends Oe{constructor(e){super("eme",e.logger),this.hls=void 0,this.config=void 0,this.media=null,this.mediaResolved=void 0,this.keyFormatPromise=null,this.keySystemAccessPromises={},this._requestLicenseFailureCount=0,this.mediaKeySessions=[],this.keyIdToKeySessionPromise={},this.mediaKeys=null,this.setMediaKeysQueue=Dt.CDMCleanupPromise?[Dt.CDMCleanupPromise]:[],this.bannedKeyIds={},this.onMediaEncrypted=t=>{const{initDataType:s,initData:i}=t,r=`"${t.type}" event: init data type: "${s}"`;if(this.debug(r),i!==null){if(!this.keyFormatPromise){let n=Object.keys(this.keySystemAccessPromises);n.length||(n=Mt(this.config));const o=n.map(Bs).filter(c=>!!c);this.keyFormatPromise=this.getKeyFormatPromise(o)}this.keyFormatPromise.then(n=>{const o=us(n);if(s!=="sinf"||o!==ce.FAIRPLAY){this.log(`Ignoring "${t.type}" event with init data type: "${s}" for selected key-system ${o}`);return}let c;try{const f=ue(new Uint8Array(i)),g=Oi(JSON.parse(f).sinf),y=Pn(g);if(!y)throw new Error("'schm' box missing or not cbcs/cenc with schi > tenc");c=new Uint8Array(y.subarray(8,24))}catch(f){this.warn(`${r} Failed to parse sinf: ${f}`);return}const l=ye(c),{keyIdToKeySessionPromise:h,mediaKeySessions:d}=this;let u=h[l];for(let f=0;fthis.generateRequestWithPreferredKeySession(g,s,i,"encrypted-event-key-match")),u.catch(E=>this.handleError(E));break}}u||this.handleError(new Error(`Key ID ${l} not encountered in playlist. Key-system sessions ${d.length}.`))}).catch(n=>this.handleError(n))}},this.onWaitingForKey=t=>{this.log(`"${t.type}" event`)},this.hls=e,this.config=e.config,this.registerListeners()}destroy(){this.onDestroying(),this.onMediaDetached();const e=this.config;e.requestMediaKeySystemAccessFunc=null,e.licenseXhrSetup=e.licenseResponseCallback=void 0,e.drmSystems=e.drmSystemOptions={},this.hls=this.config=this.keyIdToKeySessionPromise=null,this.onMediaEncrypted=this.onWaitingForKey=null}registerListeners(){this.hls.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),this.hls.on(m.MEDIA_DETACHED,this.onMediaDetached,this),this.hls.on(m.MANIFEST_LOADING,this.onManifestLoading,this),this.hls.on(m.MANIFEST_LOADED,this.onManifestLoaded,this),this.hls.on(m.DESTROYING,this.onDestroying,this)}unregisterListeners(){this.hls.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),this.hls.off(m.MEDIA_DETACHED,this.onMediaDetached,this),this.hls.off(m.MANIFEST_LOADING,this.onManifestLoading,this),this.hls.off(m.MANIFEST_LOADED,this.onManifestLoaded,this),this.hls.off(m.DESTROYING,this.onDestroying,this)}getLicenseServerUrl(e){const{drmSystems:t,widevineLicenseUrl:s}=this.config,i=t==null?void 0:t[e];if(i)return i.licenseUrl;if(e===ce.WIDEVINE&&s)return s}getLicenseServerUrlOrThrow(e){const t=this.getLicenseServerUrl(e);if(t===void 0)throw new Error(`no license server URL configured for key-system "${e}"`);return t}getServerCertificateUrl(e){const{drmSystems:t}=this.config,s=t==null?void 0:t[e];if(s)return s.serverCertificateUrl;this.log(`No Server Certificate in config.drmSystems["${e}"]`)}attemptKeySystemAccess(e){const t=this.hls.levels,s=(n,o,c)=>!!n&&c.indexOf(n)===o,i=t.map(n=>n.audioCodec).filter(s),r=t.map(n=>n.videoCodec).filter(s);return i.length+r.length===0&&r.push("avc1.42e01e"),new Promise((n,o)=>{const c=l=>{const h=l.shift();this.getMediaKeysPromise(h,i,r).then(d=>n({keySystem:h,mediaKeys:d})).catch(d=>{l.length?c(l):d instanceof Le?o(d):o(new Le({type:Y.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_NO_ACCESS,error:d,fatal:!0},d.message))})};c(e)})}requestMediaKeySystemAccess(e,t){const{requestMediaKeySystemAccessFunc:s}=this.config;if(typeof s!="function"){let i=`Configured requestMediaKeySystemAccess is not a function ${s}`;return jn===null&&self.location.protocol==="http:"&&(i=`navigator.requestMediaKeySystemAccess is not available over insecure protocol ${location.protocol}`),Promise.reject(new Error(i))}return s(e,t)}getMediaKeysPromise(e,t,s){var i;const r=Ll(e,t,s,this.config.drmSystemOptions||{});let n=this.keySystemAccessPromises[e],o=(i=n)==null?void 0:i.keySystemAccess;if(!o){this.log(`Requesting encrypted media "${e}" key-system access with config: ${oe(r)}`),o=this.requestMediaKeySystemAccess(e,r);const c=n=this.keySystemAccessPromises[e]={keySystemAccess:o};return o.catch(l=>{this.log(`Failed to obtain access to key-system "${e}": ${l}`)}),o.then(l=>{this.log(`Access for key-system "${l.keySystem}" obtained`);const h=this.fetchServerCertificate(e);this.log(`Create media-keys for "${e}"`);const d=c.mediaKeys=l.createMediaKeys().then(u=>(this.log(`Media-keys created for "${e}"`),c.hasMediaKeys=!0,h.then(f=>f?this.setMediaKeysServerCertificate(u,e,f):u)));return d.catch(u=>{this.error(`Failed to create media-keys for "${e}"}: ${u}`)}),d})}return o.then(()=>n.mediaKeys)}createMediaKeySessionContext({decryptdata:e,keySystem:t,mediaKeys:s}){this.log(`Creating key-system session "${t}" keyId: ${ye(e.keyId||[])} keyUri: ${e.uri}`);const i=s.createSession(),r={decryptdata:e,keySystem:t,mediaKeys:s,mediaKeysSession:i,keyStatus:"status-pending"};return this.mediaKeySessions.push(r),r}renewKeySession(e){const t=e.decryptdata;if(t.pssh){const s=this.createMediaKeySessionContext(e),i=rs(t),r="cenc";this.keyIdToKeySessionPromise[i]=this.generateRequestWithPreferredKeySession(s,r,t.pssh.buffer,"expired")}else this.warn("Could not renew expired session. Missing pssh initData.");this.removeSession(e)}updateKeySession(e,t){const s=e.mediaKeysSession;return this.log(`Updating key-session "${s.sessionId}" for keyId ${ye(e.decryptdata.keyId||[])} - } (data length: ${t.byteLength})`),s.update(t)}getSelectedKeySystemFormats(){return Object.keys(this.keySystemAccessPromises).map(e=>({keySystem:e,hasMediaKeys:this.keySystemAccessPromises[e].hasMediaKeys})).filter(({hasMediaKeys:e})=>!!e).map(({keySystem:e})=>Bs(e)).filter(e=>!!e)}getKeySystemAccess(e){return this.getKeySystemSelectionPromise(e).then(({keySystem:t,mediaKeys:s})=>this.attemptSetMediaKeys(t,s))}selectKeySystem(e){return new Promise((t,s)=>{this.getKeySystemSelectionPromise(e).then(({keySystem:i})=>{const r=Bs(i);r?t(r):s(new Error(`Unable to find format for key-system "${i}"`))}).catch(s)})}selectKeySystemFormat(e){const t=Object.keys(e.levelkeys||{});return this.keyFormatPromise||(this.log(`Selecting key-system from fragment (sn: ${e.sn} ${e.type}: ${e.level}) key formats ${t.join(", ")}`),this.keyFormatPromise=this.getKeyFormatPromise(t)),this.keyFormatPromise}getKeyFormatPromise(e){const t=Mt(this.config),s=e.map(us).filter(i=>!!i&&t.indexOf(i)!==-1);return this.selectKeySystem(s)}getKeyStatus(e){const{mediaKeySessions:t}=this;for(let s=0;s(this.throwIfDestroyed(),this.log(`Handle encrypted media sn: ${e.frag.sn} ${e.frag.type}: ${e.frag.level} using key ${r}`),this.attemptSetMediaKeys(c,l).then(()=>(this.throwIfDestroyed(),this.createMediaKeySessionContext({keySystem:c,mediaKeys:l,decryptdata:t}))))).then(c=>{const l="cenc",h=t.pssh?t.pssh.buffer:null;return this.generateRequestWithPreferredKeySession(c,l,h,"playlist-key")});return o.catch(c=>this.handleError(c,e.frag)),this.keyIdToKeySessionPromise[s]=o,o}return n.catch(o=>{if(o instanceof Le){const c=ie({},o.data);this.getKeyStatus(t)==="internal-error"&&(c.decryptdata=t);const l=new Le(c,o.message);this.handleError(l,e.frag)}}),n}throwIfDestroyed(e="Invalid state"){if(!this.hls)throw new Error("invalid state")}handleError(e,t){if(this.hls)if(e instanceof Le){t&&(e.data.frag=t);const s=e.data.decryptdata;this.error(`${e.message}${s?` (${ye(s.keyId||[])})`:""}`),this.hls.trigger(m.ERROR,e.data)}else this.error(e.message),this.hls.trigger(m.ERROR,{type:Y.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_NO_KEYS,error:e,fatal:!0})}getKeySystemForKeyPromise(e){const t=rs(e),s=this.keyIdToKeySessionPromise[t];if(!s){const i=us(e.keyFormat),r=i?[i]:Mt(this.config);return this.attemptKeySystemAccess(r)}return s}getKeySystemSelectionPromise(e){if(e.length||(e=Mt(this.config)),e.length===0)throw new Le({type:Y.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_NO_CONFIGURED_LICENSE,fatal:!0},`Missing key-system license configuration options ${oe({drmSystems:this.config.drmSystems})}`);return this.attemptKeySystemAccess(e)}attemptSetMediaKeys(e,t){if(this.mediaResolved=void 0,this.mediaKeys===t)return Promise.resolve();const s=this.setMediaKeysQueue.slice();this.log(`Setting media-keys for "${e}"`);const i=Promise.all(s).then(()=>this.media?this.media.setMediaKeys(t):new Promise((r,n)=>{this.mediaResolved=()=>{if(this.mediaResolved=void 0,!this.media)return n(new Error("Attempted to set mediaKeys without media element attached"));this.mediaKeys=t,this.media.setMediaKeys(t).then(r).catch(n)}}));return this.mediaKeys=t,this.setMediaKeysQueue.push(i),i.then(()=>{this.log(`Media-keys set for "${e}"`),s.push(i),this.setMediaKeysQueue=this.setMediaKeysQueue.filter(r=>s.indexOf(r)===-1)})}generateRequestWithPreferredKeySession(e,t,s,i){var r;const n=(r=this.config.drmSystems)==null||(r=r[e.keySystem])==null?void 0:r.generateRequest;if(n)try{const g=n.call(this.hls,t,s,e);if(!g)throw new Error("Invalid response from configured generateRequest filter");t=g.initDataType,s=g.initData?g.initData:null,e.decryptdata.pssh=s?new Uint8Array(s):null}catch(g){if(this.warn(g.message),this.hls&&this.hls.config.debug)throw g}if(s===null)return this.log(`Skipping key-session request for "${i}" (no initData)`),Promise.resolve(e);const o=rs(e.decryptdata),c=e.decryptdata.uri;this.log(`Generating key-session request for "${i}" keyId: ${o} URI: ${c} (init data type: ${t} length: ${s.byteLength})`);const l=new Mi,h=e._onmessage=g=>{const y=e.mediaKeysSession;if(!y){l.emit("error",new Error("invalid state"));return}const{messageType:p,message:E}=g;this.log(`"${p}" message event for session "${y.sessionId}" message size: ${E.byteLength}`),p==="license-request"||p==="license-renewal"?this.renewLicense(e,E).catch(T=>{l.eventNames().length?l.emit("error",T):this.handleError(T)}):p==="license-release"?e.keySystem===ce.FAIRPLAY&&this.updateKeySession(e,hi("acknowledged")).then(()=>this.removeSession(e)).catch(T=>this.handleError(T)):this.warn(`unhandled media key message type "${p}"`)},d=(g,y)=>{y.keyStatus=g;let p;g.startsWith("usable")?l.emit("resolved"):g==="internal-error"||g==="output-restricted"||g==="output-downscaled"?p=sn(g,y.decryptdata):g==="expired"?p=new Error(`key expired (keyId: ${o})`):g==="released"?p=new Error("key released"):g==="status-pending"||this.warn(`unhandled key status change "${g}" (keyId: ${o})`),p&&(l.eventNames().length?l.emit("error",p):this.handleError(p))},u=e._onkeystatuseschange=g=>{if(!e.mediaKeysSession){l.emit("error",new Error("invalid state"));return}const p=this.getKeyStatuses(e);if(!Object.keys(p).some(v=>p[v]!=="status-pending"))return;if(p[o]==="expired"){this.log(`Expired key ${oe(p)} in key-session "${e.mediaKeysSession.sessionId}"`),this.renewKeySession(e);return}let T=p[o];if(T)d(T,e);else{var S;e.keyStatusTimeouts||(e.keyStatusTimeouts={}),(S=e.keyStatusTimeouts)[o]||(S[o]=self.setTimeout(()=>{if(!e.mediaKeysSession||!this.mediaKeys)return;const x=this.getKeyStatus(e.decryptdata);if(x&&x!=="status-pending")return this.log(`No status for keyId ${o} in key-session "${e.mediaKeysSession.sessionId}". Using session key-status ${x} from other session.`),d(x,e);this.log(`key status for ${o} in key-session "${e.mediaKeysSession.sessionId}" timed out after 1000ms`),T="internal-error",d(T,e)},1e3)),this.log(`No status for keyId ${o} (${oe(p)}).`)}};xe(e.mediaKeysSession,"message",h),xe(e.mediaKeysSession,"keystatuseschange",u);const f=new Promise((g,y)=>{l.on("error",y),l.on("resolved",g)});return e.mediaKeysSession.generateRequest(t,s).then(()=>{this.log(`Request generated for key-session "${e.mediaKeysSession.sessionId}" keyId: ${o} URI: ${c}`)}).catch(g=>{throw new Le({type:Y.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_NO_SESSION,error:g,decryptdata:e.decryptdata,fatal:!1},`Error generating key-session request: ${g}`)}).then(()=>f).catch(g=>(l.removeAllListeners(),this.removeSession(e).then(()=>{throw g}))).then(()=>(l.removeAllListeners(),e))}getKeyStatuses(e){const t={};return e.mediaKeysSession.keyStatuses.forEach((s,i)=>{if(typeof i=="string"&&typeof s=="object"){const o=i;i=s,s=o}const r="buffer"in i?new Uint8Array(i.buffer,i.byteOffset,i.byteLength):new Uint8Array(i);if(e.keySystem===ce.PLAYREADY&&r.length===16){const o=ye(r);t[o]=s,Wn(r)}const n=ye(r);s==="internal-error"&&(this.bannedKeyIds[n]=s),this.log(`key status change "${s}" for keyStatuses keyId: ${n} key-session "${e.mediaKeysSession.sessionId}"`),t[n]=s}),t}fetchServerCertificate(e){const t=this.config,s=t.loader,i=new s(t),r=this.getServerCertificateUrl(e);return r?(this.log(`Fetching server certificate for "${e}"`),new Promise((n,o)=>{const c={responseType:"arraybuffer",url:r},l=t.certLoadPolicy.default,h={loadPolicy:l,timeout:l.maxLoadTimeMs,maxRetry:0,retryDelay:0,maxRetryDelay:0},d={onSuccess:(u,f,g,y)=>{n(u.data)},onError:(u,f,g,y)=>{o(new Le({type:Y.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED,fatal:!0,networkDetails:g,response:ie({url:c.url,data:void 0},u)},`"${e}" certificate request failed (${r}). Status: ${u.code} (${u.text})`))},onTimeout:(u,f,g)=>{o(new Le({type:Y.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED,fatal:!0,networkDetails:g,response:{url:c.url,data:void 0}},`"${e}" certificate request timed out (${r})`))},onAbort:(u,f,g)=>{o(new Error("aborted"))}};i.load(c,h,d)})):Promise.resolve()}setMediaKeysServerCertificate(e,t,s){return new Promise((i,r)=>{e.setServerCertificate(s).then(n=>{this.log(`setServerCertificate ${n?"success":"not supported by CDM"} (${s.byteLength}) on "${t}"`),i(e)}).catch(n=>{r(new Le({type:Y.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_SERVER_CERTIFICATE_UPDATE_FAILED,error:n,fatal:!0},n.message))})})}renewLicense(e,t){return this.requestLicense(e,new Uint8Array(t)).then(s=>this.updateKeySession(e,new Uint8Array(s)).catch(i=>{throw new Le({type:Y.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_SESSION_UPDATE_FAILED,decryptdata:e.decryptdata,error:i,fatal:!1},i.message)}))}unpackPlayReadyKeyMessage(e,t){const s=String.fromCharCode.apply(null,new Uint16Array(t.buffer));if(!s.includes("PlayReadyKeyMessage"))return e.setRequestHeader("Content-Type","text/xml; charset=utf-8"),t;const i=new DOMParser().parseFromString(s,"application/xml"),r=i.querySelectorAll("HttpHeader");if(r.length>0){let h;for(let d=0,u=r.length;d in key message");return hi(atob(l))}setupLicenseXHR(e,t,s,i){const r=this.config.licenseXhrSetup;return r?Promise.resolve().then(()=>{if(!s.decryptdata)throw new Error("Key removed");return r.call(this.hls,e,t,s,i)}).catch(n=>{if(!s.decryptdata)throw n;return e.open("POST",t,!0),r.call(this.hls,e,t,s,i)}).then(n=>(e.readyState||e.open("POST",t,!0),{xhr:e,licenseChallenge:n||i})):(e.open("POST",t,!0),Promise.resolve({xhr:e,licenseChallenge:i}))}requestLicense(e,t){const s=this.config.keyLoadPolicy.default;return new Promise((i,r)=>{const n=this.getLicenseServerUrlOrThrow(e.keySystem);this.log(`Sending license request to URL: ${n}`);const o=new XMLHttpRequest;o.responseType="arraybuffer",o.onreadystatechange=()=>{if(!this.hls||!e.mediaKeysSession)return r(new Error("invalid state"));if(o.readyState===4)if(o.status===200){this._requestLicenseFailureCount=0;let c=o.response;this.log(`License received ${c instanceof ArrayBuffer?c.byteLength:c}`);const l=this.config.licenseResponseCallback;if(l)try{c=l.call(this.hls,o,n,e)}catch(h){this.error(h)}i(c)}else{const c=s.errorRetry,l=c?c.maxNumRetry:0;if(this._requestLicenseFailureCount++,this._requestLicenseFailureCount>l||o.status>=400&&o.status<500)r(new Le({type:Y.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_LICENSE_REQUEST_FAILED,decryptdata:e.decryptdata,fatal:!0,networkDetails:o,response:{url:n,data:void 0,code:o.status,text:o.statusText}},`License Request XHR failed (${n}). Status: ${o.status} (${o.statusText})`));else{const h=l-this._requestLicenseFailureCount+1;this.warn(`Retrying license request, ${h} attempts left`),this.requestLicense(e,t).then(i,r)}}},e.licenseXhr&&e.licenseXhr.readyState!==XMLHttpRequest.DONE&&e.licenseXhr.abort(),e.licenseXhr=o,this.setupLicenseXHR(o,n,e,t).then(({xhr:c,licenseChallenge:l})=>{e.keySystem==ce.PLAYREADY&&(l=this.unpackPlayReadyKeyMessage(c,l)),c.send(l)}).catch(r)})}onDestroying(){this.unregisterListeners(),this._clear()}onMediaAttached(e,t){if(!this.config.emeEnabled)return;const s=t.media;this.media=s,xe(s,"encrypted",this.onMediaEncrypted),xe(s,"waitingforkey",this.onWaitingForKey);const i=this.mediaResolved;i?i():this.mediaKeys=s.mediaKeys}onMediaDetached(){const e=this.media;e&&(Ie(e,"encrypted",this.onMediaEncrypted),Ie(e,"waitingforkey",this.onWaitingForKey),this.media=null,this.mediaKeys=null)}_clear(){var e;this._requestLicenseFailureCount=0,this.keyIdToKeySessionPromise={},this.bannedKeyIds={};const t=this.mediaResolved;if(t&&t(),!this.mediaKeys&&!this.mediaKeySessions.length)return;const s=this.media,i=this.mediaKeySessions.slice();this.mediaKeySessions=[],this.mediaKeys=null,nt.clearKeyUriToKeyIdMap();const r=i.length;Dt.CDMCleanupPromise=Promise.all(i.map(n=>this.removeSession(n)).concat((s==null||(e=s.setMediaKeys(null))==null?void 0:e.catch(n=>{this.log(`Could not clear media keys: ${n}`),this.hls&&this.hls.trigger(m.ERROR,{type:Y.OTHER_ERROR,details:R.KEY_SYSTEM_DESTROY_MEDIA_KEYS_ERROR,fatal:!1,error:new Error(`Could not clear media keys: ${n}`)})}))||Promise.resolve())).catch(n=>{this.log(`Could not close sessions and clear media keys: ${n}`),this.hls&&this.hls.trigger(m.ERROR,{type:Y.OTHER_ERROR,details:R.KEY_SYSTEM_DESTROY_CLOSE_SESSION_ERROR,fatal:!1,error:new Error(`Could not close sessions and clear media keys: ${n}`)})}).then(()=>{r&&this.log("finished closing key sessions and clearing media keys")})}onManifestLoading(){this._clear()}onManifestLoaded(e,{sessionKeys:t}){if(!(!t||!this.config.emeEnabled)&&!this.keyFormatPromise){const s=t.reduce((i,r)=>(i.indexOf(r.keyFormat)===-1&&i.push(r.keyFormat),i),[]);this.log(`Selecting key-system from session-keys ${s.join(", ")}`),this.keyFormatPromise=this.getKeyFormatPromise(s)}}removeSession(e){const{mediaKeysSession:t,licenseXhr:s,decryptdata:i}=e;if(t){this.log(`Remove licenses and keys and close session "${t.sessionId}" keyId: ${ye((i==null?void 0:i.keyId)||[])}`),e._onmessage&&(t.removeEventListener("message",e._onmessage),e._onmessage=void 0),e._onkeystatuseschange&&(t.removeEventListener("keystatuseschange",e._onkeystatuseschange),e._onkeystatuseschange=void 0),s&&s.readyState!==XMLHttpRequest.DONE&&s.abort(),e.mediaKeysSession=e.decryptdata=e.licenseXhr=void 0;const r=this.mediaKeySessions.indexOf(e);r>-1&&this.mediaKeySessions.splice(r,1);const{keyStatusTimeouts:n}=e;n&&Object.keys(n).forEach(l=>self.clearTimeout(n[l]));const{drmSystemOptions:o}=this.config;return(bl(o)?new Promise((l,h)=>{self.setTimeout(()=>h(new Error("MediaKeySession.remove() timeout")),8e3),t.remove().then(l).catch(h)}):Promise.resolve()).catch(l=>{this.log(`Could not remove session: ${l}`),this.hls&&this.hls.trigger(m.ERROR,{type:Y.OTHER_ERROR,details:R.KEY_SYSTEM_DESTROY_REMOVE_SESSION_ERROR,fatal:!1,error:new Error(`Could not remove session: ${l}`)})}).then(()=>t.close()).catch(l=>{this.log(`Could not close session: ${l}`),this.hls&&this.hls.trigger(m.ERROR,{type:Y.OTHER_ERROR,details:R.KEY_SYSTEM_DESTROY_CLOSE_SESSION_ERROR,fatal:!1,error:new Error(`Could not close session: ${l}`)})})}return Promise.resolve()}}Dt.CDMCleanupPromise=void 0;function rs(a){if(!a)throw new Error("Could not read keyId of undefined decryptdata");if(a.keyId===null)throw new Error("keyId is null");return ye(a.keyId)}function Wh(a,e){if(a.keyId&&e.mediaKeysSession.keyStatuses.has(a.keyId))return e.mediaKeysSession.keyStatuses.get(a.keyId);if(a.matches(e.decryptdata))return e.keyStatus}class Le extends Error{constructor(e,t){super(t),this.data=void 0,e.error||(e.error=new Error(t)),this.data=e,e.err=e.error}}function sn(a,e){const t=a==="output-restricted",s=t?R.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED:R.KEY_SYSTEM_STATUS_INTERNAL_ERROR;return new Le({type:Y.KEY_SYSTEM_ERROR,details:s,fatal:!1,decryptdata:e},t?"HDCP level output restricted":`key status changed to "${a}"`)}class qh{constructor(e){this.hls=void 0,this.isVideoPlaybackQualityAvailable=!1,this.timer=void 0,this.media=null,this.lastTime=void 0,this.lastDroppedFrames=0,this.lastDecodedFrames=0,this.streamController=void 0,this.hls=e,this.registerListeners()}setStreamController(e){this.streamController=e}registerListeners(){this.hls.on(m.MEDIA_ATTACHING,this.onMediaAttaching,this),this.hls.on(m.MEDIA_DETACHING,this.onMediaDetaching,this)}unregisterListeners(){this.hls.off(m.MEDIA_ATTACHING,this.onMediaAttaching,this),this.hls.off(m.MEDIA_DETACHING,this.onMediaDetaching,this)}destroy(){this.timer&&clearInterval(this.timer),this.unregisterListeners(),this.isVideoPlaybackQualityAvailable=!1,this.media=null}onMediaAttaching(e,t){const s=this.hls.config;if(s.capLevelOnFPSDrop){const i=t.media instanceof self.HTMLVideoElement?t.media:null;this.media=i,i&&typeof i.getVideoPlaybackQuality=="function"&&(this.isVideoPlaybackQualityAvailable=!0),self.clearInterval(this.timer),this.timer=self.setInterval(this.checkFPSInterval.bind(this),s.fpsDroppedMonitoringPeriod)}}onMediaDetaching(){this.media=null}checkFPS(e,t,s){const i=performance.now();if(t){if(this.lastTime){const r=i-this.lastTime,n=s-this.lastDroppedFrames,o=t-this.lastDecodedFrames,c=1e3*n/r,l=this.hls;if(l.trigger(m.FPS_DROP,{currentDropped:n,currentDecoded:o,totalDroppedFrames:s}),c>0&&n>l.config.fpsDroppedMonitoringThreshold*o){let h=l.currentLevel;l.logger.warn("drop FPS ratio greater than max allowed value for currentLevel: "+h),h>0&&(l.autoLevelCapping===-1||l.autoLevelCapping>=h)&&(h=h-1,l.trigger(m.FPS_DROP_LEVEL_CAPPING,{level:h,droppedLevel:l.currentLevel}),l.autoLevelCapping=h,this.streamController.nextLevelSwitch())}}this.lastTime=i,this.lastDroppedFrames=s,this.lastDecodedFrames=t}}checkFPSInterval(){const e=this.media;if(e)if(this.isVideoPlaybackQualityAvailable){const t=e.getVideoPlaybackQuality();this.checkFPS(e,t.totalVideoFrames,t.droppedVideoFrames)}else this.checkFPS(e,e.webkitDecodedFrameCount,e.webkitDroppedFrameCount)}}function Ba(a,e){let t;try{t=new Event("addtrack")}catch{t=document.createEvent("Event"),t.initEvent("addtrack",!1,!1)}t.track=a,e.dispatchEvent(t)}function $a(a,e){const t=a.mode;if(t==="disabled"&&(a.mode="hidden"),a.cues&&!a.cues.getCueById(e.id))try{if(a.addCue(e),!a.cues.getCueById(e.id))throw new Error(`addCue is failed for: ${e}`)}catch(s){re.debug(`[texttrack-utils]: ${s}`);try{const i=new self.TextTrackCue(e.startTime,e.endTime,e.text);i.id=e.id,a.addCue(i)}catch(i){re.debug(`[texttrack-utils]: Legacy TextTrackCue fallback failed: ${i}`)}}t==="disabled"&&(a.mode=t)}function Lt(a,e){const t=a.mode;if(t==="disabled"&&(a.mode="hidden"),a.cues)for(let s=a.cues.length;s--;)e&&a.cues[s].removeEventListener("enter",e),a.removeCue(a.cues[s]);t==="disabled"&&(a.mode=t)}function Ti(a,e,t,s){const i=a.mode;if(i==="disabled"&&(a.mode="hidden"),a.cues&&a.cues.length>0){const r=Xh(a.cues,e,t);for(let n=0;na[t].endTime)return-1;let s=0,i=t,r;for(;s<=i;)if(r=Math.floor((i+s)/2),ea[r].startTime&&s-1)for(let r=i,n=a.length;r=e&&o.endTime<=t)s.push(o);else if(o.startTime>t)return s}return s}function ps(a){const e=[];for(let t=0;tthis.pollTrackChange(0),this.onTextTracksChanged=()=>{if(this.useTextTrackPolling||self.clearInterval(this.subtitlePollingInterval),!this.media||!this.hls.config.renderTextTracksNatively)return;let t=null;const s=ps(this.media.textTracks);for(let r=0;r-1&&this.toggleTrackModes()}registerListeners(){const{hls:e}=this;e.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.MANIFEST_PARSED,this.onManifestParsed,this),e.on(m.LEVEL_LOADING,this.onLevelLoading,this),e.on(m.LEVEL_SWITCHING,this.onLevelSwitching,this),e.on(m.SUBTITLE_TRACK_LOADED,this.onSubtitleTrackLoaded,this),e.on(m.ERROR,this.onError,this)}unregisterListeners(){const{hls:e}=this;e.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.MANIFEST_PARSED,this.onManifestParsed,this),e.off(m.LEVEL_LOADING,this.onLevelLoading,this),e.off(m.LEVEL_SWITCHING,this.onLevelSwitching,this),e.off(m.SUBTITLE_TRACK_LOADED,this.onSubtitleTrackLoaded,this),e.off(m.ERROR,this.onError,this)}onMediaAttached(e,t){this.media=t.media,this.media&&(this.queuedDefaultTrack>-1&&(this.subtitleTrack=this.queuedDefaultTrack,this.queuedDefaultTrack=-1),this.useTextTrackPolling=!(this.media.textTracks&&"onchange"in this.media.textTracks),this.useTextTrackPolling?this.pollTrackChange(500):this.media.textTracks.addEventListener("change",this.asyncPollTrackChange))}pollTrackChange(e){self.clearInterval(this.subtitlePollingInterval),this.subtitlePollingInterval=self.setInterval(this.onTextTracksChanged,e)}onMediaDetaching(e,t){const s=this.media;if(!s)return;const i=!!t.transferMedia;if(self.clearInterval(this.subtitlePollingInterval),this.useTextTrackPolling||s.textTracks.removeEventListener("change",this.asyncPollTrackChange),this.trackId>-1&&(this.queuedDefaultTrack=this.trackId),this.subtitleTrack=-1,this.media=null,i)return;ps(s.textTracks).forEach(n=>{Lt(n)})}onManifestLoading(){this.tracks=[],this.groupIds=null,this.tracksInGroup=[],this.trackId=-1,this.currentTrack=null,this.selectDefaultTrack=!0}onManifestParsed(e,t){this.tracks=t.subtitleTracks}onSubtitleTrackLoaded(e,t){const{id:s,groupId:i,details:r}=t,n=this.tracksInGroup[s];if(!n||n.groupId!==i){this.warn(`Subtitle track with id:${s} and group:${i} not found in active group ${n==null?void 0:n.groupId}`);return}const o=n.details;n.details=t.details,this.log(`Subtitle track ${s} "${n.name}" lang:${n.lang} group:${i} loaded [${r.startSN}-${r.endSN}]`),s===this.trackId&&this.playlistLoaded(s,t,o)}onLevelLoading(e,t){this.switchLevel(t.level)}onLevelSwitching(e,t){this.switchLevel(t.level)}switchLevel(e){const t=this.hls.levels[e];if(!t)return;const s=t.subtitleGroups||null,i=this.groupIds;let r=this.currentTrack;if(!s||(i==null?void 0:i.length)!==(s==null?void 0:s.length)||s!=null&&s.some(n=>(i==null?void 0:i.indexOf(n))===-1)){this.groupIds=s,this.trackId=-1,this.currentTrack=null;const n=this.tracks.filter(h=>!s||s.indexOf(h.groupId)!==-1);if(n.length)this.selectDefaultTrack&&!n.some(h=>h.default)&&(this.selectDefaultTrack=!1),n.forEach((h,d)=>{h.id=d});else if(!r&&!this.tracksInGroup.length)return;this.tracksInGroup=n;const o=this.hls.config.subtitlePreference;if(!r&&o){this.selectDefaultTrack=!1;const h=We(o,n);if(h>-1)r=n[h];else{const d=We(o,this.tracks);r=this.tracks[d]}}let c=this.findTrackId(r);c===-1&&r&&(c=this.findTrackId(null));const l={subtitleTracks:n};this.log(`Updating subtitle tracks, ${n.length} track(s) found in "${s==null?void 0:s.join(",")}" group-id`),this.hls.trigger(m.SUBTITLE_TRACKS_UPDATED,l),c!==-1&&this.trackId===-1&&this.setSubtitleTrack(c)}}findTrackId(e){const t=this.tracksInGroup,s=this.selectDefaultTrack;for(let i=0;i-1){const r=this.tracksInGroup[i];return this.setSubtitleTrack(i),r}else{if(s)return null;{const r=We(e,t);if(r>-1)return t[r]}}}}return null}loadPlaylist(e){super.loadPlaylist(),this.shouldLoadPlaylist(this.currentTrack)&&this.scheduleLoading(this.currentTrack,e)}loadingPlaylist(e,t){super.loadingPlaylist(e,t);const s=e.id,i=e.groupId,r=this.getUrlWithDirectives(e.url,t),n=e.details,o=n==null?void 0:n.age;this.log(`Loading subtitle ${s} "${e.name}" lang:${e.lang} group:${i}${(t==null?void 0:t.msn)!==void 0?" at sn "+t.msn+" part "+t.part:""}${o&&n.live?" age "+o.toFixed(1)+(n.type&&" "+n.type||""):""} ${r}`),this.hls.trigger(m.SUBTITLE_TRACK_LOADING,{url:r,id:s,groupId:i,deliveryDirectives:t||null,track:e})}toggleTrackModes(){const{media:e}=this;if(!e)return;const t=ps(e.textTracks),s=this.currentTrack;let i;if(s&&(i=t.filter(r=>mi(s,r))[0],i||this.warn(`Unable to find subtitle TextTrack with name "${s.name}" and language "${s.lang}"`)),[].slice.call(t).forEach(r=>{r.mode!=="disabled"&&r!==i&&(r.mode="disabled")}),i){const r=this.subtitleDisplay?"showing":"hidden";i.mode!==r&&(i.mode=r)}}setSubtitleTrack(e){const t=this.tracksInGroup;if(!this.media){this.queuedDefaultTrack=e;return}if(e<-1||e>=t.length||!B(e)){this.warn(`Invalid subtitle track id: ${e}`);return}this.selectDefaultTrack=!1;const s=this.currentTrack,i=t[e]||null;if(this.trackId=e,this.currentTrack=i,this.toggleTrackModes(),!i){this.hls.trigger(m.SUBTITLE_TRACK_SWITCH,{id:e});return}const r=!!i.details&&!i.details.live;if(e===this.trackId&&i===s&&r)return;this.log(`Switching to subtitle-track ${e}`+(i?` "${i.name}" lang:${i.lang} group:${i.groupId}`:""));const{id:n,groupId:o="",name:c,type:l,url:h}=i;this.hls.trigger(m.SUBTITLE_TRACK_SWITCH,{id:n,groupId:o,name:c,type:l,url:h});const d=this.switchParams(i.url,s==null?void 0:s.details,i.details);this.loadPlaylist(d)}}function Qh(){try{return crypto.randomUUID()}catch{try{const e=URL.createObjectURL(new Blob),t=e.toString();return URL.revokeObjectURL(e),t.slice(t.lastIndexOf("/")+1)}catch{let t=new Date().getTime();return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,i=>{const r=(t+Math.random()*16)%16|0;return t=Math.floor(t/16),(i=="x"?r:r&3|8).toString(16)})}}}function $t(a){let e=5381,t=a.length;for(;t;)e=e*33^a.charCodeAt(--t);return(e>>>0).toString()}const Ct=.025;let _s=function(a){return a[a.Point=0]="Point",a[a.Range=1]="Range",a}({});function Zh(a,e,t){return`${a.identifier}-${t+1}-${$t(e)}`}class Jh{constructor(e,t){this.base=void 0,this._duration=null,this._timelineStart=null,this.appendInPlaceDisabled=void 0,this.appendInPlaceStarted=void 0,this.dateRange=void 0,this.hasPlayed=!1,this.cumulativeDuration=0,this.resumeOffset=NaN,this.playoutLimit=NaN,this.restrictions={skip:!1,jump:!1},this.snapOptions={out:!1,in:!1},this.assetList=[],this.assetListLoader=void 0,this.assetListResponse=null,this.resumeAnchor=void 0,this.error=void 0,this.resetOnResume=void 0,this.base=t,this.dateRange=e,this.setDateRange(e)}setDateRange(e){this.dateRange=e,this.resumeOffset=e.attr.optionalFloat("X-RESUME-OFFSET",this.resumeOffset),this.playoutLimit=e.attr.optionalFloat("X-PLAYOUT-LIMIT",this.playoutLimit),this.restrictions=e.attr.enumeratedStringList("X-RESTRICT",this.restrictions),this.snapOptions=e.attr.enumeratedStringList("X-SNAP",this.snapOptions)}reset(){var e;this.appendInPlaceStarted=!1,(e=this.assetListLoader)==null||e.destroy(),this.assetListLoader=void 0,this.supplementsPrimary||(this.assetListResponse=null,this.assetList=[],this._duration=null)}isAssetPastPlayoutLimit(e){var t;if(e>0&&e>=this.assetList.length)return!0;const s=this.playoutLimit;return e<=0||isNaN(s)?!1:s===0?!0:(((t=this.assetList[e])==null?void 0:t.startOffset)||0)>s}findAssetIndex(e){return this.assetList.indexOf(e)}get identifier(){return this.dateRange.id}get startDate(){return this.dateRange.startDate}get startTime(){const e=this.dateRange.startTime;if(this.snapOptions.out){const t=this.dateRange.tagAnchor;if(t)return qs(e,t)}return e}get startOffset(){return this.cue.pre?0:this.startTime}get startIsAligned(){if(this.startTime===0||this.snapOptions.out)return!0;const e=this.dateRange.tagAnchor;if(e){const t=this.dateRange.startTime,s=qs(t,e);return t-s<.1}return!1}get resumptionOffset(){const e=this.resumeOffset,t=B(e)?e:this.duration;return this.cumulativeDuration+t}get resumeTime(){const e=this.startOffset+this.resumptionOffset;if(this.snapOptions.in){const t=this.resumeAnchor;if(t)return qs(e,t)}return e}get appendInPlace(){return this.appendInPlaceStarted?!0:this.appendInPlaceDisabled?!1:!!(!this.cue.once&&!this.cue.pre&&this.startIsAligned&&(isNaN(this.playoutLimit)&&isNaN(this.resumeOffset)||this.resumeOffset&&this.duration&&Math.abs(this.resumeOffset-this.duration)0||this.assetListResponse!==null}toString(){return ed(this)}}function qs(a,e){return a-e.start":a.cue.post?"":""}${a.timelineStart.toFixed(2)}-${a.resumeTime.toFixed(2)}]`}function It(a){const e=a.timelineStart,t=a.duration||0;return`["${a.identifier}" ${e.toFixed(2)}-${(e+t).toFixed(2)}]`}class td{constructor(e,t,s,i){this.hls=void 0,this.interstitial=void 0,this.assetItem=void 0,this.tracks=null,this.hasDetails=!1,this.mediaAttached=null,this._currentTime=void 0,this._bufferedEosTime=void 0,this.checkPlayout=()=>{this.reachedPlayout(this.currentTime)&&this.hls&&this.hls.trigger(m.PLAYOUT_LIMIT_REACHED,{})};const r=this.hls=new e(t);this.interstitial=s,this.assetItem=i;const n=()=>{this.hasDetails=!0};r.once(m.LEVEL_LOADED,n),r.once(m.AUDIO_TRACK_LOADED,n),r.once(m.SUBTITLE_TRACK_LOADED,n),r.on(m.MEDIA_ATTACHING,(o,{media:c})=>{this.removeMediaListeners(),this.mediaAttached=c,this.interstitial.playoutLimit&&(c.addEventListener("timeupdate",this.checkPlayout),this.appendInPlace&&r.on(m.BUFFER_APPENDED,()=>{const h=this.bufferedEnd;this.reachedPlayout(h)&&(this._bufferedEosTime=h,r.trigger(m.BUFFERED_TO_END,void 0))}))})}get appendInPlace(){return this.interstitial.appendInPlace}loadSource(){const e=this.hls;if(e)if(e.url)e.levels.length&&!e.started&&e.startLoad(-1,!0);else{let t=this.assetItem.uri;try{t=Ua(t,e.config.primarySessionId||"").href}catch{}e.loadSource(t)}}bufferedInPlaceToEnd(e){var t;if(!this.appendInPlace)return!1;if((t=this.hls)!=null&&t.bufferedToEnd)return!0;if(!e)return!1;const s=Math.min(this._bufferedEosTime||1/0,this.duration),i=this.timelineOffset,r=X.bufferInfo(e,i,0);return this.getAssetTime(r.end)>=s-.02}reachedPlayout(e){const s=this.interstitial.playoutLimit;return this.startOffset+e>=s}get destroyed(){var e;return!((e=this.hls)!=null&&e.userConfig)}get assetId(){return this.assetItem.identifier}get interstitialId(){return this.assetItem.parentIdentifier}get media(){var e;return((e=this.hls)==null?void 0:e.media)||null}get bufferedEnd(){const e=this.media||this.mediaAttached;if(!e)return this._bufferedEosTime?this._bufferedEosTime:this.currentTime;const t=X.bufferInfo(e,e.currentTime,.001);return this.getAssetTime(t.end)}get currentTime(){const e=this.media||this.mediaAttached;return e?this.getAssetTime(e.currentTime):this._currentTime||0}get duration(){const e=this.assetItem.duration;if(!e)return 0;const t=this.interstitial.playoutLimit;if(t){const s=t-this.startOffset;if(s>0&&s1/9e4&&this.hls){if(this.hasDetails)throw new Error("Cannot set timelineOffset after playlists are loaded");this.hls.config.timelineOffset=e}}}getAssetTime(e){const t=this.timelineOffset,s=this.duration;return Math.min(Math.max(0,e-t),s)}removeMediaListeners(){const e=this.mediaAttached;e&&(this._currentTime=e.currentTime,this.bufferSnapShot(),e.removeEventListener("timeupdate",this.checkPlayout))}bufferSnapShot(){if(this.mediaAttached){var e;(e=this.hls)!=null&&e.bufferedToEnd&&(this._bufferedEosTime=this.bufferedEnd)}}destroy(){this.removeMediaListeners(),this.hls&&this.hls.destroy(),this.hls=null,this.tracks=this.mediaAttached=this.checkPlayout=null}attachMedia(e){var t;this.loadSource(),(t=this.hls)==null||t.attachMedia(e)}detachMedia(){var e;this.removeMediaListeners(),this.mediaAttached=null,(e=this.hls)==null||e.detachMedia()}resumeBuffering(){var e;(e=this.hls)==null||e.resumeBuffering()}pauseBuffering(){var e;(e=this.hls)==null||e.pauseBuffering()}transferMedia(){var e;return this.bufferSnapShot(),((e=this.hls)==null?void 0:e.transferMedia())||null}resetDetails(){const e=this.hls;if(e&&this.hasDetails){e.stopLoad();const t=s=>delete s.details;e.levels.forEach(t),e.allAudioTracks.forEach(t),e.allSubtitleTracks.forEach(t),this.hasDetails=!1}}on(e,t,s){var i;(i=this.hls)==null||i.on(e,t)}once(e,t,s){var i;(i=this.hls)==null||i.once(e,t)}off(e,t,s){var i;(i=this.hls)==null||i.off(e,t)}toString(){var e;return`HlsAssetPlayer: ${It(this.assetItem)} ${(e=this.hls)==null?void 0:e.sessionId} ${this.appendInPlace?"append-in-place":""}`}}const rn=.033;class sd extends Oe{constructor(e,t){super("interstitials-sched",t),this.onScheduleUpdate=void 0,this.eventMap={},this.events=null,this.items=null,this.durations={primary:0,playout:0,integrated:0},this.onScheduleUpdate=e}destroy(){this.reset(),this.onScheduleUpdate=null}reset(){this.eventMap={},this.setDurations(0,0,0),this.events&&this.events.forEach(e=>e.reset()),this.events=this.items=null}resetErrorsInRange(e,t){return this.events?this.events.reduce((s,i)=>e<=i.startOffset&&t>i.startOffset?(delete i.error,s+1):s,0):0}get duration(){const e=this.items;return e?e[e.length-1].end:0}get length(){return this.items?this.items.length:0}getEvent(e){return e&&this.eventMap[e]||null}hasEvent(e){return e in this.eventMap}findItemIndex(e,t){if(e.event)return this.findEventIndex(e.event.identifier);let s=-1;e.nextEvent?s=this.findEventIndex(e.nextEvent.identifier)-1:e.previousEvent&&(s=this.findEventIndex(e.previousEvent.identifier)+1);const i=this.items;if(i)for(i[s]||(t===void 0&&(t=e.start),s=this.findItemIndexAtTime(t));s>=0&&(r=i[s])!=null&&r.event;){var r;s--}return s}findItemIndexAtTime(e,t){const s=this.items;if(s)for(let i=0;ir.start&&e1)for(let r=0;ro&&(t!o.includes(l.identifier)):[];n.length&&n.sort((l,h)=>{const d=l.cue.pre,u=l.cue.post,f=h.cue.pre,g=h.cue.post;if(d&&!f)return-1;if(f&&!d||u&&!g)return 1;if(g&&!u)return-1;if(!d&&!f&&!u&&!g){const y=l.startTime,p=h.startTime;if(y!==p)return y-p}return l.dateRange.tagOrder-h.dateRange.tagOrder}),this.events=n,c.forEach(l=>{this.removeEvent(l)}),this.updateSchedule(e,c)}updateSchedule(e,t=[],s=!1){const i=this.events||[];if(i.length||t.length||this.length<2){const r=this.items,n=this.parseSchedule(i,e);(s||t.length||(r==null?void 0:r.length)!==n.length||n.some((c,l)=>Math.abs(c.playout.start-r[l].playout.start)>.005||Math.abs(c.playout.end-r[l].playout.end)>.005))&&(this.items=n,this.onScheduleUpdate(t,r))}}parseDateRanges(e,t,s){const i=[],r=Object.keys(e);for(let n=0;n!c.error&&!(c.cue.once&&c.hasPlayed)),e.length){this.resolveOffsets(e,t);let c=0,l=0;if(e.forEach((h,d)=>{const u=h.cue.pre,f=h.cue.post,g=e[d-1]||null,y=h.appendInPlace,p=f?r:h.startOffset,E=h.duration,T=h.timelineOccupancy===_s.Range?E:0,S=h.resumptionOffset,v=(g==null?void 0:g.startTime)===p,x=p+h.cumulativeDuration;let D=y?x+E:p+S;if(u||!f&&p<=0){const _=l;l+=T,h.timelineStart=x;const b=n;n+=E,s.push({event:h,start:x,end:D,playout:{start:b,end:n},integrated:{start:_,end:l}})}else if(p<=r){if(!v){const I=p-c;if(I>rn){const P=c,M=l;l+=I;const G=n;n+=I;const W={previousEvent:e[d-1]||null,nextEvent:h,start:P,end:P+I,playout:{start:G,end:n},integrated:{start:M,end:l}};s.push(W)}else I>0&&g&&(g.cumulativeDuration+=I,s[s.length-1].end=p)}f&&(D=x),h.timelineStart=x;const _=l;l+=T;const b=n;n+=E,s.push({event:h,start:x,end:D,playout:{start:b,end:n},integrated:{start:_,end:l}})}else return;const A=h.resumeTime;f||A>r?c=r:c=A}),c{const l=o.cue.pre,h=o.cue.post,d=l?0:h?i:o.startTime;this.updateAssetDurations(o),n===d?o.cumulativeDuration=r:(r=0,n=d),!h&&o.snapOptions.in&&(o.resumeAnchor=pt(null,s.fragments,o.startOffset+o.resumptionOffset,0,0)||void 0),o.appendInPlace&&!o.appendInPlaceStarted&&(this.primaryCanResumeInPlaceAt(o,t)||(o.appendInPlace=!1)),!o.appendInPlace&&c+1Ct?(this.log(`"${e.identifier}" resumption ${s} not aligned with estimated timeline end ${i}`),!1):!Object.keys(t).some(n=>{const o=t[n].details,c=o.edge;if(s>=c)return this.log(`"${e.identifier}" resumption ${s} past ${n} playlist end ${c}`),!1;const l=pt(null,o.fragments,s);if(!l)return this.log(`"${e.identifier}" resumption ${s} does not align with any fragments in ${n} playlist (${o.fragStart}-${o.fragmentEnd})`),!0;const h=n==="audio"?.175:0;return Math.abs(l.start-s){const p=u.data,E=p==null?void 0:p.ASSETS;if(!Array.isArray(E)){const T=this.assignAssetListError(e,R.ASSET_LIST_PARSING_ERROR,new Error("Invalid interstitial asset list"),g.url,f,y);this.hls.trigger(m.ERROR,T);return}e.assetListResponse=p,this.hls.trigger(m.ASSET_LIST_LOADED,{event:e,assetListResponse:p,networkDetails:y})},onError:(u,f,g,y)=>{const p=this.assignAssetListError(e,R.ASSET_LIST_LOAD_ERROR,new Error(`Error loading X-ASSET-LIST: HTTP status ${u.code} ${u.text} (${f.url})`),f.url,y,g);this.hls.trigger(m.ERROR,p)},onTimeout:(u,f,g)=>{const y=this.assignAssetListError(e,R.ASSET_LIST_LOAD_TIMEOUT,new Error(`Timeout loading X-ASSET-LIST (${f.url})`),f.url,u,g);this.hls.trigger(m.ERROR,y)}};return o.load(c,h,d),this.hls.trigger(m.ASSET_LIST_LOADING,{event:e}),o}assignAssetListError(e,t,s,i,r,n){return e.error=s,{type:Y.NETWORK_ERROR,details:t,fatal:!1,interstitial:e,url:i,error:s,networkDetails:n,stats:r}}}function nn(a){var e;a==null||(e=a.play())==null||e.catch(()=>{})}function At(a,e){return`[${a}] Advancing timeline position to ${e}`}class rd extends Oe{constructor(e,t){super("interstitials",e.logger),this.HlsPlayerClass=void 0,this.hls=void 0,this.assetListLoader=void 0,this.mediaSelection=null,this.altSelection=null,this.media=null,this.detachedData=null,this.requiredTracks=null,this.manager=null,this.playerQueue=[],this.bufferedPos=-1,this.timelinePos=-1,this.schedule=void 0,this.playingItem=null,this.bufferingItem=null,this.waitingItem=null,this.endedItem=null,this.playingAsset=null,this.endedAsset=null,this.bufferingAsset=null,this.shouldPlay=!1,this.onPlay=()=>{this.shouldPlay=!0},this.onPause=()=>{this.shouldPlay=!1},this.onSeeking=()=>{const s=this.currentTime;if(s===void 0||this.playbackDisabled||!this.schedule)return;const i=s-this.timelinePos;if(Math.abs(i)<1/7056e5)return;const n=i<=-.01;this.timelinePos===-1&&!this.effectivePlayingItem&&this.checkStart(),this.timelinePos=s,this.bufferedPos=s;const o=this.playingItem;if(!o){this.checkBuffer();return}if(n&&this.schedule.resetErrorsInRange(s,s-i)&&this.updateSchedule(!0),this.checkBuffer(),n&&s=o.end){var c;const f=this.findItemIndex(o);let g=this.schedule.findItemIndexAtTime(s);if(g===-1&&(g=f+(n?-1:1),this.log(`seeked ${n?"back ":""}to position not covered by schedule ${s} (resolving from ${f} to ${g})`)),!this.isInterstitial(o)&&(c=this.media)!=null&&c.paused&&(this.shouldPlay=!1),!n&&g>f){const y=this.schedule.findJumpRestrictedIndex(f+1,g);if(y>f){this.setSchedulePosition(y);return}}this.setSchedulePosition(g);return}const l=this.playingAsset;if(!l){if(this.playingLastItem&&this.isInterstitial(o)){const f=o.event.assetList[0];f&&(this.endedItem=this.playingItem,this.playingItem=null,this.setScheduleToAssetAtTime(s,f))}return}const h=l.timelineStart,d=l.duration||0;if(n&&s=h+d){var u;(u=o.event)!=null&&u.appendInPlace&&(this.clearAssetPlayers(o.event,o),this.flushFrontBuffer(s)),this.setScheduleToAssetAtTime(s,l)}},this.onTimeupdate=()=>{const s=this.currentTime;if(s===void 0||this.playbackDisabled)return;if(this.timelinePos===-1&&!this.effectivePlayingItem&&this.checkStart(),s>this.timelinePos)this.timelinePos=s,s>this.bufferedPos&&this.checkBuffer();else return;const i=this.playingItem;if(!i||this.playingLastItem)return;if(s>=i.end){this.timelinePos=i.end;const o=this.findItemIndex(i);this.setSchedulePosition(o+1)}const r=this.playingAsset;if(!r)return;const n=r.timelineStart+(r.duration||0);s>=n&&this.setScheduleToAssetAtTime(s,r)},this.onScheduleUpdate=(s,i)=>{const r=this.schedule;if(!r)return;const n=this.playingItem,o=r.events||[],c=r.items||[],l=r.durations,h=s.map(y=>y.identifier),d=!!(o.length||h.length);(d||i)&&this.log(`INTERSTITIALS_UPDATED (${o.length}): ${o} -Schedule: ${c.map(y=>Me(y))} pos: ${this.timelinePos}`),h.length&&this.log(`Removed events ${h}`);let u=null,f=null;n&&(u=this.updateItem(n,this.timelinePos),this.itemsMatch(n,u)?this.playingItem=u:this.waitingItem=this.endedItem=null),this.waitingItem=this.updateItem(this.waitingItem),this.endedItem=this.updateItem(this.endedItem);const g=this.bufferingItem;if(g&&(f=this.updateItem(g,this.bufferedPos),this.itemsMatch(g,f)?this.bufferingItem=f:g.event&&(this.bufferingItem=this.playingItem,this.clearInterstitial(g.event,null))),s.forEach(y=>{y.assetList.forEach(p=>{this.clearAssetPlayer(p.identifier,null)})}),this.playerQueue.forEach(y=>{if(y.interstitial.appendInPlace){const p=y.assetItem.timelineStart,E=y.timelineOffset-p;if(E)try{y.timelineOffset=p}catch(T){Math.abs(E)>Ct&&this.warn(`${T} ("${y.assetId}" ${y.timelineOffset}->${p})`)}}}),d||i){if(this.hls.trigger(m.INTERSTITIALS_UPDATED,{events:o.slice(0),schedule:c.slice(0),durations:l,removedIds:h}),this.isInterstitial(n)&&h.includes(n.event.identifier)){this.warn(`Interstitial "${n.event.identifier}" removed while playing`),this.primaryFallback(n.event);return}n&&this.trimInPlace(u,n),g&&f!==u&&this.trimInPlace(f,g),this.checkBuffer()}},this.hls=e,this.HlsPlayerClass=t,this.assetListLoader=new id(e),this.schedule=new sd(this.onScheduleUpdate,e.logger),this.registerListeners()}registerListeners(){const e=this.hls;e&&(e.on(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.on(m.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),e.on(m.AUDIO_TRACK_UPDATED,this.onAudioTrackUpdated,this),e.on(m.SUBTITLE_TRACK_SWITCH,this.onSubtitleTrackSwitch,this),e.on(m.SUBTITLE_TRACK_UPDATED,this.onSubtitleTrackUpdated,this),e.on(m.EVENT_CUE_ENTER,this.onInterstitialCueEnter,this),e.on(m.ASSET_LIST_LOADED,this.onAssetListLoaded,this),e.on(m.BUFFER_APPENDED,this.onBufferAppended,this),e.on(m.BUFFER_FLUSHED,this.onBufferFlushed,this),e.on(m.BUFFERED_TO_END,this.onBufferedToEnd,this),e.on(m.MEDIA_ENDED,this.onMediaEnded,this),e.on(m.ERROR,this.onError,this),e.on(m.DESTROYING,this.onDestroying,this))}unregisterListeners(){const e=this.hls;e&&(e.off(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.off(m.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),e.off(m.AUDIO_TRACK_UPDATED,this.onAudioTrackUpdated,this),e.off(m.SUBTITLE_TRACK_SWITCH,this.onSubtitleTrackSwitch,this),e.off(m.SUBTITLE_TRACK_UPDATED,this.onSubtitleTrackUpdated,this),e.off(m.EVENT_CUE_ENTER,this.onInterstitialCueEnter,this),e.off(m.ASSET_LIST_LOADED,this.onAssetListLoaded,this),e.off(m.BUFFER_CODECS,this.onBufferCodecs,this),e.off(m.BUFFER_APPENDED,this.onBufferAppended,this),e.off(m.BUFFER_FLUSHED,this.onBufferFlushed,this),e.off(m.BUFFERED_TO_END,this.onBufferedToEnd,this),e.off(m.MEDIA_ENDED,this.onMediaEnded,this),e.off(m.ERROR,this.onError,this),e.off(m.DESTROYING,this.onDestroying,this))}startLoad(){this.resumeBuffering()}stopLoad(){this.pauseBuffering()}resumeBuffering(){var e;(e=this.getBufferingPlayer())==null||e.resumeBuffering()}pauseBuffering(){var e;(e=this.getBufferingPlayer())==null||e.pauseBuffering()}destroy(){this.unregisterListeners(),this.stopLoad(),this.assetListLoader&&this.assetListLoader.destroy(),this.emptyPlayerQueue(),this.clearScheduleState(),this.schedule&&this.schedule.destroy(),this.media=this.detachedData=this.mediaSelection=this.requiredTracks=this.altSelection=this.schedule=this.manager=null,this.hls=this.HlsPlayerClass=this.log=null,this.assetListLoader=null,this.onPlay=this.onPause=this.onSeeking=this.onTimeupdate=null,this.onScheduleUpdate=null}onDestroying(){const e=this.primaryMedia||this.media;e&&this.removeMediaListeners(e)}removeMediaListeners(e){Ie(e,"play",this.onPlay),Ie(e,"pause",this.onPause),Ie(e,"seeking",this.onSeeking),Ie(e,"timeupdate",this.onTimeupdate)}onMediaAttaching(e,t){const s=this.media=t.media;xe(s,"seeking",this.onSeeking),xe(s,"timeupdate",this.onTimeupdate),xe(s,"play",this.onPlay),xe(s,"pause",this.onPause)}onMediaAttached(e,t){const s=this.effectivePlayingItem,i=this.detachedData;if(this.detachedData=null,s===null)this.checkStart();else if(!i){this.clearScheduleState();const r=this.findItemIndex(s);this.setSchedulePosition(r)}}clearScheduleState(){this.log("clear schedule state"),this.playingItem=this.bufferingItem=this.waitingItem=this.endedItem=this.playingAsset=this.endedAsset=this.bufferingAsset=null}onMediaDetaching(e,t){const s=!!t.transferMedia,i=this.media;if(this.media=null,!s&&(i&&this.removeMediaListeners(i),this.detachedData)){const r=this.getBufferingPlayer();r&&(this.log(`Removing schedule state for detachedData and ${r}`),this.playingAsset=this.endedAsset=this.bufferingAsset=this.bufferingItem=this.waitingItem=this.detachedData=null,r.detachMedia()),this.shouldPlay=!1}}get interstitialsManager(){if(!this.hls)return null;if(this.manager)return this.manager;const e=this,t=()=>e.bufferingItem||e.waitingItem,s=d=>d&&e.getAssetPlayer(d.identifier),i=(d,u,f,g,y)=>{if(d){let p=d[u].start;const E=d.event;if(E){if(u==="playout"||E.timelineOccupancy!==_s.Point){const T=s(f);(T==null?void 0:T.interstitial)===E&&(p+=T.assetItem.startOffset+T[y])}}else{const T=g==="bufferedPos"?n():e[g];p+=T-d.start}return p}return 0},r=(d,u)=>{var f;if(d!==0&&u!=="primary"&&(f=e.schedule)!=null&&f.length){var g;const y=e.schedule.findItemIndexAtTime(d),p=(g=e.schedule.items)==null?void 0:g[y];if(p){const E=p[u].start-p.start;return d+E}}return d},n=()=>{const d=e.bufferedPos;return d===Number.MAX_VALUE?o("primary"):Math.max(d,0)},o=d=>{var u,f;return(u=e.primaryDetails)!=null&&u.live?e.primaryDetails.edge:((f=e.schedule)==null?void 0:f.durations[d])||0},c=(d,u)=>{var f,g;const y=e.effectivePlayingItem;if(y!=null&&(f=y.event)!=null&&f.restrictions.skip||!e.schedule)return;e.log(`seek to ${d} "${u}"`);const p=e.effectivePlayingItem,E=e.schedule.findItemIndexAtTime(d,u),T=(g=e.schedule.items)==null?void 0:g[E],S=e.getBufferingPlayer(),v=S==null?void 0:S.interstitial,x=v==null?void 0:v.appendInPlace,D=p&&e.itemsMatch(p,T);if(p&&(x||D)){const A=s(e.playingAsset),_=(A==null?void 0:A.media)||e.primaryMedia;if(_){const b=u==="primary"?_.currentTime:i(p,u,e.playingAsset,"timelinePos","currentTime"),I=d-b,P=(x?b:_.currentTime)+I;if(P>=0&&(!A||x||P<=A.duration)){_.currentTime=P;return}}}if(T){let A=d;if(u!=="primary"){const b=T[u].start,I=d-b;A=T.start+I}const _=!e.isInterstitial(T);if((!e.isInterstitial(p)||p.event.appendInPlace)&&(_||T.event.appendInPlace)){const b=e.media||(x?S==null?void 0:S.media:null);b&&(b.currentTime=A)}else if(p){const b=e.findItemIndex(p);if(E>b){const P=e.schedule.findJumpRestrictedIndex(b+1,E);if(P>b){e.setSchedulePosition(P);return}}let I=0;if(_)e.timelinePos=A,e.checkBuffer();else{const P=T.event.assetList,M=d-(T[u]||T).start;for(let G=P.length;G--;){const W=P[G];if(W.duration&&M>=W.startOffset&&M{const d=e.effectivePlayingItem;if(e.isInterstitial(d))return d;const u=t();return e.isInterstitial(u)?u:null},h={get bufferedEnd(){const d=t(),u=e.bufferingItem;if(u&&u===d){var f;return i(u,"playout",e.bufferingAsset,"bufferedPos","bufferedEnd")-u.playout.start||((f=e.bufferingAsset)==null?void 0:f.startOffset)||0}return 0},get currentTime(){const d=l(),u=e.effectivePlayingItem;return u&&u===d?i(u,"playout",e.effectivePlayingAsset,"timelinePos","currentTime")-u.playout.start:0},set currentTime(d){const u=l(),f=e.effectivePlayingItem;f&&f===u&&c(d+f.playout.start,"playout")},get duration(){const d=l();return d?d.playout.end-d.playout.start:0},get assetPlayers(){var d;const u=(d=l())==null?void 0:d.event.assetList;return u?u.map(f=>e.getAssetPlayer(f.identifier)):[]},get playingIndex(){var d;const u=(d=l())==null?void 0:d.event;return u&&e.effectivePlayingAsset?u.findAssetIndex(e.effectivePlayingAsset):-1},get scheduleItem(){return l()}};return this.manager={get events(){var d;return((d=e.schedule)==null||(d=d.events)==null?void 0:d.slice(0))||[]},get schedule(){var d;return((d=e.schedule)==null||(d=d.items)==null?void 0:d.slice(0))||[]},get interstitialPlayer(){return l()?h:null},get playerQueue(){return e.playerQueue.slice(0)},get bufferingAsset(){return e.bufferingAsset},get bufferingItem(){return t()},get bufferingIndex(){const d=t();return e.findItemIndex(d)},get playingAsset(){return e.effectivePlayingAsset},get playingItem(){return e.effectivePlayingItem},get playingIndex(){const d=e.effectivePlayingItem;return e.findItemIndex(d)},primary:{get bufferedEnd(){return n()},get currentTime(){const d=e.timelinePos;return d>0?d:0},set currentTime(d){c(d,"primary")},get duration(){return o("primary")},get seekableStart(){var d;return((d=e.primaryDetails)==null?void 0:d.fragmentStart)||0}},integrated:{get bufferedEnd(){return i(t(),"integrated",e.bufferingAsset,"bufferedPos","bufferedEnd")},get currentTime(){return i(e.effectivePlayingItem,"integrated",e.effectivePlayingAsset,"timelinePos","currentTime")},set currentTime(d){c(d,"integrated")},get duration(){return o("integrated")},get seekableStart(){var d;return r(((d=e.primaryDetails)==null?void 0:d.fragmentStart)||0,"integrated")}},skip:()=>{const d=e.effectivePlayingItem,u=d==null?void 0:d.event;if(u&&!u.restrictions.skip){const f=e.findItemIndex(d);if(u.appendInPlace){const g=d.playout.start+d.event.duration;c(g+.001,"playout")}else e.advanceAfterAssetEnded(u,f,1/0)}}}}get effectivePlayingItem(){return this.waitingItem||this.playingItem||this.endedItem}get effectivePlayingAsset(){return this.playingAsset||this.endedAsset}get playingLastItem(){var e;const t=this.playingItem,s=(e=this.schedule)==null?void 0:e.items;return!this.playbackStarted||!t||!s?!1:this.findItemIndex(t)===s.length-1}get playbackStarted(){return this.effectivePlayingItem!==null}get currentTime(){var e,t;if(this.mediaSelection===null)return;const s=this.waitingItem||this.playingItem;if(this.isInterstitial(s)&&!s.event.appendInPlace)return;let i=this.media;!i&&(e=this.bufferingItem)!=null&&(e=e.event)!=null&&e.appendInPlace&&(i=this.primaryMedia);const r=(t=i)==null?void 0:t.currentTime;if(!(r===void 0||!B(r)))return r}get primaryMedia(){var e;return this.media||((e=this.detachedData)==null?void 0:e.media)||null}isInterstitial(e){return!!(e!=null&&e.event)}retreiveMediaSource(e,t){const s=this.getAssetPlayer(e);s&&this.transferMediaFromPlayer(s,t)}transferMediaFromPlayer(e,t){const s=e.interstitial.appendInPlace,i=e.media;if(s&&i===this.primaryMedia){if(this.bufferingAsset=null,(!t||this.isInterstitial(t)&&!t.event.appendInPlace)&&t&&i){this.detachedData={media:i};return}const r=e.transferMedia();this.log(`transfer MediaSource from ${e} ${oe(r)}`),this.detachedData=r}else t&&i&&(this.shouldPlay||(this.shouldPlay=!i.paused))}transferMediaTo(e,t){var s,i;if(e.media===t)return;let r=null;const n=this.hls,o=e!==n,c=o&&e.interstitial.appendInPlace,l=(s=this.detachedData)==null?void 0:s.mediaSource;let h;if(n.media)c&&(r=n.transferMedia(),this.detachedData=r),h="Primary";else if(l){const g=this.getBufferingPlayer();g?(r=g.transferMedia(),h=`${g}`):h="detached MediaSource"}else h="detached media";if(!r){if(l)r=this.detachedData,this.log(`using detachedData: MediaSource ${oe(r)}`);else if(!this.detachedData||n.media===t){const g=this.playerQueue;g.length>1&&g.forEach(y=>{if(o&&y.interstitial.appendInPlace!==c){const p=y.interstitial;this.clearInterstitial(y.interstitial,null),p.appendInPlace=!1,p.appendInPlace&&this.warn(`Could not change append strategy for queued assets ${p}`)}}),this.hls.detachMedia(),this.detachedData={media:t}}}const d=r&&"mediaSource"in r&&((i=r.mediaSource)==null?void 0:i.readyState)!=="closed",u=d&&r?r:t;this.log(`${d?"transfering MediaSource":"attaching media"} to ${o?e:"Primary"} from ${h} (media.currentTime: ${t.currentTime})`);const f=this.schedule;if(u===r&&f){const g=o&&e.assetId===f.assetIdAtEnd;u.overrides={duration:f.duration,endOfStream:!o||g,cueRemoval:!o}}e.attachMedia(u)}onInterstitialCueEnter(){this.onTimeupdate()}checkStart(){const e=this.schedule,t=e==null?void 0:e.events;if(!t||this.playbackDisabled||!this.media)return;this.bufferedPos===-1&&(this.bufferedPos=0);const s=this.timelinePos,i=this.effectivePlayingItem;if(s===-1){const r=this.hls.startPosition;if(this.timelinePos=r,t.length===0)this.setSchedulePosition(0);else if(t[0].cue.pre){this.log(At("checkStart (preroll)",r));const n=e.findEventIndex(t[0].identifier);this.setSchedulePosition(n)}else if(r>=0||!this.primaryLive){this.log(At("checkStart",r));const n=this.timelinePos=r>0?r:0,o=e.findItemIndexAtTime(n);this.setSchedulePosition(o)}else this.hls.liveSyncPosition===0?this.setSchedulePosition(0):this.log("[checkStart] waiting for live start")}else if(i&&!this.playingItem){this.log(At("checkStart (playing item)",i.start));const r=e.findItemIndex(i);this.setSchedulePosition(r)}}advanceAssetBuffering(e,t){const s=e.event,i=s.findAssetIndex(t),r=js(s,i);if(!s.isAssetPastPlayoutLimit(r))this.bufferedToEvent(e,r);else if(this.schedule){var n;const o=(n=this.schedule.items)==null?void 0:n[this.findItemIndex(e)+1];o&&this.bufferedToItem(o)}}advanceAfterAssetEnded(e,t,s){const i=js(e,s);if(e.isAssetPastPlayoutLimit(i)){if(this.schedule){const r=this.schedule.items;if(r){const n=t+1,o=r.length;if(n>=o){this.setSchedulePosition(-1);return}const c=e.resumeTime;this.timelinePos=0?i[e]:null;this.log(`setSchedulePosition ${e}, ${t} (${r&&Me(r)}) pos: ${this.timelinePos}`);const n=this.waitingItem||this.playingItem,o=this.playingLastItem;if(this.isInterstitial(n)){const h=n.event,d=this.playingAsset,u=d==null?void 0:d.identifier,f=u?this.getAssetPlayer(u):null;if(f&&u&&(!this.eventItemsMatch(n,r)||t!==void 0&&u!==h.assetList[t].identifier)){var c;const g=h.findAssetIndex(d);if(this.log(`INTERSTITIAL_ASSET_ENDED ${g+1}/${h.assetList.length} ${It(d)}`),this.endedAsset=d,this.playingAsset=null,this.hls.trigger(m.INTERSTITIAL_ASSET_ENDED,{asset:d,assetListIndex:g,event:h,schedule:i.slice(0),scheduleIndex:e,player:f}),n!==this.playingItem){this.itemsMatch(n,this.playingItem)&&!this.playingAsset&&this.advanceAfterAssetEnded(h,this.findItemIndex(this.playingItem),g);return}this.retreiveMediaSource(u,r),f.media&&!((c=this.detachedData)!=null&&c.mediaSource)&&f.detachMedia()}if(!this.eventItemsMatch(n,r)&&(this.endedItem=n,this.playingItem=null,this.log(`INTERSTITIAL_ENDED ${h} ${Me(n)}`),h.hasPlayed=!0,this.hls.trigger(m.INTERSTITIAL_ENDED,{event:h,schedule:i.slice(0),scheduleIndex:e}),h.cue.once)){var l;this.updateSchedule();const g=(l=this.schedule)==null?void 0:l.items;if(r&&g){const y=this.findItemIndex(r);this.advanceSchedule(y,g,t,n,o)}return}}this.advanceSchedule(e,i,t,n,o)}advanceSchedule(e,t,s,i,r){const n=this.schedule;if(!n)return;const o=t[e]||null,c=this.primaryMedia,l=this.playerQueue;if(l.length&&l.forEach(h=>{const d=h.interstitial,u=n.findEventIndex(d.identifier);(ue+1)&&this.clearInterstitial(d,o)}),this.isInterstitial(o)){this.timelinePos=Math.min(Math.max(this.timelinePos,o.start),o.end);const h=o.event;if(s===void 0){s=n.findAssetIndex(h,this.timelinePos);const g=js(h,s-1);if(h.isAssetPastPlayoutLimit(g)||h.appendInPlace&&this.timelinePos===o.end){this.advanceAfterAssetEnded(h,e,s);return}s=g}const d=this.waitingItem;this.assetsBuffered(o,c)||this.setBufferingItem(o);let u=this.preloadAssets(h,s);if(this.eventItemsMatch(o,d||i)||(this.waitingItem=o,this.log(`INTERSTITIAL_STARTED ${Me(o)} ${h.appendInPlace?"append in place":""}`),this.hls.trigger(m.INTERSTITIAL_STARTED,{event:h,schedule:t.slice(0),scheduleIndex:e})),!h.assetListLoaded){this.log(`Waiting for ASSET-LIST to complete loading ${h}`);return}if(h.assetListLoader&&(h.assetListLoader.destroy(),h.assetListLoader=void 0),!c){this.log(`Waiting for attachMedia to start Interstitial ${h}`);return}this.waitingItem=this.endedItem=null,this.playingItem=o;const f=h.assetList[s];if(!f){this.advanceAfterAssetEnded(h,e,s||0);return}if(u||(u=this.getAssetPlayer(f.identifier)),u===null||u.destroyed){const g=h.assetList.length;this.warn(`asset ${s+1}/${g} player destroyed ${h}`),u=this.createAssetPlayer(h,f,s),u.loadSource()}if(!this.eventItemsMatch(o,this.bufferingItem)&&h.appendInPlace&&this.isAssetBuffered(f))return;this.startAssetPlayer(u,s,t,e,c),this.shouldPlay&&nn(u.media)}else o?(this.resumePrimary(o,e,i),this.shouldPlay&&nn(this.hls.media)):r&&this.isInterstitial(i)&&(this.endedItem=null,this.playingItem=i,i.event.appendInPlace||this.attachPrimary(n.durations.primary,null))}get playbackDisabled(){return this.hls.config.enableInterstitialPlayback===!1}get primaryDetails(){var e;return(e=this.mediaSelection)==null?void 0:e.main.details}get primaryLive(){var e;return!!((e=this.primaryDetails)!=null&&e.live)}resumePrimary(e,t,s){var i,r;if(this.playingItem=e,this.playingAsset=this.endedAsset=null,this.waitingItem=this.endedItem=null,this.bufferedToItem(e),this.log(`resuming ${Me(e)}`),!((i=this.detachedData)!=null&&i.mediaSource)){let o=this.timelinePos;(o=e.end)&&(o=this.getPrimaryResumption(e,t),this.log(At("resumePrimary",o)),this.timelinePos=o),this.attachPrimary(o,e)}if(!s)return;const n=(r=this.schedule)==null?void 0:r.items;n&&(this.log(`INTERSTITIALS_PRIMARY_RESUMED ${Me(e)}`),this.hls.trigger(m.INTERSTITIALS_PRIMARY_RESUMED,{schedule:n.slice(0),scheduleIndex:t}),this.checkBuffer())}getPrimaryResumption(e,t){const s=e.start;if(this.primaryLive){const i=this.primaryDetails;if(t===0)return this.hls.startPosition;if(i&&(si.edge))return this.hls.liveSyncPosition||-1}return s}isAssetBuffered(e){const t=this.getAssetPlayer(e.identifier);return t!=null&&t.hls?t.hls.bufferedToEnd:X.bufferInfo(this.primaryMedia,this.timelinePos,0).end+1>=e.timelineStart+(e.duration||0)}attachPrimary(e,t,s){t?this.setBufferingItem(t):this.bufferingItem=this.playingItem,this.bufferingAsset=null;const i=this.primaryMedia;if(!i)return;const r=this.hls;r.media?this.checkBuffer():(this.transferMediaTo(r,i),s&&this.startLoadingPrimaryAt(e,s)),s||(this.log(At("attachPrimary",e)),this.timelinePos=e,this.startLoadingPrimaryAt(e,s))}startLoadingPrimaryAt(e,t){var s;const i=this.hls;!i.loadingEnabled||!i.media||Math.abs((((s=i.mainForwardBufferInfo)==null?void 0:s.start)||i.media.currentTime)-e)>.5?i.startLoad(e,t):i.bufferingEnabled||i.resumeBuffering()}onManifestLoading(){var e;this.stopLoad(),(e=this.schedule)==null||e.reset(),this.emptyPlayerQueue(),this.clearScheduleState(),this.shouldPlay=!1,this.bufferedPos=this.timelinePos=-1,this.mediaSelection=this.altSelection=this.manager=this.requiredTracks=null,this.hls.off(m.BUFFER_CODECS,this.onBufferCodecs,this),this.hls.on(m.BUFFER_CODECS,this.onBufferCodecs,this)}onLevelUpdated(e,t){if(t.level===-1||!this.schedule)return;const s=this.hls.levels[t.level];if(!s.details)return;const i=ie(ie({},this.mediaSelection||this.altSelection),{},{main:s});this.mediaSelection=i,this.schedule.parseInterstitialDateRanges(i,this.hls.config.interstitialAppendInPlace),!this.effectivePlayingItem&&this.schedule.items&&this.checkStart()}onAudioTrackUpdated(e,t){const s=this.hls.audioTracks[t.id],i=this.mediaSelection;if(!i){this.altSelection=ie(ie({},this.altSelection),{},{audio:s});return}const r=ie(ie({},i),{},{audio:s});this.mediaSelection=r}onSubtitleTrackUpdated(e,t){const s=this.hls.subtitleTracks[t.id],i=this.mediaSelection;if(!i){this.altSelection=ie(ie({},this.altSelection),{},{subtitles:s});return}const r=ie(ie({},i),{},{subtitles:s});this.mediaSelection=r}onAudioTrackSwitching(e,t){const s=fr(t);this.playerQueue.forEach(({hls:i})=>i&&(i.setAudioOption(t)||i.setAudioOption(s)))}onSubtitleTrackSwitch(e,t){const s=fr(t);this.playerQueue.forEach(({hls:i})=>i&&(i.setSubtitleOption(t)||t.id!==-1&&i.setSubtitleOption(s)))}onBufferCodecs(e,t){const s=t.tracks;s&&(this.requiredTracks=s)}onBufferAppended(e,t){this.checkBuffer()}onBufferFlushed(e,t){const s=this.playingItem;if(s&&!this.itemsMatch(s,this.bufferingItem)&&!this.isInterstitial(s)){const i=this.timelinePos;this.bufferedPos=i,this.checkBuffer()}}onBufferedToEnd(e){if(!this.schedule)return;const t=this.schedule.events;if(this.bufferedPos.25){e.event.assetList.forEach((r,n)=>{e.event.isAssetPastPlayoutLimit(n)&&this.clearAssetPlayer(r.identifier,null)});const s=e.end+.25,i=X.bufferInfo(this.primaryMedia,s,0);(i.end>s||(i.nextStart||0)>s)&&(this.log(`trim buffered interstitial ${Me(e)} (was ${Me(t)})`),this.attachPrimary(s,null,!0),this.flushFrontBuffer(s))}}itemsMatch(e,t){return!!t&&(e===t||e.event&&t.event&&this.eventItemsMatch(e,t)||!e.event&&!t.event&&this.findItemIndex(e)===this.findItemIndex(t))}eventItemsMatch(e,t){var s;return!!t&&(e===t||e.event.identifier===((s=t.event)==null?void 0:s.identifier))}findItemIndex(e,t){return e&&this.schedule?this.schedule.findItemIndex(e,t):-1}updateSchedule(e=!1){var t;const s=this.mediaSelection;s&&((t=this.schedule)==null||t.updateSchedule(s,[],e))}checkBuffer(e){var t;const s=(t=this.schedule)==null?void 0:t.items;if(!s)return;const i=X.bufferInfo(this.primaryMedia,this.timelinePos,0);e&&(this.bufferedPos=this.timelinePos),e||(e=i.len<1),this.updateBufferedPos(i.end,s,e)}updateBufferedPos(e,t,s){const i=this.schedule,r=this.bufferingItem;if(this.bufferedPos>e||!i)return;if(t.length===1&&this.itemsMatch(t[0],r)){this.bufferedPos=e;return}const n=this.playingItem,o=this.findItemIndex(n);let c=i.findItemIndexAtTime(e);if(this.bufferedPos=r.end||(l=u.event)!=null&&l.appendInPlace&&e+.01>=u.start)&&(c=d),this.isInterstitial(r)){const f=r.event;if(d-o>1&&f.appendInPlace===!1||f.assetList.length===0&&f.assetListLoader)return}if(this.bufferedPos=e,c>h&&c>o)this.bufferedToItem(u);else{const f=this.primaryDetails;this.primaryLive&&f&&e>f.edge-f.targetduration&&u.start{const r=this.getAssetPlayer(i.identifier);return!(r!=null&&r.bufferedInPlaceToEnd(t))})}setBufferingItem(e){const t=this.bufferingItem,s=this.schedule;if(!this.itemsMatch(e,t)&&s){const{items:i,events:r}=s;if(!i||!r)return t;const n=this.isInterstitial(e),o=this.getBufferingPlayer();this.bufferingItem=e,this.bufferedPos=Math.max(e.start,Math.min(e.end,this.timelinePos));const c=o?o.remaining:t?t.end-this.timelinePos:0;if(this.log(`INTERSTITIALS_BUFFERED_TO_BOUNDARY ${Me(e)}`+(t?` (${c.toFixed(2)} remaining)`:"")),!this.playbackDisabled)if(n){const l=s.findAssetIndex(e.event,this.bufferedPos);e.event.assetList.forEach((h,d)=>{const u=this.getAssetPlayer(h.identifier);u&&(d===l&&u.loadSource(),u.resumeBuffering())})}else this.hls.resumeBuffering(),this.playerQueue.forEach(l=>l.pauseBuffering());this.hls.trigger(m.INTERSTITIALS_BUFFERED_TO_BOUNDARY,{events:r.slice(0),schedule:i.slice(0),bufferingIndex:this.findItemIndex(e),playingIndex:this.findItemIndex(this.playingItem)})}else this.bufferingItem!==e&&(this.bufferingItem=e);return t}bufferedToItem(e,t=0){const s=this.setBufferingItem(e);if(!this.playbackDisabled){if(this.isInterstitial(e))this.bufferedToEvent(e,t);else if(s!==null){this.bufferingAsset=null;const i=this.detachedData;i?i.mediaSource?this.attachPrimary(e.start,e,!0):this.preloadPrimary(e):this.preloadPrimary(e)}}}preloadPrimary(e){const t=this.findItemIndex(e),s=this.getPrimaryResumption(e,t);this.startLoadingPrimaryAt(s)}bufferedToEvent(e,t){const s=e.event,i=s.assetList.length===0&&!s.assetListLoader,r=s.cue.once;if(i||!r){const n=this.preloadAssets(s,t);if(n!=null&&n.interstitial.appendInPlace){const o=this.primaryMedia;o&&this.bufferAssetPlayer(n,o)}}}preloadAssets(e,t){const s=e.assetUrl,i=e.assetList.length,r=i===0&&!e.assetListLoader,n=e.cue.once;if(r){const c=e.timelineStart;if(e.appendInPlace){var o;const u=this.playingItem;!this.isInterstitial(u)&&(u==null||(o=u.nextEvent)==null?void 0:o.identifier)===e.identifier&&this.flushFrontBuffer(c+.25)}let l,h=0;if(!this.playingItem&&this.primaryLive&&(h=this.hls.startPosition,h===-1&&(h=this.hls.liveSyncPosition||0)),h&&!(e.cue.pre||e.cue.post)){const u=h-c;u>0&&(l=Math.round(u*1e3)/1e3)}if(this.log(`Load interstitial asset ${t+1}/${s?1:i} ${e}${l?` live-start: ${h} start-offset: ${l}`:""}`),s)return this.createAsset(e,0,0,c,e.duration,s);const d=this.assetListLoader.loadAssetList(e,l);d&&(e.assetListLoader=d)}else if(!n&&i){for(let l=t;l{this.hls.trigger(m.BUFFER_FLUSHING,{startOffset:e,endOffset:1/0,type:i})})}getAssetPlayerQueueIndex(e){const t=this.playerQueue;for(let s=0;s1){const x=t.duration;x&&v{if(v.live){var x;const _=new Error(`Interstitials MUST be VOD assets ${e}`),b={fatal:!0,type:Y.OTHER_ERROR,details:R.INTERSTITIAL_ASSET_ITEM_ERROR,error:_},I=((x=this.schedule)==null?void 0:x.findEventIndex(e.identifier))||-1;this.handleAssetItemError(b,e,I,s,_.message);return}const D=v.edge-v.fragmentStart,A=t.duration;(y||A===null||D>A)&&(y=!1,this.log(`Interstitial asset "${d}" duration change ${A} > ${D}`),t.duration=D,this.updateSchedule())};g.on(m.LEVEL_UPDATED,(v,{details:x})=>p(x)),g.on(m.LEVEL_PTS_UPDATED,(v,{details:x})=>p(x)),g.on(m.EVENT_CUE_ENTER,()=>this.onInterstitialCueEnter());const E=(v,x)=>{const D=this.getAssetPlayer(d);if(D&&x.tracks){D.off(m.BUFFER_CODECS,E),D.tracks=x.tracks;const A=this.primaryMedia;this.bufferingAsset===D.assetItem&&A&&!D.media&&this.bufferAssetPlayer(D,A)}};g.on(m.BUFFER_CODECS,E);const T=()=>{var v;const x=this.getAssetPlayer(d);if(this.log(`buffered to end of asset ${x}`),!x||!this.schedule)return;const D=this.schedule.findEventIndex(e.identifier),A=(v=this.schedule.items)==null?void 0:v[D];this.isInterstitial(A)&&this.advanceAssetBuffering(A,t)};g.on(m.BUFFERED_TO_END,T);const S=v=>()=>{if(!this.getAssetPlayer(d)||!this.schedule)return;this.shouldPlay=!0;const D=this.schedule.findEventIndex(e.identifier);this.advanceAfterAssetEnded(e,D,v)};return g.once(m.MEDIA_ENDED,S(s)),g.once(m.PLAYOUT_LIMIT_REACHED,S(1/0)),g.on(m.ERROR,(v,x)=>{if(!this.schedule)return;const D=this.getAssetPlayer(d);if(x.details===R.BUFFER_STALLED_ERROR){if(D!=null&&D.appendInPlace){this.handleInPlaceStall(e);return}this.onTimeupdate(),this.checkBuffer(!0);return}this.handleAssetItemError(x,e,this.schedule.findEventIndex(e.identifier),s,`Asset player error ${x.error} ${e}`)}),g.on(m.DESTROYING,()=>{if(!this.getAssetPlayer(d)||!this.schedule)return;const x=new Error(`Asset player destroyed unexpectedly ${d}`),D={fatal:!0,type:Y.OTHER_ERROR,details:R.INTERSTITIAL_ASSET_ITEM_ERROR,error:x};this.handleAssetItemError(D,e,this.schedule.findEventIndex(e.identifier),s,x.message)}),this.log(`INTERSTITIAL_ASSET_PLAYER_CREATED ${It(t)}`),this.hls.trigger(m.INTERSTITIAL_ASSET_PLAYER_CREATED,{asset:t,assetListIndex:s,event:e,player:g}),g}clearInterstitial(e,t){this.clearAssetPlayers(e,t),e.reset()}clearAssetPlayers(e,t){e.assetList.forEach(s=>{this.clearAssetPlayer(s.identifier,t)})}resetAssetPlayer(e){const t=this.getAssetPlayerQueueIndex(e);if(t!==-1){this.log(`reset asset player "${e}" after error`);const s=this.playerQueue[t];this.transferMediaFromPlayer(s,null),s.resetDetails()}}clearAssetPlayer(e,t){const s=this.getAssetPlayerQueueIndex(e);if(s!==-1){const i=this.playerQueue[s];this.log(`clear ${i} toSegment: ${t&&Me(t)}`),this.transferMediaFromPlayer(i,t),this.playerQueue.splice(s,1),i.destroy()}}emptyPlayerQueue(){let e;for(;e=this.playerQueue.pop();)e.destroy();this.playerQueue=[]}startAssetPlayer(e,t,s,i,r){const{interstitial:n,assetItem:o,assetId:c}=e,l=n.assetList.length,h=this.playingAsset;this.endedAsset=null,this.playingAsset=o,(!h||h.identifier!==c)&&(h&&(this.clearAssetPlayer(h.identifier,s[i]),delete h.error),this.log(`INTERSTITIAL_ASSET_STARTED ${t+1}/${l} ${It(o)}`),this.hls.trigger(m.INTERSTITIAL_ASSET_STARTED,{asset:o,assetListIndex:t,event:n,schedule:s.slice(0),scheduleIndex:i,player:e})),this.bufferAssetPlayer(e,r)}bufferAssetPlayer(e,t){var s,i;if(!this.schedule)return;const{interstitial:r,assetItem:n}=e,o=this.schedule.findEventIndex(r.identifier),c=(s=this.schedule.items)==null?void 0:s[o];if(!c)return;e.loadSource(),this.setBufferingItem(c),this.bufferingAsset=n;const l=this.getBufferingPlayer();if(l===e)return;const h=r.appendInPlace;if(h&&(l==null?void 0:l.interstitial.appendInPlace)===!1)return;const d=(l==null?void 0:l.tracks)||((i=this.detachedData)==null?void 0:i.tracks)||this.requiredTracks;if(h&&n!==this.playingAsset){if(!e.tracks){this.log(`Waiting for track info before buffering ${e}`);return}if(d&&!xn(d,e.tracks)){const u=new Error(`Asset ${It(n)} SourceBuffer tracks ('${Object.keys(e.tracks)}') are not compatible with primary content tracks ('${Object.keys(d)}')`),f={fatal:!0,type:Y.OTHER_ERROR,details:R.INTERSTITIAL_ASSET_ITEM_ERROR,error:u},g=r.findAssetIndex(n);this.handleAssetItemError(f,r,o,g,u.message);return}}this.transferMediaTo(e,t)}handleInPlaceStall(e){const t=this.schedule,s=this.primaryMedia;if(!t||!s)return;const i=s.currentTime,r=t.findAssetIndex(e,i),n=e.assetList[r];if(n){const o=this.getAssetPlayer(n.identifier);if(o){const c=o.currentTime||i-n.timelineStart,l=o.duration-c;if(this.warn(`Stalled at ${c} of ${c+l} in ${o} ${e} (media.currentTime: ${i})`),c&&(l/s.playbackRate<.5||o.bufferedInPlaceToEnd(s))&&o.hls){const h=t.findEventIndex(e.identifier);this.advanceAfterAssetEnded(e,h,r)}}}}advanceInPlace(e){const t=this.primaryMedia;t&&t.currentTime!y.error))t.error=g;else for(let y=i;y{const E=parseFloat(y.DURATION);this.createAsset(r,p,h,c+h,E,y.URI),h+=E}),r.duration=h,this.log(`Loaded asset-list with duration: ${h} (was: ${l}) ${r}`);const d=this.waitingItem,u=(d==null?void 0:d.event.identifier)===n;this.updateSchedule();const f=(i=this.bufferingItem)==null?void 0:i.event;if(u){var g;const y=this.schedule.findEventIndex(n),p=(g=this.schedule.items)==null?void 0:g[y];if(p){if(!this.playingItem&&this.timelinePos>p.end&&this.schedule.findItemIndexAtTime(this.timelinePos)!==y){r.error=new Error(`Interstitial ${o.length?"no longer within playback range":"asset-list is empty"} ${this.timelinePos} ${r}`),this.log(r.error.message),this.updateSchedule(!0),this.primaryFallback(r);return}this.setBufferingItem(p)}this.setSchedulePosition(y)}else if((f==null?void 0:f.identifier)===n){const y=r.assetList[0];if(y){const p=this.getAssetPlayer(y.identifier);if(f.appendInPlace){const E=this.primaryMedia;p&&E&&this.bufferAssetPlayer(p,E)}else p&&p.loadSource()}}}onError(e,t){if(this.schedule)switch(t.details){case R.ASSET_LIST_PARSING_ERROR:case R.ASSET_LIST_LOAD_ERROR:case R.ASSET_LIST_LOAD_TIMEOUT:{const s=t.interstitial;s&&(this.updateSchedule(!0),this.primaryFallback(s));break}case R.BUFFER_STALLED_ERROR:{const s=this.endedItem||this.waitingItem||this.playingItem;if(this.isInterstitial(s)&&s.event.appendInPlace){this.handleInPlaceStall(s.event);return}this.log(`Primary player stall @${this.timelinePos} bufferedPos: ${this.bufferedPos}`),this.onTimeupdate(),this.checkBuffer(!0);break}}}}const an=500;class nd extends Fi{constructor(e,t,s){super(e,t,s,"subtitle-stream-controller",U.SUBTITLE),this.currentTrackId=-1,this.tracksBuffered=[],this.mainDetails=null,this.registerListeners()}onHandlerDestroying(){this.unregisterListeners(),super.onHandlerDestroying(),this.mainDetails=null}registerListeners(){super.registerListeners();const{hls:e}=this;e.on(m.LEVEL_LOADED,this.onLevelLoaded,this),e.on(m.SUBTITLE_TRACKS_UPDATED,this.onSubtitleTracksUpdated,this),e.on(m.SUBTITLE_TRACK_SWITCH,this.onSubtitleTrackSwitch,this),e.on(m.SUBTITLE_TRACK_LOADED,this.onSubtitleTrackLoaded,this),e.on(m.SUBTITLE_FRAG_PROCESSED,this.onSubtitleFragProcessed,this),e.on(m.BUFFER_FLUSHING,this.onBufferFlushing,this)}unregisterListeners(){super.unregisterListeners();const{hls:e}=this;e.off(m.LEVEL_LOADED,this.onLevelLoaded,this),e.off(m.SUBTITLE_TRACKS_UPDATED,this.onSubtitleTracksUpdated,this),e.off(m.SUBTITLE_TRACK_SWITCH,this.onSubtitleTrackSwitch,this),e.off(m.SUBTITLE_TRACK_LOADED,this.onSubtitleTrackLoaded,this),e.off(m.SUBTITLE_FRAG_PROCESSED,this.onSubtitleFragProcessed,this),e.off(m.BUFFER_FLUSHING,this.onBufferFlushing,this)}startLoad(e,t){this.stopLoad(),this.state=C.IDLE,this.setInterval(an),this.nextLoadPosition=this.lastCurrentTime=e+this.timelineOffset,this.startPosition=t?-1:e,this.tick()}onManifestLoading(){super.onManifestLoading(),this.mainDetails=null}onMediaDetaching(e,t){this.tracksBuffered=[],super.onMediaDetaching(e,t)}onLevelLoaded(e,t){this.mainDetails=t.details}onSubtitleFragProcessed(e,t){const{frag:s,success:i}=t;if(this.fragContextChanged(s)||(de(s)&&(this.fragPrevious=s),this.state=C.IDLE),!i)return;const r=this.tracksBuffered[this.currentTrackId];if(!r)return;let n;const o=s.start;for(let l=0;l=r[l].start&&o<=r[l].end){n=r[l];break}const c=s.start+s.duration;n?n.end=c:(n={start:o,end:c},r.push(n)),this.fragmentTracker.fragBuffered(s),this.fragBufferedComplete(s,null),this.media&&this.tick()}onBufferFlushing(e,t){const{startOffset:s,endOffset:i}=t;if(s===0&&i!==Number.POSITIVE_INFINITY){const r=i-1;if(r<=0)return;t.endOffsetSubtitles=Math.max(0,r),this.tracksBuffered.forEach(n=>{for(let o=0;onew Kt(s));return}this.tracksBuffered=[],this.levels=t.map(s=>{const i=new Kt(s);return this.tracksBuffered[i.id]=[],i}),this.fragmentTracker.removeFragmentsInRange(0,Number.POSITIVE_INFINITY,U.SUBTITLE),this.fragPrevious=null,this.mediaBuffer=null}onSubtitleTrackSwitch(e,t){var s;if(this.currentTrackId=t.id,!((s=this.levels)!=null&&s.length)||this.currentTrackId===-1){this.clearInterval();return}const i=this.levels[this.currentTrackId];i!=null&&i.details?this.mediaBuffer=this.mediaBufferTimeRanges:this.mediaBuffer=null,i&&this.state!==C.STOPPED&&this.setInterval(an)}onSubtitleTrackLoaded(e,t){var s;const{currentTrackId:i,levels:r}=this,{details:n,id:o}=t;if(!r){this.warn(`Subtitle tracks were reset while loading level ${o}`);return}const c=r[o];if(o>=r.length||!c)return;this.log(`Subtitle track ${o} loaded [${n.startSN},${n.endSN}]${n.lastPartSn?`[part-${n.lastPartSn}-${n.lastPartIndex}]`:""},duration:${n.totalduration}`),this.mediaBuffer=this.mediaBufferTimeRanges;let l=0;if(n.live||(s=c.details)!=null&&s.live){if(n.deltaUpdateFailed)return;const d=this.mainDetails;if(!d){this.startFragRequested=!1;return}const u=d.fragments[0];if(!c.details)n.hasProgramDateTime&&d.hasProgramDateTime?(Rs(n,d),l=n.fragmentStart):u&&(l=u.start,ui(n,l));else{var h;l=this.alignPlaylists(n,c.details,(h=this.levelLastLoaded)==null?void 0:h.details),l===0&&u&&(l=u.start,ui(n,l))}d&&!this.startFragRequested&&this.setStartPosition(d,l)}c.details=n,this.levelLastLoaded=c,o===i&&(this.hls.trigger(m.SUBTITLE_TRACK_UPDATED,{details:n,id:o,groupId:t.groupId}),this.tick(),n.live&&!this.fragCurrent&&this.media&&this.state===C.IDLE&&(pt(null,n.fragments,this.media.currentTime,0)||(this.warn("Subtitle playlist not aligned with playback"),c.details=void 0)))}_handleFragmentLoadComplete(e){const{frag:t,payload:s}=e,i=t.decryptdata,r=this.hls;if(!this.fragContextChanged(t)&&s&&s.byteLength>0&&i!=null&&i.key&&i.iv&&_t(i.method)){const n=performance.now();this.decrypter.decrypt(new Uint8Array(s),i.key.buffer,i.iv.buffer,wi(i.method)).catch(o=>{throw r.trigger(m.ERROR,{type:Y.MEDIA_ERROR,details:R.FRAG_DECRYPT_ERROR,fatal:!1,error:o,reason:o.message,frag:t}),o}).then(o=>{const c=performance.now();r.trigger(m.FRAG_DECRYPTED,{frag:t,payload:o,stats:{tstart:n,tdecrypt:c}})}).catch(o=>{this.warn(`${o.name}: ${o.message}`),this.state=C.IDLE})}}doTick(){if(!this.media){this.state=C.IDLE;return}if(this.state===C.IDLE){const{currentTrackId:e,levels:t}=this,s=t==null?void 0:t[e];if(!s||!t.length||!s.details||this.waitForLive(s))return;const{config:i}=this,r=this.getLoadPosition(),n=X.bufferedInfo(this.tracksBuffered[this.currentTrackId]||[],r,i.maxBufferHole),{end:o,len:c}=n,l=s.details,h=this.hls.maxBufferLength+l.levelTargetDuration;if(c>h)return;const d=l.fragments,u=d.length,f=l.edge;let g=null;const y=this.fragPrevious;if(of-T?0:T;g=pt(y,d,Math.max(d[0].start,o),S),!g&&y&&y.start{if(i=i>>>0,i>r-1)throw new DOMException(`Failed to execute '${s}' on 'TimeRanges': The index provided (${i}) is greater than the maximum bound (${r})`);return e[i][s]};this.buffered={get length(){return e.length},end(s){return t("end",s,e.length)},start(s){return t("start",s,e.length)}}}}const od={42:225,92:233,94:237,95:243,96:250,123:231,124:247,125:209,126:241,127:9608,128:174,129:176,130:189,131:191,132:8482,133:162,134:163,135:9834,136:224,137:32,138:232,139:226,140:234,141:238,142:244,143:251,144:193,145:201,146:211,147:218,148:220,149:252,150:8216,151:161,152:42,153:8217,154:9473,155:169,156:8480,157:8226,158:8220,159:8221,160:192,161:194,162:199,163:200,164:202,165:203,166:235,167:206,168:207,169:239,170:212,171:217,172:249,173:219,174:171,175:187,176:195,177:227,178:205,179:204,180:236,181:210,182:242,183:213,184:245,185:123,186:125,187:92,188:94,189:95,190:124,191:8764,192:196,193:228,194:214,195:246,196:223,197:165,198:164,199:9475,200:197,201:229,202:216,203:248,204:9487,205:9491,206:9495,207:9499},Ga=a=>String.fromCharCode(od[a]||a),Ne=15,Qe=100,ld={17:1,18:3,21:5,22:7,23:9,16:11,19:12,20:14},cd={17:2,18:4,21:6,22:8,23:10,19:13,20:15},hd={25:1,26:3,29:5,30:7,31:9,24:11,27:12,28:14},dd={25:2,26:4,29:6,30:8,31:10,27:13,28:15},ud=["white","green","blue","cyan","red","yellow","magenta","black","transparent"];class fd{constructor(){this.time=null,this.verboseLevel=0}log(e,t){if(this.verboseLevel>=e){const s=typeof t=="function"?t():t;re.log(`${this.time} [${e}] ${s}`)}}}const ut=function(e){const t=[];for(let s=0;sQe&&(this.logger.log(3,"Too large cursor position "+this.pos),this.pos=Qe)}moveCursor(e){const t=this.pos+e;if(e>1)for(let s=this.pos+1;s=144&&this.backSpace();const t=Ga(e);if(this.pos>=Qe){this.logger.log(0,()=>"Cannot insert "+e.toString(16)+" ("+t+") at position "+this.pos+". Skipping it!");return}this.chars[this.pos].setChar(t,this.currPenState),this.moveCursor(1)}clearFromPos(e){let t;for(t=e;t"pacData = "+oe(e));let t=e.row-1;if(this.nrRollUpRows&&t"bkgData = "+oe(e)),this.backSpace(),this.setPen(e),this.insertChar(32)}setRollUpRows(e){this.nrRollUpRows=e}rollUp(){if(this.nrRollUpRows===null){this.logger.log(3,"roll_up but nrRollUpRows not set yet");return}this.logger.log(1,()=>this.getDisplayText());const e=this.currRow+1-this.nrRollUpRows,t=this.rows.splice(e,1)[0];t.clear(),this.rows.splice(this.currRow,0,t),this.logger.log(2,"Rolling up")}getDisplayText(e){e=e||!1;const t=[];let s="",i=-1;for(let r=0;r0&&(e?s="["+t.join(" | ")+"]":s=t.join(` -`)),s}getTextAndFormat(){return this.rows}}class on{constructor(e,t,s){this.chNr=void 0,this.outputFilter=void 0,this.mode=void 0,this.verbose=void 0,this.displayedMemory=void 0,this.nonDisplayedMemory=void 0,this.lastOutputScreen=void 0,this.currRollUpRow=void 0,this.writeScreen=void 0,this.cueStartTime=void 0,this.logger=void 0,this.chNr=e,this.outputFilter=t,this.mode=null,this.verbose=0,this.displayedMemory=new Xs(s),this.nonDisplayedMemory=new Xs(s),this.lastOutputScreen=new Xs(s),this.currRollUpRow=this.displayedMemory.rows[Ne-1],this.writeScreen=this.displayedMemory,this.mode=null,this.cueStartTime=null,this.logger=s}reset(){this.mode=null,this.displayedMemory.reset(),this.nonDisplayedMemory.reset(),this.lastOutputScreen.reset(),this.outputFilter.reset(),this.currRollUpRow=this.displayedMemory.rows[Ne-1],this.writeScreen=this.displayedMemory,this.mode=null,this.cueStartTime=null}getHandler(){return this.outputFilter}setHandler(e){this.outputFilter=e}setPAC(e){this.writeScreen.setPAC(e)}setBkgData(e){this.writeScreen.setBkgData(e)}setMode(e){e!==this.mode&&(this.mode=e,this.logger.log(2,()=>"MODE="+e),this.mode==="MODE_POP-ON"?this.writeScreen=this.nonDisplayedMemory:(this.writeScreen=this.displayedMemory,this.writeScreen.reset()),this.mode!=="MODE_ROLL-UP"&&(this.displayedMemory.nrRollUpRows=null,this.nonDisplayedMemory.nrRollUpRows=null),this.mode=e)}insertChars(e){for(let s=0;st+": "+this.writeScreen.getDisplayText(!0)),(this.mode==="MODE_PAINT-ON"||this.mode==="MODE_ROLL-UP")&&(this.logger.log(1,()=>"DISPLAYED: "+this.displayedMemory.getDisplayText(!0)),this.outputDataUpdate())}ccRCL(){this.logger.log(2,"RCL - Resume Caption Loading"),this.setMode("MODE_POP-ON")}ccBS(){this.logger.log(2,"BS - BackSpace"),this.mode!=="MODE_TEXT"&&(this.writeScreen.backSpace(),this.writeScreen===this.displayedMemory&&this.outputDataUpdate())}ccAOF(){}ccAON(){}ccDER(){this.logger.log(2,"DER- Delete to End of Row"),this.writeScreen.clearToEndOfRow(),this.outputDataUpdate()}ccRU(e){this.logger.log(2,"RU("+e+") - Roll Up"),this.writeScreen=this.displayedMemory,this.setMode("MODE_ROLL-UP"),this.writeScreen.setRollUpRows(e)}ccFON(){this.logger.log(2,"FON - Flash On"),this.writeScreen.setPen({flash:!0})}ccRDC(){this.logger.log(2,"RDC - Resume Direct Captioning"),this.setMode("MODE_PAINT-ON")}ccTR(){this.logger.log(2,"TR"),this.setMode("MODE_TEXT")}ccRTD(){this.logger.log(2,"RTD"),this.setMode("MODE_TEXT")}ccEDM(){this.logger.log(2,"EDM - Erase Displayed Memory"),this.displayedMemory.reset(),this.outputDataUpdate(!0)}ccCR(){this.logger.log(2,"CR - Carriage Return"),this.writeScreen.rollUp(),this.outputDataUpdate(!0)}ccENM(){this.logger.log(2,"ENM - Erase Non-displayed Memory"),this.nonDisplayedMemory.reset()}ccEOC(){if(this.logger.log(2,"EOC - End Of Caption"),this.mode==="MODE_POP-ON"){const e=this.displayedMemory;this.displayedMemory=this.nonDisplayedMemory,this.nonDisplayedMemory=e,this.writeScreen=this.nonDisplayedMemory,this.logger.log(1,()=>"DISP: "+this.displayedMemory.getDisplayText())}this.outputDataUpdate(!0)}ccTO(e){this.logger.log(2,"TO("+e+") - Tab Offset"),this.writeScreen.moveCursor(e)}ccMIDROW(e){const t={flash:!1};if(t.underline=e%2===1,t.italics=e>=46,t.italics)t.foreground="white";else{const s=Math.floor(e/2)-16,i=["white","green","blue","cyan","red","yellow","magenta"];t.foreground=i[s]}this.logger.log(2,"MIDROW: "+oe(t)),this.writeScreen.setPen(t)}outputDataUpdate(e=!1){const t=this.logger.time;t!==null&&this.outputFilter&&(this.cueStartTime===null&&!this.displayedMemory.isEmpty()?this.cueStartTime=t:this.displayedMemory.equals(this.lastOutputScreen)||(this.outputFilter.newCue(this.cueStartTime,t,this.lastOutputScreen),e&&this.outputFilter.dispatchCue&&this.outputFilter.dispatchCue(),this.cueStartTime=this.displayedMemory.isEmpty()?null:t),this.lastOutputScreen.copy(this.displayedMemory))}cueSplitAtTime(e){this.outputFilter&&(this.displayedMemory.isEmpty()||(this.outputFilter.newCue&&this.outputFilter.newCue(this.cueStartTime,e,this.displayedMemory),this.cueStartTime=e))}}class ln{constructor(e,t,s){this.channels=void 0,this.currentChannel=0,this.cmdHistory=yd(),this.logger=void 0;const i=this.logger=new fd;this.channels=[null,new on(e,t,i),new on(e+1,s,i)]}getHandler(e){return this.channels[e].getHandler()}setHandler(e,t){this.channels[e].setHandler(t)}addData(e,t){this.logger.time=e;for(let s=0;s"["+ut([t[s],t[s+1]])+"] -> ("+ut([i,r])+")");const c=this.cmdHistory;if(i>=16&&i<=31){if(pd(i,r,c)){ns(null,null,c),this.logger.log(3,()=>"Repeated command ("+ut([i,r])+") is dropped");continue}ns(i,r,this.cmdHistory),n=this.parseCmd(i,r),n||(n=this.parseMidrow(i,r)),n||(n=this.parsePAC(i,r)),n||(n=this.parseBackgroundAttributes(i,r))}else ns(null,null,c);if(!n&&(o=this.parseChars(i,r),o)){const h=this.currentChannel;h&&h>0?this.channels[h].insertChars(o):this.logger.log(2,"No channel found yet. TEXT-MODE?")}!n&&!o&&this.logger.log(2,()=>"Couldn't parse cleaned data "+ut([i,r])+" orig: "+ut([t[s],t[s+1]]))}}parseCmd(e,t){const s=(e===20||e===28||e===21||e===29)&&t>=32&&t<=47,i=(e===23||e===31)&&t>=33&&t<=35;if(!(s||i))return!1;const r=e===20||e===21||e===23?1:2,n=this.channels[r];return e===20||e===21||e===28||e===29?t===32?n.ccRCL():t===33?n.ccBS():t===34?n.ccAOF():t===35?n.ccAON():t===36?n.ccDER():t===37?n.ccRU(2):t===38?n.ccRU(3):t===39?n.ccRU(4):t===40?n.ccFON():t===41?n.ccRDC():t===42?n.ccTR():t===43?n.ccRTD():t===44?n.ccEDM():t===45?n.ccCR():t===46?n.ccENM():t===47&&n.ccEOC():n.ccTO(t-32),this.currentChannel=r,!0}parseMidrow(e,t){let s=0;if((e===17||e===25)&&t>=32&&t<=47){if(e===17?s=1:s=2,s!==this.currentChannel)return this.logger.log(0,"Mismatch channel in midrow parsing"),!1;const i=this.channels[s];return i?(i.ccMIDROW(t),this.logger.log(3,()=>"MIDROW ("+ut([e,t])+")"),!0):!1}return!1}parsePAC(e,t){let s;const i=(e>=17&&e<=23||e>=25&&e<=31)&&t>=64&&t<=127,r=(e===16||e===24)&&t>=64&&t<=95;if(!(i||r))return!1;const n=e<=23?1:2;t>=64&&t<=95?s=n===1?ld[e]:hd[e]:s=n===1?cd[e]:dd[e];const o=this.channels[n];return o?(o.setPAC(this.interpretPAC(s,t)),this.currentChannel=n,!0):!1}interpretPAC(e,t){let s;const i={color:null,italics:!1,indent:null,underline:!1,row:e};return t>95?s=t-96:s=t-64,i.underline=(s&1)===1,s<=13?i.color=["white","green","blue","cyan","red","yellow","magenta","white"][Math.floor(s/2)]:s<=15?(i.italics=!0,i.color="white"):i.indent=Math.floor((s-16)/2)*4,i}parseChars(e,t){let s,i=null,r=null;if(e>=25?(s=2,r=e-8):(s=1,r=e),r>=17&&r<=19){let n;r===17?n=t+80:r===18?n=t+112:n=t+144,this.logger.log(2,()=>"Special char '"+Ga(n)+"' in channel "+s),i=[n]}else e>=32&&e<=127&&(i=t===0?[e]:[e,t]);return i&&this.logger.log(3,()=>"Char codes = "+ut(i).join(",")),i}parseBackgroundAttributes(e,t){const s=(e===16||e===24)&&t>=32&&t<=47,i=(e===23||e===31)&&t>=45&&t<=47;if(!(s||i))return!1;let r;const n={};e===16||e===24?(r=Math.floor((t-32)/2),n.background=ud[r],t%2===1&&(n.background=n.background+"_semi")):t===45?n.background="transparent":(n.foreground="black",t===47&&(n.underline=!0));const o=e<=23?1:2;return this.channels[o].setBkgData(n),!0}reset(){for(let e=0;e100)throw new Error("Position must be between 0 and 100.");D=I,this.hasBeenReset=!0}})),Object.defineProperty(h,"positionAlign",r({},d,{get:function(){return A},set:function(I){const P=i(I);if(!P)throw new SyntaxError("An invalid or illegal string was specified.");A=P,this.hasBeenReset=!0}})),Object.defineProperty(h,"size",r({},d,{get:function(){return _},set:function(I){if(I<0||I>100)throw new Error("Size must be between 0 and 100.");_=I,this.hasBeenReset=!0}})),Object.defineProperty(h,"align",r({},d,{get:function(){return b},set:function(I){const P=i(I);if(!P)throw new SyntaxError("An invalid or illegal string was specified.");b=P,this.hasBeenReset=!0}})),h.displayState=void 0}return n.prototype.getCueAsHTML=function(){return self.WebVTT.convertCueToDOMTree(self,this.text)},n}();class Ed{decode(e,t){if(!e)return"";if(typeof e!="string")throw new Error("Error - expected string data.");return decodeURIComponent(encodeURIComponent(e))}}function Va(a){function e(s,i,r,n){return(s|0)*3600+(i|0)*60+(r|0)+parseFloat(n||0)}const t=a.match(/^(?:(\d+):)?(\d{2}):(\d{2})(\.\d+)?/);return t?parseFloat(t[2])>59?e(t[2],t[3],0,t[4]):e(t[1],t[2],t[3],t[4]):null}class Td{constructor(){this.values=Object.create(null)}set(e,t){!this.get(e)&&t!==""&&(this.values[e]=t)}get(e,t,s){return s?this.has(e)?this.values[e]:t[s]:this.has(e)?this.values[e]:t}has(e){return e in this.values}alt(e,t,s){for(let i=0;i=0&&s<=100)return this.set(e,s),!0}return!1}}function Ha(a,e,t,s){const i=s?a.split(s):[a];for(const r in i){if(typeof i[r]!="string")continue;const n=i[r].split(t);if(n.length!==2)continue;const o=n[0],c=n[1];e(o,c)}}const Si=new qi(0,0,""),as=Si.align==="middle"?"middle":"center";function Sd(a,e,t){const s=a;function i(){const o=Va(a);if(o===null)throw new Error("Malformed timestamp: "+s);return a=a.replace(/^[^\sa-zA-Z-]+/,""),o}function r(o,c){const l=new Td;Ha(o,function(u,f){let g;switch(u){case"region":for(let y=t.length-1;y>=0;y--)if(t[y].id===f){l.set(u,t[y].region);break}break;case"vertical":l.alt(u,f,["rl","lr"]);break;case"line":g=f.split(","),l.integer(u,g[0]),l.percent(u,g[0])&&l.set("snapToLines",!1),l.alt(u,g[0],["auto"]),g.length===2&&l.alt("lineAlign",g[1],["start",as,"end"]);break;case"position":g=f.split(","),l.percent(u,g[0]),g.length===2&&l.alt("positionAlign",g[1],["start",as,"end","line-left","line-right","auto"]);break;case"size":l.percent(u,f);break;case"align":l.alt(u,f,["start",as,"end","left","right"]);break}},/:/,/\s/),c.region=l.get("region",null),c.vertical=l.get("vertical","");let h=l.get("line","auto");h==="auto"&&Si.line===-1&&(h=-1),c.line=h,c.lineAlign=l.get("lineAlign","start"),c.snapToLines=l.get("snapToLines",!0),c.size=l.get("size",100),c.align=l.get("align",as);let d=l.get("position","auto");d==="auto"&&Si.position===50&&(d=c.align==="start"||c.align==="left"?0:c.align==="end"||c.align==="right"?100:50),c.position=d}function n(){a=a.replace(/^\s+/,"")}if(n(),e.startTime=i(),n(),a.slice(0,3)!=="-->")throw new Error("Malformed time stamp (time stamps must be separated by '-->'): "+s);a=a.slice(3),n(),e.endTime=i(),n(),r(a,e)}function Ya(a){return a.replace(//gi,` -`)}class vd{constructor(){this.state="INITIAL",this.buffer="",this.decoder=new Ed,this.regionList=[],this.cue=null,this.oncue=void 0,this.onparsingerror=void 0,this.onflush=void 0}parse(e){const t=this;e&&(t.buffer+=t.decoder.decode(e,{stream:!0}));function s(){let r=t.buffer,n=0;for(r=Ya(r);ns.label).join(", "))||""}}const Nr=/(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\.[^.,]+)+/,ha="HlsJsTrackRemovedError";class bc extends Error{constructor(e){super(e),this.name=ha}}class _c extends Ce{constructor(e,t){super("buffer-controller",e.logger),this.hls=void 0,this.fragmentTracker=void 0,this.details=null,this._objectUrl=null,this.operationQueue=null,this.bufferCodecEventsTotal=0,this.media=null,this.mediaSource=null,this.lastMpegAudioChunk=null,this.blockedAudioAppend=null,this.lastVideoAppendEnd=0,this.appendSource=void 0,this.transferData=void 0,this.overrides=void 0,this.appendErrors={audio:0,video:0,audiovideo:0},this.tracks={},this.sourceBuffers=[[null,null],[null,null]],this._onEndStreaming=s=>{var i;this.hls&&((i=this.mediaSource)==null?void 0:i.readyState)==="open"&&this.hls.pauseBuffering()},this._onStartStreaming=s=>{this.hls&&this.hls.resumeBuffering()},this._onMediaSourceOpen=s=>{const{media:i,mediaSource:r}=this;s&&this.log("Media source opened"),!(!i||!r)&&(r.removeEventListener("sourceopen",this._onMediaSourceOpen),i.removeEventListener("emptied",this._onMediaEmptied),this.updateDuration(),this.hls.trigger(m.MEDIA_ATTACHED,{media:i,mediaSource:r}),this.mediaSource!==null&&this.checkPendingTracks())},this._onMediaSourceClose=()=>{this.log("Media source closed")},this._onMediaSourceEnded=()=>{this.log("Media source ended")},this._onMediaEmptied=()=>{const{mediaSrc:s,_objectUrl:i}=this;s!==i&&this.error(`Media element src was set while attaching MediaSource (${i} > ${s})`)},this.hls=e,this.fragmentTracker=t,this.appendSource=Xa(Je(e.config.preferManagedMediaSource)),this.initTracks(),this.registerListeners()}hasSourceTypes(){return Object.keys(this.tracks).length>0}destroy(){this.unregisterListeners(),this.details=null,this.lastMpegAudioChunk=this.blockedAudioAppend=null,this.transferData=this.overrides=void 0,this.operationQueue&&(this.operationQueue.destroy(),this.operationQueue=null),this.hls=this.fragmentTracker=null,this._onMediaSourceOpen=this._onMediaSourceClose=null,this._onMediaSourceEnded=null,this._onStartStreaming=this._onEndStreaming=null}registerListeners(){const{hls:e}=this;e.on(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.MANIFEST_PARSED,this.onManifestParsed,this),e.on(m.BUFFER_RESET,this.onBufferReset,this),e.on(m.BUFFER_APPENDING,this.onBufferAppending,this),e.on(m.BUFFER_CODECS,this.onBufferCodecs,this),e.on(m.BUFFER_EOS,this.onBufferEos,this),e.on(m.BUFFER_FLUSHING,this.onBufferFlushing,this),e.on(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.on(m.FRAG_PARSED,this.onFragParsed,this),e.on(m.FRAG_CHANGED,this.onFragChanged,this),e.on(m.ERROR,this.onError,this)}unregisterListeners(){const{hls:e}=this;e.off(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.MANIFEST_PARSED,this.onManifestParsed,this),e.off(m.BUFFER_RESET,this.onBufferReset,this),e.off(m.BUFFER_APPENDING,this.onBufferAppending,this),e.off(m.BUFFER_CODECS,this.onBufferCodecs,this),e.off(m.BUFFER_EOS,this.onBufferEos,this),e.off(m.BUFFER_FLUSHING,this.onBufferFlushing,this),e.off(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.off(m.FRAG_PARSED,this.onFragParsed,this),e.off(m.FRAG_CHANGED,this.onFragChanged,this),e.off(m.ERROR,this.onError,this)}transferMedia(){const{media:e,mediaSource:t}=this;if(!e)return null;const s={};if(this.operationQueue){const r=this.isUpdating();r||this.operationQueue.removeBlockers();const n=this.isQueued();(r||n)&&this.warn(`Transfering MediaSource with${n?" operations in queue":""}${r?" updating SourceBuffer(s)":""} ${this.operationQueue}`),this.operationQueue.destroy()}const i=this.transferData;return!this.sourceBufferCount&&i&&i.mediaSource===t?ie(s,i.tracks):this.sourceBuffers.forEach(r=>{const[n]=r;n&&(s[n]=ie({},this.tracks[n]),this.removeBuffer(n)),r[0]=r[1]=null}),{media:e,mediaSource:t,tracks:s}}initTracks(){const e={};this.sourceBuffers=[[null,null],[null,null]],this.tracks=e,this.resetQueue(),this.resetAppendErrors(),this.lastMpegAudioChunk=this.blockedAudioAppend=null,this.lastVideoAppendEnd=0}onManifestLoading(){this.bufferCodecEventsTotal=0,this.details=null}onManifestParsed(e,t){var s;let i=2;(t.audio&&!t.video||!t.altAudio)&&(i=1),this.bufferCodecEventsTotal=i,this.log(`${i} bufferCodec event(s) expected.`),(s=this.transferData)!=null&&s.mediaSource&&this.sourceBufferCount&&i&&this.bufferCreated()}onMediaAttaching(e,t){const s=this.media=t.media;this.transferData=this.overrides=void 0;const i=Je(this.appendSource);if(i){const r=!!t.mediaSource;(r||t.overrides)&&(this.transferData=t,this.overrides=t.overrides);const n=this.mediaSource=t.mediaSource||new i;if(this.assignMediaSource(n),r)this._objectUrl=s.src,this.attachTransferred();else{const o=this._objectUrl=self.URL.createObjectURL(n);if(this.appendSource)try{s.removeAttribute("src");const c=self.ManagedMediaSource;s.disableRemotePlayback=s.disableRemotePlayback||c&&n instanceof c,Br(s),Dc(s,o),s.load()}catch{s.src=o}else s.src=o}s.addEventListener("emptied",this._onMediaEmptied)}}assignMediaSource(e){var t,s;this.log(`${((t=this.transferData)==null?void 0:t.mediaSource)===e?"transferred":"created"} media source: ${(s=e.constructor)==null?void 0:s.name}`),e.addEventListener("sourceopen",this._onMediaSourceOpen),e.addEventListener("sourceended",this._onMediaSourceEnded),e.addEventListener("sourceclose",this._onMediaSourceClose),this.appendSource&&(e.addEventListener("startstreaming",this._onStartStreaming),e.addEventListener("endstreaming",this._onEndStreaming))}attachTransferred(){const e=this.media,t=this.transferData;if(!t||!e)return;const s=this.tracks,i=t.tracks,r=i?Object.keys(i):null,n=r?r.length:0,o=()=>{Promise.resolve().then(()=>{this.media&&this.mediaSourceOpenOrEnded&&this._onMediaSourceOpen()})};if(i&&r&&n){if(!this.tracksReady){this.hls.config.startFragPrefetch=!0,this.log("attachTransferred: waiting for SourceBuffer track info");return}if(this.log(`attachTransferred: (bufferCodecEventsTotal ${this.bufferCodecEventsTotal}) +required tracks: ${ne(s,(c,l)=>c==="initSegment"?void 0:l)}; +transfer tracks: ${ne(i,(c,l)=>c==="initSegment"?void 0:l)}}`),!an(i,s)){t.mediaSource=null,t.tracks=void 0;const c=e.currentTime,l=this.details,h=Math.max(c,(l==null?void 0:l.fragments[0].start)||0);if(h-c>1){this.log(`attachTransferred: waiting for playback to reach new tracks start time ${c} -> ${h}`);return}this.warn(`attachTransferred: resetting MediaSource for incompatible tracks ("${Object.keys(i)}"->"${Object.keys(s)}") start time: ${h} currentTime: ${c}`),this.onMediaDetaching(m.MEDIA_DETACHING,{}),this.onMediaAttaching(m.MEDIA_ATTACHING,t),e.currentTime=h;return}this.transferData=void 0,r.forEach(c=>{const l=c,h=i[l];if(h){const u=h.buffer;if(u){const d=this.fragmentTracker,f=h.id;if(d.hasFragments(f)||d.hasParts(f)){const p=q.getBuffered(u);d.detectEvictedFragments(l,p,f,null,!0)}const g=Ms(l),y=[l,u];this.sourceBuffers[g]=y,u.updating&&this.operationQueue&&this.operationQueue.prependBlocker(l),this.trackSourceBuffer(l,h)}}}),o(),this.bufferCreated()}else this.log("attachTransferred: MediaSource w/o SourceBuffers"),o()}get mediaSourceOpenOrEnded(){var e;const t=(e=this.mediaSource)==null?void 0:e.readyState;return t==="open"||t==="ended"}onMediaDetaching(e,t){const s=!!t.transferMedia;this.transferData=this.overrides=void 0;const{media:i,mediaSource:r,_objectUrl:n}=this;if(r){if(this.log(`media source ${s?"transferring":"detaching"}`),s)this.sourceBuffers.forEach(([o])=>{o&&this.removeBuffer(o)}),this.resetQueue();else{if(this.mediaSourceOpenOrEnded){const o=r.readyState==="open";try{const c=r.sourceBuffers;for(let l=c.length;l--;)o&&c[l].abort(),r.removeSourceBuffer(c[l]);o&&r.endOfStream()}catch(c){this.warn(`onMediaDetaching: ${c.message} while calling endOfStream`)}}this.sourceBufferCount&&this.onBufferReset()}r.removeEventListener("sourceopen",this._onMediaSourceOpen),r.removeEventListener("sourceended",this._onMediaSourceEnded),r.removeEventListener("sourceclose",this._onMediaSourceClose),this.appendSource&&(r.removeEventListener("startstreaming",this._onStartStreaming),r.removeEventListener("endstreaming",this._onEndStreaming)),this.mediaSource=null,this._objectUrl=null}i&&(i.removeEventListener("emptied",this._onMediaEmptied),s||(n&&self.URL.revokeObjectURL(n),this.mediaSrc===n?(i.removeAttribute("src"),this.appendSource&&Br(i),i.load()):this.warn("media|source.src was changed by a third party - skip cleanup")),this.media=null),this.hls.trigger(m.MEDIA_DETACHED,t)}onBufferReset(){this.sourceBuffers.forEach(([e])=>{e&&this.resetBuffer(e)}),this.initTracks()}resetBuffer(e){var t;const s=(t=this.tracks[e])==null?void 0:t.buffer;if(this.removeBuffer(e),s)try{var i;(i=this.mediaSource)!=null&&i.sourceBuffers.length&&this.mediaSource.removeSourceBuffer(s)}catch(r){this.warn(`onBufferReset ${e}`,r)}delete this.tracks[e]}removeBuffer(e){this.removeBufferListeners(e),this.sourceBuffers[Ms(e)]=[null,null];const t=this.tracks[e];t&&(t.buffer=void 0)}resetQueue(){this.operationQueue&&this.operationQueue.destroy(),this.operationQueue=new Rc(this.tracks)}onBufferCodecs(e,t){var s;const i=this.tracks,r=Object.keys(t);this.log(`BUFFER_CODECS: "${r}" (current SB count ${this.sourceBufferCount})`);const n="audiovideo"in t&&(i.audio||i.video)||i.audiovideo&&("audio"in t||"video"in t),o=!n&&this.sourceBufferCount&&this.media&&r.some(c=>!i[c]);if(n||o){this.warn(`Unsupported transition between "${Object.keys(i)}" and "${r}" SourceBuffers`);return}r.forEach(c=>{var l,h;const u=t[c],{id:d,codec:f,levelCodec:g,container:y,metadata:p,supplemental:E}=u;let T=i[c];const S=(l=this.transferData)==null||(l=l.tracks)==null?void 0:l[c],v=S!=null&&S.buffer?S:T,x=(v==null?void 0:v.pendingCodec)||(v==null?void 0:v.codec),D=v==null?void 0:v.levelCodec;T||(T=i[c]={buffer:void 0,listeners:[],codec:f,supplemental:E,container:y,levelCodec:g,metadata:p,id:d});const A=es(x,D),_=A==null?void 0:A.replace(Nr,"$1");let b=es(f,g);const I=(h=b)==null?void 0:h.replace(Nr,"$1");b&&A&&_!==I&&(c.slice(0,5)==="audio"&&(b=cs(b,this.appendSource)),this.log(`switching codec ${x} to ${b}`),b!==(T.pendingCodec||T.codec)&&(T.pendingCodec=b),T.container=y,this.appendChangeType(c,y,b))}),(this.tracksReady||this.sourceBufferCount)&&(t.tracks=this.sourceBufferTracks),!this.sourceBufferCount&&(this.bufferCodecEventsTotal>1&&!this.tracks.video&&!t.video&&((s=t.audio)==null?void 0:s.id)==="main"&&(this.log("Main audio-only"),this.bufferCodecEventsTotal=1),this.mediaSourceOpenOrEnded&&this.checkPendingTracks())}get sourceBufferTracks(){return Object.keys(this.tracks).reduce((e,t)=>{const s=this.tracks[t];return e[t]={id:s.id,container:s.container,codec:s.codec,levelCodec:s.levelCodec},e},{})}appendChangeType(e,t,s){const i=`${t};codecs=${s}`,r={label:`change-type=${i}`,execute:()=>{const n=this.tracks[e];if(n){const o=n.buffer;o!=null&&o.changeType&&(this.log(`changing ${e} sourceBuffer type to ${i}`),o.changeType(i),n.codec=s,n.container=t)}this.shiftAndExecuteNext(e)},onStart:()=>{},onComplete:()=>{},onError:n=>{this.warn(`Failed to change ${e} SourceBuffer type`,n)}};this.append(r,e,this.isPending(this.tracks[e]))}blockAudio(e){var t;const s=e.start,i=s+e.duration*.05;if(((t=this.fragmentTracker.getAppendedFrag(s,B.MAIN))==null?void 0:t.gap)===!0)return;const n={label:"block-audio",execute:()=>{var o;const c=this.tracks.video;(this.lastVideoAppendEnd>i||c!=null&&c.buffer&&q.isBuffered(c.buffer,i)||((o=this.fragmentTracker.getAppendedFrag(i,B.MAIN))==null?void 0:o.gap)===!0)&&(this.blockedAudioAppend=null,this.shiftAndExecuteNext("audio"))},onStart:()=>{},onComplete:()=>{},onError:o=>{this.warn("Error executing block-audio operation",o)}};this.blockedAudioAppend={op:n,frag:e},this.append(n,"audio",!0)}unblockAudio(){const{blockedAudioAppend:e,operationQueue:t}=this;e&&t&&(this.blockedAudioAppend=null,t.unblockAudio(e.op))}onBufferAppending(e,t){const{tracks:s}=this,{data:i,type:r,parent:n,frag:o,part:c,chunkMeta:l,offset:h}=t,u=l.buffering[r],{sn:d,cc:f}=o,g=self.performance.now();u.start=g;const y=o.stats.buffering,p=c?c.stats.buffering:null;y.start===0&&(y.start=g),p&&p.start===0&&(p.start=g);const E=s.audio;let T=!1;r==="audio"&&(E==null?void 0:E.container)==="audio/mpeg"&&(T=!this.lastMpegAudioChunk||l.id===1||this.lastMpegAudioChunk.sn!==l.sn,this.lastMpegAudioChunk=l);const S=s.video,v=S==null?void 0:S.buffer;if(v&&d!=="initSegment"){const A=c||o,_=this.blockedAudioAppend;if(r==="audio"&&n!=="main"&&!this.blockedAudioAppend&&!(S.ending||S.ended)){const I=A.start+A.duration*.05,P=v.buffered,F=this.currentOp("video");!P.length&&!F?this.blockAudio(A):!F&&!q.isBuffered(v,I)&&this.lastVideoAppendEndI||b{var A;u.executeStart=self.performance.now();const _=(A=this.tracks[r])==null?void 0:A.buffer;_&&(T?this.updateTimestampOffset(_,x,.1,r,d,f):h!==void 0&&M(h)&&this.updateTimestampOffset(_,h,1e-6,r,d,f)),this.appendExecutor(i,r)},onStart:()=>{},onComplete:()=>{const A=self.performance.now();u.executeEnd=u.end=A,y.first===0&&(y.first=A),p&&p.first===0&&(p.first=A);const _={};this.sourceBuffers.forEach(([b,I])=>{b&&(_[b]=q.getBuffered(I))}),this.appendErrors[r]=0,r==="audio"||r==="video"?this.appendErrors.audiovideo=0:(this.appendErrors.audio=0,this.appendErrors.video=0),this.hls.trigger(m.BUFFER_APPENDED,{type:r,frag:o,part:c,chunkMeta:l,parent:o.type,timeRanges:_})},onError:A=>{var _;const b={type:V.MEDIA_ERROR,parent:o.type,details:R.BUFFER_APPEND_ERROR,sourceBufferName:r,frag:o,part:c,chunkMeta:l,error:A,err:A,fatal:!1},I=(_=this.media)==null?void 0:_.error;if(A.code===DOMException.QUOTA_EXCEEDED_ERR||A.name=="QuotaExceededError"||"quota"in A)b.details=R.BUFFER_FULL_ERROR;else if(A.code===DOMException.INVALID_STATE_ERR&&this.mediaSourceOpenOrEnded&&!I)b.errorAction=Et(!0);else if(A.name===ha&&this.sourceBufferCount===0)b.errorAction=Et(!0);else{const P=++this.appendErrors[r];this.warn(`Failed ${P}/${this.hls.config.appendErrorMaxRetry} times to append segment in "${r}" sourceBuffer (${I||"no media error"})`),(P>=this.hls.config.appendErrorMaxRetry||I)&&(b.fatal=!0)}this.hls.trigger(m.ERROR,b)}};this.log(`queuing "${r}" append sn: ${d}${c?" p: "+c.index:""} of ${o.type===B.MAIN?"level":"track"} ${o.level} cc: ${f}`),this.append(D,r,this.isPending(this.tracks[r]))}getFlushOp(e,t,s){return this.log(`queuing "${e}" remove ${t}-${s}`),{label:"remove",execute:()=>{this.removeExecutor(e,t,s)},onStart:()=>{},onComplete:()=>{this.hls.trigger(m.BUFFER_FLUSHED,{type:e})},onError:i=>{this.warn(`Failed to remove ${t}-${s} from "${e}" SourceBuffer`,i)}}}onBufferFlushing(e,t){const{type:s,startOffset:i,endOffset:r}=t;s?this.append(this.getFlushOp(s,i,r),s):this.sourceBuffers.forEach(([n])=>{n&&this.append(this.getFlushOp(n,i,r),n)})}onFragParsed(e,t){const{frag:s,part:i}=t,r=[],n=i?i.elementaryStreams:s.elementaryStreams;n[re.AUDIOVIDEO]?r.push("audiovideo"):(n[re.AUDIO]&&r.push("audio"),n[re.VIDEO]&&r.push("video"));const o=()=>{const c=self.performance.now();s.stats.buffering.end=c,i&&(i.stats.buffering.end=c);const l=i?i.stats:s.stats;this.hls.trigger(m.FRAG_BUFFERED,{frag:s,part:i,stats:l,id:s.type})};r.length===0&&this.warn(`Fragments must have at least one ElementaryStreamType set. type: ${s.type} level: ${s.level} sn: ${s.sn}`),this.blockBuffers(o,r).catch(c=>{this.warn(`Fragment buffered callback ${c}`),this.stepOperationQueue(this.sourceBufferTypes)})}onFragChanged(e,t){this.trimBuffers()}get bufferedToEnd(){return this.sourceBufferCount>0&&!this.sourceBuffers.some(([e])=>{if(e){const t=this.tracks[e];if(t)return!t.ended||t.ending}return!1})}onBufferEos(e,t){var s;this.sourceBuffers.forEach(([n])=>{if(n){const o=this.tracks[n];(!t.type||t.type===n)&&(o.ending=!0,o.ended||(o.ended=!0,this.log(`${n} buffer reached EOS`)))}});const i=((s=this.overrides)==null?void 0:s.endOfStream)!==!1;this.sourceBufferCount>0&&!this.sourceBuffers.some(([n])=>{var o;return n&&!((o=this.tracks[n])!=null&&o.ended)})?i?(this.log("Queueing EOS"),this.blockUntilOpen(()=>{this.tracksEnded();const{mediaSource:n}=this;if(!n||n.readyState!=="open"){n&&this.log(`Could not call mediaSource.endOfStream(). mediaSource.readyState: ${n.readyState}`);return}this.log("Calling mediaSource.endOfStream()"),n.endOfStream(),this.hls.trigger(m.BUFFERED_TO_END,void 0)})):(this.tracksEnded(),this.hls.trigger(m.BUFFERED_TO_END,void 0)):t.type==="video"&&this.unblockAudio()}tracksEnded(){this.sourceBuffers.forEach(([e])=>{if(e!==null){const t=this.tracks[e];t&&(t.ending=!1)}})}onLevelUpdated(e,{details:t}){t.fragments.length&&(this.details=t,this.updateDuration())}updateDuration(){this.blockUntilOpen(()=>{const e=this.getDurationAndRange();e&&this.updateMediaSource(e)})}onError(e,t){if(t.details===R.BUFFER_APPEND_ERROR&&t.frag){var s;const i=(s=t.errorAction)==null?void 0:s.nextAutoLevel;M(i)&&i!==t.frag.level&&this.resetAppendErrors()}}resetAppendErrors(){this.appendErrors={audio:0,video:0,audiovideo:0}}trimBuffers(){const{hls:e,details:t,media:s}=this;if(!s||t===null||!this.sourceBufferCount)return;const i=e.config,r=s.currentTime,n=t.levelTargetDuration,o=t.live&&i.liveBackBufferLength!==null?i.liveBackBufferLength:i.backBufferLength;if(M(o)&&o>=0){const l=Math.max(o,n),h=Math.floor(r/n)*n-l;this.flushBackBuffer(r,n,h)}const c=i.frontBufferFlushThreshold;if(M(c)&&c>0){const l=Math.max(i.maxBufferLength,c),h=Math.max(l,n),u=Math.floor(r/n)*n+h;this.flushFrontBuffer(r,n,u)}}flushBackBuffer(e,t,s){this.sourceBuffers.forEach(([i,r])=>{if(r){const o=q.getBuffered(r);if(o.length>0&&s>o.start(0)){var n;this.hls.trigger(m.BACK_BUFFER_REACHED,{bufferEnd:s});const c=this.tracks[i];if((n=this.details)!=null&&n.live)this.hls.trigger(m.LIVE_BACK_BUFFER_REACHED,{bufferEnd:s});else if(c!=null&&c.ended){this.log(`Cannot flush ${i} back buffer while SourceBuffer is in ended state`);return}this.hls.trigger(m.BUFFER_FLUSHING,{startOffset:0,endOffset:s,type:i})}}})}flushFrontBuffer(e,t,s){this.sourceBuffers.forEach(([i,r])=>{if(r){const n=q.getBuffered(r),o=n.length;if(o<2)return;const c=n.start(o-1),l=n.end(o-1);if(s>c||e>=c&&e<=l)return;this.hls.trigger(m.BUFFER_FLUSHING,{startOffset:c,endOffset:1/0,type:i})}})}getDurationAndRange(){var e;const{details:t,mediaSource:s}=this;if(!t||!this.media||(s==null?void 0:s.readyState)!=="open")return null;const i=t.edge;if(t.live&&this.hls.config.liveDurationInfinity){if(t.fragments.length&&s.setLiveSeekableRange){const l=Math.max(0,t.fragmentStart),h=Math.max(l,i);return{duration:1/0,start:l,end:h}}return{duration:1/0}}const r=(e=this.overrides)==null?void 0:e.duration;if(r)return M(r)?{duration:r}:null;const n=this.media.duration,o=M(s.duration)?s.duration:0;return i>o&&i>n||!M(n)?{duration:i}:null}updateMediaSource({duration:e,start:t,end:s}){const i=this.mediaSource;!this.media||!i||i.readyState!=="open"||(i.duration!==e&&(M(e)&&this.log(`Updating MediaSource duration to ${e.toFixed(3)}`),i.duration=e),t!==void 0&&s!==void 0&&(this.log(`MediaSource duration is set to ${i.duration}. Setting seekable range to ${t}-${s}.`),i.setLiveSeekableRange(t,s)))}get tracksReady(){const e=this.pendingTrackCount;return e>0&&(e>=this.bufferCodecEventsTotal||this.isPending(this.tracks.audiovideo))}checkPendingTracks(){const{bufferCodecEventsTotal:e,pendingTrackCount:t,tracks:s}=this;if(this.log(`checkPendingTracks (pending: ${t} codec events expected: ${e}) ${ne(s)}`),this.tracksReady){var i;const r=(i=this.transferData)==null?void 0:i.tracks;r&&Object.keys(r).length?this.attachTransferred():this.createSourceBuffers()}}bufferCreated(){if(this.sourceBufferCount){const e={};this.sourceBuffers.forEach(([t,s])=>{if(t){const i=this.tracks[t];e[t]={buffer:s,container:i.container,codec:i.codec,supplemental:i.supplemental,levelCodec:i.levelCodec,id:i.id,metadata:i.metadata}}}),this.hls.trigger(m.BUFFER_CREATED,{tracks:e}),this.log(`SourceBuffers created. Running queue: ${this.operationQueue}`),this.sourceBuffers.forEach(([t])=>{this.executeNext(t)})}else{const e=new Error("could not create source buffer for media codec(s)");this.hls.trigger(m.ERROR,{type:V.MEDIA_ERROR,details:R.BUFFER_INCOMPATIBLE_CODECS_ERROR,fatal:!0,error:e,reason:e.message})}}createSourceBuffers(){const{tracks:e,sourceBuffers:t,mediaSource:s}=this;if(!s)throw new Error("createSourceBuffers called when mediaSource was null");for(const r in e){const n=r,o=e[n];if(this.isPending(o)){const c=this.getTrackCodec(o,n),l=`${o.container};codecs=${c}`;o.codec=c,this.log(`creating sourceBuffer(${l})${this.currentOp(n)?" Queued":""} ${ne(o)}`);try{const h=s.addSourceBuffer(l),u=Ms(n),d=[n,h];t[u]=d,o.buffer=h}catch(h){var i;this.error(`error while trying to add sourceBuffer: ${h.message}`),this.shiftAndExecuteNext(n),(i=this.operationQueue)==null||i.removeBlockers(),delete this.tracks[n],this.hls.trigger(m.ERROR,{type:V.MEDIA_ERROR,details:R.BUFFER_ADD_CODEC_ERROR,fatal:!1,error:h,sourceBufferName:n,mimeType:l,parent:o.id});return}this.trackSourceBuffer(n,o)}}this.bufferCreated()}getTrackCodec(e,t){const s=e.supplemental;let i=e.codec;s&&(t==="video"||t==="audiovideo")&&kt(s,"video")&&(i=Eo(i,s));const r=es(i,e.levelCodec);return r?t.slice(0,5)==="audio"?cs(r,this.appendSource):r:""}trackSourceBuffer(e,t){const s=t.buffer;if(!s)return;const i=this.getTrackCodec(t,e);this.tracks[e]={buffer:s,codec:i,container:t.container,levelCodec:t.levelCodec,supplemental:t.supplemental,metadata:t.metadata,id:t.id,listeners:[]},this.removeBufferListeners(e),this.addBufferListener(e,"updatestart",this.onSBUpdateStart),this.addBufferListener(e,"updateend",this.onSBUpdateEnd),this.addBufferListener(e,"error",this.onSBUpdateError),this.appendSource&&this.addBufferListener(e,"bufferedchange",(r,n)=>{const o=n.removedRanges;o!=null&&o.length&&this.hls.trigger(m.BUFFER_FLUSHED,{type:r})})}get mediaSrc(){var e,t;const s=((e=this.media)==null||(t=e.querySelector)==null?void 0:t.call(e,"source"))||this.media;return s==null?void 0:s.src}onSBUpdateStart(e){const t=this.currentOp(e);t&&t.onStart()}onSBUpdateEnd(e){var t;if(((t=this.mediaSource)==null?void 0:t.readyState)==="closed"){this.resetBuffer(e);return}const s=this.currentOp(e);s&&(s.onComplete(),this.shiftAndExecuteNext(e))}onSBUpdateError(e,t){var s;const i=new Error(`${e} SourceBuffer error. MediaSource readyState: ${(s=this.mediaSource)==null?void 0:s.readyState}`);this.error(`${i}`,t),this.hls.trigger(m.ERROR,{type:V.MEDIA_ERROR,details:R.BUFFER_APPENDING_ERROR,sourceBufferName:e,error:i,fatal:!1});const r=this.currentOp(e);r&&r.onError(i)}updateTimestampOffset(e,t,s,i,r,n){const o=t-e.timestampOffset;Math.abs(o)>=s&&(this.log(`Updating ${i} SourceBuffer timestampOffset to ${t} (sn: ${r} cc: ${n})`),e.timestampOffset=t)}removeExecutor(e,t,s){const{media:i,mediaSource:r}=this,n=this.tracks[e],o=n==null?void 0:n.buffer;if(!i||!r||!o){this.warn(`Attempting to remove from the ${e} SourceBuffer, but it does not exist`),this.shiftAndExecuteNext(e);return}const c=M(i.duration)?i.duration:1/0,l=M(r.duration)?r.duration:1/0,h=Math.max(0,t),u=Math.min(s,c,l);u>h&&(!n.ending||n.ended)?(n.ended=!1,this.log(`Removing [${h},${u}] from the ${e} SourceBuffer`),o.remove(h,u)):this.shiftAndExecuteNext(e)}appendExecutor(e,t){const s=this.tracks[t],i=s==null?void 0:s.buffer;if(!i)throw new bc(`Attempting to append to the ${t} SourceBuffer, but it does not exist`);s.ending=!1,s.ended=!1,i.appendBuffer(e)}blockUntilOpen(e){if(this.isUpdating()||this.isQueued())this.blockBuffers(e).catch(t=>{this.warn(`SourceBuffer blocked callback ${t}`),this.stepOperationQueue(this.sourceBufferTypes)});else try{e()}catch(t){this.warn(`Callback run without blocking ${this.operationQueue} ${t}`)}}isUpdating(){return this.sourceBuffers.some(([e,t])=>e&&t.updating)}isQueued(){return this.sourceBuffers.some(([e])=>e&&!!this.currentOp(e))}isPending(e){return!!e&&!e.buffer}blockBuffers(e,t=this.sourceBufferTypes){if(!t.length)return this.log("Blocking operation requested, but no SourceBuffers exist"),Promise.resolve().then(e);const{operationQueue:s}=this,i=t.map(n=>this.appendBlocker(n));return t.length>1&&!!this.blockedAudioAppend&&this.unblockAudio(),Promise.all(i).then(n=>{s===this.operationQueue&&(e(),this.stepOperationQueue(this.sourceBufferTypes))})}stepOperationQueue(e){e.forEach(t=>{var s;const i=(s=this.tracks[t])==null?void 0:s.buffer;!i||i.updating||this.shiftAndExecuteNext(t)})}append(e,t,s){this.operationQueue&&this.operationQueue.append(e,t,s)}appendBlocker(e){if(this.operationQueue)return this.operationQueue.appendBlocker(e)}currentOp(e){return this.operationQueue?this.operationQueue.current(e):null}executeNext(e){e&&this.operationQueue&&this.operationQueue.executeNext(e)}shiftAndExecuteNext(e){this.operationQueue&&this.operationQueue.shiftAndExecuteNext(e)}get pendingTrackCount(){return Object.keys(this.tracks).reduce((e,t)=>e+(this.isPending(this.tracks[t])?1:0),0)}get sourceBufferCount(){return this.sourceBuffers.reduce((e,[t])=>e+(t?1:0),0)}get sourceBufferTypes(){return this.sourceBuffers.map(([e])=>e).filter(e=>!!e)}addBufferListener(e,t,s){const i=this.tracks[e];if(!i)return;const r=i.buffer;if(!r)return;const n=s.bind(this,e);i.listeners.push({event:t,listener:n}),r.addEventListener(t,n)}removeBufferListeners(e){const t=this.tracks[e];if(!t)return;const s=t.buffer;s&&(t.listeners.forEach(i=>{s.removeEventListener(i.event,i.listener)}),t.listeners.length=0)}}function Br(a){const e=a.querySelectorAll("source");[].slice.call(e).forEach(t=>{a.removeChild(t)})}function Dc(a,e){const t=self.document.createElement("source");t.type="video/mp4",t.src=e,a.appendChild(t)}function Ms(a){return a==="audio"?1:0}class ki{constructor(e){this.hls=void 0,this.autoLevelCapping=void 0,this.firstLevel=void 0,this.media=void 0,this.restrictedLevels=void 0,this.timer=void 0,this.clientRect=void 0,this.streamController=void 0,this.hls=e,this.autoLevelCapping=Number.POSITIVE_INFINITY,this.firstLevel=-1,this.media=null,this.restrictedLevels=[],this.timer=void 0,this.clientRect=null,this.registerListeners()}setStreamController(e){this.streamController=e}destroy(){this.hls&&this.unregisterListener(),this.timer&&this.stopCapping(),this.media=null,this.clientRect=null,this.hls=this.streamController=null}registerListeners(){const{hls:e}=this;e.on(m.FPS_DROP_LEVEL_CAPPING,this.onFpsDropLevelCapping,this),e.on(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(m.MANIFEST_PARSED,this.onManifestParsed,this),e.on(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.on(m.BUFFER_CODECS,this.onBufferCodecs,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this)}unregisterListener(){const{hls:e}=this;e.off(m.FPS_DROP_LEVEL_CAPPING,this.onFpsDropLevelCapping,this),e.off(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(m.MANIFEST_PARSED,this.onManifestParsed,this),e.off(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.off(m.BUFFER_CODECS,this.onBufferCodecs,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this)}onFpsDropLevelCapping(e,t){const s=this.hls.levels[t.droppedLevel];this.isLevelAllowed(s)&&this.restrictedLevels.push({bitrate:s.bitrate,height:s.height,width:s.width})}onMediaAttaching(e,t){this.media=t.media instanceof HTMLVideoElement?t.media:null,this.clientRect=null,this.timer&&this.hls.levels.length&&this.detectPlayerSize()}onManifestParsed(e,t){const s=this.hls;this.restrictedLevels=[],this.firstLevel=t.firstLevel,s.config.capLevelToPlayerSize&&t.video&&this.startCapping()}onLevelsUpdated(e,t){this.timer&&M(this.autoLevelCapping)&&this.detectPlayerSize()}onBufferCodecs(e,t){this.hls.config.capLevelToPlayerSize&&t.video&&this.startCapping()}onMediaDetaching(){this.stopCapping(),this.media=null}detectPlayerSize(){if(this.media){if(this.mediaHeight<=0||this.mediaWidth<=0){this.clientRect=null;return}const e=this.hls.levels;if(e.length){const t=this.hls,s=this.getMaxLevel(e.length-1);s!==this.autoLevelCapping&&t.logger.log(`Setting autoLevelCapping to ${s}: ${e[s].height}p@${e[s].bitrate} for media ${this.mediaWidth}x${this.mediaHeight}`),t.autoLevelCapping=s,t.autoLevelEnabled&&t.autoLevelCapping>this.autoLevelCapping&&this.streamController&&this.streamController.nextLevelSwitch(),this.autoLevelCapping=t.autoLevelCapping}}}getMaxLevel(e){const t=this.hls.levels;if(!t.length)return-1;const s=t.filter((i,r)=>this.isLevelAllowed(i)&&r<=e);return this.clientRect=null,ki.getMaxLevelByMediaSize(s,this.mediaWidth,this.mediaHeight)}startCapping(){this.timer||(this.autoLevelCapping=Number.POSITIVE_INFINITY,self.clearInterval(this.timer),this.timer=self.setInterval(this.detectPlayerSize.bind(this),1e3),this.detectPlayerSize())}stopCapping(){this.restrictedLevels=[],this.firstLevel=-1,this.autoLevelCapping=Number.POSITIVE_INFINITY,this.timer&&(self.clearInterval(this.timer),this.timer=void 0)}getDimensions(){if(this.clientRect)return this.clientRect;const e=this.media,t={width:0,height:0};if(e){const s=e.getBoundingClientRect();t.width=s.width,t.height=s.height,!t.width&&!t.height&&(t.width=s.right-s.left||e.width||0,t.height=s.bottom-s.top||e.height||0)}return this.clientRect=t,t}get mediaWidth(){return this.getDimensions().width*this.contentScaleFactor}get mediaHeight(){return this.getDimensions().height*this.contentScaleFactor}get contentScaleFactor(){let e=1;if(!this.hls.config.ignoreDevicePixelRatio)try{e=self.devicePixelRatio}catch{}return Math.min(e,this.hls.config.maxDevicePixelRatio)}isLevelAllowed(e){return!this.restrictedLevels.some(s=>e.bitrate===s.bitrate&&e.width===s.width&&e.height===s.height)}static getMaxLevelByMediaSize(e,t,s){if(!(e!=null&&e.length))return-1;const i=(o,c)=>c?o.width!==c.width||o.height!==c.height:!0;let r=e.length-1;const n=Math.max(t,s);for(let o=0;o=n||c.height>=n)&&i(c,e[o+1])){r=o;break}}return r}}const Cc={MANIFEST:"m",AUDIO:"a",VIDEO:"v",MUXED:"av",INIT:"i",CAPTION:"c",TIMED_TEXT:"tt",KEY:"k",OTHER:"o"},Se=Cc,Pc={HLS:"h"},kc=Pc;class Ke{constructor(e,t){Array.isArray(e)&&(e=e.map(s=>s instanceof Ke?s:new Ke(s))),this.value=e,this.params=t}}const wc="Dict";function Oc(a){return Array.isArray(a)?JSON.stringify(a):a instanceof Map?"Map{}":a instanceof Set?"Set{}":typeof a=="object"?JSON.stringify(a):String(a)}function Fc(a,e,t,s){return new Error(`failed to ${a} "${Oc(e)}" as ${t}`,{cause:s})}function Ve(a,e,t){return Fc("serialize",a,e,t)}class ua{constructor(e){this.description=e}}const Ur="Bare Item",Mc="Boolean";function Nc(a){if(typeof a!="boolean")throw Ve(a,Mc);return a?"?1":"?0"}function Bc(a){return btoa(String.fromCharCode(...a))}const Uc="Byte Sequence";function $c(a){if(ArrayBuffer.isView(a)===!1)throw Ve(a,Uc);return`:${Bc(a)}:`}const Gc="Integer";function Kc(a){return a<-999999999999999||99999999999999912)throw Ve(a,Hc);const t=e.toString();return t.includes(".")?t:`${t}.0`}const Wc="String",qc=/[\x00-\x1f\x7f]+/;function jc(a){if(qc.test(a))throw Ve(a,Wc);return`"${a.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}function Xc(a){return a.description||a.toString().slice(7,-1)}const zc="Token";function $r(a){const e=Xc(a);if(/^([a-zA-Z*])([!#$%&'*+\-.^_`|~\w:/]*)$/.test(e)===!1)throw Ve(e,zc);return e}function ai(a){switch(typeof a){case"number":if(!M(a))throw Ve(a,Ur);return Number.isInteger(a)?da(a):Yc(a);case"string":return jc(a);case"symbol":return $r(a);case"boolean":return Nc(a);case"object":if(a instanceof Date)return Vc(a);if(a instanceof Uint8Array)return $c(a);if(a instanceof ua)return $r(a);default:throw Ve(a,Ur)}}const Qc="Key";function oi(a){if(/^[a-z*][a-z0-9\-_.*]*$/.test(a)===!1)throw Ve(a,Qc);return a}function wi(a){return a==null?"":Object.entries(a).map(([e,t])=>t===!0?`;${oi(e)}`:`;${oi(e)}=${ai(t)}`).join("")}function ga(a){return a instanceof Ke?`${ai(a.value)}${wi(a.params)}`:ai(a)}function Zc(a){return`(${a.value.map(ga).join(" ")})${wi(a.params)}`}function Jc(a,e={whitespace:!0}){if(typeof a!="object"||a==null)throw Ve(a,wc);const t=a instanceof Map?a.entries():Object.entries(a),s=e!=null&&e.whitespace?" ":"";return Array.from(t).map(([i,r])=>{r instanceof Ke||(r=new Ke(r));let n=oi(i);return r.value===!0?n+=wi(r.params):(n+="=",Array.isArray(r.value)?n+=Zc(r):n+=ga(r)),n}).join(`,${s}`)}function ma(a,e){return Jc(a,e)}const Me="CMCD-Object",le="CMCD-Request",rt="CMCD-Session",Xe="CMCD-Status",eh={br:Me,ab:Me,d:Me,ot:Me,tb:Me,tpb:Me,lb:Me,tab:Me,lab:Me,url:Me,pb:le,bl:le,tbl:le,dl:le,ltc:le,mtp:le,nor:le,nrr:le,rc:le,sn:le,sta:le,su:le,ttfb:le,ttfbb:le,ttlb:le,cmsdd:le,cmsds:le,smrt:le,df:le,cs:le,ts:le,cid:rt,pr:rt,sf:rt,sid:rt,st:rt,v:rt,msd:rt,bs:Xe,bsd:Xe,cdn:Xe,rtp:Xe,bg:Xe,pt:Xe,ec:Xe,e:Xe},th={REQUEST:le};function sh(a){return Object.keys(a).reduce((e,t)=>{var s;return(s=a[t])===null||s===void 0||s.forEach(i=>e[i]=t),e},{})}function ih(a,e){const t={};if(!a)return t;const s=Object.keys(a),i=e?sh(e):{};return s.reduce((r,n)=>{var o;const c=eh[n]||i[n]||th.REQUEST,l=(o=r[c])!==null&&o!==void 0?o:r[c]={};return l[n]=a[n],r},t)}function rh(a){return["ot","sf","st","e","sta"].includes(a)}function nh(a){return typeof a=="number"?M(a):a!=null&&a!==""&&a!==!1}const pa="event";function ah(a,e){const t=new URL(a),s=new URL(e);if(t.origin!==s.origin)return a;const i=t.pathname.split("/").slice(1),r=s.pathname.split("/").slice(1,-1);for(;i[0]===r[0];)i.shift(),r.shift();for(;r.length;)r.shift(),i.unshift("..");return i.join("/")+t.search+t.hash}const ns=a=>Math.round(a),li=(a,e)=>Array.isArray(a)?a.map(t=>li(t,e)):a instanceof Ke&&typeof a.value=="string"?new Ke(li(a.value,e),a.params):(e.baseUrl&&(a=ah(a,e.baseUrl)),e.version===1?encodeURIComponent(a):a),qt=a=>ns(a/100)*100,oh=(a,e)=>{let t=a;return e.version>=2&&(a instanceof Ke&&typeof a.value=="string"?t=new Ke([a]):typeof a=="string"&&(t=[a])),li(t,e)},lh={br:ns,d:ns,bl:qt,dl:qt,mtp:qt,nor:oh,rtp:qt,tb:ns},ya="request",Ea="response",Oi=["ab","bg","bl","br","bs","bsd","cdn","cid","cs","df","ec","lab","lb","ltc","msd","mtp","pb","pr","pt","sf","sid","sn","st","sta","tab","tb","tbl","tpb","ts","v"],ch=["e"],hh=/^[a-zA-Z0-9-.]+-[a-zA-Z0-9-.]+$/;function vs(a){return hh.test(a)}function uh(a){return Oi.includes(a)||ch.includes(a)||vs(a)}const Ta=["d","dl","nor","ot","rtp","su"];function dh(a){return Oi.includes(a)||Ta.includes(a)||vs(a)}const fh=["cmsdd","cmsds","rc","smrt","ttfb","ttfbb","ttlb","url"];function gh(a){return Oi.includes(a)||Ta.includes(a)||fh.includes(a)||vs(a)}const mh=["bl","br","bs","cid","d","dl","mtp","nor","nrr","ot","pr","rtp","sf","sid","st","su","tb","v"];function ph(a){return mh.includes(a)||vs(a)}const yh={[Ea]:gh,[pa]:uh,[ya]:dh};function Sa(a,e={}){const t={};if(a==null||typeof a!="object")return t;const s=e.version||a.v||1,i=e.reportingMode||ya,r=s===1?ph:yh[i];let n=Object.keys(a).filter(r);const o=e.filter;typeof o=="function"&&(n=n.filter(o));const c=i===Ea||i===pa;c&&!n.includes("ts")&&n.push("ts"),s>1&&!n.includes("v")&&n.push("v");const l=ie({},lh,e.formatters),h={version:s,reportingMode:i,baseUrl:e.baseUrl};return n.sort().forEach(u=>{let d=a[u];const f=l[u];if(typeof f=="function"&&(d=f(d,h)),u==="v"){if(s===1)return;d=s}u=="pr"&&d===1||(c&&u==="ts"&&!M(d)&&(d=Date.now()),nh(d)&&(rh(u)&&typeof d=="string"&&(d=new ua(d)),t[u]=d))}),t}function Eh(a,e={}){const t={};if(!a)return t;const s=Sa(a,e),i=ih(s,e==null?void 0:e.customHeaderMap);return Object.entries(i).reduce((r,[n,o])=>{const c=ma(o,{whitespace:!1});return c&&(r[n]=c),r},t)}function Th(a,e,t){return ie(a,Eh(e,t))}const Sh="CMCD";function vh(a,e={}){return a?ma(Sa(a,e),{whitespace:!1}):""}function xh(a,e={}){if(!a)return"";const t=vh(a,e);return encodeURIComponent(t)}function Ah(a,e={}){if(!a)return"";const t=xh(a,e);return`${Sh}=${t}`}const Gr=/CMCD=[^&#]+/;function Ih(a,e,t){const s=Ah(e,t);if(!s)return a;if(Gr.test(a))return a.replace(Gr,s);const i=a.includes("?")?"&":"?";return`${a}${i}${s}`}class Lh{constructor(e){this.hls=void 0,this.config=void 0,this.media=void 0,this.sid=void 0,this.cid=void 0,this.useHeaders=!1,this.includeKeys=void 0,this.initialized=!1,this.starved=!1,this.buffering=!0,this.audioBuffer=void 0,this.videoBuffer=void 0,this.onWaiting=()=>{this.initialized&&(this.starved=!0),this.buffering=!0},this.onPlaying=()=>{this.initialized||(this.initialized=!0),this.buffering=!1},this.applyPlaylistData=i=>{try{this.apply(i,{ot:Se.MANIFEST,su:!this.initialized})}catch(r){this.hls.logger.warn("Could not generate manifest CMCD data.",r)}},this.applyFragmentData=i=>{try{const{frag:r,part:n}=i,o=this.hls.levels[r.level],c=this.getObjectType(r),l={d:(n||r).duration*1e3,ot:c};(c===Se.VIDEO||c===Se.AUDIO||c==Se.MUXED)&&(l.br=o.bitrate/1e3,l.tb=this.getTopBandwidth(c)/1e3,l.bl=this.getBufferLength(c));const h=n?this.getNextPart(n):this.getNextFrag(r);h!=null&&h.url&&h.url!==r.url&&(l.nor=h.url),this.apply(i,l)}catch(r){this.hls.logger.warn("Could not generate segment CMCD data.",r)}},this.hls=e;const t=this.config=e.config,{cmcd:s}=t;s!=null&&(t.pLoader=this.createPlaylistLoader(),t.fLoader=this.createFragmentLoader(),this.sid=s.sessionId||e.sessionId,this.cid=s.contentId,this.useHeaders=s.useHeaders===!0,this.includeKeys=s.includeKeys,this.registerListeners())}registerListeners(){const e=this.hls;e.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(m.MEDIA_DETACHED,this.onMediaDetached,this),e.on(m.BUFFER_CREATED,this.onBufferCreated,this)}unregisterListeners(){const e=this.hls;e.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(m.MEDIA_DETACHED,this.onMediaDetached,this),e.off(m.BUFFER_CREATED,this.onBufferCreated,this)}destroy(){this.unregisterListeners(),this.onMediaDetached(),this.hls=this.config=this.audioBuffer=this.videoBuffer=null,this.onWaiting=this.onPlaying=this.media=null}onMediaAttached(e,t){this.media=t.media,this.media.addEventListener("waiting",this.onWaiting),this.media.addEventListener("playing",this.onPlaying)}onMediaDetached(){this.media&&(this.media.removeEventListener("waiting",this.onWaiting),this.media.removeEventListener("playing",this.onPlaying),this.media=null)}onBufferCreated(e,t){var s,i;this.audioBuffer=(s=t.tracks.audio)==null?void 0:s.buffer,this.videoBuffer=(i=t.tracks.video)==null?void 0:i.buffer}createData(){var e;return{v:1,sf:kc.HLS,sid:this.sid,cid:this.cid,pr:(e=this.media)==null?void 0:e.playbackRate,mtp:this.hls.bandwidthEstimate/1e3}}apply(e,t={}){ie(t,this.createData());const s=t.ot===Se.INIT||t.ot===Se.VIDEO||t.ot===Se.MUXED;this.starved&&s&&(t.bs=!0,t.su=!0,this.starved=!1),t.su==null&&(t.su=this.buffering);const{includeKeys:i}=this;i&&(t=Object.keys(t).reduce((n,o)=>(i.includes(o)&&(n[o]=t[o]),n),{}));const r={baseUrl:e.url};this.useHeaders?(e.headers||(e.headers={}),Th(e.headers,t,r)):e.url=Ih(e.url,t,r)}getNextFrag(e){var t;const s=(t=this.hls.levels[e.level])==null?void 0:t.details;if(s){const i=e.sn-s.startSN;return s.fragments[i+1]}}getNextPart(e){var t;const{index:s,fragment:i}=e,r=(t=this.hls.levels[i.level])==null||(t=t.details)==null?void 0:t.partList;if(r){const{sn:n}=i;for(let o=r.length-1;o>=0;o--){const c=r[o];if(c.index===s&&c.fragment.sn===n)return r[o+1]}}}getObjectType(e){const{type:t}=e;if(t==="subtitle")return Se.TIMED_TEXT;if(e.sn==="initSegment")return Se.INIT;if(t==="audio")return Se.AUDIO;if(t==="main")return this.hls.audioTracks.length?Se.VIDEO:Se.MUXED}getTopBandwidth(e){let t=0,s;const i=this.hls;if(e===Se.AUDIO)s=i.audioTracks;else{const r=i.maxAutoLevel,n=r>-1?r+1:i.levels.length;s=i.levels.slice(0,n)}return s.forEach(r=>{r.bitrate>t&&(t=r.bitrate)}),t>0?t:NaN}getBufferLength(e){const t=this.media,s=e===Se.AUDIO?this.audioBuffer:this.videoBuffer;return!s||!t?NaN:q.bufferInfo(s,t.currentTime,this.config.maxBufferHole).len*1e3}createPlaylistLoader(){const{pLoader:e}=this.config,t=this.applyPlaylistData,s=e||this.config.loader;return class{constructor(r){this.loader=void 0,this.loader=new s(r)}get stats(){return this.loader.stats}get context(){return this.loader.context}destroy(){this.loader.destroy()}abort(){this.loader.abort()}load(r,n,o){t(r),this.loader.load(r,n,o)}}}createFragmentLoader(){const{fLoader:e}=this.config,t=this.applyFragmentData,s=e||this.config.loader;return class{constructor(r){this.loader=void 0,this.loader=new s(r)}get stats(){return this.loader.stats}get context(){return this.loader.context}destroy(){this.loader.destroy()}abort(){this.loader.abort()}load(r,n,o){t(r),this.loader.load(r,n,o)}}}}const Rh=3e5;class bh extends Ce{constructor(e){super("content-steering",e.logger),this.hls=void 0,this.loader=null,this.uri=null,this.pathwayId=".",this._pathwayPriority=null,this.timeToLoad=300,this.reloadTimer=-1,this.updated=0,this.started=!1,this.enabled=!0,this.levels=null,this.audioTracks=null,this.subtitleTracks=null,this.penalizedPathways={},this.hls=e,this.registerListeners()}registerListeners(){const e=this.hls;e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.on(m.MANIFEST_PARSED,this.onManifestParsed,this),e.on(m.ERROR,this.onError,this)}unregisterListeners(){const e=this.hls;e&&(e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.off(m.MANIFEST_PARSED,this.onManifestParsed,this),e.off(m.ERROR,this.onError,this))}pathways(){return(this.levels||[]).reduce((e,t)=>(e.indexOf(t.pathwayId)===-1&&e.push(t.pathwayId),e),[])}get pathwayPriority(){return this._pathwayPriority}set pathwayPriority(e){this.updatePathwayPriority(e)}startLoad(){if(this.started=!0,this.clearTimeout(),this.enabled&&this.uri){if(this.updated){const e=this.timeToLoad*1e3-(performance.now()-this.updated);if(e>0){this.scheduleRefresh(this.uri,e);return}}this.loadSteeringManifest(this.uri)}}stopLoad(){this.started=!1,this.loader&&(this.loader.destroy(),this.loader=null),this.clearTimeout()}clearTimeout(){this.reloadTimer!==-1&&(self.clearTimeout(this.reloadTimer),this.reloadTimer=-1)}destroy(){this.unregisterListeners(),this.stopLoad(),this.hls=null,this.levels=this.audioTracks=this.subtitleTracks=null}removeLevel(e){const t=this.levels;t&&(this.levels=t.filter(s=>s!==e))}onManifestLoading(){this.stopLoad(),this.enabled=!0,this.timeToLoad=300,this.updated=0,this.uri=null,this.pathwayId=".",this.levels=this.audioTracks=this.subtitleTracks=null}onManifestLoaded(e,t){const{contentSteering:s}=t;s!==null&&(this.pathwayId=s.pathwayId,this.uri=s.uri,this.started&&this.startLoad())}onManifestParsed(e,t){this.audioTracks=t.audioTracks,this.subtitleTracks=t.subtitleTracks}onError(e,t){const{errorAction:s}=t;if((s==null?void 0:s.action)===ge.SendAlternateToPenaltyBox&&s.flags===Ae.MoveAllAlternatesMatchingHost){const i=this.levels;let r=this._pathwayPriority,n=this.pathwayId;if(t.context){const{groupId:o,pathwayId:c,type:l}=t.context;o&&i?n=this.getPathwayForGroupId(o,l,n):c&&(n=c)}n in this.penalizedPathways||(this.penalizedPathways[n]=performance.now()),!r&&i&&(r=this.pathways()),r&&r.length>1&&(this.updatePathwayPriority(r),s.resolved=this.pathwayId!==n),t.details===R.BUFFER_APPEND_ERROR&&!t.fatal?s.resolved=!0:s.resolved||this.warn(`Could not resolve ${t.details} ("${t.error.message}") with content-steering for Pathway: ${n} levels: ${i&&i.length} priorities: ${ne(r)} penalized: ${ne(this.penalizedPathways)}`)}}filterParsedLevels(e){this.levels=e;let t=this.getLevelsForPathway(this.pathwayId);if(t.length===0){const s=e[0].pathwayId;this.log(`No levels found in Pathway ${this.pathwayId}. Setting initial Pathway to "${s}"`),t=this.getLevelsForPathway(s),this.pathwayId=s}return t.length!==e.length&&this.log(`Found ${t.length}/${e.length} levels in Pathway "${this.pathwayId}"`),t}getLevelsForPathway(e){return this.levels===null?[]:this.levels.filter(t=>e===t.pathwayId)}updatePathwayPriority(e){this._pathwayPriority=e;let t;const s=this.penalizedPathways,i=performance.now();Object.keys(s).forEach(r=>{i-s[r]>Rh&&delete s[r]});for(let r=0;r0){this.log(`Setting Pathway to "${n}"`),this.pathwayId=n,$n(t),this.hls.trigger(m.LEVELS_UPDATED,{levels:t});const l=this.hls.levels[o];c&&l&&this.levels&&(l.attrs["STABLE-VARIANT-ID"]!==c.attrs["STABLE-VARIANT-ID"]&&l.bitrate!==c.bitrate&&this.log(`Unstable Pathways change from bitrate ${c.bitrate} to ${l.bitrate}`),this.hls.nextLoadLevel=o);break}}}getPathwayForGroupId(e,t,s){const i=this.getLevelsForPathway(s).concat(this.levels||[]);for(let r=0;r{const{ID:n,"BASE-ID":o,"URI-REPLACEMENT":c}=r;if(t.some(h=>h.pathwayId===n))return;const l=this.getLevelsForPathway(o).map(h=>{const u=new ae(h.attrs);u["PATHWAY-ID"]=n;const d=u.AUDIO&&`${u.AUDIO}_clone_${n}`,f=u.SUBTITLES&&`${u.SUBTITLES}_clone_${n}`;d&&(s[u.AUDIO]=d,u.AUDIO=d),f&&(i[u.SUBTITLES]=f,u.SUBTITLES=f);const g=va(h.uri,u["STABLE-VARIANT-ID"],"PER-VARIANT-URIS",c),y=new Ot({attrs:u,audioCodec:h.audioCodec,bitrate:h.bitrate,height:h.height,name:h.name,url:g,videoCodec:h.videoCodec,width:h.width});if(h.audioGroups)for(let p=1;p{this.log(`Loaded steering manifest: "${i}"`);const g=h.data;if((g==null?void 0:g.VERSION)!==1){this.log(`Steering VERSION ${g.VERSION} not supported!`);return}this.updated=performance.now(),this.timeToLoad=g.TTL;const{"RELOAD-URI":y,"PATHWAY-CLONES":p,"PATHWAY-PRIORITY":E}=g;if(y)try{this.uri=new self.URL(y,i).href}catch{this.enabled=!1,this.log(`Failed to parse Steering Manifest RELOAD-URI: ${y}`);return}this.scheduleRefresh(this.uri||d.url),p&&this.clonePathways(p);const T={steeringManifest:g,url:i.toString()};this.hls.trigger(m.STEERING_MANIFEST_LOADED,T),E&&this.updatePathwayPriority(E)},onError:(h,u,d,f)=>{if(this.log(`Error loading steering manifest: ${h.code} ${h.text} (${u.url})`),this.stopLoad(),h.code===410){this.enabled=!1,this.log(`Steering manifest ${u.url} no longer available`);return}let g=this.timeToLoad*1e3;if(h.code===429){const y=this.loader;if(typeof(y==null?void 0:y.getResponseHeader)=="function"){const p=y.getResponseHeader("Retry-After");p&&(g=parseFloat(p)*1e3)}this.log(`Steering manifest ${u.url} rate limited`);return}this.scheduleRefresh(this.uri||u.url,g)},onTimeout:(h,u,d)=>{this.log(`Timeout loading steering manifest (${u.url})`),this.scheduleRefresh(this.uri||u.url)}};this.log(`Requesting steering manifest: ${i}`),this.loader.load(r,c,l)}scheduleRefresh(e,t=this.timeToLoad*1e3){this.clearTimeout(),this.reloadTimer=self.setTimeout(()=>{var s;const i=(s=this.hls)==null?void 0:s.media;if(i&&!i.ended){this.loadSteeringManifest(e);return}this.scheduleRefresh(e,this.timeToLoad*1e3)},t)}}function Kr(a,e,t,s){a&&Object.keys(e).forEach(i=>{const r=a.filter(n=>n.groupId===i).map(n=>{const o=ie({},n);return o.details=void 0,o.attrs=new ae(o.attrs),o.url=o.attrs.URI=va(n.url,n.attrs["STABLE-RENDITION-ID"],"PER-RENDITION-URIS",t),o.groupId=o.attrs["GROUP-ID"]=e[i],o.attrs["PATHWAY-ID"]=s,o});a.push(...r)})}function va(a,e,t,s){const{HOST:i,PARAMS:r,[t]:n}=s;let o;e&&(o=n==null?void 0:n[e],o&&(a=o));const c=new self.URL(a);return i&&!o&&(c.host=i),r&&Object.keys(r).sort().forEach(l=>{l&&c.searchParams.set(l,r[l])}),c.href}class St extends Ce{constructor(e){super("eme",e.logger),this.hls=void 0,this.config=void 0,this.media=null,this.mediaResolved=void 0,this.keyFormatPromise=null,this.keySystemAccessPromises={},this._requestLicenseFailureCount=0,this.mediaKeySessions=[],this.keyIdToKeySessionPromise={},this.mediaKeys=null,this.setMediaKeysQueue=St.CDMCleanupPromise?[St.CDMCleanupPromise]:[],this.bannedKeyIds={},this.onMediaEncrypted=t=>{const{initDataType:s,initData:i}=t,r=`"${t.type}" event: init data type: "${s}"`;if(this.debug(r),i!==null){if(!this.keyFormatPromise){let n=Object.keys(this.keySystemAccessPromises);n.length||(n=_t(this.config));const o=n.map(_s).filter(c=>!!c);this.keyFormatPromise=this.getKeyFormatPromise(o)}this.keyFormatPromise.then(n=>{const o=ss(n);if(s!=="sinf"||o!==oe.FAIRPLAY){this.log(`Ignoring "${t.type}" event with init data type: "${s}" for selected key-system ${o}`);return}let c;try{const f=he(new Uint8Array(i)),g=xi(JSON.parse(f).sinf),y=mn(g);if(!y)throw new Error("'schm' box missing or not cbcs/cenc with schi > tenc");c=new Uint8Array(y.subarray(8,24))}catch(f){this.warn(`${r} Failed to parse sinf: ${f}`);return}const l=me(c),{keyIdToKeySessionPromise:h,mediaKeySessions:u}=this;let d=h[l];for(let f=0;fthis.generateRequestWithPreferredKeySession(g,s,i,"encrypted-event-key-match")),d.catch(E=>this.handleError(E));break}}d||this.handleError(new Error(`Key ID ${l} not encountered in playlist. Key-system sessions ${u.length}.`))}).catch(n=>this.handleError(n))}},this.onWaitingForKey=t=>{this.log(`"${t.type}" event`)},this.hls=e,this.config=e.config,this.registerListeners()}destroy(){this.onDestroying(),this.onMediaDetached();const e=this.config;e.requestMediaKeySystemAccessFunc=null,e.licenseXhrSetup=e.licenseResponseCallback=void 0,e.drmSystems=e.drmSystemOptions={},this.hls=this.config=this.keyIdToKeySessionPromise=null,this.onMediaEncrypted=this.onWaitingForKey=null}registerListeners(){this.hls.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),this.hls.on(m.MEDIA_DETACHED,this.onMediaDetached,this),this.hls.on(m.MANIFEST_LOADING,this.onManifestLoading,this),this.hls.on(m.MANIFEST_LOADED,this.onManifestLoaded,this),this.hls.on(m.DESTROYING,this.onDestroying,this)}unregisterListeners(){this.hls.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),this.hls.off(m.MEDIA_DETACHED,this.onMediaDetached,this),this.hls.off(m.MANIFEST_LOADING,this.onManifestLoading,this),this.hls.off(m.MANIFEST_LOADED,this.onManifestLoaded,this),this.hls.off(m.DESTROYING,this.onDestroying,this)}getLicenseServerUrl(e){const{drmSystems:t,widevineLicenseUrl:s}=this.config,i=t==null?void 0:t[e];if(i)return i.licenseUrl;if(e===oe.WIDEVINE&&s)return s}getLicenseServerUrlOrThrow(e){const t=this.getLicenseServerUrl(e);if(t===void 0)throw new Error(`no license server URL configured for key-system "${e}"`);return t}getServerCertificateUrl(e){const{drmSystems:t}=this.config,s=t==null?void 0:t[e];if(s)return s.serverCertificateUrl;this.log(`No Server Certificate in config.drmSystems["${e}"]`)}attemptKeySystemAccess(e){const t=this.hls.levels,s=(n,o,c)=>!!n&&c.indexOf(n)===o,i=t.map(n=>n.audioCodec).filter(s),r=t.map(n=>n.videoCodec).filter(s);return i.length+r.length===0&&r.push("avc1.42e01e"),new Promise((n,o)=>{const c=l=>{const h=l.shift();this.getMediaKeysPromise(h,i,r).then(u=>n({keySystem:h,mediaKeys:u})).catch(u=>{l.length?c(l):u instanceof xe?o(u):o(new xe({type:V.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_NO_ACCESS,error:u,fatal:!0},u.message))})};c(e)})}requestMediaKeySystemAccess(e,t){const{requestMediaKeySystemAccessFunc:s}=this.config;if(typeof s!="function"){let i=`Configured requestMediaKeySystemAccess is not a function ${s}`;return kn===null&&self.location.protocol==="http:"&&(i=`navigator.requestMediaKeySystemAccess is not available over insecure protocol ${location.protocol}`),Promise.reject(new Error(i))}return s(e,t)}getMediaKeysPromise(e,t,s){var i;const r=ol(e,t,s,this.config.drmSystemOptions||{});let n=this.keySystemAccessPromises[e],o=(i=n)==null?void 0:i.keySystemAccess;if(!o){this.log(`Requesting encrypted media "${e}" key-system access with config: ${ne(r)}`),o=this.requestMediaKeySystemAccess(e,r);const c=n=this.keySystemAccessPromises[e]={keySystemAccess:o};return o.catch(l=>{this.log(`Failed to obtain access to key-system "${e}": ${l}`)}),o.then(l=>{this.log(`Access for key-system "${l.keySystem}" obtained`);const h=this.fetchServerCertificate(e);this.log(`Create media-keys for "${e}"`);const u=c.mediaKeys=l.createMediaKeys().then(d=>(this.log(`Media-keys created for "${e}"`),c.hasMediaKeys=!0,h.then(f=>f?this.setMediaKeysServerCertificate(d,e,f):d)));return u.catch(d=>{this.error(`Failed to create media-keys for "${e}"}: ${d}`)}),u})}return o.then(()=>n.mediaKeys)}createMediaKeySessionContext({decryptdata:e,keySystem:t,mediaKeys:s}){this.log(`Creating key-system session "${t}" keyId: ${me(e.keyId||[])} keyUri: ${e.uri}`);const i=s.createSession(),r={decryptdata:e,keySystem:t,mediaKeys:s,mediaKeysSession:i,keyStatus:"status-pending"};return this.mediaKeySessions.push(r),r}renewKeySession(e){const t=e.decryptdata;if(t.pssh){const s=this.createMediaKeySessionContext(e),i=jt(t),r="cenc";this.keyIdToKeySessionPromise[i]=this.generateRequestWithPreferredKeySession(s,r,t.pssh.buffer,"expired")}else this.warn("Could not renew expired session. Missing pssh initData.");this.removeSession(e)}updateKeySession(e,t){const s=e.mediaKeysSession;return this.log(`Updating key-session "${s.sessionId}" for keyId ${me(e.decryptdata.keyId||[])} + } (data length: ${t.byteLength})`),s.update(t)}getSelectedKeySystemFormats(){return Object.keys(this.keySystemAccessPromises).map(e=>({keySystem:e,hasMediaKeys:this.keySystemAccessPromises[e].hasMediaKeys})).filter(({hasMediaKeys:e})=>!!e).map(({keySystem:e})=>_s(e)).filter(e=>!!e)}getKeySystemAccess(e){return this.getKeySystemSelectionPromise(e).then(({keySystem:t,mediaKeys:s})=>this.attemptSetMediaKeys(t,s))}selectKeySystem(e){return new Promise((t,s)=>{this.getKeySystemSelectionPromise(e).then(({keySystem:i})=>{const r=_s(i);r?t(r):s(new Error(`Unable to find format for key-system "${i}"`))}).catch(s)})}selectKeySystemFormat(e){const t=Object.keys(e.levelkeys||{});return this.keyFormatPromise||(this.log(`Selecting key-system from fragment (sn: ${e.sn} ${e.type}: ${e.level}) key formats ${t.join(", ")}`),this.keyFormatPromise=this.getKeyFormatPromise(t)),this.keyFormatPromise}getKeyFormatPromise(e){const t=_t(this.config),s=e.map(ss).filter(i=>!!i&&t.indexOf(i)!==-1);return this.selectKeySystem(s)}getKeyStatus(e){const{mediaKeySessions:t}=this;for(let s=0;s(this.throwIfDestroyed(),this.log(`Handle encrypted media sn: ${e.frag.sn} ${e.frag.type}: ${e.frag.level} using key ${r}`),this.attemptSetMediaKeys(c,l).then(()=>(this.throwIfDestroyed(),this.createMediaKeySessionContext({keySystem:c,mediaKeys:l,decryptdata:t}))))).then(c=>{const l="cenc",h=t.pssh?t.pssh.buffer:null;return this.generateRequestWithPreferredKeySession(c,l,h,"playlist-key")});return o.catch(c=>this.handleError(c,e.frag)),this.keyIdToKeySessionPromise[s]=o,o}return n.catch(o=>{if(o instanceof xe){const c=te({},o.data);this.getKeyStatus(t)==="internal-error"&&(c.decryptdata=t);const l=new xe(c,o.message);this.handleError(l,e.frag)}}),n}throwIfDestroyed(e="Invalid state"){if(!this.hls)throw new Error("invalid state")}handleError(e,t){if(this.hls)if(e instanceof xe){t&&(e.data.frag=t);const s=e.data.decryptdata;this.error(`${e.message}${s?` (${me(s.keyId||[])})`:""}`),this.hls.trigger(m.ERROR,e.data)}else this.error(e.message),this.hls.trigger(m.ERROR,{type:V.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_NO_KEYS,error:e,fatal:!0})}getKeySystemForKeyPromise(e){const t=jt(e),s=this.keyIdToKeySessionPromise[t];if(!s){const i=ss(e.keyFormat),r=i?[i]:_t(this.config);return this.attemptKeySystemAccess(r)}return s}getKeySystemSelectionPromise(e){if(e.length||(e=_t(this.config)),e.length===0)throw new xe({type:V.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_NO_CONFIGURED_LICENSE,fatal:!0},`Missing key-system license configuration options ${ne({drmSystems:this.config.drmSystems})}`);return this.attemptKeySystemAccess(e)}attemptSetMediaKeys(e,t){if(this.mediaResolved=void 0,this.mediaKeys===t)return Promise.resolve();const s=this.setMediaKeysQueue.slice();this.log(`Setting media-keys for "${e}"`);const i=Promise.all(s).then(()=>this.media?this.media.setMediaKeys(t):new Promise((r,n)=>{this.mediaResolved=()=>{if(this.mediaResolved=void 0,!this.media)return n(new Error("Attempted to set mediaKeys without media element attached"));this.mediaKeys=t,this.media.setMediaKeys(t).then(r).catch(n)}}));return this.mediaKeys=t,this.setMediaKeysQueue.push(i),i.then(()=>{this.log(`Media-keys set for "${e}"`),s.push(i),this.setMediaKeysQueue=this.setMediaKeysQueue.filter(r=>s.indexOf(r)===-1)})}generateRequestWithPreferredKeySession(e,t,s,i){var r;const n=(r=this.config.drmSystems)==null||(r=r[e.keySystem])==null?void 0:r.generateRequest;if(n)try{const g=n.call(this.hls,t,s,e);if(!g)throw new Error("Invalid response from configured generateRequest filter");t=g.initDataType,s=g.initData?g.initData:null,e.decryptdata.pssh=s?new Uint8Array(s):null}catch(g){if(this.warn(g.message),this.hls&&this.hls.config.debug)throw g}if(s===null)return this.log(`Skipping key-session request for "${i}" (no initData)`),Promise.resolve(e);const o=jt(e.decryptdata),c=e.decryptdata.uri;this.log(`Generating key-session request for "${i}" keyId: ${o} URI: ${c} (init data type: ${t} length: ${s.byteLength})`);const l=new Ii,h=e._onmessage=g=>{const y=e.mediaKeysSession;if(!y){l.emit("error",new Error("invalid state"));return}const{messageType:p,message:E}=g;this.log(`"${p}" message event for session "${y.sessionId}" message size: ${E.byteLength}`),p==="license-request"||p==="license-renewal"?this.renewLicense(e,E).catch(T=>{l.eventNames().length?l.emit("error",T):this.handleError(T)}):p==="license-release"?e.keySystem===oe.FAIRPLAY&&this.updateKeySession(e,ei("acknowledged")).then(()=>this.removeSession(e)).catch(T=>this.handleError(T)):this.warn(`unhandled media key message type "${p}"`)},u=(g,y)=>{y.keyStatus=g;let p;g.startsWith("usable")?l.emit("resolved"):g==="internal-error"||g==="output-restricted"||g==="output-downscaled"?p=Vr(g,y.decryptdata):g==="expired"?p=new Error(`key expired (keyId: ${o})`):g==="released"?p=new Error("key released"):g==="status-pending"||this.warn(`unhandled key status change "${g}" (keyId: ${o})`),p&&(l.eventNames().length?l.emit("error",p):this.handleError(p))},d=e._onkeystatuseschange=g=>{if(!e.mediaKeysSession){l.emit("error",new Error("invalid state"));return}const p=this.getKeyStatuses(e);if(!Object.keys(p).some(v=>p[v]!=="status-pending"))return;if(p[o]==="expired"){this.log(`Expired key ${ne(p)} in key-session "${e.mediaKeysSession.sessionId}"`),this.renewKeySession(e);return}let T=p[o];if(T)u(T,e);else{var S;e.keyStatusTimeouts||(e.keyStatusTimeouts={}),(S=e.keyStatusTimeouts)[o]||(S[o]=self.setTimeout(()=>{if(!e.mediaKeysSession||!this.mediaKeys)return;const x=this.getKeyStatus(e.decryptdata);if(x&&x!=="status-pending")return this.log(`No status for keyId ${o} in key-session "${e.mediaKeysSession.sessionId}". Using session key-status ${x} from other session.`),u(x,e);this.log(`key status for ${o} in key-session "${e.mediaKeysSession.sessionId}" timed out after 1000ms`),T="internal-error",u(T,e)},1e3)),this.log(`No status for keyId ${o} (${ne(p)}).`)}};Te(e.mediaKeysSession,"message",h),Te(e.mediaKeysSession,"keystatuseschange",d);const f=new Promise((g,y)=>{l.on("error",y),l.on("resolved",g)});return e.mediaKeysSession.generateRequest(t,s).then(()=>{this.log(`Request generated for key-session "${e.mediaKeysSession.sessionId}" keyId: ${o} URI: ${c}`)}).catch(g=>{throw new xe({type:V.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_NO_SESSION,error:g,decryptdata:e.decryptdata,fatal:!1},`Error generating key-session request: ${g}`)}).then(()=>f).catch(g=>(l.removeAllListeners(),this.removeSession(e).then(()=>{throw g}))).then(()=>(l.removeAllListeners(),e))}getKeyStatuses(e){const t={};return e.mediaKeysSession.keyStatuses.forEach((s,i)=>{if(typeof i=="string"&&typeof s=="object"){const o=i;i=s,s=o}const r="buffer"in i?new Uint8Array(i.buffer,i.byteOffset,i.byteLength):new Uint8Array(i);if(e.keySystem===oe.PLAYREADY&&r.length===16){const o=me(r);t[o]=s,Cn(r)}const n=me(r);s==="internal-error"&&(this.bannedKeyIds[n]=s),this.log(`key status change "${s}" for keyStatuses keyId: ${n} key-session "${e.mediaKeysSession.sessionId}"`),t[n]=s}),t}fetchServerCertificate(e){const t=this.config,s=t.loader,i=new s(t),r=this.getServerCertificateUrl(e);return r?(this.log(`Fetching server certificate for "${e}"`),new Promise((n,o)=>{const c={responseType:"arraybuffer",url:r},l=t.certLoadPolicy.default,h={loadPolicy:l,timeout:l.maxLoadTimeMs,maxRetry:0,retryDelay:0,maxRetryDelay:0},u={onSuccess:(d,f,g,y)=>{n(d.data)},onError:(d,f,g,y)=>{o(new xe({type:V.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED,fatal:!0,networkDetails:g,response:te({url:c.url,data:void 0},d)},`"${e}" certificate request failed (${r}). Status: ${d.code} (${d.text})`))},onTimeout:(d,f,g)=>{o(new xe({type:V.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED,fatal:!0,networkDetails:g,response:{url:c.url,data:void 0}},`"${e}" certificate request timed out (${r})`))},onAbort:(d,f,g)=>{o(new Error("aborted"))}};i.load(c,h,u)})):Promise.resolve()}setMediaKeysServerCertificate(e,t,s){return new Promise((i,r)=>{e.setServerCertificate(s).then(n=>{this.log(`setServerCertificate ${n?"success":"not supported by CDM"} (${s.byteLength}) on "${t}"`),i(e)}).catch(n=>{r(new xe({type:V.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_SERVER_CERTIFICATE_UPDATE_FAILED,error:n,fatal:!0},n.message))})})}renewLicense(e,t){return this.requestLicense(e,new Uint8Array(t)).then(s=>this.updateKeySession(e,new Uint8Array(s)).catch(i=>{throw new xe({type:V.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_SESSION_UPDATE_FAILED,decryptdata:e.decryptdata,error:i,fatal:!1},i.message)}))}unpackPlayReadyKeyMessage(e,t){const s=String.fromCharCode.apply(null,new Uint16Array(t.buffer));if(!s.includes("PlayReadyKeyMessage"))return e.setRequestHeader("Content-Type","text/xml; charset=utf-8"),t;const i=new DOMParser().parseFromString(s,"application/xml"),r=i.querySelectorAll("HttpHeader");if(r.length>0){let h;for(let u=0,d=r.length;u in key message");return ei(atob(l))}setupLicenseXHR(e,t,s,i){const r=this.config.licenseXhrSetup;return r?Promise.resolve().then(()=>{if(!s.decryptdata)throw new Error("Key removed");return r.call(this.hls,e,t,s,i)}).catch(n=>{if(!s.decryptdata)throw n;return e.open("POST",t,!0),r.call(this.hls,e,t,s,i)}).then(n=>(e.readyState||e.open("POST",t,!0),{xhr:e,licenseChallenge:n||i})):(e.open("POST",t,!0),Promise.resolve({xhr:e,licenseChallenge:i}))}requestLicense(e,t){const s=this.config.keyLoadPolicy.default;return new Promise((i,r)=>{const n=this.getLicenseServerUrlOrThrow(e.keySystem);this.log(`Sending license request to URL: ${n}`);const o=new XMLHttpRequest;o.responseType="arraybuffer",o.onreadystatechange=()=>{if(!this.hls||!e.mediaKeysSession)return r(new Error("invalid state"));if(o.readyState===4)if(o.status===200){this._requestLicenseFailureCount=0;let c=o.response;this.log(`License received ${c instanceof ArrayBuffer?c.byteLength:c}`);const l=this.config.licenseResponseCallback;if(l)try{c=l.call(this.hls,o,n,e)}catch(h){this.error(h)}i(c)}else{const c=s.errorRetry,l=c?c.maxNumRetry:0;if(this._requestLicenseFailureCount++,this._requestLicenseFailureCount>l||o.status>=400&&o.status<500)r(new xe({type:V.KEY_SYSTEM_ERROR,details:R.KEY_SYSTEM_LICENSE_REQUEST_FAILED,decryptdata:e.decryptdata,fatal:!0,networkDetails:o,response:{url:n,data:void 0,code:o.status,text:o.statusText}},`License Request XHR failed (${n}). Status: ${o.status} (${o.statusText})`));else{const h=l-this._requestLicenseFailureCount+1;this.warn(`Retrying license request, ${h} attempts left`),this.requestLicense(e,t).then(i,r)}}},e.licenseXhr&&e.licenseXhr.readyState!==XMLHttpRequest.DONE&&e.licenseXhr.abort(),e.licenseXhr=o,this.setupLicenseXHR(o,n,e,t).then(({xhr:c,licenseChallenge:l})=>{e.keySystem==oe.PLAYREADY&&(l=this.unpackPlayReadyKeyMessage(c,l)),c.send(l)}).catch(r)})}onDestroying(){this.unregisterListeners(),this._clear()}onMediaAttached(e,t){if(!this.config.emeEnabled)return;const s=t.media;this.media=s,Te(s,"encrypted",this.onMediaEncrypted),Te(s,"waitingforkey",this.onWaitingForKey);const i=this.mediaResolved;i?i():this.mediaKeys=s.mediaKeys}onMediaDetached(){const e=this.media;e&&(ve(e,"encrypted",this.onMediaEncrypted),ve(e,"waitingforkey",this.onWaitingForKey),this.media=null,this.mediaKeys=null)}_clear(){var e;this._requestLicenseFailureCount=0,this.keyIdToKeySessionPromise={},this.bannedKeyIds={};const t=this.mediaResolved;if(t&&t(),!this.mediaKeys&&!this.mediaKeySessions.length)return;const s=this.media,i=this.mediaKeySessions.slice();this.mediaKeySessions=[],this.mediaKeys=null,Ze.clearKeyUriToKeyIdMap();const r=i.length;St.CDMCleanupPromise=Promise.all(i.map(n=>this.removeSession(n)).concat((s==null||(e=s.setMediaKeys(null))==null?void 0:e.catch(n=>{this.log(`Could not clear media keys: ${n}`),this.hls&&this.hls.trigger(m.ERROR,{type:V.OTHER_ERROR,details:R.KEY_SYSTEM_DESTROY_MEDIA_KEYS_ERROR,fatal:!1,error:new Error(`Could not clear media keys: ${n}`)})}))||Promise.resolve())).catch(n=>{this.log(`Could not close sessions and clear media keys: ${n}`),this.hls&&this.hls.trigger(m.ERROR,{type:V.OTHER_ERROR,details:R.KEY_SYSTEM_DESTROY_CLOSE_SESSION_ERROR,fatal:!1,error:new Error(`Could not close sessions and clear media keys: ${n}`)})}).then(()=>{r&&this.log("finished closing key sessions and clearing media keys")})}onManifestLoading(){this._clear()}onManifestLoaded(e,{sessionKeys:t}){if(!(!t||!this.config.emeEnabled)&&!this.keyFormatPromise){const s=t.reduce((i,r)=>(i.indexOf(r.keyFormat)===-1&&i.push(r.keyFormat),i),[]);this.log(`Selecting key-system from session-keys ${s.join(", ")}`),this.keyFormatPromise=this.getKeyFormatPromise(s)}}removeSession(e){const{mediaKeysSession:t,licenseXhr:s,decryptdata:i}=e;if(t){this.log(`Remove licenses and keys and close session "${t.sessionId}" keyId: ${me((i==null?void 0:i.keyId)||[])}`),e._onmessage&&(t.removeEventListener("message",e._onmessage),e._onmessage=void 0),e._onkeystatuseschange&&(t.removeEventListener("keystatuseschange",e._onkeystatuseschange),e._onkeystatuseschange=void 0),s&&s.readyState!==XMLHttpRequest.DONE&&s.abort(),e.mediaKeysSession=e.decryptdata=e.licenseXhr=void 0;const r=this.mediaKeySessions.indexOf(e);r>-1&&this.mediaKeySessions.splice(r,1);const{keyStatusTimeouts:n}=e;n&&Object.keys(n).forEach(l=>self.clearTimeout(n[l]));const{drmSystemOptions:o}=this.config;return(cl(o)?new Promise((l,h)=>{self.setTimeout(()=>h(new Error("MediaKeySession.remove() timeout")),8e3),t.remove().then(l).catch(h)}):Promise.resolve()).catch(l=>{this.log(`Could not remove session: ${l}`),this.hls&&this.hls.trigger(m.ERROR,{type:V.OTHER_ERROR,details:R.KEY_SYSTEM_DESTROY_REMOVE_SESSION_ERROR,fatal:!1,error:new Error(`Could not remove session: ${l}`)})}).then(()=>t.close()).catch(l=>{this.log(`Could not close session: ${l}`),this.hls&&this.hls.trigger(m.ERROR,{type:V.OTHER_ERROR,details:R.KEY_SYSTEM_DESTROY_CLOSE_SESSION_ERROR,fatal:!1,error:new Error(`Could not close session: ${l}`)})})}return Promise.resolve()}}St.CDMCleanupPromise=void 0;function jt(a){if(!a)throw new Error("Could not read keyId of undefined decryptdata");if(a.keyId===null)throw new Error("keyId is null");return me(a.keyId)}function _h(a,e){if(a.keyId&&e.mediaKeysSession.keyStatuses.has(a.keyId))return e.mediaKeysSession.keyStatuses.get(a.keyId);if(a.matches(e.decryptdata))return e.keyStatus}class xe extends Error{constructor(e,t){super(t),this.data=void 0,e.error||(e.error=new Error(t)),this.data=e,e.err=e.error}}function Vr(a,e){const t=a==="output-restricted",s=t?R.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED:R.KEY_SYSTEM_STATUS_INTERNAL_ERROR;return new xe({type:V.KEY_SYSTEM_ERROR,details:s,fatal:!1,decryptdata:e},t?"HDCP level output restricted":`key status changed to "${a}"`)}class Dh{constructor(e){this.hls=void 0,this.isVideoPlaybackQualityAvailable=!1,this.timer=void 0,this.media=null,this.lastTime=void 0,this.lastDroppedFrames=0,this.lastDecodedFrames=0,this.streamController=void 0,this.hls=e,this.registerListeners()}setStreamController(e){this.streamController=e}registerListeners(){this.hls.on(m.MEDIA_ATTACHING,this.onMediaAttaching,this),this.hls.on(m.MEDIA_DETACHING,this.onMediaDetaching,this)}unregisterListeners(){this.hls.off(m.MEDIA_ATTACHING,this.onMediaAttaching,this),this.hls.off(m.MEDIA_DETACHING,this.onMediaDetaching,this)}destroy(){this.timer&&clearInterval(this.timer),this.unregisterListeners(),this.isVideoPlaybackQualityAvailable=!1,this.media=null}onMediaAttaching(e,t){const s=this.hls.config;if(s.capLevelOnFPSDrop){const i=t.media instanceof self.HTMLVideoElement?t.media:null;this.media=i,i&&typeof i.getVideoPlaybackQuality=="function"&&(this.isVideoPlaybackQualityAvailable=!0),self.clearInterval(this.timer),this.timer=self.setInterval(this.checkFPSInterval.bind(this),s.fpsDroppedMonitoringPeriod)}}onMediaDetaching(){this.media=null}checkFPS(e,t,s){const i=performance.now();if(t){if(this.lastTime){const r=i-this.lastTime,n=s-this.lastDroppedFrames,o=t-this.lastDecodedFrames,c=1e3*n/r,l=this.hls;if(l.trigger(m.FPS_DROP,{currentDropped:n,currentDecoded:o,totalDroppedFrames:s}),c>0&&n>l.config.fpsDroppedMonitoringThreshold*o){let h=l.currentLevel;l.logger.warn("drop FPS ratio greater than max allowed value for currentLevel: "+h),h>0&&(l.autoLevelCapping===-1||l.autoLevelCapping>=h)&&(h=h-1,l.trigger(m.FPS_DROP_LEVEL_CAPPING,{level:h,droppedLevel:l.currentLevel}),l.autoLevelCapping=h,this.streamController.nextLevelSwitch())}}this.lastTime=i,this.lastDroppedFrames=s,this.lastDecodedFrames=t}}checkFPSInterval(){const e=this.media;if(e)if(this.isVideoPlaybackQualityAvailable){const t=e.getVideoPlaybackQuality();this.checkFPS(e,t.totalVideoFrames,t.droppedVideoFrames)}else this.checkFPS(e,e.webkitDecodedFrameCount,e.webkitDroppedFrameCount)}}function xa(a,e){let t;try{t=new Event("addtrack")}catch{t=document.createEvent("Event"),t.initEvent("addtrack",!1,!1)}t.track=a,e.dispatchEvent(t)}function Aa(a,e){const t=a.mode;if(t==="disabled"&&(a.mode="hidden"),a.cues&&!a.cues.getCueById(e.id))try{if(a.addCue(e),!a.cues.getCueById(e.id))throw new Error(`addCue is failed for: ${e}`)}catch(s){se.debug(`[texttrack-utils]: ${s}`);try{const i=new self.TextTrackCue(e.startTime,e.endTime,e.text);i.id=e.id,a.addCue(i)}catch(i){se.debug(`[texttrack-utils]: Legacy TextTrackCue fallback failed: ${i}`)}}t==="disabled"&&(a.mode=t)}function yt(a,e){const t=a.mode;if(t==="disabled"&&(a.mode="hidden"),a.cues)for(let s=a.cues.length;s--;)e&&a.cues[s].removeEventListener("enter",e),a.removeCue(a.cues[s]);t==="disabled"&&(a.mode=t)}function ci(a,e,t,s){const i=a.mode;if(i==="disabled"&&(a.mode="hidden"),a.cues&&a.cues.length>0){const r=Ph(a.cues,e,t);for(let n=0;na[t].endTime)return-1;let s=0,i=t,r;for(;s<=i;)if(r=Math.floor((i+s)/2),ea[r].startTime&&s-1)for(let r=i,n=a.length;r=e&&o.endTime<=t)s.push(o);else if(o.startTime>t)return s}return s}function as(a){const e=[];for(let t=0;tthis.pollTrackChange(0),this.onTextTracksChanged=()=>{if(this.useTextTrackPolling||self.clearInterval(this.subtitlePollingInterval),!this.media||!this.hls.config.renderTextTracksNatively)return;let t=null;const s=as(this.media.textTracks);for(let r=0;r-1&&this.toggleTrackModes()}registerListeners(){const{hls:e}=this;e.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.MANIFEST_PARSED,this.onManifestParsed,this),e.on(m.LEVEL_LOADING,this.onLevelLoading,this),e.on(m.LEVEL_SWITCHING,this.onLevelSwitching,this),e.on(m.SUBTITLE_TRACK_LOADED,this.onSubtitleTrackLoaded,this),e.on(m.ERROR,this.onError,this)}unregisterListeners(){const{hls:e}=this;e.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.MANIFEST_PARSED,this.onManifestParsed,this),e.off(m.LEVEL_LOADING,this.onLevelLoading,this),e.off(m.LEVEL_SWITCHING,this.onLevelSwitching,this),e.off(m.SUBTITLE_TRACK_LOADED,this.onSubtitleTrackLoaded,this),e.off(m.ERROR,this.onError,this)}onMediaAttached(e,t){this.media=t.media,this.media&&(this.queuedDefaultTrack>-1&&(this.subtitleTrack=this.queuedDefaultTrack,this.queuedDefaultTrack=-1),this.useTextTrackPolling=!(this.media.textTracks&&"onchange"in this.media.textTracks),this.useTextTrackPolling?this.pollTrackChange(500):this.media.textTracks.addEventListener("change",this.asyncPollTrackChange))}pollTrackChange(e){self.clearInterval(this.subtitlePollingInterval),this.subtitlePollingInterval=self.setInterval(this.onTextTracksChanged,e)}onMediaDetaching(e,t){const s=this.media;if(!s)return;const i=!!t.transferMedia;if(self.clearInterval(this.subtitlePollingInterval),this.useTextTrackPolling||s.textTracks.removeEventListener("change",this.asyncPollTrackChange),this.trackId>-1&&(this.queuedDefaultTrack=this.trackId),this.subtitleTrack=-1,this.media=null,i)return;as(s.textTracks).forEach(n=>{yt(n)})}onManifestLoading(){this.tracks=[],this.groupIds=null,this.tracksInGroup=[],this.trackId=-1,this.currentTrack=null,this.selectDefaultTrack=!0}onManifestParsed(e,t){this.tracks=t.subtitleTracks}onSubtitleTrackLoaded(e,t){const{id:s,groupId:i,details:r}=t,n=this.tracksInGroup[s];if(!n||n.groupId!==i){this.warn(`Subtitle track with id:${s} and group:${i} not found in active group ${n==null?void 0:n.groupId}`);return}const o=n.details;n.details=t.details,this.log(`Subtitle track ${s} "${n.name}" lang:${n.lang} group:${i} loaded [${r.startSN}-${r.endSN}]`),s===this.trackId&&this.playlistLoaded(s,t,o)}onLevelLoading(e,t){this.switchLevel(t.level)}onLevelSwitching(e,t){this.switchLevel(t.level)}switchLevel(e){const t=this.hls.levels[e];if(!t)return;const s=t.subtitleGroups||null,i=this.groupIds;let r=this.currentTrack;if(!s||(i==null?void 0:i.length)!==(s==null?void 0:s.length)||s!=null&&s.some(n=>(i==null?void 0:i.indexOf(n))===-1)){this.groupIds=s,this.trackId=-1,this.currentTrack=null;const n=this.tracks.filter(h=>!s||s.indexOf(h.groupId)!==-1);if(n.length)this.selectDefaultTrack&&!n.some(h=>h.default)&&(this.selectDefaultTrack=!1),n.forEach((h,u)=>{h.id=u});else if(!r&&!this.tracksInGroup.length)return;this.tracksInGroup=n;const o=this.hls.config.subtitlePreference;if(!r&&o){this.selectDefaultTrack=!1;const h=$e(o,n);if(h>-1)r=n[h];else{const u=$e(o,this.tracks);r=this.tracks[u]}}let c=this.findTrackId(r);c===-1&&r&&(c=this.findTrackId(null));const l={subtitleTracks:n};this.log(`Updating subtitle tracks, ${n.length} track(s) found in "${s==null?void 0:s.join(",")}" group-id`),this.hls.trigger(m.SUBTITLE_TRACKS_UPDATED,l),c!==-1&&this.trackId===-1&&this.setSubtitleTrack(c)}}findTrackId(e){const t=this.tracksInGroup,s=this.selectDefaultTrack;for(let i=0;i-1){const r=this.tracksInGroup[i];return this.setSubtitleTrack(i),r}else{if(s)return null;{const r=$e(e,t);if(r>-1)return t[r]}}}}return null}loadPlaylist(e){super.loadPlaylist(),this.shouldLoadPlaylist(this.currentTrack)&&this.scheduleLoading(this.currentTrack,e)}loadingPlaylist(e,t){super.loadingPlaylist(e,t);const s=e.id,i=e.groupId,r=this.getUrlWithDirectives(e.url,t),n=e.details,o=n==null?void 0:n.age;this.log(`Loading subtitle ${s} "${e.name}" lang:${e.lang} group:${i}${(t==null?void 0:t.msn)!==void 0?" at sn "+t.msn+" part "+t.part:""}${o&&n.live?" age "+o.toFixed(1)+(n.type&&" "+n.type||""):""} ${r}`),this.hls.trigger(m.SUBTITLE_TRACK_LOADING,{url:r,id:s,groupId:i,deliveryDirectives:t||null,track:e})}toggleTrackModes(){const{media:e}=this;if(!e)return;const t=as(e.textTracks),s=this.currentTrack;let i;if(s&&(i=t.filter(r=>ni(s,r))[0],i||this.warn(`Unable to find subtitle TextTrack with name "${s.name}" and language "${s.lang}"`)),[].slice.call(t).forEach(r=>{r.mode!=="disabled"&&r!==i&&(r.mode="disabled")}),i){const r=this.subtitleDisplay?"showing":"hidden";i.mode!==r&&(i.mode=r)}}setSubtitleTrack(e){const t=this.tracksInGroup;if(!this.media){this.queuedDefaultTrack=e;return}if(e<-1||e>=t.length||!M(e)){this.warn(`Invalid subtitle track id: ${e}`);return}this.selectDefaultTrack=!1;const s=this.currentTrack,i=t[e]||null;if(this.trackId=e,this.currentTrack=i,this.toggleTrackModes(),!i){this.hls.trigger(m.SUBTITLE_TRACK_SWITCH,{id:e});return}const r=!!i.details&&!i.details.live;if(e===this.trackId&&i===s&&r)return;this.log(`Switching to subtitle-track ${e}`+(i?` "${i.name}" lang:${i.lang} group:${i.groupId}`:""));const{id:n,groupId:o="",name:c,type:l,url:h}=i;this.hls.trigger(m.SUBTITLE_TRACK_SWITCH,{id:n,groupId:o,name:c,type:l,url:h});const u=this.switchParams(i.url,s==null?void 0:s.details,i.details);this.loadPlaylist(u)}}function wh(){try{return crypto.randomUUID()}catch{try{const e=URL.createObjectURL(new Blob),t=e.toString();return URL.revokeObjectURL(e),t.slice(t.lastIndexOf("/")+1)}catch{let t=new Date().getTime();return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,i=>{const r=(t+Math.random()*16)%16|0;return t=Math.floor(t/16),(i=="x"?r:r&3|8).toString(16)})}}}function Pt(a){let e=5381,t=a.length;for(;t;)e=e*33^a.charCodeAt(--t);return(e>>>0).toString()}const vt=.025;let Es=function(a){return a[a.Point=0]="Point",a[a.Range=1]="Range",a}({});function Oh(a,e,t){return`${a.identifier}-${t+1}-${Pt(e)}`}class Fh{constructor(e,t){this.base=void 0,this._duration=null,this._timelineStart=null,this.appendInPlaceDisabled=void 0,this.appendInPlaceStarted=void 0,this.dateRange=void 0,this.hasPlayed=!1,this.cumulativeDuration=0,this.resumeOffset=NaN,this.playoutLimit=NaN,this.restrictions={skip:!1,jump:!1},this.snapOptions={out:!1,in:!1},this.assetList=[],this.assetListLoader=void 0,this.assetListResponse=null,this.resumeAnchor=void 0,this.error=void 0,this.resetOnResume=void 0,this.base=t,this.dateRange=e,this.setDateRange(e)}setDateRange(e){this.dateRange=e,this.resumeOffset=e.attr.optionalFloat("X-RESUME-OFFSET",this.resumeOffset),this.playoutLimit=e.attr.optionalFloat("X-PLAYOUT-LIMIT",this.playoutLimit),this.restrictions=e.attr.enumeratedStringList("X-RESTRICT",this.restrictions),this.snapOptions=e.attr.enumeratedStringList("X-SNAP",this.snapOptions)}reset(){var e;this.appendInPlaceStarted=!1,(e=this.assetListLoader)==null||e.destroy(),this.assetListLoader=void 0,this.supplementsPrimary||(this.assetListResponse=null,this.assetList=[],this._duration=null)}isAssetPastPlayoutLimit(e){var t;if(e>0&&e>=this.assetList.length)return!0;const s=this.playoutLimit;return e<=0||isNaN(s)?!1:s===0?!0:(((t=this.assetList[e])==null?void 0:t.startOffset)||0)>s}findAssetIndex(e){return this.assetList.indexOf(e)}get identifier(){return this.dateRange.id}get startDate(){return this.dateRange.startDate}get startTime(){const e=this.dateRange.startTime;if(this.snapOptions.out){const t=this.dateRange.tagAnchor;if(t)return Ns(e,t)}return e}get startOffset(){return this.cue.pre?0:this.startTime}get startIsAligned(){if(this.startTime===0||this.snapOptions.out)return!0;const e=this.dateRange.tagAnchor;if(e){const t=this.dateRange.startTime,s=Ns(t,e);return t-s<.1}return!1}get resumptionOffset(){const e=this.resumeOffset,t=M(e)?e:this.duration;return this.cumulativeDuration+t}get resumeTime(){const e=this.startOffset+this.resumptionOffset;if(this.snapOptions.in){const t=this.resumeAnchor;if(t)return Ns(e,t)}return e}get appendInPlace(){return this.appendInPlaceStarted?!0:this.appendInPlaceDisabled?!1:!!(!this.cue.once&&!this.cue.pre&&this.startIsAligned&&(isNaN(this.playoutLimit)&&isNaN(this.resumeOffset)||this.resumeOffset&&this.duration&&Math.abs(this.resumeOffset-this.duration)0||this.assetListResponse!==null}toString(){return Mh(this)}}function Ns(a,e){return a-e.start":a.cue.post?"":""}${a.timelineStart.toFixed(2)}-${a.resumeTime.toFixed(2)}]`}function pt(a){const e=a.timelineStart,t=a.duration||0;return`["${a.identifier}" ${e.toFixed(2)}-${(e+t).toFixed(2)}]`}class Nh{constructor(e,t,s,i){this.hls=void 0,this.interstitial=void 0,this.assetItem=void 0,this.tracks=null,this.hasDetails=!1,this.mediaAttached=null,this._currentTime=void 0,this._bufferedEosTime=void 0,this.checkPlayout=()=>{this.reachedPlayout(this.currentTime)&&this.hls&&this.hls.trigger(m.PLAYOUT_LIMIT_REACHED,{})};const r=this.hls=new e(t);this.interstitial=s,this.assetItem=i;const n=()=>{this.hasDetails=!0};r.once(m.LEVEL_LOADED,n),r.once(m.AUDIO_TRACK_LOADED,n),r.once(m.SUBTITLE_TRACK_LOADED,n),r.on(m.MEDIA_ATTACHING,(o,{media:c})=>{this.removeMediaListeners(),this.mediaAttached=c,this.interstitial.playoutLimit&&(c.addEventListener("timeupdate",this.checkPlayout),this.appendInPlace&&r.on(m.BUFFER_APPENDED,()=>{const h=this.bufferedEnd;this.reachedPlayout(h)&&(this._bufferedEosTime=h,r.trigger(m.BUFFERED_TO_END,void 0))}))})}get appendInPlace(){return this.interstitial.appendInPlace}loadSource(){const e=this.hls;if(e)if(e.url)e.levels.length&&!e.started&&e.startLoad(-1,!0);else{let t=this.assetItem.uri;try{t=Ia(t,e.config.primarySessionId||"").href}catch{}e.loadSource(t)}}bufferedInPlaceToEnd(e){var t;if(!this.appendInPlace)return!1;if((t=this.hls)!=null&&t.bufferedToEnd)return!0;if(!e)return!1;const s=Math.min(this._bufferedEosTime||1/0,this.duration),i=this.timelineOffset,r=q.bufferInfo(e,i,0);return this.getAssetTime(r.end)>=s-.02}reachedPlayout(e){const s=this.interstitial.playoutLimit;return this.startOffset+e>=s}get destroyed(){var e;return!((e=this.hls)!=null&&e.userConfig)}get assetId(){return this.assetItem.identifier}get interstitialId(){return this.assetItem.parentIdentifier}get media(){var e;return((e=this.hls)==null?void 0:e.media)||null}get bufferedEnd(){const e=this.media||this.mediaAttached;if(!e)return this._bufferedEosTime?this._bufferedEosTime:this.currentTime;const t=q.bufferInfo(e,e.currentTime,.001);return this.getAssetTime(t.end)}get currentTime(){const e=this.media||this.mediaAttached;return e?this.getAssetTime(e.currentTime):this._currentTime||0}get duration(){const e=this.assetItem.duration;if(!e)return 0;const t=this.interstitial.playoutLimit;if(t){const s=t-this.startOffset;if(s>0&&s1/9e4&&this.hls){if(this.hasDetails)throw new Error("Cannot set timelineOffset after playlists are loaded");this.hls.config.timelineOffset=e}}}getAssetTime(e){const t=this.timelineOffset,s=this.duration;return Math.min(Math.max(0,e-t),s)}removeMediaListeners(){const e=this.mediaAttached;e&&(this._currentTime=e.currentTime,this.bufferSnapShot(),e.removeEventListener("timeupdate",this.checkPlayout))}bufferSnapShot(){if(this.mediaAttached){var e;(e=this.hls)!=null&&e.bufferedToEnd&&(this._bufferedEosTime=this.bufferedEnd)}}destroy(){this.removeMediaListeners(),this.hls&&this.hls.destroy(),this.hls=null,this.tracks=this.mediaAttached=this.checkPlayout=null}attachMedia(e){var t;this.loadSource(),(t=this.hls)==null||t.attachMedia(e)}detachMedia(){var e;this.removeMediaListeners(),this.mediaAttached=null,(e=this.hls)==null||e.detachMedia()}resumeBuffering(){var e;(e=this.hls)==null||e.resumeBuffering()}pauseBuffering(){var e;(e=this.hls)==null||e.pauseBuffering()}transferMedia(){var e;return this.bufferSnapShot(),((e=this.hls)==null?void 0:e.transferMedia())||null}resetDetails(){const e=this.hls;if(e&&this.hasDetails){e.stopLoad();const t=s=>delete s.details;e.levels.forEach(t),e.allAudioTracks.forEach(t),e.allSubtitleTracks.forEach(t),this.hasDetails=!1}}on(e,t,s){var i;(i=this.hls)==null||i.on(e,t)}once(e,t,s){var i;(i=this.hls)==null||i.once(e,t)}off(e,t,s){var i;(i=this.hls)==null||i.off(e,t)}toString(){var e;return`HlsAssetPlayer: ${pt(this.assetItem)} ${(e=this.hls)==null?void 0:e.sessionId} ${this.appendInPlace?"append-in-place":""}`}}const Hr=.033;class Bh extends Ce{constructor(e,t){super("interstitials-sched",t),this.onScheduleUpdate=void 0,this.eventMap={},this.events=null,this.items=null,this.durations={primary:0,playout:0,integrated:0},this.onScheduleUpdate=e}destroy(){this.reset(),this.onScheduleUpdate=null}reset(){this.eventMap={},this.setDurations(0,0,0),this.events&&this.events.forEach(e=>e.reset()),this.events=this.items=null}resetErrorsInRange(e,t){return this.events?this.events.reduce((s,i)=>e<=i.startOffset&&t>i.startOffset?(delete i.error,s+1):s,0):0}get duration(){const e=this.items;return e?e[e.length-1].end:0}get length(){return this.items?this.items.length:0}getEvent(e){return e&&this.eventMap[e]||null}hasEvent(e){return e in this.eventMap}findItemIndex(e,t){if(e.event)return this.findEventIndex(e.event.identifier);let s=-1;e.nextEvent?s=this.findEventIndex(e.nextEvent.identifier)-1:e.previousEvent&&(s=this.findEventIndex(e.previousEvent.identifier)+1);const i=this.items;if(i)for(i[s]||(t===void 0&&(t=e.start),s=this.findItemIndexAtTime(t));s>=0&&(r=i[s])!=null&&r.event;){var r;s--}return s}findItemIndexAtTime(e,t){const s=this.items;if(s)for(let i=0;ir.start&&e1)for(let r=0;ro&&(t!o.includes(l.identifier)):[];n.length&&n.sort((l,h)=>{const u=l.cue.pre,d=l.cue.post,f=h.cue.pre,g=h.cue.post;if(u&&!f)return-1;if(f&&!u||d&&!g)return 1;if(g&&!d)return-1;if(!u&&!f&&!d&&!g){const y=l.startTime,p=h.startTime;if(y!==p)return y-p}return l.dateRange.tagOrder-h.dateRange.tagOrder}),this.events=n,c.forEach(l=>{this.removeEvent(l)}),this.updateSchedule(e,c)}updateSchedule(e,t=[],s=!1){const i=this.events||[];if(i.length||t.length||this.length<2){const r=this.items,n=this.parseSchedule(i,e);(s||t.length||(r==null?void 0:r.length)!==n.length||n.some((c,l)=>Math.abs(c.playout.start-r[l].playout.start)>.005||Math.abs(c.playout.end-r[l].playout.end)>.005))&&(this.items=n,this.onScheduleUpdate(t,r))}}parseDateRanges(e,t,s){const i=[],r=Object.keys(e);for(let n=0;n!c.error&&!(c.cue.once&&c.hasPlayed)),e.length){this.resolveOffsets(e,t);let c=0,l=0;if(e.forEach((h,u)=>{const d=h.cue.pre,f=h.cue.post,g=e[u-1]||null,y=h.appendInPlace,p=f?r:h.startOffset,E=h.duration,T=h.timelineOccupancy===Es.Range?E:0,S=h.resumptionOffset,v=(g==null?void 0:g.startTime)===p,x=p+h.cumulativeDuration;let D=y?x+E:p+S;if(d||!f&&p<=0){const _=l;l+=T,h.timelineStart=x;const b=n;n+=E,s.push({event:h,start:x,end:D,playout:{start:b,end:n},integrated:{start:_,end:l}})}else if(p<=r){if(!v){const I=p-c;if(I>Hr){const P=c,F=l;l+=I;const U=n;n+=I;const H={previousEvent:e[u-1]||null,nextEvent:h,start:P,end:P+I,playout:{start:U,end:n},integrated:{start:F,end:l}};s.push(H)}else I>0&&g&&(g.cumulativeDuration+=I,s[s.length-1].end=p)}f&&(D=x),h.timelineStart=x;const _=l;l+=T;const b=n;n+=E,s.push({event:h,start:x,end:D,playout:{start:b,end:n},integrated:{start:_,end:l}})}else return;const A=h.resumeTime;f||A>r?c=r:c=A}),c{const l=o.cue.pre,h=o.cue.post,u=l?0:h?i:o.startTime;this.updateAssetDurations(o),n===u?o.cumulativeDuration=r:(r=0,n=u),!h&&o.snapOptions.in&&(o.resumeAnchor=lt(null,s.fragments,o.startOffset+o.resumptionOffset,0,0)||void 0),o.appendInPlace&&!o.appendInPlaceStarted&&(this.primaryCanResumeInPlaceAt(o,t)||(o.appendInPlace=!1)),!o.appendInPlace&&c+1vt?(this.log(`"${e.identifier}" resumption ${s} not aligned with estimated timeline end ${i}`),!1):!Object.keys(t).some(n=>{const o=t[n].details,c=o.edge;if(s>=c)return this.log(`"${e.identifier}" resumption ${s} past ${n} playlist end ${c}`),!1;const l=lt(null,o.fragments,s);if(!l)return this.log(`"${e.identifier}" resumption ${s} does not align with any fragments in ${n} playlist (${o.fragStart}-${o.fragmentEnd})`),!0;const h=n==="audio"?.175:0;return Math.abs(l.start-s){const p=d.data,E=p==null?void 0:p.ASSETS;if(!Array.isArray(E)){const T=this.assignAssetListError(e,R.ASSET_LIST_PARSING_ERROR,new Error("Invalid interstitial asset list"),g.url,f,y);this.hls.trigger(m.ERROR,T);return}e.assetListResponse=p,this.hls.trigger(m.ASSET_LIST_LOADED,{event:e,assetListResponse:p,networkDetails:y})},onError:(d,f,g,y)=>{const p=this.assignAssetListError(e,R.ASSET_LIST_LOAD_ERROR,new Error(`Error loading X-ASSET-LIST: HTTP status ${d.code} ${d.text} (${f.url})`),f.url,y,g);this.hls.trigger(m.ERROR,p)},onTimeout:(d,f,g)=>{const y=this.assignAssetListError(e,R.ASSET_LIST_LOAD_TIMEOUT,new Error(`Timeout loading X-ASSET-LIST (${f.url})`),f.url,d,g);this.hls.trigger(m.ERROR,y)}};return o.load(c,h,u),this.hls.trigger(m.ASSET_LIST_LOADING,{event:e}),o}assignAssetListError(e,t,s,i,r,n){return e.error=s,{type:V.NETWORK_ERROR,details:t,fatal:!1,interstitial:e,url:i,error:s,networkDetails:n,stats:r}}}function Yr(a){var e;a==null||(e=a.play())==null||e.catch(()=>{})}function mt(a,e){return`[${a}] Advancing timeline position to ${e}`}class $h extends Ce{constructor(e,t){super("interstitials",e.logger),this.HlsPlayerClass=void 0,this.hls=void 0,this.assetListLoader=void 0,this.mediaSelection=null,this.altSelection=null,this.media=null,this.detachedData=null,this.requiredTracks=null,this.manager=null,this.playerQueue=[],this.bufferedPos=-1,this.timelinePos=-1,this.schedule=void 0,this.playingItem=null,this.bufferingItem=null,this.waitingItem=null,this.endedItem=null,this.playingAsset=null,this.endedAsset=null,this.bufferingAsset=null,this.shouldPlay=!1,this.onPlay=()=>{this.shouldPlay=!0},this.onPause=()=>{this.shouldPlay=!1},this.onSeeking=()=>{const s=this.currentTime;if(s===void 0||this.playbackDisabled||!this.schedule)return;const i=s-this.timelinePos;if(Math.abs(i)<1/7056e5)return;const n=i<=-.01;this.timelinePos===-1&&!this.effectivePlayingItem&&this.checkStart(),this.timelinePos=s,this.bufferedPos=s;const o=this.playingItem;if(!o){this.checkBuffer();return}if(n&&this.schedule.resetErrorsInRange(s,s-i)&&this.updateSchedule(!0),this.checkBuffer(),n&&s=o.end){var c;const f=this.findItemIndex(o);let g=this.schedule.findItemIndexAtTime(s);if(g===-1&&(g=f+(n?-1:1),this.log(`seeked ${n?"back ":""}to position not covered by schedule ${s} (resolving from ${f} to ${g})`)),!this.isInterstitial(o)&&(c=this.media)!=null&&c.paused&&(this.shouldPlay=!1),!n&&g>f){const y=this.schedule.findJumpRestrictedIndex(f+1,g);if(y>f){this.setSchedulePosition(y);return}}this.setSchedulePosition(g);return}const l=this.playingAsset;if(!l){if(this.playingLastItem&&this.isInterstitial(o)){const f=o.event.assetList[0];f&&(this.endedItem=this.playingItem,this.playingItem=null,this.setScheduleToAssetAtTime(s,f))}return}const h=l.timelineStart,u=l.duration||0;if(n&&s=h+u){var d;(d=o.event)!=null&&d.appendInPlace&&(this.clearAssetPlayers(o.event,o),this.flushFrontBuffer(s)),this.setScheduleToAssetAtTime(s,l)}},this.onTimeupdate=()=>{const s=this.currentTime;if(s===void 0||this.playbackDisabled)return;if(this.timelinePos===-1&&!this.effectivePlayingItem&&this.checkStart(),s>this.timelinePos)this.timelinePos=s,s>this.bufferedPos&&this.checkBuffer();else return;const i=this.playingItem;if(!i||this.playingLastItem)return;if(s>=i.end){this.timelinePos=i.end;const o=this.findItemIndex(i);this.setSchedulePosition(o+1)}const r=this.playingAsset;if(!r)return;const n=r.timelineStart+(r.duration||0);s>=n&&this.setScheduleToAssetAtTime(s,r)},this.onScheduleUpdate=(s,i)=>{const r=this.schedule;if(!r)return;const n=this.playingItem,o=r.events||[],c=r.items||[],l=r.durations,h=s.map(y=>y.identifier),u=!!(o.length||h.length);(u||i)&&this.log(`INTERSTITIALS_UPDATED (${o.length}): ${o} +Schedule: ${c.map(y=>ke(y))} pos: ${this.timelinePos}`),h.length&&this.log(`Removed events ${h}`);let d=null,f=null;n&&(d=this.updateItem(n,this.timelinePos),this.itemsMatch(n,d)?this.playingItem=d:this.waitingItem=this.endedItem=null),this.waitingItem=this.updateItem(this.waitingItem),this.endedItem=this.updateItem(this.endedItem);const g=this.bufferingItem;if(g&&(f=this.updateItem(g,this.bufferedPos),this.itemsMatch(g,f)?this.bufferingItem=f:g.event&&(this.bufferingItem=this.playingItem,this.clearInterstitial(g.event,null))),s.forEach(y=>{y.assetList.forEach(p=>{this.clearAssetPlayer(p.identifier,null)})}),this.playerQueue.forEach(y=>{if(y.interstitial.appendInPlace){const p=y.assetItem.timelineStart,E=y.timelineOffset-p;if(E)try{y.timelineOffset=p}catch(T){Math.abs(E)>vt&&this.warn(`${T} ("${y.assetId}" ${y.timelineOffset}->${p})`)}}}),u||i){if(this.hls.trigger(m.INTERSTITIALS_UPDATED,{events:o.slice(0),schedule:c.slice(0),durations:l,removedIds:h}),this.isInterstitial(n)&&h.includes(n.event.identifier)){this.warn(`Interstitial "${n.event.identifier}" removed while playing`),this.primaryFallback(n.event);return}n&&this.trimInPlace(d,n),g&&f!==d&&this.trimInPlace(f,g),this.checkBuffer()}},this.hls=e,this.HlsPlayerClass=t,this.assetListLoader=new Uh(e),this.schedule=new Bh(this.onScheduleUpdate,e.logger),this.registerListeners()}registerListeners(){const e=this.hls;e&&(e.on(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.on(m.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),e.on(m.AUDIO_TRACK_UPDATED,this.onAudioTrackUpdated,this),e.on(m.SUBTITLE_TRACK_SWITCH,this.onSubtitleTrackSwitch,this),e.on(m.SUBTITLE_TRACK_UPDATED,this.onSubtitleTrackUpdated,this),e.on(m.EVENT_CUE_ENTER,this.onInterstitialCueEnter,this),e.on(m.ASSET_LIST_LOADED,this.onAssetListLoaded,this),e.on(m.BUFFER_APPENDED,this.onBufferAppended,this),e.on(m.BUFFER_FLUSHED,this.onBufferFlushed,this),e.on(m.BUFFERED_TO_END,this.onBufferedToEnd,this),e.on(m.MEDIA_ENDED,this.onMediaEnded,this),e.on(m.ERROR,this.onError,this),e.on(m.DESTROYING,this.onDestroying,this))}unregisterListeners(){const e=this.hls;e&&(e.off(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.off(m.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),e.off(m.AUDIO_TRACK_UPDATED,this.onAudioTrackUpdated,this),e.off(m.SUBTITLE_TRACK_SWITCH,this.onSubtitleTrackSwitch,this),e.off(m.SUBTITLE_TRACK_UPDATED,this.onSubtitleTrackUpdated,this),e.off(m.EVENT_CUE_ENTER,this.onInterstitialCueEnter,this),e.off(m.ASSET_LIST_LOADED,this.onAssetListLoaded,this),e.off(m.BUFFER_CODECS,this.onBufferCodecs,this),e.off(m.BUFFER_APPENDED,this.onBufferAppended,this),e.off(m.BUFFER_FLUSHED,this.onBufferFlushed,this),e.off(m.BUFFERED_TO_END,this.onBufferedToEnd,this),e.off(m.MEDIA_ENDED,this.onMediaEnded,this),e.off(m.ERROR,this.onError,this),e.off(m.DESTROYING,this.onDestroying,this))}startLoad(){this.resumeBuffering()}stopLoad(){this.pauseBuffering()}resumeBuffering(){var e;(e=this.getBufferingPlayer())==null||e.resumeBuffering()}pauseBuffering(){var e;(e=this.getBufferingPlayer())==null||e.pauseBuffering()}destroy(){this.unregisterListeners(),this.stopLoad(),this.assetListLoader&&this.assetListLoader.destroy(),this.emptyPlayerQueue(),this.clearScheduleState(),this.schedule&&this.schedule.destroy(),this.media=this.detachedData=this.mediaSelection=this.requiredTracks=this.altSelection=this.schedule=this.manager=null,this.hls=this.HlsPlayerClass=this.log=null,this.assetListLoader=null,this.onPlay=this.onPause=this.onSeeking=this.onTimeupdate=null,this.onScheduleUpdate=null}onDestroying(){const e=this.primaryMedia||this.media;e&&this.removeMediaListeners(e)}removeMediaListeners(e){ve(e,"play",this.onPlay),ve(e,"pause",this.onPause),ve(e,"seeking",this.onSeeking),ve(e,"timeupdate",this.onTimeupdate)}onMediaAttaching(e,t){const s=this.media=t.media;Te(s,"seeking",this.onSeeking),Te(s,"timeupdate",this.onTimeupdate),Te(s,"play",this.onPlay),Te(s,"pause",this.onPause)}onMediaAttached(e,t){const s=this.effectivePlayingItem,i=this.detachedData;if(this.detachedData=null,s===null)this.checkStart();else if(!i){this.clearScheduleState();const r=this.findItemIndex(s);this.setSchedulePosition(r)}}clearScheduleState(){this.log("clear schedule state"),this.playingItem=this.bufferingItem=this.waitingItem=this.endedItem=this.playingAsset=this.endedAsset=this.bufferingAsset=null}onMediaDetaching(e,t){const s=!!t.transferMedia,i=this.media;if(this.media=null,!s&&(i&&this.removeMediaListeners(i),this.detachedData)){const r=this.getBufferingPlayer();r&&(this.log(`Removing schedule state for detachedData and ${r}`),this.playingAsset=this.endedAsset=this.bufferingAsset=this.bufferingItem=this.waitingItem=this.detachedData=null,r.detachMedia()),this.shouldPlay=!1}}get interstitialsManager(){if(!this.hls)return null;if(this.manager)return this.manager;const e=this,t=()=>e.bufferingItem||e.waitingItem,s=u=>u&&e.getAssetPlayer(u.identifier),i=(u,d,f,g,y)=>{if(u){let p=u[d].start;const E=u.event;if(E){if(d==="playout"||E.timelineOccupancy!==Es.Point){const T=s(f);(T==null?void 0:T.interstitial)===E&&(p+=T.assetItem.startOffset+T[y])}}else{const T=g==="bufferedPos"?n():e[g];p+=T-u.start}return p}return 0},r=(u,d)=>{var f;if(u!==0&&d!=="primary"&&(f=e.schedule)!=null&&f.length){var g;const y=e.schedule.findItemIndexAtTime(u),p=(g=e.schedule.items)==null?void 0:g[y];if(p){const E=p[d].start-p.start;return u+E}}return u},n=()=>{const u=e.bufferedPos;return u===Number.MAX_VALUE?o("primary"):Math.max(u,0)},o=u=>{var d,f;return(d=e.primaryDetails)!=null&&d.live?e.primaryDetails.edge:((f=e.schedule)==null?void 0:f.durations[u])||0},c=(u,d)=>{var f,g;const y=e.effectivePlayingItem;if(y!=null&&(f=y.event)!=null&&f.restrictions.skip||!e.schedule)return;e.log(`seek to ${u} "${d}"`);const p=e.effectivePlayingItem,E=e.schedule.findItemIndexAtTime(u,d),T=(g=e.schedule.items)==null?void 0:g[E],S=e.getBufferingPlayer(),v=S==null?void 0:S.interstitial,x=v==null?void 0:v.appendInPlace,D=p&&e.itemsMatch(p,T);if(p&&(x||D)){const A=s(e.playingAsset),_=(A==null?void 0:A.media)||e.primaryMedia;if(_){const b=d==="primary"?_.currentTime:i(p,d,e.playingAsset,"timelinePos","currentTime"),I=u-b,P=(x?b:_.currentTime)+I;if(P>=0&&(!A||x||P<=A.duration)){_.currentTime=P;return}}}if(T){let A=u;if(d!=="primary"){const b=T[d].start,I=u-b;A=T.start+I}const _=!e.isInterstitial(T);if((!e.isInterstitial(p)||p.event.appendInPlace)&&(_||T.event.appendInPlace)){const b=e.media||(x?S==null?void 0:S.media:null);b&&(b.currentTime=A)}else if(p){const b=e.findItemIndex(p);if(E>b){const P=e.schedule.findJumpRestrictedIndex(b+1,E);if(P>b){e.setSchedulePosition(P);return}}let I=0;if(_)e.timelinePos=A,e.checkBuffer();else{const P=T.event.assetList,F=u-(T[d]||T).start;for(let U=P.length;U--;){const H=P[U];if(H.duration&&F>=H.startOffset&&F{const u=e.effectivePlayingItem;if(e.isInterstitial(u))return u;const d=t();return e.isInterstitial(d)?d:null},h={get bufferedEnd(){const u=t(),d=e.bufferingItem;if(d&&d===u){var f;return i(d,"playout",e.bufferingAsset,"bufferedPos","bufferedEnd")-d.playout.start||((f=e.bufferingAsset)==null?void 0:f.startOffset)||0}return 0},get currentTime(){const u=l(),d=e.effectivePlayingItem;return d&&d===u?i(d,"playout",e.effectivePlayingAsset,"timelinePos","currentTime")-d.playout.start:0},set currentTime(u){const d=l(),f=e.effectivePlayingItem;f&&f===d&&c(u+f.playout.start,"playout")},get duration(){const u=l();return u?u.playout.end-u.playout.start:0},get assetPlayers(){var u;const d=(u=l())==null?void 0:u.event.assetList;return d?d.map(f=>e.getAssetPlayer(f.identifier)):[]},get playingIndex(){var u;const d=(u=l())==null?void 0:u.event;return d&&e.effectivePlayingAsset?d.findAssetIndex(e.effectivePlayingAsset):-1},get scheduleItem(){return l()}};return this.manager={get events(){var u;return((u=e.schedule)==null||(u=u.events)==null?void 0:u.slice(0))||[]},get schedule(){var u;return((u=e.schedule)==null||(u=u.items)==null?void 0:u.slice(0))||[]},get interstitialPlayer(){return l()?h:null},get playerQueue(){return e.playerQueue.slice(0)},get bufferingAsset(){return e.bufferingAsset},get bufferingItem(){return t()},get bufferingIndex(){const u=t();return e.findItemIndex(u)},get playingAsset(){return e.effectivePlayingAsset},get playingItem(){return e.effectivePlayingItem},get playingIndex(){const u=e.effectivePlayingItem;return e.findItemIndex(u)},primary:{get bufferedEnd(){return n()},get currentTime(){const u=e.timelinePos;return u>0?u:0},set currentTime(u){c(u,"primary")},get duration(){return o("primary")},get seekableStart(){var u;return((u=e.primaryDetails)==null?void 0:u.fragmentStart)||0}},integrated:{get bufferedEnd(){return i(t(),"integrated",e.bufferingAsset,"bufferedPos","bufferedEnd")},get currentTime(){return i(e.effectivePlayingItem,"integrated",e.effectivePlayingAsset,"timelinePos","currentTime")},set currentTime(u){c(u,"integrated")},get duration(){return o("integrated")},get seekableStart(){var u;return r(((u=e.primaryDetails)==null?void 0:u.fragmentStart)||0,"integrated")}},skip:()=>{const u=e.effectivePlayingItem,d=u==null?void 0:u.event;if(d&&!d.restrictions.skip){const f=e.findItemIndex(u);if(d.appendInPlace){const g=u.playout.start+u.event.duration;c(g+.001,"playout")}else e.advanceAfterAssetEnded(d,f,1/0)}}}}get effectivePlayingItem(){return this.waitingItem||this.playingItem||this.endedItem}get effectivePlayingAsset(){return this.playingAsset||this.endedAsset}get playingLastItem(){var e;const t=this.playingItem,s=(e=this.schedule)==null?void 0:e.items;return!this.playbackStarted||!t||!s?!1:this.findItemIndex(t)===s.length-1}get playbackStarted(){return this.effectivePlayingItem!==null}get currentTime(){var e,t;if(this.mediaSelection===null)return;const s=this.waitingItem||this.playingItem;if(this.isInterstitial(s)&&!s.event.appendInPlace)return;let i=this.media;!i&&(e=this.bufferingItem)!=null&&(e=e.event)!=null&&e.appendInPlace&&(i=this.primaryMedia);const r=(t=i)==null?void 0:t.currentTime;if(!(r===void 0||!M(r)))return r}get primaryMedia(){var e;return this.media||((e=this.detachedData)==null?void 0:e.media)||null}isInterstitial(e){return!!(e!=null&&e.event)}retreiveMediaSource(e,t){const s=this.getAssetPlayer(e);s&&this.transferMediaFromPlayer(s,t)}transferMediaFromPlayer(e,t){const s=e.interstitial.appendInPlace,i=e.media;if(s&&i===this.primaryMedia){if(this.bufferingAsset=null,(!t||this.isInterstitial(t)&&!t.event.appendInPlace)&&t&&i){this.detachedData={media:i};return}const r=e.transferMedia();this.log(`transfer MediaSource from ${e} ${ne(r)}`),this.detachedData=r}else t&&i&&(this.shouldPlay||(this.shouldPlay=!i.paused))}transferMediaTo(e,t){var s,i;if(e.media===t)return;let r=null;const n=this.hls,o=e!==n,c=o&&e.interstitial.appendInPlace,l=(s=this.detachedData)==null?void 0:s.mediaSource;let h;if(n.media)c&&(r=n.transferMedia(),this.detachedData=r),h="Primary";else if(l){const g=this.getBufferingPlayer();g?(r=g.transferMedia(),h=`${g}`):h="detached MediaSource"}else h="detached media";if(!r){if(l)r=this.detachedData,this.log(`using detachedData: MediaSource ${ne(r)}`);else if(!this.detachedData||n.media===t){const g=this.playerQueue;g.length>1&&g.forEach(y=>{if(o&&y.interstitial.appendInPlace!==c){const p=y.interstitial;this.clearInterstitial(y.interstitial,null),p.appendInPlace=!1,p.appendInPlace&&this.warn(`Could not change append strategy for queued assets ${p}`)}}),this.hls.detachMedia(),this.detachedData={media:t}}}const u=r&&"mediaSource"in r&&((i=r.mediaSource)==null?void 0:i.readyState)!=="closed",d=u&&r?r:t;this.log(`${u?"transfering MediaSource":"attaching media"} to ${o?e:"Primary"} from ${h} (media.currentTime: ${t.currentTime})`);const f=this.schedule;if(d===r&&f){const g=o&&e.assetId===f.assetIdAtEnd;d.overrides={duration:f.duration,endOfStream:!o||g,cueRemoval:!o}}e.attachMedia(d)}onInterstitialCueEnter(){this.onTimeupdate()}checkStart(){const e=this.schedule,t=e==null?void 0:e.events;if(!t||this.playbackDisabled||!this.media)return;this.bufferedPos===-1&&(this.bufferedPos=0);const s=this.timelinePos,i=this.effectivePlayingItem;if(s===-1){const r=this.hls.startPosition;if(this.timelinePos=r,t.length===0)this.setSchedulePosition(0);else if(t[0].cue.pre){this.log(mt("checkStart (preroll)",r));const n=e.findEventIndex(t[0].identifier);this.setSchedulePosition(n)}else if(r>=0||!this.primaryLive){this.log(mt("checkStart",r));const n=this.timelinePos=r>0?r:0,o=e.findItemIndexAtTime(n);this.setSchedulePosition(o)}else this.hls.liveSyncPosition===0?this.setSchedulePosition(0):this.log("[checkStart] waiting for live start")}else if(i&&!this.playingItem){this.log(mt("checkStart (playing item)",i.start));const r=e.findItemIndex(i);this.setSchedulePosition(r)}}advanceAssetBuffering(e,t){const s=e.event,i=s.findAssetIndex(t),r=Bs(s,i);if(!s.isAssetPastPlayoutLimit(r))this.bufferedToEvent(e,r);else if(this.schedule){var n;const o=(n=this.schedule.items)==null?void 0:n[this.findItemIndex(e)+1];o&&this.bufferedToItem(o)}}advanceAfterAssetEnded(e,t,s){const i=Bs(e,s);if(e.isAssetPastPlayoutLimit(i)){if(this.schedule){const r=this.schedule.items;if(r){const n=t+1,o=r.length;if(n>=o){this.setSchedulePosition(-1);return}const c=e.resumeTime;this.timelinePos=0?i[e]:null;this.log(`setSchedulePosition ${e}, ${t} (${r&&ke(r)}) pos: ${this.timelinePos}`);const n=this.waitingItem||this.playingItem,o=this.playingLastItem;if(this.isInterstitial(n)){const h=n.event,u=this.playingAsset,d=u==null?void 0:u.identifier,f=d?this.getAssetPlayer(d):null;if(f&&d&&(!this.eventItemsMatch(n,r)||t!==void 0&&d!==h.assetList[t].identifier)){var c;const g=h.findAssetIndex(u);if(this.log(`INTERSTITIAL_ASSET_ENDED ${g+1}/${h.assetList.length} ${pt(u)}`),this.endedAsset=u,this.playingAsset=null,this.hls.trigger(m.INTERSTITIAL_ASSET_ENDED,{asset:u,assetListIndex:g,event:h,schedule:i.slice(0),scheduleIndex:e,player:f}),n!==this.playingItem){this.itemsMatch(n,this.playingItem)&&!this.playingAsset&&this.advanceAfterAssetEnded(h,this.findItemIndex(this.playingItem),g);return}this.retreiveMediaSource(d,r),f.media&&!((c=this.detachedData)!=null&&c.mediaSource)&&f.detachMedia()}if(!this.eventItemsMatch(n,r)&&(this.endedItem=n,this.playingItem=null,this.log(`INTERSTITIAL_ENDED ${h} ${ke(n)}`),h.hasPlayed=!0,this.hls.trigger(m.INTERSTITIAL_ENDED,{event:h,schedule:i.slice(0),scheduleIndex:e}),h.cue.once)){var l;this.updateSchedule();const g=(l=this.schedule)==null?void 0:l.items;if(r&&g){const y=this.findItemIndex(r);this.advanceSchedule(y,g,t,n,o)}return}}this.advanceSchedule(e,i,t,n,o)}advanceSchedule(e,t,s,i,r){const n=this.schedule;if(!n)return;const o=t[e]||null,c=this.primaryMedia,l=this.playerQueue;if(l.length&&l.forEach(h=>{const u=h.interstitial,d=n.findEventIndex(u.identifier);(de+1)&&this.clearInterstitial(u,o)}),this.isInterstitial(o)){this.timelinePos=Math.min(Math.max(this.timelinePos,o.start),o.end);const h=o.event;if(s===void 0){s=n.findAssetIndex(h,this.timelinePos);const g=Bs(h,s-1);if(h.isAssetPastPlayoutLimit(g)||h.appendInPlace&&this.timelinePos===o.end){this.advanceAfterAssetEnded(h,e,s);return}s=g}const u=this.waitingItem;this.assetsBuffered(o,c)||this.setBufferingItem(o);let d=this.preloadAssets(h,s);if(this.eventItemsMatch(o,u||i)||(this.waitingItem=o,this.log(`INTERSTITIAL_STARTED ${ke(o)} ${h.appendInPlace?"append in place":""}`),this.hls.trigger(m.INTERSTITIAL_STARTED,{event:h,schedule:t.slice(0),scheduleIndex:e})),!h.assetListLoaded){this.log(`Waiting for ASSET-LIST to complete loading ${h}`);return}if(h.assetListLoader&&(h.assetListLoader.destroy(),h.assetListLoader=void 0),!c){this.log(`Waiting for attachMedia to start Interstitial ${h}`);return}this.waitingItem=this.endedItem=null,this.playingItem=o;const f=h.assetList[s];if(!f){this.advanceAfterAssetEnded(h,e,s||0);return}if(d||(d=this.getAssetPlayer(f.identifier)),d===null||d.destroyed){const g=h.assetList.length;this.warn(`asset ${s+1}/${g} player destroyed ${h}`),d=this.createAssetPlayer(h,f,s),d.loadSource()}if(!this.eventItemsMatch(o,this.bufferingItem)&&h.appendInPlace&&this.isAssetBuffered(f))return;this.startAssetPlayer(d,s,t,e,c),this.shouldPlay&&Yr(d.media)}else o?(this.resumePrimary(o,e,i),this.shouldPlay&&Yr(this.hls.media)):r&&this.isInterstitial(i)&&(this.endedItem=null,this.playingItem=i,i.event.appendInPlace||this.attachPrimary(n.durations.primary,null))}get playbackDisabled(){return this.hls.config.enableInterstitialPlayback===!1}get primaryDetails(){var e;return(e=this.mediaSelection)==null?void 0:e.main.details}get primaryLive(){var e;return!!((e=this.primaryDetails)!=null&&e.live)}resumePrimary(e,t,s){var i,r;if(this.playingItem=e,this.playingAsset=this.endedAsset=null,this.waitingItem=this.endedItem=null,this.bufferedToItem(e),this.log(`resuming ${ke(e)}`),!((i=this.detachedData)!=null&&i.mediaSource)){let o=this.timelinePos;(o=e.end)&&(o=this.getPrimaryResumption(e,t),this.log(mt("resumePrimary",o)),this.timelinePos=o),this.attachPrimary(o,e)}if(!s)return;const n=(r=this.schedule)==null?void 0:r.items;n&&(this.log(`INTERSTITIALS_PRIMARY_RESUMED ${ke(e)}`),this.hls.trigger(m.INTERSTITIALS_PRIMARY_RESUMED,{schedule:n.slice(0),scheduleIndex:t}),this.checkBuffer())}getPrimaryResumption(e,t){const s=e.start;if(this.primaryLive){const i=this.primaryDetails;if(t===0)return this.hls.startPosition;if(i&&(si.edge))return this.hls.liveSyncPosition||-1}return s}isAssetBuffered(e){const t=this.getAssetPlayer(e.identifier);return t!=null&&t.hls?t.hls.bufferedToEnd:q.bufferInfo(this.primaryMedia,this.timelinePos,0).end+1>=e.timelineStart+(e.duration||0)}attachPrimary(e,t,s){t?this.setBufferingItem(t):this.bufferingItem=this.playingItem,this.bufferingAsset=null;const i=this.primaryMedia;if(!i)return;const r=this.hls;r.media?this.checkBuffer():(this.transferMediaTo(r,i),s&&this.startLoadingPrimaryAt(e,s)),s||(this.log(mt("attachPrimary",e)),this.timelinePos=e,this.startLoadingPrimaryAt(e,s))}startLoadingPrimaryAt(e,t){var s;const i=this.hls;!i.loadingEnabled||!i.media||Math.abs((((s=i.mainForwardBufferInfo)==null?void 0:s.start)||i.media.currentTime)-e)>.5?i.startLoad(e,t):i.bufferingEnabled||i.resumeBuffering()}onManifestLoading(){var e;this.stopLoad(),(e=this.schedule)==null||e.reset(),this.emptyPlayerQueue(),this.clearScheduleState(),this.shouldPlay=!1,this.bufferedPos=this.timelinePos=-1,this.mediaSelection=this.altSelection=this.manager=this.requiredTracks=null,this.hls.off(m.BUFFER_CODECS,this.onBufferCodecs,this),this.hls.on(m.BUFFER_CODECS,this.onBufferCodecs,this)}onLevelUpdated(e,t){if(t.level===-1||!this.schedule)return;const s=this.hls.levels[t.level];if(!s.details)return;const i=te(te({},this.mediaSelection||this.altSelection),{},{main:s});this.mediaSelection=i,this.schedule.parseInterstitialDateRanges(i,this.hls.config.interstitialAppendInPlace),!this.effectivePlayingItem&&this.schedule.items&&this.checkStart()}onAudioTrackUpdated(e,t){const s=this.hls.audioTracks[t.id],i=this.mediaSelection;if(!i){this.altSelection=te(te({},this.altSelection),{},{audio:s});return}const r=te(te({},i),{},{audio:s});this.mediaSelection=r}onSubtitleTrackUpdated(e,t){const s=this.hls.subtitleTracks[t.id],i=this.mediaSelection;if(!i){this.altSelection=te(te({},this.altSelection),{},{subtitles:s});return}const r=te(te({},i),{},{subtitles:s});this.mediaSelection=r}onAudioTrackSwitching(e,t){const s=er(t);this.playerQueue.forEach(({hls:i})=>i&&(i.setAudioOption(t)||i.setAudioOption(s)))}onSubtitleTrackSwitch(e,t){const s=er(t);this.playerQueue.forEach(({hls:i})=>i&&(i.setSubtitleOption(t)||t.id!==-1&&i.setSubtitleOption(s)))}onBufferCodecs(e,t){const s=t.tracks;s&&(this.requiredTracks=s)}onBufferAppended(e,t){this.checkBuffer()}onBufferFlushed(e,t){const s=this.playingItem;if(s&&!this.itemsMatch(s,this.bufferingItem)&&!this.isInterstitial(s)){const i=this.timelinePos;this.bufferedPos=i,this.checkBuffer()}}onBufferedToEnd(e){if(!this.schedule)return;const t=this.schedule.events;if(this.bufferedPos.25){e.event.assetList.forEach((r,n)=>{e.event.isAssetPastPlayoutLimit(n)&&this.clearAssetPlayer(r.identifier,null)});const s=e.end+.25,i=q.bufferInfo(this.primaryMedia,s,0);(i.end>s||(i.nextStart||0)>s)&&(this.log(`trim buffered interstitial ${ke(e)} (was ${ke(t)})`),this.attachPrimary(s,null,!0),this.flushFrontBuffer(s))}}itemsMatch(e,t){return!!t&&(e===t||e.event&&t.event&&this.eventItemsMatch(e,t)||!e.event&&!t.event&&this.findItemIndex(e)===this.findItemIndex(t))}eventItemsMatch(e,t){var s;return!!t&&(e===t||e.event.identifier===((s=t.event)==null?void 0:s.identifier))}findItemIndex(e,t){return e&&this.schedule?this.schedule.findItemIndex(e,t):-1}updateSchedule(e=!1){var t;const s=this.mediaSelection;s&&((t=this.schedule)==null||t.updateSchedule(s,[],e))}checkBuffer(e){var t;const s=(t=this.schedule)==null?void 0:t.items;if(!s)return;const i=q.bufferInfo(this.primaryMedia,this.timelinePos,0);e&&(this.bufferedPos=this.timelinePos),e||(e=i.len<1),this.updateBufferedPos(i.end,s,e)}updateBufferedPos(e,t,s){const i=this.schedule,r=this.bufferingItem;if(this.bufferedPos>e||!i)return;if(t.length===1&&this.itemsMatch(t[0],r)){this.bufferedPos=e;return}const n=this.playingItem,o=this.findItemIndex(n);let c=i.findItemIndexAtTime(e);if(this.bufferedPos=r.end||(l=d.event)!=null&&l.appendInPlace&&e+.01>=d.start)&&(c=u),this.isInterstitial(r)){const f=r.event;if(u-o>1&&f.appendInPlace===!1||f.assetList.length===0&&f.assetListLoader)return}if(this.bufferedPos=e,c>h&&c>o)this.bufferedToItem(d);else{const f=this.primaryDetails;this.primaryLive&&f&&e>f.edge-f.targetduration&&d.start{const r=this.getAssetPlayer(i.identifier);return!(r!=null&&r.bufferedInPlaceToEnd(t))})}setBufferingItem(e){const t=this.bufferingItem,s=this.schedule;if(!this.itemsMatch(e,t)&&s){const{items:i,events:r}=s;if(!i||!r)return t;const n=this.isInterstitial(e),o=this.getBufferingPlayer();this.bufferingItem=e,this.bufferedPos=Math.max(e.start,Math.min(e.end,this.timelinePos));const c=o?o.remaining:t?t.end-this.timelinePos:0;if(this.log(`INTERSTITIALS_BUFFERED_TO_BOUNDARY ${ke(e)}`+(t?` (${c.toFixed(2)} remaining)`:"")),!this.playbackDisabled)if(n){const l=s.findAssetIndex(e.event,this.bufferedPos);e.event.assetList.forEach((h,u)=>{const d=this.getAssetPlayer(h.identifier);d&&(u===l&&d.loadSource(),d.resumeBuffering())})}else this.hls.resumeBuffering(),this.playerQueue.forEach(l=>l.pauseBuffering());this.hls.trigger(m.INTERSTITIALS_BUFFERED_TO_BOUNDARY,{events:r.slice(0),schedule:i.slice(0),bufferingIndex:this.findItemIndex(e),playingIndex:this.findItemIndex(this.playingItem)})}else this.bufferingItem!==e&&(this.bufferingItem=e);return t}bufferedToItem(e,t=0){const s=this.setBufferingItem(e);if(!this.playbackDisabled){if(this.isInterstitial(e))this.bufferedToEvent(e,t);else if(s!==null){this.bufferingAsset=null;const i=this.detachedData;i?i.mediaSource?this.attachPrimary(e.start,e,!0):this.preloadPrimary(e):this.preloadPrimary(e)}}}preloadPrimary(e){const t=this.findItemIndex(e),s=this.getPrimaryResumption(e,t);this.startLoadingPrimaryAt(s)}bufferedToEvent(e,t){const s=e.event,i=s.assetList.length===0&&!s.assetListLoader,r=s.cue.once;if(i||!r){const n=this.preloadAssets(s,t);if(n!=null&&n.interstitial.appendInPlace){const o=this.primaryMedia;o&&this.bufferAssetPlayer(n,o)}}}preloadAssets(e,t){const s=e.assetUrl,i=e.assetList.length,r=i===0&&!e.assetListLoader,n=e.cue.once;if(r){const c=e.timelineStart;if(e.appendInPlace){var o;const d=this.playingItem;!this.isInterstitial(d)&&(d==null||(o=d.nextEvent)==null?void 0:o.identifier)===e.identifier&&this.flushFrontBuffer(c+.25)}let l,h=0;if(!this.playingItem&&this.primaryLive&&(h=this.hls.startPosition,h===-1&&(h=this.hls.liveSyncPosition||0)),h&&!(e.cue.pre||e.cue.post)){const d=h-c;d>0&&(l=Math.round(d*1e3)/1e3)}if(this.log(`Load interstitial asset ${t+1}/${s?1:i} ${e}${l?` live-start: ${h} start-offset: ${l}`:""}`),s)return this.createAsset(e,0,0,c,e.duration,s);const u=this.assetListLoader.loadAssetList(e,l);u&&(e.assetListLoader=u)}else if(!n&&i){for(let l=t;l{this.hls.trigger(m.BUFFER_FLUSHING,{startOffset:e,endOffset:1/0,type:i})})}getAssetPlayerQueueIndex(e){const t=this.playerQueue;for(let s=0;s1){const x=t.duration;x&&v{if(v.live){var x;const _=new Error(`Interstitials MUST be VOD assets ${e}`),b={fatal:!0,type:V.OTHER_ERROR,details:R.INTERSTITIAL_ASSET_ITEM_ERROR,error:_},I=((x=this.schedule)==null?void 0:x.findEventIndex(e.identifier))||-1;this.handleAssetItemError(b,e,I,s,_.message);return}const D=v.edge-v.fragmentStart,A=t.duration;(y||A===null||D>A)&&(y=!1,this.log(`Interstitial asset "${u}" duration change ${A} > ${D}`),t.duration=D,this.updateSchedule())};g.on(m.LEVEL_UPDATED,(v,{details:x})=>p(x)),g.on(m.LEVEL_PTS_UPDATED,(v,{details:x})=>p(x)),g.on(m.EVENT_CUE_ENTER,()=>this.onInterstitialCueEnter());const E=(v,x)=>{const D=this.getAssetPlayer(u);if(D&&x.tracks){D.off(m.BUFFER_CODECS,E),D.tracks=x.tracks;const A=this.primaryMedia;this.bufferingAsset===D.assetItem&&A&&!D.media&&this.bufferAssetPlayer(D,A)}};g.on(m.BUFFER_CODECS,E);const T=()=>{var v;const x=this.getAssetPlayer(u);if(this.log(`buffered to end of asset ${x}`),!x||!this.schedule)return;const D=this.schedule.findEventIndex(e.identifier),A=(v=this.schedule.items)==null?void 0:v[D];this.isInterstitial(A)&&this.advanceAssetBuffering(A,t)};g.on(m.BUFFERED_TO_END,T);const S=v=>()=>{if(!this.getAssetPlayer(u)||!this.schedule)return;this.shouldPlay=!0;const D=this.schedule.findEventIndex(e.identifier);this.advanceAfterAssetEnded(e,D,v)};return g.once(m.MEDIA_ENDED,S(s)),g.once(m.PLAYOUT_LIMIT_REACHED,S(1/0)),g.on(m.ERROR,(v,x)=>{if(!this.schedule)return;const D=this.getAssetPlayer(u);if(x.details===R.BUFFER_STALLED_ERROR){if(D!=null&&D.appendInPlace){this.handleInPlaceStall(e);return}this.onTimeupdate(),this.checkBuffer(!0);return}this.handleAssetItemError(x,e,this.schedule.findEventIndex(e.identifier),s,`Asset player error ${x.error} ${e}`)}),g.on(m.DESTROYING,()=>{if(!this.getAssetPlayer(u)||!this.schedule)return;const x=new Error(`Asset player destroyed unexpectedly ${u}`),D={fatal:!0,type:V.OTHER_ERROR,details:R.INTERSTITIAL_ASSET_ITEM_ERROR,error:x};this.handleAssetItemError(D,e,this.schedule.findEventIndex(e.identifier),s,x.message)}),this.log(`INTERSTITIAL_ASSET_PLAYER_CREATED ${pt(t)}`),this.hls.trigger(m.INTERSTITIAL_ASSET_PLAYER_CREATED,{asset:t,assetListIndex:s,event:e,player:g}),g}clearInterstitial(e,t){this.clearAssetPlayers(e,t),e.reset()}clearAssetPlayers(e,t){e.assetList.forEach(s=>{this.clearAssetPlayer(s.identifier,t)})}resetAssetPlayer(e){const t=this.getAssetPlayerQueueIndex(e);if(t!==-1){this.log(`reset asset player "${e}" after error`);const s=this.playerQueue[t];this.transferMediaFromPlayer(s,null),s.resetDetails()}}clearAssetPlayer(e,t){const s=this.getAssetPlayerQueueIndex(e);if(s!==-1){const i=this.playerQueue[s];this.log(`clear ${i} toSegment: ${t&&ke(t)}`),this.transferMediaFromPlayer(i,t),this.playerQueue.splice(s,1),i.destroy()}}emptyPlayerQueue(){let e;for(;e=this.playerQueue.pop();)e.destroy();this.playerQueue=[]}startAssetPlayer(e,t,s,i,r){const{interstitial:n,assetItem:o,assetId:c}=e,l=n.assetList.length,h=this.playingAsset;this.endedAsset=null,this.playingAsset=o,(!h||h.identifier!==c)&&(h&&(this.clearAssetPlayer(h.identifier,s[i]),delete h.error),this.log(`INTERSTITIAL_ASSET_STARTED ${t+1}/${l} ${pt(o)}`),this.hls.trigger(m.INTERSTITIAL_ASSET_STARTED,{asset:o,assetListIndex:t,event:n,schedule:s.slice(0),scheduleIndex:i,player:e})),this.bufferAssetPlayer(e,r)}bufferAssetPlayer(e,t){var s,i;if(!this.schedule)return;const{interstitial:r,assetItem:n}=e,o=this.schedule.findEventIndex(r.identifier),c=(s=this.schedule.items)==null?void 0:s[o];if(!c)return;e.loadSource(),this.setBufferingItem(c),this.bufferingAsset=n;const l=this.getBufferingPlayer();if(l===e)return;const h=r.appendInPlace;if(h&&(l==null?void 0:l.interstitial.appendInPlace)===!1)return;const u=(l==null?void 0:l.tracks)||((i=this.detachedData)==null?void 0:i.tracks)||this.requiredTracks;if(h&&n!==this.playingAsset){if(!e.tracks){this.log(`Waiting for track info before buffering ${e}`);return}if(u&&!an(u,e.tracks)){const d=new Error(`Asset ${pt(n)} SourceBuffer tracks ('${Object.keys(e.tracks)}') are not compatible with primary content tracks ('${Object.keys(u)}')`),f={fatal:!0,type:V.OTHER_ERROR,details:R.INTERSTITIAL_ASSET_ITEM_ERROR,error:d},g=r.findAssetIndex(n);this.handleAssetItemError(f,r,o,g,d.message);return}}this.transferMediaTo(e,t)}handleInPlaceStall(e){const t=this.schedule,s=this.primaryMedia;if(!t||!s)return;const i=s.currentTime,r=t.findAssetIndex(e,i),n=e.assetList[r];if(n){const o=this.getAssetPlayer(n.identifier);if(o){const c=o.currentTime||i-n.timelineStart,l=o.duration-c;if(this.warn(`Stalled at ${c} of ${c+l} in ${o} ${e} (media.currentTime: ${i})`),c&&(l/s.playbackRate<.5||o.bufferedInPlaceToEnd(s))&&o.hls){const h=t.findEventIndex(e.identifier);this.advanceAfterAssetEnded(e,h,r)}}}}advanceInPlace(e){const t=this.primaryMedia;t&&t.currentTime!y.error))t.error=g;else for(let y=i;y{const E=parseFloat(y.DURATION);this.createAsset(r,p,h,c+h,E,y.URI),h+=E}),r.duration=h,this.log(`Loaded asset-list with duration: ${h} (was: ${l}) ${r}`);const u=this.waitingItem,d=(u==null?void 0:u.event.identifier)===n;this.updateSchedule();const f=(i=this.bufferingItem)==null?void 0:i.event;if(d){var g;const y=this.schedule.findEventIndex(n),p=(g=this.schedule.items)==null?void 0:g[y];if(p){if(!this.playingItem&&this.timelinePos>p.end&&this.schedule.findItemIndexAtTime(this.timelinePos)!==y){r.error=new Error(`Interstitial ${o.length?"no longer within playback range":"asset-list is empty"} ${this.timelinePos} ${r}`),this.log(r.error.message),this.updateSchedule(!0),this.primaryFallback(r);return}this.setBufferingItem(p)}this.setSchedulePosition(y)}else if((f==null?void 0:f.identifier)===n){const y=r.assetList[0];if(y){const p=this.getAssetPlayer(y.identifier);if(f.appendInPlace){const E=this.primaryMedia;p&&E&&this.bufferAssetPlayer(p,E)}else p&&p.loadSource()}}}onError(e,t){if(this.schedule)switch(t.details){case R.ASSET_LIST_PARSING_ERROR:case R.ASSET_LIST_LOAD_ERROR:case R.ASSET_LIST_LOAD_TIMEOUT:{const s=t.interstitial;s&&(this.updateSchedule(!0),this.primaryFallback(s));break}case R.BUFFER_STALLED_ERROR:{const s=this.endedItem||this.waitingItem||this.playingItem;if(this.isInterstitial(s)&&s.event.appendInPlace){this.handleInPlaceStall(s.event);return}this.log(`Primary player stall @${this.timelinePos} bufferedPos: ${this.bufferedPos}`),this.onTimeupdate(),this.checkBuffer(!0);break}}}}const Wr=500;class Gh extends Ai{constructor(e,t,s){super(e,t,s,"subtitle-stream-controller",B.SUBTITLE),this.currentTrackId=-1,this.tracksBuffered=[],this.mainDetails=null,this.registerListeners()}onHandlerDestroying(){this.unregisterListeners(),super.onHandlerDestroying(),this.mainDetails=null}registerListeners(){super.registerListeners();const{hls:e}=this;e.on(m.LEVEL_LOADED,this.onLevelLoaded,this),e.on(m.SUBTITLE_TRACKS_UPDATED,this.onSubtitleTracksUpdated,this),e.on(m.SUBTITLE_TRACK_SWITCH,this.onSubtitleTrackSwitch,this),e.on(m.SUBTITLE_TRACK_LOADED,this.onSubtitleTrackLoaded,this),e.on(m.SUBTITLE_FRAG_PROCESSED,this.onSubtitleFragProcessed,this),e.on(m.BUFFER_FLUSHING,this.onBufferFlushing,this)}unregisterListeners(){super.unregisterListeners();const{hls:e}=this;e.off(m.LEVEL_LOADED,this.onLevelLoaded,this),e.off(m.SUBTITLE_TRACKS_UPDATED,this.onSubtitleTracksUpdated,this),e.off(m.SUBTITLE_TRACK_SWITCH,this.onSubtitleTrackSwitch,this),e.off(m.SUBTITLE_TRACK_LOADED,this.onSubtitleTrackLoaded,this),e.off(m.SUBTITLE_FRAG_PROCESSED,this.onSubtitleFragProcessed,this),e.off(m.BUFFER_FLUSHING,this.onBufferFlushing,this)}startLoad(e,t){this.stopLoad(),this.state=C.IDLE,this.setInterval(Wr),this.nextLoadPosition=this.lastCurrentTime=e+this.timelineOffset,this.startPosition=t?-1:e,this.tick()}onManifestLoading(){super.onManifestLoading(),this.mainDetails=null}onMediaDetaching(e,t){this.tracksBuffered=[],super.onMediaDetaching(e,t)}onLevelLoaded(e,t){this.mainDetails=t.details}onSubtitleFragProcessed(e,t){const{frag:s,success:i}=t;if(this.fragContextChanged(s)||(ce(s)&&(this.fragPrevious=s),this.state=C.IDLE),!i)return;const r=this.tracksBuffered[this.currentTrackId];if(!r)return;let n;const o=s.start;for(let l=0;l=r[l].start&&o<=r[l].end){n=r[l];break}const c=s.start+s.duration;n?n.end=c:(n={start:o,end:c},r.push(n)),this.fragmentTracker.fragBuffered(s),this.fragBufferedComplete(s,null),this.media&&this.tick()}onBufferFlushing(e,t){const{startOffset:s,endOffset:i}=t;if(s===0&&i!==Number.POSITIVE_INFINITY){const r=i-1;if(r<=0)return;t.endOffsetSubtitles=Math.max(0,r),this.tracksBuffered.forEach(n=>{for(let o=0;onew Ot(s));return}this.tracksBuffered=[],this.levels=t.map(s=>{const i=new Ot(s);return this.tracksBuffered[i.id]=[],i}),this.fragmentTracker.removeFragmentsInRange(0,Number.POSITIVE_INFINITY,B.SUBTITLE),this.fragPrevious=null,this.mediaBuffer=null}onSubtitleTrackSwitch(e,t){var s;if(this.currentTrackId=t.id,!((s=this.levels)!=null&&s.length)||this.currentTrackId===-1){this.clearInterval();return}const i=this.levels[this.currentTrackId];i!=null&&i.details?this.mediaBuffer=this.mediaBufferTimeRanges:this.mediaBuffer=null,i&&this.state!==C.STOPPED&&this.setInterval(Wr)}onSubtitleTrackLoaded(e,t){var s;const{currentTrackId:i,levels:r}=this,{details:n,id:o}=t;if(!r){this.warn(`Subtitle tracks were reset while loading level ${o}`);return}const c=r[o];if(o>=r.length||!c)return;this.log(`Subtitle track ${o} loaded [${n.startSN},${n.endSN}]${n.lastPartSn?`[part-${n.lastPartSn}-${n.lastPartIndex}]`:""},duration:${n.totalduration}`),this.mediaBuffer=this.mediaBufferTimeRanges;let l=0;if(n.live||(s=c.details)!=null&&s.live){if(n.deltaUpdateFailed)return;const u=this.mainDetails;if(!u){this.startFragRequested=!1;return}const d=u.fragments[0];if(!c.details)n.hasProgramDateTime&&u.hasProgramDateTime?(ps(n,u),l=n.fragmentStart):d&&(l=d.start,si(n,l));else{var h;l=this.alignPlaylists(n,c.details,(h=this.levelLastLoaded)==null?void 0:h.details),l===0&&d&&(l=d.start,si(n,l))}u&&!this.startFragRequested&&this.setStartPosition(u,l)}c.details=n,this.levelLastLoaded=c,o===i&&(this.hls.trigger(m.SUBTITLE_TRACK_UPDATED,{details:n,id:o,groupId:t.groupId}),this.tick(),n.live&&!this.fragCurrent&&this.media&&this.state===C.IDLE&&(lt(null,n.fragments,this.media.currentTime,0)||(this.warn("Subtitle playlist not aligned with playback"),c.details=void 0)))}_handleFragmentLoadComplete(e){const{frag:t,payload:s}=e,i=t.decryptdata,r=this.hls;if(!this.fragContextChanged(t)&&s&&s.byteLength>0&&i!=null&&i.key&&i.iv&&Tt(i.method)){const n=performance.now();this.decrypter.decrypt(new Uint8Array(s),i.key.buffer,i.iv.buffer,vi(i.method)).catch(o=>{throw r.trigger(m.ERROR,{type:V.MEDIA_ERROR,details:R.FRAG_DECRYPT_ERROR,fatal:!1,error:o,reason:o.message,frag:t}),o}).then(o=>{const c=performance.now();r.trigger(m.FRAG_DECRYPTED,{frag:t,payload:o,stats:{tstart:n,tdecrypt:c}})}).catch(o=>{this.warn(`${o.name}: ${o.message}`),this.state=C.IDLE})}}doTick(){if(!this.media){this.state=C.IDLE;return}if(this.state===C.IDLE){const{currentTrackId:e,levels:t}=this,s=t==null?void 0:t[e];if(!s||!t.length||!s.details||this.waitForLive(s))return;const{config:i}=this,r=this.getLoadPosition(),n=q.bufferedInfo(this.tracksBuffered[this.currentTrackId]||[],r,i.maxBufferHole),{end:o,len:c}=n,l=s.details,h=this.hls.maxBufferLength+l.levelTargetDuration;if(c>h)return;const u=l.fragments,d=u.length,f=l.edge;let g=null;const y=this.fragPrevious;if(of-T?0:T;g=lt(y,u,Math.max(u[0].start,o),S),!g&&y&&y.start{if(i=i>>>0,i>r-1)throw new DOMException(`Failed to execute '${s}' on 'TimeRanges': The index provided (${i}) is greater than the maximum bound (${r})`);return e[i][s]};this.buffered={get length(){return e.length},end(s){return t("end",s,e.length)},start(s){return t("start",s,e.length)}}}}const Vh={42:225,92:233,94:237,95:243,96:250,123:231,124:247,125:209,126:241,127:9608,128:174,129:176,130:189,131:191,132:8482,133:162,134:163,135:9834,136:224,137:32,138:232,139:226,140:234,141:238,142:244,143:251,144:193,145:201,146:211,147:218,148:220,149:252,150:8216,151:161,152:42,153:8217,154:9473,155:169,156:8480,157:8226,158:8220,159:8221,160:192,161:194,162:199,163:200,164:202,165:203,166:235,167:206,168:207,169:239,170:212,171:217,172:249,173:219,174:171,175:187,176:195,177:227,178:205,179:204,180:236,181:210,182:242,183:213,184:245,185:123,186:125,187:92,188:94,189:95,190:124,191:8764,192:196,193:228,194:214,195:246,196:223,197:165,198:164,199:9475,200:197,201:229,202:216,203:248,204:9487,205:9491,206:9495,207:9499},La=a=>String.fromCharCode(Vh[a]||a),we=15,Ye=100,Hh={17:1,18:3,21:5,22:7,23:9,16:11,19:12,20:14},Yh={17:2,18:4,21:6,22:8,23:10,19:13,20:15},Wh={25:1,26:3,29:5,30:7,31:9,24:11,27:12,28:14},qh={25:2,26:4,29:6,30:8,31:10,27:13,28:15},jh=["white","green","blue","cyan","red","yellow","magenta","black","transparent"];class Xh{constructor(){this.time=null,this.verboseLevel=0}log(e,t){if(this.verboseLevel>=e){const s=typeof t=="function"?t():t;se.log(`${this.time} [${e}] ${s}`)}}}const nt=function(e){const t=[];for(let s=0;sYe&&(this.logger.log(3,"Too large cursor position "+this.pos),this.pos=Ye)}moveCursor(e){const t=this.pos+e;if(e>1)for(let s=this.pos+1;s=144&&this.backSpace();const t=La(e);if(this.pos>=Ye){this.logger.log(0,()=>"Cannot insert "+e.toString(16)+" ("+t+") at position "+this.pos+". Skipping it!");return}this.chars[this.pos].setChar(t,this.currPenState),this.moveCursor(1)}clearFromPos(e){let t;for(t=e;t"pacData = "+ne(e));let t=e.row-1;if(this.nrRollUpRows&&t"bkgData = "+ne(e)),this.backSpace(),this.setPen(e),this.insertChar(32)}setRollUpRows(e){this.nrRollUpRows=e}rollUp(){if(this.nrRollUpRows===null){this.logger.log(3,"roll_up but nrRollUpRows not set yet");return}this.logger.log(1,()=>this.getDisplayText());const e=this.currRow+1-this.nrRollUpRows,t=this.rows.splice(e,1)[0];t.clear(),this.rows.splice(this.currRow,0,t),this.logger.log(2,"Rolling up")}getDisplayText(e){e=e||!1;const t=[];let s="",i=-1;for(let r=0;r0&&(e?s="["+t.join(" | ")+"]":s=t.join(` +`)),s}getTextAndFormat(){return this.rows}}class qr{constructor(e,t,s){this.chNr=void 0,this.outputFilter=void 0,this.mode=void 0,this.verbose=void 0,this.displayedMemory=void 0,this.nonDisplayedMemory=void 0,this.lastOutputScreen=void 0,this.currRollUpRow=void 0,this.writeScreen=void 0,this.cueStartTime=void 0,this.logger=void 0,this.chNr=e,this.outputFilter=t,this.mode=null,this.verbose=0,this.displayedMemory=new Us(s),this.nonDisplayedMemory=new Us(s),this.lastOutputScreen=new Us(s),this.currRollUpRow=this.displayedMemory.rows[we-1],this.writeScreen=this.displayedMemory,this.mode=null,this.cueStartTime=null,this.logger=s}reset(){this.mode=null,this.displayedMemory.reset(),this.nonDisplayedMemory.reset(),this.lastOutputScreen.reset(),this.outputFilter.reset(),this.currRollUpRow=this.displayedMemory.rows[we-1],this.writeScreen=this.displayedMemory,this.mode=null,this.cueStartTime=null}getHandler(){return this.outputFilter}setHandler(e){this.outputFilter=e}setPAC(e){this.writeScreen.setPAC(e)}setBkgData(e){this.writeScreen.setBkgData(e)}setMode(e){e!==this.mode&&(this.mode=e,this.logger.log(2,()=>"MODE="+e),this.mode==="MODE_POP-ON"?this.writeScreen=this.nonDisplayedMemory:(this.writeScreen=this.displayedMemory,this.writeScreen.reset()),this.mode!=="MODE_ROLL-UP"&&(this.displayedMemory.nrRollUpRows=null,this.nonDisplayedMemory.nrRollUpRows=null),this.mode=e)}insertChars(e){for(let s=0;st+": "+this.writeScreen.getDisplayText(!0)),(this.mode==="MODE_PAINT-ON"||this.mode==="MODE_ROLL-UP")&&(this.logger.log(1,()=>"DISPLAYED: "+this.displayedMemory.getDisplayText(!0)),this.outputDataUpdate())}ccRCL(){this.logger.log(2,"RCL - Resume Caption Loading"),this.setMode("MODE_POP-ON")}ccBS(){this.logger.log(2,"BS - BackSpace"),this.mode!=="MODE_TEXT"&&(this.writeScreen.backSpace(),this.writeScreen===this.displayedMemory&&this.outputDataUpdate())}ccAOF(){}ccAON(){}ccDER(){this.logger.log(2,"DER- Delete to End of Row"),this.writeScreen.clearToEndOfRow(),this.outputDataUpdate()}ccRU(e){this.logger.log(2,"RU("+e+") - Roll Up"),this.writeScreen=this.displayedMemory,this.setMode("MODE_ROLL-UP"),this.writeScreen.setRollUpRows(e)}ccFON(){this.logger.log(2,"FON - Flash On"),this.writeScreen.setPen({flash:!0})}ccRDC(){this.logger.log(2,"RDC - Resume Direct Captioning"),this.setMode("MODE_PAINT-ON")}ccTR(){this.logger.log(2,"TR"),this.setMode("MODE_TEXT")}ccRTD(){this.logger.log(2,"RTD"),this.setMode("MODE_TEXT")}ccEDM(){this.logger.log(2,"EDM - Erase Displayed Memory"),this.displayedMemory.reset(),this.outputDataUpdate(!0)}ccCR(){this.logger.log(2,"CR - Carriage Return"),this.writeScreen.rollUp(),this.outputDataUpdate(!0)}ccENM(){this.logger.log(2,"ENM - Erase Non-displayed Memory"),this.nonDisplayedMemory.reset()}ccEOC(){if(this.logger.log(2,"EOC - End Of Caption"),this.mode==="MODE_POP-ON"){const e=this.displayedMemory;this.displayedMemory=this.nonDisplayedMemory,this.nonDisplayedMemory=e,this.writeScreen=this.nonDisplayedMemory,this.logger.log(1,()=>"DISP: "+this.displayedMemory.getDisplayText())}this.outputDataUpdate(!0)}ccTO(e){this.logger.log(2,"TO("+e+") - Tab Offset"),this.writeScreen.moveCursor(e)}ccMIDROW(e){const t={flash:!1};if(t.underline=e%2===1,t.italics=e>=46,t.italics)t.foreground="white";else{const s=Math.floor(e/2)-16,i=["white","green","blue","cyan","red","yellow","magenta"];t.foreground=i[s]}this.logger.log(2,"MIDROW: "+ne(t)),this.writeScreen.setPen(t)}outputDataUpdate(e=!1){const t=this.logger.time;t!==null&&this.outputFilter&&(this.cueStartTime===null&&!this.displayedMemory.isEmpty()?this.cueStartTime=t:this.displayedMemory.equals(this.lastOutputScreen)||(this.outputFilter.newCue(this.cueStartTime,t,this.lastOutputScreen),e&&this.outputFilter.dispatchCue&&this.outputFilter.dispatchCue(),this.cueStartTime=this.displayedMemory.isEmpty()?null:t),this.lastOutputScreen.copy(this.displayedMemory))}cueSplitAtTime(e){this.outputFilter&&(this.displayedMemory.isEmpty()||(this.outputFilter.newCue&&this.outputFilter.newCue(this.cueStartTime,e,this.displayedMemory),this.cueStartTime=e))}}class jr{constructor(e,t,s){this.channels=void 0,this.currentChannel=0,this.cmdHistory=Jh(),this.logger=void 0;const i=this.logger=new Xh;this.channels=[null,new qr(e,t,i),new qr(e+1,s,i)]}getHandler(e){return this.channels[e].getHandler()}setHandler(e,t){this.channels[e].setHandler(t)}addData(e,t){this.logger.time=e;for(let s=0;s"["+nt([t[s],t[s+1]])+"] -> ("+nt([i,r])+")");const c=this.cmdHistory;if(i>=16&&i<=31){if(Zh(i,r,c)){Xt(null,null,c),this.logger.log(3,()=>"Repeated command ("+nt([i,r])+") is dropped");continue}Xt(i,r,this.cmdHistory),n=this.parseCmd(i,r),n||(n=this.parseMidrow(i,r)),n||(n=this.parsePAC(i,r)),n||(n=this.parseBackgroundAttributes(i,r))}else Xt(null,null,c);if(!n&&(o=this.parseChars(i,r),o)){const h=this.currentChannel;h&&h>0?this.channels[h].insertChars(o):this.logger.log(2,"No channel found yet. TEXT-MODE?")}!n&&!o&&this.logger.log(2,()=>"Couldn't parse cleaned data "+nt([i,r])+" orig: "+nt([t[s],t[s+1]]))}}parseCmd(e,t){const s=(e===20||e===28||e===21||e===29)&&t>=32&&t<=47,i=(e===23||e===31)&&t>=33&&t<=35;if(!(s||i))return!1;const r=e===20||e===21||e===23?1:2,n=this.channels[r];return e===20||e===21||e===28||e===29?t===32?n.ccRCL():t===33?n.ccBS():t===34?n.ccAOF():t===35?n.ccAON():t===36?n.ccDER():t===37?n.ccRU(2):t===38?n.ccRU(3):t===39?n.ccRU(4):t===40?n.ccFON():t===41?n.ccRDC():t===42?n.ccTR():t===43?n.ccRTD():t===44?n.ccEDM():t===45?n.ccCR():t===46?n.ccENM():t===47&&n.ccEOC():n.ccTO(t-32),this.currentChannel=r,!0}parseMidrow(e,t){let s=0;if((e===17||e===25)&&t>=32&&t<=47){if(e===17?s=1:s=2,s!==this.currentChannel)return this.logger.log(0,"Mismatch channel in midrow parsing"),!1;const i=this.channels[s];return i?(i.ccMIDROW(t),this.logger.log(3,()=>"MIDROW ("+nt([e,t])+")"),!0):!1}return!1}parsePAC(e,t){let s;const i=(e>=17&&e<=23||e>=25&&e<=31)&&t>=64&&t<=127,r=(e===16||e===24)&&t>=64&&t<=95;if(!(i||r))return!1;const n=e<=23?1:2;t>=64&&t<=95?s=n===1?Hh[e]:Wh[e]:s=n===1?Yh[e]:qh[e];const o=this.channels[n];return o?(o.setPAC(this.interpretPAC(s,t)),this.currentChannel=n,!0):!1}interpretPAC(e,t){let s;const i={color:null,italics:!1,indent:null,underline:!1,row:e};return t>95?s=t-96:s=t-64,i.underline=(s&1)===1,s<=13?i.color=["white","green","blue","cyan","red","yellow","magenta","white"][Math.floor(s/2)]:s<=15?(i.italics=!0,i.color="white"):i.indent=Math.floor((s-16)/2)*4,i}parseChars(e,t){let s,i=null,r=null;if(e>=25?(s=2,r=e-8):(s=1,r=e),r>=17&&r<=19){let n;r===17?n=t+80:r===18?n=t+112:n=t+144,this.logger.log(2,()=>"Special char '"+La(n)+"' in channel "+s),i=[n]}else e>=32&&e<=127&&(i=t===0?[e]:[e,t]);return i&&this.logger.log(3,()=>"Char codes = "+nt(i).join(",")),i}parseBackgroundAttributes(e,t){const s=(e===16||e===24)&&t>=32&&t<=47,i=(e===23||e===31)&&t>=45&&t<=47;if(!(s||i))return!1;let r;const n={};e===16||e===24?(r=Math.floor((t-32)/2),n.background=jh[r],t%2===1&&(n.background=n.background+"_semi")):t===45?n.background="transparent":(n.foreground="black",t===47&&(n.underline=!0));const o=e<=23?1:2;return this.channels[o].setBkgData(n),!0}reset(){for(let e=0;e100)throw new Error("Position must be between 0 and 100.");D=I,this.hasBeenReset=!0}})),Object.defineProperty(h,"positionAlign",r({},u,{get:function(){return A},set:function(I){const P=i(I);if(!P)throw new SyntaxError("An invalid or illegal string was specified.");A=P,this.hasBeenReset=!0}})),Object.defineProperty(h,"size",r({},u,{get:function(){return _},set:function(I){if(I<0||I>100)throw new Error("Size must be between 0 and 100.");_=I,this.hasBeenReset=!0}})),Object.defineProperty(h,"align",r({},u,{get:function(){return b},set:function(I){const P=i(I);if(!P)throw new SyntaxError("An invalid or illegal string was specified.");b=P,this.hasBeenReset=!0}})),h.displayState=void 0}return n.prototype.getCueAsHTML=function(){return self.WebVTT.convertCueToDOMTree(self,this.text)},n}();class eu{decode(e,t){if(!e)return"";if(typeof e!="string")throw new Error("Error - expected string data.");return decodeURIComponent(encodeURIComponent(e))}}function ba(a){function e(s,i,r,n){return(s|0)*3600+(i|0)*60+(r|0)+parseFloat(n||0)}const t=a.match(/^(?:(\d+):)?(\d{2}):(\d{2})(\.\d+)?/);return t?parseFloat(t[2])>59?e(t[2],t[3],0,t[4]):e(t[1],t[2],t[3],t[4]):null}class tu{constructor(){this.values=Object.create(null)}set(e,t){!this.get(e)&&t!==""&&(this.values[e]=t)}get(e,t,s){return s?this.has(e)?this.values[e]:t[s]:this.has(e)?this.values[e]:t}has(e){return e in this.values}alt(e,t,s){for(let i=0;i=0&&s<=100)return this.set(e,s),!0}return!1}}function _a(a,e,t,s){const i=s?a.split(s):[a];for(const r in i){if(typeof i[r]!="string")continue;const n=i[r].split(t);if(n.length!==2)continue;const o=n[0],c=n[1];e(o,c)}}const hi=new Fi(0,0,""),zt=hi.align==="middle"?"middle":"center";function su(a,e,t){const s=a;function i(){const o=ba(a);if(o===null)throw new Error("Malformed timestamp: "+s);return a=a.replace(/^[^\sa-zA-Z-]+/,""),o}function r(o,c){const l=new tu;_a(o,function(d,f){let g;switch(d){case"region":for(let y=t.length-1;y>=0;y--)if(t[y].id===f){l.set(d,t[y].region);break}break;case"vertical":l.alt(d,f,["rl","lr"]);break;case"line":g=f.split(","),l.integer(d,g[0]),l.percent(d,g[0])&&l.set("snapToLines",!1),l.alt(d,g[0],["auto"]),g.length===2&&l.alt("lineAlign",g[1],["start",zt,"end"]);break;case"position":g=f.split(","),l.percent(d,g[0]),g.length===2&&l.alt("positionAlign",g[1],["start",zt,"end","line-left","line-right","auto"]);break;case"size":l.percent(d,f);break;case"align":l.alt(d,f,["start",zt,"end","left","right"]);break}},/:/,/\s/),c.region=l.get("region",null),c.vertical=l.get("vertical","");let h=l.get("line","auto");h==="auto"&&hi.line===-1&&(h=-1),c.line=h,c.lineAlign=l.get("lineAlign","start"),c.snapToLines=l.get("snapToLines",!0),c.size=l.get("size",100),c.align=l.get("align",zt);let u=l.get("position","auto");u==="auto"&&hi.position===50&&(u=c.align==="start"||c.align==="left"?0:c.align==="end"||c.align==="right"?100:50),c.position=u}function n(){a=a.replace(/^\s+/,"")}if(n(),e.startTime=i(),n(),a.slice(0,3)!=="-->")throw new Error("Malformed time stamp (time stamps must be separated by '-->'): "+s);a=a.slice(3),n(),e.endTime=i(),n(),r(a,e)}function Da(a){return a.replace(//gi,` +`)}class iu{constructor(){this.state="INITIAL",this.buffer="",this.decoder=new eu,this.regionList=[],this.cue=null,this.oncue=void 0,this.onparsingerror=void 0,this.onflush=void 0}parse(e){const t=this;e&&(t.buffer+=t.decoder.decode(e,{stream:!0}));function s(){let r=t.buffer,n=0;for(r=Da(r);n")===-1){t.cue.id=r;continue}case"CUE":if(!t.cue){t.state="BADCUE";continue}try{Sd(r,t.cue,t.regionList)}catch{t.cue=null,t.state="BADCUE";continue}t.state="CUETEXT";continue;case"CUETEXT":{const o=r.indexOf("-->")!==-1;if(!r||o&&(n=!0)){t.oncue&&t.cue&&t.oncue(t.cue),t.cue=null,t.state="ID";continue}if(t.cue===null)continue;t.cue.text&&(t.cue.text+=` +`&&++n,t.buffer=r.slice(n),o}function i(r){_a(r,function(n,o){},/:/)}try{let r="";if(t.state==="INITIAL"){if(!/\r\n|\n/.test(t.buffer))return this;r=s();const o=r.match(/^()?WEBVTT([ \t].*)?$/);if(!(o!=null&&o[0]))throw new Error("Malformed WebVTT signature.");t.state="HEADER"}let n=!1;for(;t.buffer;){if(!/\r\n|\n/.test(t.buffer))return this;switch(n?n=!1:r=s(),t.state){case"HEADER":/:/.test(r)?i(r):r||(t.state="ID");continue;case"NOTE":r||(t.state="ID");continue;case"ID":if(/^NOTE($|[ \t])/.test(r)){t.state="NOTE";break}if(!r)continue;if(t.cue=new Fi(0,0,""),t.state="CUE",r.indexOf("-->")===-1){t.cue.id=r;continue}case"CUE":if(!t.cue){t.state="BADCUE";continue}try{su(r,t.cue,t.regionList)}catch{t.cue=null,t.state="BADCUE";continue}t.state="CUETEXT";continue;case"CUETEXT":{const o=r.indexOf("-->")!==-1;if(!r||o&&(n=!0)){t.oncue&&t.cue&&t.oncue(t.cue),t.cue=null,t.state="ID";continue}if(t.cue===null)continue;t.cue.text&&(t.cue.text+=` `),t.cue.text+=r}continue;case"BADCUE":r||(t.state="ID")}}}catch{t.state==="CUETEXT"&&t.cue&&t.oncue&&t.oncue(t.cue),t.cue=null,t.state=t.state==="INITIAL"?"BADWEBVTT":"BADCUE"}return this}flush(){const e=this;try{if((e.cue||e.state==="HEADER")&&(e.buffer+=` -`,e.parse()),e.state==="INITIAL"||e.state==="BADWEBVTT")throw new Error("Malformed WebVTT signature.")}catch(t){e.onparsingerror&&e.onparsingerror(t)}return e.onflush&&e.onflush(),this}}const xd=/\r\n|\n\r|\n|\r/g,zs=function(e,t,s=0){return e.slice(s,s+t.length)===t},Ad=function(e){let t=parseInt(e.slice(-3));const s=parseInt(e.slice(-6,-4)),i=parseInt(e.slice(-9,-7)),r=e.length>9?parseInt(e.substring(0,e.indexOf(":"))):0;if(!B(t)||!B(s)||!B(i)||!B(r))throw Error(`Malformed X-TIMESTAMP-MAP: Local:${e}`);return t+=1e3*s,t+=60*1e3*i,t+=60*60*1e3*r,t};function ji(a,e,t){return $t(a.toString())+$t(e.toString())+$t(t)}const Id=function(e,t,s){let i=e[t],r=e[i.prevCC];if(!r||!r.new&&i.new){e.ccOffset=e.presentationOffset=i.start,i.new=!1;return}for(;(n=r)!=null&&n.new;){var n;e.ccOffset+=i.start-r.start,i.new=!1,i=r,r=e[i.prevCC]}e.presentationOffset=s};function Ld(a,e,t,s,i,r,n){const o=new vd,c=De(new Uint8Array(a)).trim().replace(xd,` +`,e.parse()),e.state==="INITIAL"||e.state==="BADWEBVTT")throw new Error("Malformed WebVTT signature.")}catch(t){e.onparsingerror&&e.onparsingerror(t)}return e.onflush&&e.onflush(),this}}const ru=/\r\n|\n\r|\n|\r/g,$s=function(e,t,s=0){return e.slice(s,s+t.length)===t},nu=function(e){let t=parseInt(e.slice(-3));const s=parseInt(e.slice(-6,-4)),i=parseInt(e.slice(-9,-7)),r=e.length>9?parseInt(e.substring(0,e.indexOf(":"))):0;if(!M(t)||!M(s)||!M(i)||!M(r))throw Error(`Malformed X-TIMESTAMP-MAP: Local:${e}`);return t+=1e3*s,t+=60*1e3*i,t+=60*60*1e3*r,t};function Mi(a,e,t){return Pt(a.toString())+Pt(e.toString())+Pt(t)}const au=function(e,t,s){let i=e[t],r=e[i.prevCC];if(!r||!r.new&&i.new){e.ccOffset=e.presentationOffset=i.start,i.new=!1;return}for(;(n=r)!=null&&n.new;){var n;e.ccOffset+=i.start-r.start,i.new=!1,i=r,r=e[i.prevCC]}e.presentationOffset=s};function ou(a,e,t,s,i,r,n){const o=new iu,c=Re(new Uint8Array(a)).trim().replace(ru,` `).split(` -`),l=[],h=e?Pc(e.baseTime,e.timescale):0;let d="00:00.000",u=0,f=0,g,y=!0;o.oncue=function(p){const E=t[s];let T=t.ccOffset;const S=(u-h)/9e4;if(E!=null&&E.new&&(f!==void 0?T=t.ccOffset=E.start:Id(t,s,S)),S){if(!e){g=new Error("Missing initPTS for VTT MPEGTS");return}T=S-t.presentationOffset}const v=p.endTime-p.startTime,x=be((p.startTime+T-f)*9e4,i*9e4)/9e4;p.startTime=Math.max(x,0),p.endTime=Math.max(x+v,0);const D=p.text.trim();p.text=decodeURIComponent(encodeURIComponent(D)),p.id||(p.id=ji(p.startTime,p.endTime,D)),p.endTime>0&&l.push(p)},o.onparsingerror=function(p){g=p},o.onflush=function(){if(g){n(g);return}r(l)},c.forEach(p=>{if(y)if(zs(p,"X-TIMESTAMP-MAP=")){y=!1,p.slice(16).split(",").forEach(E=>{zs(E,"LOCAL:")?d=E.slice(6):zs(E,"MPEGTS:")&&(u=parseInt(E.slice(7)))});try{f=Ad(d)/1e3}catch(E){g=E}return}else p===""&&(y=!1);o.parse(p+` -`)}),o.flush()}const Qs="stpp.ttml.im1t",Wa=/^(\d{2,}):(\d{2}):(\d{2}):(\d{2})\.?(\d+)?$/,qa=/^(\d*(?:\.\d*)?)(h|m|s|ms|f|t)$/,Rd={left:"start",center:"center",right:"end",start:"start",end:"end"};function cn(a,e,t,s){const i=Z(new Uint8Array(a),["mdat"]);if(i.length===0){s(new Error("Could not parse IMSC1 mdat"));return}const r=i.map(o=>De(o)),n=Cc(e.baseTime,1,e.timescale);try{r.forEach(o=>t(bd(o,n)))}catch(o){s(o)}}function bd(a,e){const i=new DOMParser().parseFromString(a,"text/xml").getElementsByTagName("tt")[0];if(!i)throw new Error("Invalid ttml");const r={frameRate:30,subFrameRate:1,frameRateMultiplier:0,tickRate:0},n=Object.keys(r).reduce((d,u)=>(d[u]=i.getAttribute(`ttp:${u}`)||r[u],d),{}),o=i.getAttribute("xml:space")!=="preserve",c=hn(Zs(i,"styling","style")),l=hn(Zs(i,"layout","region")),h=Zs(i,"body","[begin]");return[].map.call(h,d=>{const u=ja(d,o);if(!u||!d.hasAttribute("begin"))return null;const f=ei(d.getAttribute("begin"),n),g=ei(d.getAttribute("dur"),n);let y=ei(d.getAttribute("end"),n);if(f===null)throw dn(d);if(y===null){if(g===null)throw dn(d);y=f+g}const p=new qi(f-e,y-e,u);p.id=ji(p.startTime,p.endTime,p.text);const E=l[d.getAttribute("region")],T=c[d.getAttribute("style")],S=_d(E,T,c),{textAlign:v}=S;if(v){const x=Rd[v];x&&(p.lineAlign=x),p.align=v}return ne(p,S),p}).filter(d=>d!==null)}function Zs(a,e,t){const s=a.getElementsByTagName(e)[0];return s?[].slice.call(s.querySelectorAll(t)):[]}function hn(a){return a.reduce((e,t)=>{const s=t.getAttribute("xml:id");return s&&(e[s]=t),e},{})}function ja(a,e){return[].slice.call(a.childNodes).reduce((t,s,i)=>{var r;return s.nodeName==="br"&&i?t+` -`:(r=s.childNodes)!=null&&r.length?ja(s,e):e?t+s.textContent.trim().replace(/\s+/g," "):t+s.textContent},"")}function _d(a,e,t){const s="http://www.w3.org/ns/ttml#styling";let i=null;const r=["displayAlign","textAlign","color","backgroundColor","fontSize","fontFamily"],n=a!=null&&a.hasAttribute("style")?a.getAttribute("style"):null;return n&&t.hasOwnProperty(n)&&(i=t[n]),r.reduce((o,c)=>{const l=Js(e,s,c)||Js(a,s,c)||Js(i,s,c);return l&&(o[c]=l),o},{})}function Js(a,e,t){return a&&a.hasAttributeNS(e,t)?a.getAttributeNS(e,t):null}function dn(a){return new Error(`Could not parse ttml timestamp ${a}`)}function ei(a,e){if(!a)return null;let t=Va(a);return t===null&&(Wa.test(a)?t=Dd(a,e):qa.test(a)&&(t=Cd(a,e))),t}function Dd(a,e){const t=Wa.exec(a),s=(t[4]|0)+(t[5]|0)/e.subFrameRate;return(t[1]|0)*3600+(t[2]|0)*60+(t[3]|0)+s/e.frameRate}function Cd(a,e){const t=qa.exec(a),s=Number(t[1]);switch(t[2]){case"h":return s*3600;case"m":return s*60;case"ms":return s*1e3;case"f":return s/e.frameRate;case"t":return s/e.tickRate}return s}class os{constructor(e,t){this.timelineController=void 0,this.cueRanges=[],this.trackName=void 0,this.startTime=null,this.endTime=null,this.screen=null,this.timelineController=e,this.trackName=t}dispatchCue(){this.startTime!==null&&(this.timelineController.addCues(this.trackName,this.startTime,this.endTime,this.screen,this.cueRanges),this.startTime=null)}newCue(e,t,s){(this.startTime===null||this.startTime>e)&&(this.startTime=e),this.endTime=t,this.screen=s,this.timelineController.createCaptionsTrack(this.trackName)}reset(){this.cueRanges=[],this.startTime=null}}class Pd{constructor(e){this.hls=void 0,this.media=null,this.config=void 0,this.enabled=!0,this.Cues=void 0,this.textTracks=[],this.tracks=[],this.initPTS=[],this.unparsedVttFrags=[],this.captionsTracks={},this.nonNativeCaptionsTracks={},this.cea608Parser1=void 0,this.cea608Parser2=void 0,this.lastCc=-1,this.lastSn=-1,this.lastPartIndex=-1,this.prevCC=-1,this.vttCCs=fn(),this.captionsProperties=void 0,this.hls=e,this.config=e.config,this.Cues=e.config.cueHandler,this.captionsProperties={textTrack1:{label:this.config.captionsTextTrack1Label,languageCode:this.config.captionsTextTrack1LanguageCode},textTrack2:{label:this.config.captionsTextTrack2Label,languageCode:this.config.captionsTextTrack2LanguageCode},textTrack3:{label:this.config.captionsTextTrack3Label,languageCode:this.config.captionsTextTrack3LanguageCode},textTrack4:{label:this.config.captionsTextTrack4Label,languageCode:this.config.captionsTextTrack4LanguageCode}},e.on(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.on(m.SUBTITLE_TRACKS_UPDATED,this.onSubtitleTracksUpdated,this),e.on(m.FRAG_LOADING,this.onFragLoading,this),e.on(m.FRAG_LOADED,this.onFragLoaded,this),e.on(m.FRAG_PARSING_USERDATA,this.onFragParsingUserdata,this),e.on(m.FRAG_DECRYPTED,this.onFragDecrypted,this),e.on(m.INIT_PTS_FOUND,this.onInitPtsFound,this),e.on(m.SUBTITLE_TRACKS_CLEARED,this.onSubtitleTracksCleared,this),e.on(m.BUFFER_FLUSHING,this.onBufferFlushing,this)}destroy(){const{hls:e}=this;e.off(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.off(m.SUBTITLE_TRACKS_UPDATED,this.onSubtitleTracksUpdated,this),e.off(m.FRAG_LOADING,this.onFragLoading,this),e.off(m.FRAG_LOADED,this.onFragLoaded,this),e.off(m.FRAG_PARSING_USERDATA,this.onFragParsingUserdata,this),e.off(m.FRAG_DECRYPTED,this.onFragDecrypted,this),e.off(m.INIT_PTS_FOUND,this.onInitPtsFound,this),e.off(m.SUBTITLE_TRACKS_CLEARED,this.onSubtitleTracksCleared,this),e.off(m.BUFFER_FLUSHING,this.onBufferFlushing,this),this.hls=this.config=this.media=null,this.cea608Parser1=this.cea608Parser2=void 0}initCea608Parsers(){const e=new os(this,"textTrack1"),t=new os(this,"textTrack2"),s=new os(this,"textTrack3"),i=new os(this,"textTrack4");this.cea608Parser1=new ln(1,e,t),this.cea608Parser2=new ln(3,s,i)}addCues(e,t,s,i,r){let n=!1;for(let o=r.length;o--;){const c=r[o],l=kd(c[0],c[1],t,s);if(l>=0&&(c[0]=Math.min(c[0],t),c[1]=Math.max(c[1],s),n=!0,l/(s-t)>.5))return}if(n||r.push([t,s]),this.config.renderTextTracksNatively){const o=this.captionsTracks[e];this.Cues.newCue(o,t,s,i)}else{const o=this.Cues.newCue(null,t,s,i);this.hls.trigger(m.CUES_PARSED,{type:"captions",cues:o,track:e})}}onInitPtsFound(e,{frag:t,id:s,initPTS:i,timescale:r,trackId:n}){const{unparsedVttFrags:o}=this;s===U.MAIN&&(this.initPTS[t.cc]={baseTime:i,timescale:r,trackId:n}),o.length&&(this.unparsedVttFrags=[],o.forEach(c=>{this.initPTS[c.frag.cc]?this.onFragLoaded(m.FRAG_LOADED,c):this.hls.trigger(m.SUBTITLE_FRAG_PROCESSED,{success:!1,frag:c.frag,error:new Error("Subtitle discontinuity domain does not match main")})}))}getExistingTrack(e,t){const{media:s}=this;if(s)for(let i=0;i{Lt(i[r]),delete i[r]}),this.nonNativeCaptionsTracks={}}onManifestLoading(){this.lastCc=-1,this.lastSn=-1,this.lastPartIndex=-1,this.prevCC=-1,this.vttCCs=fn(),this._cleanTracks(),this.tracks=[],this.captionsTracks={},this.nonNativeCaptionsTracks={},this.textTracks=[],this.unparsedVttFrags=[],this.initPTS=[],this.cea608Parser1&&this.cea608Parser2&&(this.cea608Parser1.reset(),this.cea608Parser2.reset())}_cleanTracks(){const{media:e}=this;if(!e)return;const t=e.textTracks;if(t)for(let s=0;sr.textCodec===Qs);if(this.config.enableWebVTT||i&&this.config.enableIMSC1){if(La(this.tracks,s)){this.tracks=s;return}if(this.textTracks=[],this.tracks=s,this.config.renderTextTracksNatively){const n=this.media,o=n?ps(n.textTracks):null;if(this.tracks.forEach((c,l)=>{let h;if(o){let d=null;for(let u=0;ul!==null).map(l=>l.label);c.length&&this.hls.logger.warn(`Media element contains unused subtitle tracks: ${c.join(", ")}. Replace media element for each source to clear TextTracks and captions menu.`)}}else if(this.tracks.length){const n=this.tracks.map(o=>({label:o.name,kind:o.type.toLowerCase(),default:o.default,subtitleTrack:o}));this.hls.trigger(m.NON_NATIVE_TEXT_TRACKS_FOUND,{tracks:n})}}}onManifestLoaded(e,t){this.config.enableCEA708Captions&&t.captions&&t.captions.forEach(s=>{const i=/(?:CC|SERVICE)([1-4])/.exec(s.instreamId);if(!i)return;const r=`textTrack${i[1]}`,n=this.captionsProperties[r];n&&(n.label=s.name,s.lang&&(n.languageCode=s.lang),n.media=s)})}closedCaptionsForLevel(e){const t=this.hls.levels[e.level];return t==null?void 0:t.attrs["CLOSED-CAPTIONS"]}onFragLoading(e,t){if(this.enabled&&t.frag.type===U.MAIN){var s,i;const{cea608Parser1:r,cea608Parser2:n,lastSn:o}=this,{cc:c,sn:l}=t.frag,h=(s=(i=t.part)==null?void 0:i.index)!=null?s:-1;r&&n&&(l!==o+1||l===o&&h!==this.lastPartIndex+1||c!==this.lastCc)&&(r.reset(),n.reset()),this.lastCc=c,this.lastSn=l,this.lastPartIndex=h}}onFragLoaded(e,t){const{frag:s,payload:i}=t;if(s.type===U.SUBTITLE)if(i.byteLength){const r=s.decryptdata,n="stats"in t;if(r==null||!r.encrypted||n){const o=this.tracks[s.level],c=this.vttCCs;c[s.cc]||(c[s.cc]={start:s.start,prevCC:this.prevCC,new:!0},this.prevCC=s.cc),o&&o.textCodec===Qs?this._parseIMSC1(s,i):this._parseVTTs(t)}}else this.hls.trigger(m.SUBTITLE_FRAG_PROCESSED,{success:!1,frag:s,error:new Error("Empty subtitle payload")})}_parseIMSC1(e,t){const s=this.hls;cn(t,this.initPTS[e.cc],i=>{this._appendCues(i,e.level),s.trigger(m.SUBTITLE_FRAG_PROCESSED,{success:!0,frag:e})},i=>{s.logger.log(`Failed to parse IMSC1: ${i}`),s.trigger(m.SUBTITLE_FRAG_PROCESSED,{success:!1,frag:e,error:i})})}_parseVTTs(e){var t;const{frag:s,payload:i}=e,{initPTS:r,unparsedVttFrags:n}=this,o=r.length-1;if(!r[s.cc]&&o===-1){n.push(e);return}const c=this.hls,l=(t=s.initSegment)!=null&&t.data?we(s.initSegment.data,new Uint8Array(i)).buffer:i;Ld(l,this.initPTS[s.cc],this.vttCCs,s.cc,s.start,h=>{this._appendCues(h,s.level),c.trigger(m.SUBTITLE_FRAG_PROCESSED,{success:!0,frag:s})},h=>{const d=h.message==="Missing initPTS for VTT MPEGTS";d?n.push(e):this._fallbackToIMSC1(s,i),c.logger.log(`Failed to parse VTT cue: ${h}`),!(d&&o>s.cc)&&c.trigger(m.SUBTITLE_FRAG_PROCESSED,{success:!1,frag:s,error:h})})}_fallbackToIMSC1(e,t){const s=this.tracks[e.level];s.textCodec||cn(t,this.initPTS[e.cc],()=>{s.textCodec=Qs,this._parseIMSC1(e,t)},()=>{s.textCodec="wvtt"})}_appendCues(e,t){const s=this.hls;if(this.config.renderTextTracksNatively){const i=this.textTracks[t];if(!i||i.mode==="disabled")return;e.forEach(r=>$a(i,r))}else{const i=this.tracks[t];if(!i)return;const r=i.default?"default":"subtitles"+t;s.trigger(m.CUES_PARSED,{type:"subtitles",cues:e,track:r})}}onFragDecrypted(e,t){const{frag:s}=t;s.type===U.SUBTITLE&&this.onFragLoaded(m.FRAG_LOADED,t)}onSubtitleTracksCleared(){this.tracks=[],this.captionsTracks={}}onFragParsingUserdata(e,t){if(!this.enabled||!this.config.enableCEA708Captions)return;const{frag:s,samples:i}=t;if(!(s.type===U.MAIN&&this.closedCaptionsForLevel(s)==="NONE"))for(let r=0;rTi(o[c],t,s))}if(this.config.renderTextTracksNatively&&t===0&&i!==void 0){const{textTracks:o}=this;Object.keys(o).forEach(c=>Ti(o[c],t,i))}}}extractCea608Data(e){const t=[[],[]],s=e[0]&31;let i=2;for(let r=0;r=16?c--:c++;const f=Ya(l.trim()),g=ji(e,t,f);a!=null&&(d=a.cues)!=null&&d.getCueById(g)||(n=new h(e,t,f),n.id=g,n.line=u+1,n.align="left",n.position=10+Math.min(80,Math.floor(c*8/32)*10),i.push(n))}return a&&i.length&&(i.sort((u,f)=>u.line==="auto"||f.line==="auto"?0:u.line>8&&f.line>8?f.line-u.line:u.line-f.line),i.forEach(u=>$a(a,u))),i}};function Fd(){if(self.fetch&&self.AbortController&&self.ReadableStream&&self.Request)try{return new self.ReadableStream({}),!0}catch{}return!1}const Md=/(\d+)-(\d+)\/(\d+)/;class gn{constructor(e){this.fetchSetup=void 0,this.requestTimeout=void 0,this.request=null,this.response=null,this.controller=void 0,this.context=null,this.config=null,this.callbacks=null,this.stats=void 0,this.loader=null,this.fetchSetup=e.fetchSetup||Ud,this.controller=new self.AbortController,this.stats=new Ri}destroy(){this.loader=this.callbacks=this.context=this.config=this.request=null,this.abortInternal(),this.response=null,this.fetchSetup=this.controller=this.stats=null}abortInternal(){this.controller&&!this.stats.loading.end&&(this.stats.aborted=!0,this.controller.abort())}abort(){var e;this.abortInternal(),(e=this.callbacks)!=null&&e.onAbort&&this.callbacks.onAbort(this.stats,this.context,this.response)}load(e,t,s){const i=this.stats;if(i.loading.start)throw new Error("Loader can only be used once.");i.loading.start=self.performance.now();const r=Nd(e,this.controller.signal),n=e.responseType==="arraybuffer",o=n?"byteLength":"length",{maxTimeToFirstByteMs:c,maxLoadTimeMs:l}=t.loadPolicy;this.context=e,this.config=t,this.callbacks=s,this.request=this.fetchSetup(e,r),self.clearTimeout(this.requestTimeout),t.timeout=c&&B(c)?c:l,this.requestTimeout=self.setTimeout(()=>{this.callbacks&&(this.abortInternal(),this.callbacks.onTimeout(i,e,this.response))},t.timeout),(Yt(this.request)?this.request.then(self.fetch):self.fetch(this.request)).then(d=>{var u;this.response=this.loader=d;const f=Math.max(self.performance.now(),i.loading.start);if(self.clearTimeout(this.requestTimeout),t.timeout=l,this.requestTimeout=self.setTimeout(()=>{this.callbacks&&(this.abortInternal(),this.callbacks.onTimeout(i,e,this.response))},l-(f-i.loading.start)),!d.ok){const{status:y,statusText:p}=d;throw new Gd(p||"fetch, bad network response",y,d)}i.loading.first=f,i.total=$d(d.headers)||i.total;const g=(u=this.callbacks)==null?void 0:u.onProgress;return g&&B(t.highWaterMark)?this.loadProgressively(d,i,e,t.highWaterMark,g):n?d.arrayBuffer():e.responseType==="json"?d.json():d.text()}).then(d=>{var u,f;const g=this.response;if(!g)throw new Error("loader destroyed");self.clearTimeout(this.requestTimeout),i.loading.end=Math.max(self.performance.now(),i.loading.first);const y=d[o];y&&(i.loaded=i.total=y);const p={url:g.url,data:d,code:g.status},E=(u=this.callbacks)==null?void 0:u.onProgress;E&&!B(t.highWaterMark)&&E(i,e,d,g),(f=this.callbacks)==null||f.onSuccess(p,i,e,g)}).catch(d=>{var u;if(self.clearTimeout(this.requestTimeout),i.aborted)return;const f=d&&d.code||0,g=d?d.message:null;(u=this.callbacks)==null||u.onError({code:f,text:g},e,d?d.details:null,i)})}getCacheAge(){let e=null;if(this.response){const t=this.response.headers.get("age");e=t?parseFloat(t):null}return e}getResponseHeader(e){return this.response?this.response.headers.get(e):null}loadProgressively(e,t,s,i=0,r){const n=new na,o=e.body.getReader(),c=()=>o.read().then(l=>{if(l.done)return n.dataLength&&r(t,s,n.flush().buffer,e),Promise.resolve(new ArrayBuffer(0));const h=l.value,d=h.length;return t.loaded+=d,d=i&&r(t,s,n.flush().buffer,e)):r(t,s,h.buffer,e),c()}).catch(()=>Promise.reject());return c()}}function Nd(a,e){const t={method:"GET",mode:"cors",credentials:"same-origin",signal:e,headers:new self.Headers(ne({},a.headers))};return a.rangeEnd&&t.headers.set("Range","bytes="+a.rangeStart+"-"+String(a.rangeEnd-1)),t}function Bd(a){const e=Md.exec(a);if(e)return parseInt(e[2])-parseInt(e[1])+1}function $d(a){const e=a.get("Content-Range");if(e){const s=Bd(e);if(B(s))return s}const t=a.get("Content-Length");if(t)return parseInt(t)}function Ud(a,e){return new self.Request(a.url,e)}class Gd extends Error{constructor(e,t,s){super(e),this.code=void 0,this.details=void 0,this.code=t,this.details=s}}const Kd=/^age:\s*[\d.]+\s*$/im;class za{constructor(e){this.xhrSetup=void 0,this.requestTimeout=void 0,this.retryTimeout=void 0,this.retryDelay=void 0,this.config=null,this.callbacks=null,this.context=null,this.loader=null,this.stats=void 0,this.xhrSetup=e&&e.xhrSetup||null,this.stats=new Ri,this.retryDelay=0}destroy(){this.callbacks=null,this.abortInternal(),this.loader=null,this.config=null,this.context=null,this.xhrSetup=null}abortInternal(){const e=this.loader;self.clearTimeout(this.requestTimeout),self.clearTimeout(this.retryTimeout),e&&(e.onreadystatechange=null,e.onprogress=null,e.readyState!==4&&(this.stats.aborted=!0,e.abort()))}abort(){var e;this.abortInternal(),(e=this.callbacks)!=null&&e.onAbort&&this.callbacks.onAbort(this.stats,this.context,this.loader)}load(e,t,s){if(this.stats.loading.start)throw new Error("Loader can only be used once.");this.stats.loading.start=self.performance.now(),this.context=e,this.config=t,this.callbacks=s,this.loadInternal()}loadInternal(){const{config:e,context:t}=this;if(!e||!t)return;const s=this.loader=new self.XMLHttpRequest,i=this.stats;i.loading.first=0,i.loaded=0,i.aborted=!1;const r=this.xhrSetup;r?Promise.resolve().then(()=>{if(!(this.loader!==s||this.stats.aborted))return r(s,t.url)}).catch(n=>{if(!(this.loader!==s||this.stats.aborted))return s.open("GET",t.url,!0),r(s,t.url)}).then(()=>{this.loader!==s||this.stats.aborted||this.openAndSendXhr(s,t,e)}).catch(n=>{var o;(o=this.callbacks)==null||o.onError({code:s.status,text:n.message},t,s,i)}):this.openAndSendXhr(s,t,e)}openAndSendXhr(e,t,s){e.readyState||e.open("GET",t.url,!0);const i=t.headers,{maxTimeToFirstByteMs:r,maxLoadTimeMs:n}=s.loadPolicy;if(i)for(const o in i)e.setRequestHeader(o,i[o]);t.rangeEnd&&e.setRequestHeader("Range","bytes="+t.rangeStart+"-"+(t.rangeEnd-1)),e.onreadystatechange=this.readystatechange.bind(this),e.onprogress=this.loadprogress.bind(this),e.responseType=t.responseType,self.clearTimeout(this.requestTimeout),s.timeout=r&&B(r)?r:n,this.requestTimeout=self.setTimeout(this.loadtimeout.bind(this),s.timeout),e.send()}readystatechange(){const{context:e,loader:t,stats:s}=this;if(!e||!t)return;const i=t.readyState,r=this.config;if(!s.aborted&&i>=2&&(s.loading.first===0&&(s.loading.first=Math.max(self.performance.now(),s.loading.start),r.timeout!==r.loadPolicy.maxLoadTimeMs&&(self.clearTimeout(this.requestTimeout),r.timeout=r.loadPolicy.maxLoadTimeMs,this.requestTimeout=self.setTimeout(this.loadtimeout.bind(this),r.loadPolicy.maxLoadTimeMs-(s.loading.first-s.loading.start)))),i===4)){self.clearTimeout(this.requestTimeout),t.onreadystatechange=null,t.onprogress=null;const l=t.status,h=t.responseType==="text"?t.responseText:null;if(l>=200&&l<300){const g=h??t.response;if(g!=null){var n,o;s.loading.end=Math.max(self.performance.now(),s.loading.first);const y=t.responseType==="arraybuffer"?g.byteLength:g.length;s.loaded=s.total=y,s.bwEstimate=s.total*8e3/(s.loading.end-s.loading.first);const p=(n=this.callbacks)==null?void 0:n.onProgress;p&&p(s,e,g,t);const E={url:t.responseURL,data:g,code:l};(o=this.callbacks)==null||o.onSuccess(E,s,e,t);return}}const d=r.loadPolicy.errorRetry,u=s.retry,f={url:e.url,data:void 0,code:l};if(As(d,u,!1,f))this.retry(d);else{var c;re.error(`${l} while loading ${e.url}`),(c=this.callbacks)==null||c.onError({code:l,text:t.statusText},e,t,s)}}}loadtimeout(){if(!this.config)return;const e=this.config.loadPolicy.timeoutRetry,t=this.stats.retry;if(As(e,t,!0))this.retry(e);else{var s;re.warn(`timeout while loading ${(s=this.context)==null?void 0:s.url}`);const i=this.callbacks;i&&(this.abortInternal(),i.onTimeout(this.stats,this.context,this.loader))}}retry(e){const{context:t,stats:s}=this;this.retryDelay=Ci(e,s.retry),s.retry++,re.warn(`${status?"HTTP Status "+status:"Timeout"} while loading ${t==null?void 0:t.url}, retrying ${s.retry}/${e.maxNumRetry} in ${this.retryDelay}ms`),this.abortInternal(),this.loader=null,self.clearTimeout(this.retryTimeout),this.retryTimeout=self.setTimeout(this.loadInternal.bind(this),this.retryDelay)}loadprogress(e){const t=this.stats;t.loaded=e.loaded,e.lengthComputable&&(t.total=e.total)}getCacheAge(){let e=null;if(this.loader&&Kd.test(this.loader.getAllResponseHeaders())){const t=this.loader.getResponseHeader("age");e=t?parseFloat(t):null}return e}getResponseHeader(e){return this.loader&&new RegExp(`^${e}:\\s*[\\d.]+\\s*$`,"im").test(this.loader.getAllResponseHeaders())?this.loader.getResponseHeader(e):null}}const Vd={maxTimeToFirstByteMs:8e3,maxLoadTimeMs:2e4,timeoutRetry:null,errorRetry:null},Hd=ie(ie({autoStartLoad:!0,startPosition:-1,defaultAudioCodec:void 0,debug:!1,capLevelOnFPSDrop:!1,capLevelToPlayerSize:!1,ignoreDevicePixelRatio:!1,maxDevicePixelRatio:Number.POSITIVE_INFINITY,preferManagedMediaSource:!0,initialLiveManifestSize:1,maxBufferLength:30,backBufferLength:1/0,frontBufferFlushThreshold:1/0,startOnSegmentBoundary:!1,maxBufferSize:60*1e3*1e3,maxFragLookUpTolerance:.25,maxBufferHole:.1,detectStallWithCurrentTimeMs:1250,highBufferWatchdogPeriod:2,nudgeOffset:.1,nudgeMaxRetry:3,nudgeOnVideoHole:!0,liveSyncMode:"edge",liveSyncDurationCount:3,liveSyncOnStallIncrease:1,liveMaxLatencyDurationCount:1/0,liveSyncDuration:void 0,liveMaxLatencyDuration:void 0,maxLiveSyncPlaybackRate:1,liveDurationInfinity:!1,liveBackBufferLength:null,maxMaxBufferLength:600,enableWorker:!0,workerPath:null,enableSoftwareAES:!0,startLevel:void 0,startFragPrefetch:!1,fpsDroppedMonitoringPeriod:5e3,fpsDroppedMonitoringThreshold:.2,appendErrorMaxRetry:3,ignorePlaylistParsingErrors:!1,loader:za,fLoader:void 0,pLoader:void 0,xhrSetup:void 0,licenseXhrSetup:void 0,licenseResponseCallback:void 0,abrController:sl,bufferController:Wc,capLevelController:Hi,errorController:ol,fpsController:qh,stretchShortVideoTrack:!1,maxAudioFramesDrift:1,forceKeyFrameOnDiscontinuity:!0,abrEwmaFastLive:3,abrEwmaSlowLive:9,abrEwmaFastVoD:3,abrEwmaSlowVoD:9,abrEwmaDefaultEstimate:5e5,abrEwmaDefaultEstimateMax:5e6,abrBandWidthFactor:.95,abrBandWidthUpFactor:.7,abrMaxWithRealBitrate:!1,maxStarvationDelay:4,maxLoadingDelay:4,minAutoBitrate:0,emeEnabled:!1,widevineLicenseUrl:void 0,drmSystems:{},drmSystemOptions:{},requestMediaKeySystemAccessFunc:jn,requireKeySystemAccessOnStart:!1,testBandwidth:!0,progressive:!1,lowLatencyMode:!0,cmcd:void 0,enableDateRangeMetadataCues:!0,enableEmsgMetadataCues:!0,enableEmsgKLVMetadata:!1,enableID3MetadataCues:!0,enableInterstitialPlayback:!0,interstitialAppendInPlace:!0,interstitialLiveLookAhead:10,useMediaCapabilities:!0,preserveManualLevelOnError:!1,certLoadPolicy:{default:Vd},keyLoadPolicy:{default:{maxTimeToFirstByteMs:8e3,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:1,retryDelayMs:1e3,maxRetryDelayMs:2e4,backoff:"linear"},errorRetry:{maxNumRetry:8,retryDelayMs:1e3,maxRetryDelayMs:2e4,backoff:"linear"}}},manifestLoadPolicy:{default:{maxTimeToFirstByteMs:1/0,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:2,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:1,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},playlistLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:2,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:2,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},fragLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:12e4,timeoutRetry:{maxNumRetry:4,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:6,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},steeringManifestLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:2,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:1,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},interstitialAssetListLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:3e4,timeoutRetry:{maxNumRetry:0,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:0,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},manifestLoadingTimeOut:1e4,manifestLoadingMaxRetry:1,manifestLoadingRetryDelay:1e3,manifestLoadingMaxRetryTimeout:64e3,levelLoadingTimeOut:1e4,levelLoadingMaxRetry:4,levelLoadingRetryDelay:1e3,levelLoadingMaxRetryTimeout:64e3,fragLoadingTimeOut:2e4,fragLoadingMaxRetry:6,fragLoadingRetryDelay:1e3,fragLoadingMaxRetryTimeout:64e3},Yd()),{},{subtitleStreamController:nd,subtitleTrackController:zh,timelineController:Pd,audioStreamController:Kc,audioTrackController:Vc,emeController:Dt,cmcdController:Vh,contentSteeringController:Yh,interstitialsController:rd});function Yd(){return{cueHandler:Od,enableWebVTT:!0,enableIMSC1:!0,enableCEA708Captions:!0,captionsTextTrack1Label:"English",captionsTextTrack1LanguageCode:"en",captionsTextTrack2Label:"Spanish",captionsTextTrack2LanguageCode:"es",captionsTextTrack3Label:"Unknown CC",captionsTextTrack3LanguageCode:"",captionsTextTrack4Label:"Unknown CC",captionsTextTrack4LanguageCode:"",renderTextTracksNatively:!0}}function Wd(a,e,t){if((e.liveSyncDurationCount||e.liveMaxLatencyDurationCount)&&(e.liveSyncDuration||e.liveMaxLatencyDuration))throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration");if(e.liveMaxLatencyDurationCount!==void 0&&(e.liveSyncDurationCount===void 0||e.liveMaxLatencyDurationCount<=e.liveSyncDurationCount))throw new Error('Illegal hls.js config: "liveMaxLatencyDurationCount" must be greater than "liveSyncDurationCount"');if(e.liveMaxLatencyDuration!==void 0&&(e.liveSyncDuration===void 0||e.liveMaxLatencyDuration<=e.liveSyncDuration))throw new Error('Illegal hls.js config: "liveMaxLatencyDuration" must be greater than "liveSyncDuration"');const s=vi(a),i=["manifest","level","frag"],r=["TimeOut","MaxRetry","RetryDelay","MaxRetryTimeout"];return i.forEach(n=>{const o=`${n==="level"?"playlist":n}LoadPolicy`,c=e[o]===void 0,l=[];r.forEach(h=>{const d=`${n}Loading${h}`,u=e[d];if(u!==void 0&&c){l.push(d);const f=s[o].default;switch(e[o]={default:f},h){case"TimeOut":f.maxLoadTimeMs=u,f.maxTimeToFirstByteMs=u;break;case"MaxRetry":f.errorRetry.maxNumRetry=u,f.timeoutRetry.maxNumRetry=u;break;case"RetryDelay":f.errorRetry.retryDelayMs=u,f.timeoutRetry.retryDelayMs=u;break;case"MaxRetryTimeout":f.errorRetry.maxRetryDelayMs=u,f.timeoutRetry.maxRetryDelayMs=u;break}}}),l.length&&t.warn(`hls.js config: "${l.join('", "')}" setting(s) are deprecated, use "${o}": ${oe(e[o])}`)}),ie(ie({},s),e)}function vi(a){return a&&typeof a=="object"?Array.isArray(a)?a.map(vi):Object.keys(a).reduce((e,t)=>(e[t]=vi(a[t]),e),{}):a}function qd(a,e){const t=a.loader;t!==gn&&t!==za?(e.log("[config]: Custom loader detected, cannot enable progressive streaming"),a.progressive=!1):Fd()&&(a.loader=gn,a.progressive=!0,a.enableSoftwareAES=!0,e.log("[config]: Progressive streaming enabled, using FetchLoader"))}const ys=2,jd=.1,Xd=.05,zd=100;class Qd extends Vn{constructor(e,t){super("gap-controller",e.logger),this.hls=void 0,this.fragmentTracker=void 0,this.media=null,this.mediaSource=void 0,this.nudgeRetry=0,this.stallReported=!1,this.stalled=null,this.moved=!1,this.seeking=!1,this.buffered={},this.lastCurrentTime=0,this.ended=0,this.waiting=0,this.onMediaPlaying=()=>{this.ended=0,this.waiting=0},this.onMediaWaiting=()=>{var s;(s=this.media)!=null&&s.seeking||(this.waiting=self.performance.now(),this.tick())},this.onMediaEnded=()=>{if(this.hls){var s;this.ended=((s=this.media)==null?void 0:s.currentTime)||1,this.hls.trigger(m.MEDIA_ENDED,{stalled:!1})}},this.hls=e,this.fragmentTracker=t,this.registerListeners()}registerListeners(){const{hls:e}=this;e&&(e.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.BUFFER_APPENDED,this.onBufferAppended,this))}unregisterListeners(){const{hls:e}=this;e&&(e.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.BUFFER_APPENDED,this.onBufferAppended,this))}destroy(){super.destroy(),this.unregisterListeners(),this.media=this.hls=this.fragmentTracker=null,this.mediaSource=void 0}onMediaAttached(e,t){this.setInterval(zd),this.mediaSource=t.mediaSource;const s=this.media=t.media;xe(s,"playing",this.onMediaPlaying),xe(s,"waiting",this.onMediaWaiting),xe(s,"ended",this.onMediaEnded)}onMediaDetaching(e,t){this.clearInterval();const{media:s}=this;s&&(Ie(s,"playing",this.onMediaPlaying),Ie(s,"waiting",this.onMediaWaiting),Ie(s,"ended",this.onMediaEnded),this.media=null),this.mediaSource=void 0}onBufferAppended(e,t){this.buffered=t.timeRanges}get hasBuffered(){return Object.keys(this.buffered).length>0}tick(){var e;if(!((e=this.media)!=null&&e.readyState)||!this.hasBuffered)return;const t=this.media.currentTime;this.poll(t,this.lastCurrentTime),this.lastCurrentTime=t}poll(e,t){var s,i;const r=(s=this.hls)==null?void 0:s.config;if(!r)return;const n=this.media;if(!n)return;const{seeking:o}=n,c=this.seeking&&!o,l=!this.seeking&&o,h=n.paused&&!o||n.ended||n.playbackRate===0;if(this.seeking=o,e!==t){t&&(this.ended=0),this.moved=!0,o||(this.nudgeRetry=0,r.nudgeOnVideoHole&&!h&&e>t&&this.nudgeOnVideoHole(e,t)),this.waiting===0&&this.stallResolved(e);return}if(l||c){c&&this.stallResolved(e);return}if(h){this.nudgeRetry=0,this.stallResolved(e),!this.ended&&n.ended&&this.hls&&(this.ended=e||1,this.hls.trigger(m.MEDIA_ENDED,{stalled:!1}));return}if(!X.getBuffered(n).length){this.nudgeRetry=0;return}const d=X.bufferInfo(n,e,0),u=d.nextStart||0,f=this.fragmentTracker;if(o&&f&&this.hls){const D=mn(this.hls.inFlightFragments,e),A=d.len>ys,_=!u||D||u-e>ys&&!f.getPartialFragment(e);if(A||_)return;this.moved=!1}const g=(i=this.hls)==null?void 0:i.latestLevelDetails;if(!this.moved&&this.stalled!==null&&f){if(!(d.len>0)&&!u)return;const A=Math.max(u,d.start||0)-e,b=!!(g!=null&&g.live)?g.targetduration*2:ys,I=ls(e,f);if(A>0&&(A<=b||I)){n.paused||this._trySkipBufferHole(I);return}}const y=r.detectStallWithCurrentTimeMs,p=self.performance.now(),E=this.waiting;let T=this.stalled;if(T===null)if(E>0&&p-E=y||E)&&this.hls){var v;if(((v=this.mediaSource)==null?void 0:v.readyState)==="ended"&&!(g!=null&&g.live)&&Math.abs(e-((g==null?void 0:g.edge)||0))<1){if(this.ended)return;this.ended=e||1,this.hls.trigger(m.MEDIA_ENDED,{stalled:!0});return}if(this._reportStall(d),!this.media||!this.hls)return}const x=X.bufferInfo(n,e,r.maxBufferHole);this._tryFixBufferStall(x,S,e)}stallResolved(e){const t=this.stalled;if(t&&this.hls&&(this.stalled=null,this.stallReported)){const s=self.performance.now()-t;this.log(`playback not stuck anymore @${e}, after ${Math.round(s)}ms`),this.stallReported=!1,this.waiting=0,this.hls.trigger(m.STALL_RESOLVED,{})}}nudgeOnVideoHole(e,t){var s;const i=this.buffered.video;if(this.hls&&this.media&&this.fragmentTracker&&(s=this.buffered.audio)!=null&&s.length&&i&&i.length>1&&e>i.end(0)){const r=X.bufferedInfo(X.timeRangesToArray(this.buffered.audio),e,0);if(r.len>1&&t>=r.start){const n=X.timeRangesToArray(i),o=X.bufferedInfo(n,t,0).bufferedIndex;if(o>-1&&oo)&&h-l<1&&e-l<2){const d=new Error(`nudging playhead to flush pipeline after video hole. currentTime: ${e} hole: ${l} -> ${h} buffered index: ${c}`);this.warn(d.message),this.media.currentTime+=1e-6;let u=ls(e,this.fragmentTracker);u&&"fragment"in u?u=u.fragment:u||(u=void 0);const f=X.bufferInfo(this.media,e,0);this.hls.trigger(m.ERROR,{type:Y.MEDIA_ERROR,details:R.BUFFER_SEEK_OVER_HOLE,fatal:!1,error:d,reason:d.message,frag:u,buffer:f.len,bufferInfo:f})}}}}}_tryFixBufferStall(e,t,s){var i,r;const{fragmentTracker:n,media:o}=this,c=(i=this.hls)==null?void 0:i.config;if(!o||!n||!c)return;const l=(r=this.hls)==null?void 0:r.latestLevelDetails,h=ls(s,n);if((h||l!=null&&l.live&&s1&&e.len>c.maxBufferHole||e.nextStart&&(e.nextStart-sc.highBufferWatchdogPeriod*1e3||this.waiting)&&(this.warn("Trying to nudge playhead over buffer-hole"),this._tryNudgeBuffer(e))}adjacentTraversal(e,t){const s=this.fragmentTracker,i=e.nextStart;if(s&&i){const r=s.getFragAtPos(t,U.MAIN),n=s.getFragAtPos(i,U.MAIN);if(r&&n)return n.sn-r.sn<2}return!1}_reportStall(e){const{hls:t,media:s,stallReported:i,stalled:r}=this;if(!i&&r!==null&&s&&t){this.stallReported=!0;const n=new Error(`Playback stalling at @${s.currentTime} due to low buffer (${oe(e)})`);this.warn(n.message),t.trigger(m.ERROR,{type:Y.MEDIA_ERROR,details:R.BUFFER_STALLED_ERROR,fatal:!1,error:n,buffer:e.len,bufferInfo:e,stalled:{start:r}})}}_trySkipBufferHole(e){var t;const{fragmentTracker:s,media:i}=this,r=(t=this.hls)==null?void 0:t.config;if(!i||!s||!r)return 0;const n=i.currentTime,o=X.bufferInfo(i,n,0),c=n0&&o.len<1&&i.readyState<3,u=c-n;if(u>0&&(h||d)){if(u>r.maxBufferHole){let g=!1;if(n===0){const y=s.getAppendedFrag(0,U.MAIN);y&&c"u"))return self.VTTCue||self.TextTrackCue}function ti(a,e,t,s,i){let r=new a(e,t,"");try{r.value=s,i&&(r.type=i)}catch{r=new a(e,t,oe(i?ie({type:i},s):s))}return r}const cs=(()=>{const a=xi();try{a&&new a(0,Number.POSITIVE_INFINITY,"")}catch{return Number.MAX_VALUE}return Number.POSITIVE_INFINITY})();class Jd{constructor(e){this.hls=void 0,this.id3Track=null,this.media=null,this.dateRangeCuesAppended={},this.removeCues=!0,this.assetCue=void 0,this.onEventCueEnter=()=>{this.hls&&this.hls.trigger(m.EVENT_CUE_ENTER,{})},this.hls=e,this._registerListeners()}destroy(){this._unregisterListeners(),this.id3Track=null,this.media=null,this.dateRangeCuesAppended={},this.hls=this.onEventCueEnter=null}_registerListeners(){const{hls:e}=this;e&&(e.on(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.FRAG_PARSING_METADATA,this.onFragParsingMetadata,this),e.on(m.BUFFER_FLUSHING,this.onBufferFlushing,this),e.on(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.on(m.LEVEL_PTS_UPDATED,this.onLevelPtsUpdated,this))}_unregisterListeners(){const{hls:e}=this;e&&(e.off(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.FRAG_PARSING_METADATA,this.onFragParsingMetadata,this),e.off(m.BUFFER_FLUSHING,this.onBufferFlushing,this),e.off(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.off(m.LEVEL_PTS_UPDATED,this.onLevelPtsUpdated,this))}onMediaAttaching(e,t){var s;this.media=t.media,((s=t.overrides)==null?void 0:s.cueRemoval)===!1&&(this.removeCues=!1)}onMediaAttached(){var e;const t=(e=this.hls)==null?void 0:e.latestLevelDetails;t&&this.updateDateRangeCues(t)}onMediaDetaching(e,t){this.media=null,!t.transferMedia&&(this.id3Track&&(this.removeCues&&Lt(this.id3Track,this.onEventCueEnter),this.id3Track=null),this.dateRangeCuesAppended={})}onManifestLoading(){this.dateRangeCuesAppended={}}createTrack(e){const t=this.getID3Track(e.textTracks);return t.mode="hidden",t}getID3Track(e){if(this.media){for(let t=0;tcs&&(d=cs),d-h<=0&&(d=h+Zd);for(let f=0;fh.type===_e.audioId3&&c:i==="video"?l=h=>h.type===_e.emsg&&o:l=h=>h.type===_e.audioId3&&c||h.type===_e.emsg&&o,Ti(r,t,s,l)}}onLevelUpdated(e,{details:t}){this.updateDateRangeCues(t,!0)}onLevelPtsUpdated(e,t){Math.abs(t.drift)>.01&&this.updateDateRangeCues(t.details)}updateDateRangeCues(e,t){if(!this.hls||!this.media)return;const{assetPlayerId:s,timelineOffset:i,enableDateRangeMetadataCues:r,interstitialsController:n}=this.hls.config;if(!r)return;const o=xi();if(s&&i&&!n){const{fragmentStart:y,fragmentEnd:p}=e;let E=this.assetCue;E?(E.startTime=y,E.endTime=p):o&&(E=this.assetCue=ti(o,y,p,{assetPlayerId:this.hls.config.assetPlayerId},"hlsjs.interstitial.asset"),E&&(E.id=s,this.id3Track||(this.id3Track=this.createTrack(this.media)),this.id3Track.addCue(E),E.addEventListener("enter",this.onEventCueEnter)))}if(!e.hasProgramDateTime)return;const{id3Track:c}=this,{dateRanges:l}=e,h=Object.keys(l);let d=this.dateRangeCuesAppended;if(c&&t){var u;if((u=c.cues)!=null&&u.length){const y=Object.keys(d).filter(p=>!h.includes(p));for(let p=y.length;p--;){var f;const E=y[p],T=(f=d[E])==null?void 0:f.cues;delete d[E],T&&Object.keys(T).forEach(S=>{const v=T[S];if(v){v.removeEventListener("enter",this.onEventCueEnter);try{c.removeCue(v)}catch{}}})}}else d=this.dateRangeCuesAppended={}}const g=e.fragments[e.fragments.length-1];if(!(h.length===0||!B(g==null?void 0:g.programDateTime))){this.id3Track||(this.id3Track=this.createTrack(this.media));for(let y=0;y{if(M!==E.id){const G=l[M];if(G.class===E.class&&G.startDate>E.startDate&&(!P||E.startDate.01&&(M.startTime=T,M.endTime=D);else if(o){let G=E.attr[P];vl(P)&&(G=An(G));const K=ti(o,T,D,{key:P,data:G},_e.dateRange);K&&(K.id=p,this.id3Track.addCue(K),v[P]=K,n&&(P==="X-ASSET-LIST"||P==="X-ASSET-URL")&&K.addEventListener("enter",this.onEventCueEnter))}}d[p]={cues:v,dateRange:E,durationKnown:x}}}}}class eu{constructor(e){this.hls=void 0,this.config=void 0,this.media=null,this.currentTime=0,this.stallCount=0,this._latency=null,this._targetLatencyUpdated=!1,this.onTimeupdate=()=>{const{media:t}=this,s=this.levelDetails;if(!t||!s)return;this.currentTime=t.currentTime;const i=this.computeLatency();if(i===null)return;this._latency=i;const{lowLatencyMode:r,maxLiveSyncPlaybackRate:n}=this.config;if(!r||n===1||!s.live)return;const o=this.targetLatency;if(o===null)return;const c=i-o,l=Math.min(this.maxLatency,o+s.targetduration);if(c.05&&this.forwardBufferLength>1){const d=Math.min(2,Math.max(1,n)),u=Math.round(2/(1+Math.exp(-.75*c-this.edgeStalled))*20)/20,f=Math.min(d,Math.max(1,u));this.changeMediaPlaybackRate(t,f)}else t.playbackRate!==1&&t.playbackRate!==0&&this.changeMediaPlaybackRate(t,1)},this.hls=e,this.config=e.config,this.registerListeners()}get levelDetails(){var e;return((e=this.hls)==null?void 0:e.latestLevelDetails)||null}get latency(){return this._latency||0}get maxLatency(){const{config:e}=this;if(e.liveMaxLatencyDuration!==void 0)return e.liveMaxLatencyDuration;const t=this.levelDetails;return t?e.liveMaxLatencyDurationCount*t.targetduration:0}get targetLatency(){const e=this.levelDetails;if(e===null||this.hls===null)return null;const{holdBack:t,partHoldBack:s,targetduration:i}=e,{liveSyncDuration:r,liveSyncDurationCount:n,lowLatencyMode:o}=this.config,c=this.hls.userConfig;let l=o&&s||t;(this._targetLatencyUpdated||c.liveSyncDuration||c.liveSyncDurationCount||l===0)&&(l=r!==void 0?r:n*i);const h=i;return l+Math.min(this.stallCount*this.config.liveSyncOnStallIncrease,h)}set targetLatency(e){this.stallCount=0,this.config.liveSyncDuration=e,this._targetLatencyUpdated=!0}get liveSyncPosition(){const e=this.estimateLiveEdge(),t=this.targetLatency;if(e===null||t===null)return null;const s=this.levelDetails;if(s===null)return null;const i=s.edge,r=e-t-this.edgeStalled,n=i-s.totalduration,o=i-(this.config.lowLatencyMode&&s.partTarget||s.targetduration);return Math.min(Math.max(n,r),o)}get drift(){const e=this.levelDetails;return e===null?1:e.drift}get edgeStalled(){const e=this.levelDetails;if(e===null)return 0;const t=(this.config.lowLatencyMode&&e.partTarget||e.targetduration)*3;return Math.max(e.age-t,0)}get forwardBufferLength(){const{media:e}=this,t=this.levelDetails;if(!e||!t)return 0;const s=e.buffered.length;return(s?e.buffered.end(s-1):t.edge)-this.currentTime}destroy(){this.unregisterListeners(),this.onMediaDetaching(),this.hls=null}registerListeners(){const{hls:e}=this;e&&(e.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.on(m.ERROR,this.onError,this))}unregisterListeners(){const{hls:e}=this;e&&(e.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.off(m.ERROR,this.onError,this))}onMediaAttached(e,t){this.media=t.media,this.media.addEventListener("timeupdate",this.onTimeupdate)}onMediaDetaching(){this.media&&(this.media.removeEventListener("timeupdate",this.onTimeupdate),this.media=null)}onManifestLoading(){this._latency=null,this.stallCount=0}onLevelUpdated(e,{details:t}){t.advanced&&this.onTimeupdate(),!t.live&&this.media&&this.media.removeEventListener("timeupdate",this.onTimeupdate)}onError(e,t){var s;t.details===R.BUFFER_STALLED_ERROR&&(this.stallCount++,this.hls&&(s=this.levelDetails)!=null&&s.live&&this.hls.logger.warn("[latency-controller]: Stall detected, adjusting target latency"))}changeMediaPlaybackRate(e,t){var s,i;e.playbackRate!==t&&((s=this.hls)==null||s.logger.debug(`[latency-controller]: latency=${this.latency.toFixed(3)}, targetLatency=${(i=this.targetLatency)==null?void 0:i.toFixed(3)}, forwardBufferLength=${this.forwardBufferLength.toFixed(3)}: adjusting playback rate from ${e.playbackRate} to ${t}`),e.playbackRate=t)}estimateLiveEdge(){const e=this.levelDetails;return e===null?null:e.edge+e.age}computeLatency(){const e=this.estimateLiveEdge();return e===null?null:e-this.currentTime}}class tu extends Vi{constructor(e,t){super(e,"level-controller"),this._levels=[],this._firstLevel=-1,this._maxAutoLevel=-1,this._startLevel=void 0,this.currentLevel=null,this.currentLevelIndex=-1,this.manualLevelIndex=-1,this.steering=void 0,this.onParsedComplete=void 0,this.steering=t,this._registerListeners()}_registerListeners(){const{hls:e}=this;e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.on(m.LEVEL_LOADED,this.onLevelLoaded,this),e.on(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.on(m.FRAG_BUFFERED,this.onFragBuffered,this),e.on(m.ERROR,this.onError,this)}_unregisterListeners(){const{hls:e}=this;e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.off(m.LEVEL_LOADED,this.onLevelLoaded,this),e.off(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.off(m.FRAG_BUFFERED,this.onFragBuffered,this),e.off(m.ERROR,this.onError,this)}destroy(){this._unregisterListeners(),this.steering=null,this.resetLevels(),super.destroy()}stopLoad(){this._levels.forEach(t=>{t.loadError=0,t.fragmentError=0}),super.stopLoad()}resetLevels(){this._startLevel=void 0,this.manualLevelIndex=-1,this.currentLevelIndex=-1,this.currentLevel=null,this._levels=[],this._maxAutoLevel=-1}onManifestLoading(e,t){this.resetLevels()}onManifestLoaded(e,t){const s=this.hls.config.preferManagedMediaSource,i=[],r={},n={};let o=!1,c=!1,l=!1;t.levels.forEach(h=>{const d=h.attrs;let{audioCodec:u,videoCodec:f}=h;u&&(h.audioCodec=u=Ts(u,s)||void 0),f&&(f=h.videoCodec=No(f));const{width:g,height:y,unknownCodecs:p}=h,E=(p==null?void 0:p.length)||0;if(o||(o=!!(g&&y)),c||(c=!!f),l||(l=!!u),E||u&&!this.isAudioSupported(u)||f&&!this.isVideoSupported(f)){this.log(`Some or all CODECS not supported "${d.CODECS}"`);return}const{CODECS:T,"FRAME-RATE":S,"HDCP-LEVEL":v,"PATHWAY-ID":x,RESOLUTION:D,"VIDEO-RANGE":A}=d,b=`${`${x||"."}-`}${h.bitrate}-${D}-${S}-${T}-${A}-${v}`;if(r[b])if(r[b].uri!==h.url&&!h.attrs["PATHWAY-ID"]){const I=n[b]+=1;h.attrs["PATHWAY-ID"]=new Array(I+1).join(".");const P=this.createLevel(h);r[b]=P,i.push(P)}else r[b].addGroupId("audio",d.AUDIO),r[b].addGroupId("text",d.SUBTITLES);else{const I=this.createLevel(h);r[b]=I,n[b]=1,i.push(I)}}),this.filterAndSortMediaOptions(i,t,o,c,l)}createLevel(e){const t=new Kt(e),s=e.supplemental;if(s!=null&&s.videoCodec&&!this.isVideoSupported(s.videoCodec)){const i=new Error(`SUPPLEMENTAL-CODECS not supported "${s.videoCodec}"`);this.log(i.message),t.supportedResult=Fn(i,[])}return t}isAudioSupported(e){return Ut(e,"audio",this.hls.config.preferManagedMediaSource)}isVideoSupported(e){return Ut(e,"video",this.hls.config.preferManagedMediaSource)}filterAndSortMediaOptions(e,t,s,i,r){var n;let o=[],c=[],l=e;const h=((n=t.stats)==null?void 0:n.parsing)||{};if((s||i)&&r&&(l=l.filter(({videoCodec:T,videoRange:S,width:v,height:x})=>(!!T||!!(v&&x))&&qo(S))),l.length===0){Promise.resolve().then(()=>{if(this.hls){let T="no level with compatible codecs found in manifest",S=T;t.levels.length&&(S=`one or more CODECS in variant not supported: ${oe(t.levels.map(x=>x.attrs.CODECS).filter((x,D,A)=>A.indexOf(x)===D))}`,this.warn(S),T+=` (${S})`);const v=new Error(T);this.hls.trigger(m.ERROR,{type:Y.MEDIA_ERROR,details:R.MANIFEST_INCOMPATIBLE_CODECS_ERROR,fatal:!0,url:t.url,error:v,reason:S})}}),h.end=performance.now();return}t.audioTracks&&(o=t.audioTracks.filter(T=>!T.audioCodec||this.isAudioSupported(T.audioCodec)),yn(o)),t.subtitles&&(c=t.subtitles,yn(c));const d=l.slice(0);l.sort((T,S)=>{if(T.attrs["HDCP-LEVEL"]!==S.attrs["HDCP-LEVEL"])return(T.attrs["HDCP-LEVEL"]||"")>(S.attrs["HDCP-LEVEL"]||"")?1:-1;if(s&&T.height!==S.height)return T.height-S.height;if(T.frameRate!==S.frameRate)return T.frameRate-S.frameRate;if(T.videoRange!==S.videoRange)return Ss.indexOf(T.videoRange)-Ss.indexOf(S.videoRange);if(T.videoCodec!==S.videoCodec){const v=or(T.videoCodec),x=or(S.videoCodec);if(v!==x)return x-v}if(T.uri===S.uri&&T.codecSet!==S.codecSet){const v=Es(T.codecSet),x=Es(S.codecSet);if(v!==x)return x-v}return T.averageBitrate!==S.averageBitrate?T.averageBitrate-S.averageBitrate:0});let u=d[0];if(this.steering&&(l=this.steering.filterParsedLevels(l),l.length!==d.length)){for(let T=0;Tv&&v===this.hls.abrEwmaDefaultEstimate&&(this.hls.bandwidthEstimate=x)}break}const g=r&&!i,y=this.hls.config,p=!!(y.audioStreamController&&y.audioTrackController),E={levels:l,audioTracks:o,subtitleTracks:c,sessionData:t.sessionData,sessionKeys:t.sessionKeys,firstLevel:this._firstLevel,stats:t.stats,audio:r,video:i,altAudio:p&&!g&&o.some(T=>!!T.url)};h.end=performance.now(),this.hls.trigger(m.MANIFEST_PARSED,E)}get levels(){return this._levels.length===0?null:this._levels}get loadLevelObj(){return this.currentLevel}get level(){return this.currentLevelIndex}set level(e){const t=this._levels;if(t.length===0)return;if(e<0||e>=t.length){const h=new Error("invalid level idx"),d=e<0;if(this.hls.trigger(m.ERROR,{type:Y.OTHER_ERROR,details:R.LEVEL_SWITCH_ERROR,level:e,fatal:d,error:h,reason:h.message}),d)return;e=Math.min(e,t.length-1)}const s=this.currentLevelIndex,i=this.currentLevel,r=i?i.attrs["PATHWAY-ID"]:void 0,n=t[e],o=n.attrs["PATHWAY-ID"];if(this.currentLevelIndex=e,this.currentLevel=n,s===e&&i&&r===o)return;this.log(`Switching to level ${e} (${n.height?n.height+"p ":""}${n.videoRange?n.videoRange+" ":""}${n.codecSet?n.codecSet+" ":""}@${n.bitrate})${o?" with Pathway "+o:""} from level ${s}${r?" with Pathway "+r:""}`);const c={level:e,attrs:n.attrs,details:n.details,bitrate:n.bitrate,averageBitrate:n.averageBitrate,maxBitrate:n.maxBitrate,realBitrate:n.realBitrate,width:n.width,height:n.height,codecSet:n.codecSet,audioCodec:n.audioCodec,videoCodec:n.videoCodec,audioGroups:n.audioGroups,subtitleGroups:n.subtitleGroups,loaded:n.loaded,loadError:n.loadError,fragmentError:n.fragmentError,name:n.name,id:n.id,uri:n.uri,url:n.url,urlId:0,audioGroupIds:n.audioGroupIds,textGroupIds:n.textGroupIds};this.hls.trigger(m.LEVEL_SWITCHING,c);const l=n.details;if(!l||l.live){const h=this.switchParams(n.uri,i==null?void 0:i.details,l);this.loadPlaylist(h)}}get manualLevel(){return this.manualLevelIndex}set manualLevel(e){this.manualLevelIndex=e,this._startLevel===void 0&&(this._startLevel=e),e!==-1&&(this.level=e)}get firstLevel(){return this._firstLevel}set firstLevel(e){this._firstLevel=e}get startLevel(){if(this._startLevel===void 0){const e=this.hls.config.startLevel;return e!==void 0?e:this.hls.firstAutoLevel}return this._startLevel}set startLevel(e){this._startLevel=e}get pathways(){return this.steering?this.steering.pathways():[]}get pathwayPriority(){return this.steering?this.steering.pathwayPriority:null}set pathwayPriority(e){if(this.steering){const t=this.steering.pathways(),s=e.filter(i=>t.indexOf(i)!==-1);if(e.length<1){this.warn(`pathwayPriority ${e} should contain at least one pathway from list: ${t}`);return}this.steering.pathwayPriority=s}}onError(e,t){t.fatal||!t.context||t.context.type===J.LEVEL&&t.context.level===this.level&&this.checkRetry(t)}onFragBuffered(e,{frag:t}){if(t!==void 0&&t.type===U.MAIN){const s=t.elementaryStreams;if(!Object.keys(s).some(r=>!!s[r]))return;const i=this._levels[t.level];i!=null&&i.loadError&&(this.log(`Resetting level error count of ${i.loadError} on frag buffered`),i.loadError=0)}}onLevelLoaded(e,t){var s;const{level:i,details:r}=t,n=t.levelInfo;if(!n){var o;this.warn(`Invalid level index ${i}`),(o=t.deliveryDirectives)!=null&&o.skip&&(r.deltaUpdateFailed=!0);return}if(n===this.currentLevel||t.withoutMultiVariant){n.fragmentError===0&&(n.loadError=0);let c=n.details;c===t.details&&c.advanced&&(c=void 0),this.playlistLoaded(i,t,c)}else(s=t.deliveryDirectives)!=null&&s.skip&&(r.deltaUpdateFailed=!0)}loadPlaylist(e){super.loadPlaylist(),this.shouldLoadPlaylist(this.currentLevel)&&this.scheduleLoading(this.currentLevel,e)}loadingPlaylist(e,t){super.loadingPlaylist(e,t);const s=this.getUrlWithDirectives(e.uri,t),i=this.currentLevelIndex,r=e.attrs["PATHWAY-ID"],n=e.details,o=n==null?void 0:n.age;this.log(`Loading level index ${i}${(t==null?void 0:t.msn)!==void 0?" at sn "+t.msn+" part "+t.part:""}${r?" Pathway "+r:""}${o&&n.live?" age "+o.toFixed(1)+(n.type&&" "+n.type||""):""} ${s}`),this.hls.trigger(m.LEVEL_LOADING,{url:s,level:i,levelInfo:e,pathwayId:e.attrs["PATHWAY-ID"],id:0,deliveryDirectives:t||null})}get nextLoadLevel(){return this.manualLevelIndex!==-1?this.manualLevelIndex:this.hls.nextAutoLevel}set nextLoadLevel(e){this.level=e,this.manualLevelIndex===-1&&(this.hls.nextAutoLevel=e)}removeLevel(e){var t;if(this._levels.length===1)return;const s=this._levels.filter((r,n)=>n!==e?!0:(this.steering&&this.steering.removeLevel(r),r===this.currentLevel&&(this.currentLevel=null,this.currentLevelIndex=-1,r.details&&r.details.fragments.forEach(o=>o.level=-1)),!1));sa(s),this._levels=s,this.currentLevelIndex>-1&&(t=this.currentLevel)!=null&&t.details&&(this.currentLevelIndex=this.currentLevel.details.fragments[0].level),this.manualLevelIndex>-1&&(this.manualLevelIndex=this.currentLevelIndex);const i=s.length-1;this._firstLevel=Math.min(this._firstLevel,i),this._startLevel&&(this._startLevel=Math.min(this._startLevel,i)),this.hls.trigger(m.LEVELS_UPDATED,{levels:s})}onLevelsUpdated(e,{levels:t}){this._levels=t}checkMaxAutoUpdated(){const{autoLevelCapping:e,maxAutoLevel:t,maxHdcpLevel:s}=this.hls;this._maxAutoLevel!==t&&(this._maxAutoLevel=t,this.hls.trigger(m.MAX_AUTO_LEVEL_UPDATED,{autoLevelCapping:e,levels:this.levels,maxAutoLevel:t,minAutoLevel:this.hls.minAutoLevel,maxHdcpLevel:s}))}}function yn(a){const e={};a.forEach(t=>{const s=t.groupId||"";t.id=e[s]=e[s]||0,e[s]++})}function Qa(){return self.SourceBuffer||self.WebKitSourceBuffer}function Za(){if(!at())return!1;const e=Qa();return!e||e.prototype&&typeof e.prototype.appendBuffer=="function"&&typeof e.prototype.remove=="function"}function su(){if(!Za())return!1;const a=at();return typeof(a==null?void 0:a.isTypeSupported)=="function"&&(["avc1.42E01E,mp4a.40.2","av01.0.01M.08","vp09.00.50.08"].some(e=>a.isTypeSupported(Gt(e,"video")))||["mp4a.40.2","fLaC"].some(e=>a.isTypeSupported(Gt(e,"audio"))))}function iu(){var a;const e=Qa();return typeof(e==null||(a=e.prototype)==null?void 0:a.changeType)=="function"}const ru=100;class nu extends Fi{constructor(e,t,s){super(e,t,s,"stream-controller",U.MAIN),this.audioCodecSwap=!1,this.level=-1,this._forceStartLoad=!1,this._hasEnoughToStart=!1,this.altAudio=0,this.audioOnly=!1,this.fragPlaying=null,this.fragLastKbps=0,this.couldBacktrack=!1,this.backtrackFragment=null,this.audioCodecSwitch=!1,this.videoBuffer=null,this.onMediaPlaying=()=>{this.tick()},this.onMediaSeeked=()=>{const i=this.media,r=i?i.currentTime:null;if(r===null||!B(r)||(this.log(`Media seeked to ${r.toFixed(3)}`),!this.getBufferedFrag(r)))return;const n=this.getFwdBufferInfoAtPos(i,r,U.MAIN,0);if(n===null||n.len===0){this.warn(`Main forward buffer length at ${r} on "seeked" event ${n?n.len:"empty"})`);return}this.tick()},this.registerListeners()}registerListeners(){super.registerListeners();const{hls:e}=this;e.on(m.MANIFEST_PARSED,this.onManifestParsed,this),e.on(m.LEVEL_LOADING,this.onLevelLoading,this),e.on(m.LEVEL_LOADED,this.onLevelLoaded,this),e.on(m.FRAG_LOAD_EMERGENCY_ABORTED,this.onFragLoadEmergencyAborted,this),e.on(m.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),e.on(m.AUDIO_TRACK_SWITCHED,this.onAudioTrackSwitched,this),e.on(m.BUFFER_CREATED,this.onBufferCreated,this),e.on(m.BUFFER_FLUSHED,this.onBufferFlushed,this),e.on(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.on(m.FRAG_BUFFERED,this.onFragBuffered,this)}unregisterListeners(){super.unregisterListeners();const{hls:e}=this;e.off(m.MANIFEST_PARSED,this.onManifestParsed,this),e.off(m.LEVEL_LOADED,this.onLevelLoaded,this),e.off(m.FRAG_LOAD_EMERGENCY_ABORTED,this.onFragLoadEmergencyAborted,this),e.off(m.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),e.off(m.AUDIO_TRACK_SWITCHED,this.onAudioTrackSwitched,this),e.off(m.BUFFER_CREATED,this.onBufferCreated,this),e.off(m.BUFFER_FLUSHED,this.onBufferFlushed,this),e.off(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.off(m.FRAG_BUFFERED,this.onFragBuffered,this)}onHandlerDestroying(){this.onMediaPlaying=this.onMediaSeeked=null,this.unregisterListeners(),super.onHandlerDestroying()}startLoad(e,t){if(this.levels){const{lastCurrentTime:s,hls:i}=this;if(this.stopLoad(),this.setInterval(ru),this.level=-1,!this.startFragRequested){let r=i.startLevel;r===-1&&(i.config.testBandwidth&&this.levels.length>1?(r=0,this.bitrateTest=!0):r=i.firstAutoLevel),i.nextLoadLevel=r,this.level=i.loadLevel,this._hasEnoughToStart=!!t}s>0&&e===-1&&!t&&(this.log(`Override startPosition with lastCurrentTime @${s.toFixed(3)}`),e=s),this.state=C.IDLE,this.nextLoadPosition=this.lastCurrentTime=e+this.timelineOffset,this.startPosition=t?-1:e,this.tick()}else this._forceStartLoad=!0,this.state=C.STOPPED}stopLoad(){this._forceStartLoad=!1,super.stopLoad()}doTick(){switch(this.state){case C.WAITING_LEVEL:{const{levels:e,level:t}=this,s=e==null?void 0:e[t],i=s==null?void 0:s.details;if(i&&(!i.live||this.levelLastLoaded===s&&!this.waitForLive(s))){if(this.waitForCdnTuneIn(i))break;this.state=C.IDLE;break}else if(this.hls.nextLoadLevel!==this.level){this.state=C.IDLE;break}break}case C.FRAG_LOADING_WAITING_RETRY:this.checkRetryDate();break}this.state===C.IDLE&&this.doTickIdle(),this.onTickEnd()}onTickEnd(){var e;super.onTickEnd(),(e=this.media)!=null&&e.readyState&&this.media.seeking===!1&&(this.lastCurrentTime=this.media.currentTime),this.checkFragmentChanged()}doTickIdle(){const{hls:e,levelLastLoaded:t,levels:s,media:i}=this;if(t===null||!i&&!this.primaryPrefetch&&(this.startFragRequested||!e.config.startFragPrefetch)||this.altAudio&&this.audioOnly)return;const r=this.buffering?e.nextLoadLevel:e.loadLevel;if(!(s!=null&&s[r]))return;const n=s[r],o=this.getMainFwdBufferInfo();if(o===null)return;const c=this.getLevelDetails();if(c&&this._streamEnded(o,c)){const y={};this.altAudio===2&&(y.type="video"),this.hls.trigger(m.BUFFER_EOS,y),this.state=C.ENDED;return}if(!this.buffering)return;e.loadLevel!==r&&e.manualLevel===-1&&this.log(`Adapting to level ${r} from level ${this.level}`),this.level=e.nextLoadLevel=r;const l=n.details;if(!l||this.state===C.WAITING_LEVEL||this.waitForLive(n)){this.level=r,this.state=C.WAITING_LEVEL,this.startFragRequested=!1;return}const h=o.len,d=this.getMaxBufferLength(n.maxBitrate);if(h>=d)return;this.backtrackFragment&&this.backtrackFragment.start>o.end&&(this.backtrackFragment=null);const u=this.backtrackFragment?this.backtrackFragment.start:o.end;let f=this.getNextFragment(u,l);if(this.couldBacktrack&&!this.fragPrevious&&f&&de(f)&&this.fragmentTracker.getState(f)!==fe.OK){var g;const p=((g=this.backtrackFragment)!=null?g:f).sn-l.startSN,E=l.fragments[p-1];E&&f.cc===E.cc&&(f=E,this.fragmentTracker.removeFragment(E))}else this.backtrackFragment&&o.len&&(this.backtrackFragment=null);if(f&&this.isLoopLoading(f,u)){if(!f.gap){const p=this.audioOnly&&!this.altAudio?ae.AUDIO:ae.VIDEO,E=(p===ae.VIDEO?this.videoBuffer:this.mediaBuffer)||this.media;E&&this.afterBufferFlushed(E,p,U.MAIN)}f=this.getNextFragmentLoopLoading(f,l,o,U.MAIN,d)}f&&(this.exceedsMaxBuffer(o,d,f)||(f.initSegment&&!f.initSegment.data&&!this.bitrateTest&&(f=f.initSegment),this.loadFragment(f,n,u)))}loadFragment(e,t,s){const i=this.fragmentTracker.getState(e);i===fe.NOT_LOADED||i===fe.PARTIAL?de(e)?this.bitrateTest?(this.log(`Fragment ${e.sn} of level ${e.level} is being downloaded to test bitrate and will not be buffered`),this._loadBitrateTestFrag(e,t)):super.loadFragment(e,t,s):this._loadInitSegment(e,t):this.clearTrackerIfNeeded(e)}getBufferedFrag(e){return this.fragmentTracker.getBufferedFrag(e,U.MAIN)}followingBufferedFrag(e){return e?this.getBufferedFrag(e.end+.5):null}immediateLevelSwitch(){if(this.abortCurrentFrag(),this.flushMainBuffer(0,Number.POSITIVE_INFINITY),this.altAudio!==0){var e;(((e=this.getLevelDetails())==null?void 0:e.fragmentStart)||0)>this.lastCurrentTime&&super.flushMainBuffer(0,Number.POSITIVE_INFINITY,"audio")}}nextLevelSwitch(){const{levels:e,media:t}=this;if(t!=null&&t.readyState){let s;const i=this.getAppendedFrag(t.currentTime);i&&i.start>1&&this.flushMainBuffer(0,i.start-1);const r=this.getLevelDetails();if(r!=null&&r.live){const o=this.getMainFwdBufferInfo();if(!o||o.len=n-t.maxFragLookUpTolerance&&r<=o;if(i!==null&&s.duration>i&&(r{this.hls&&this.hls.trigger(m.AUDIO_TRACK_SWITCHED,t)}),s.trigger(m.BUFFER_FLUSHING,{startOffset:0,endOffset:Number.POSITIVE_INFINITY,type:null});return}s.trigger(m.AUDIO_TRACK_SWITCHED,t)}}onAudioTrackSwitched(e,t){const s=vs(t.url,this.hls);if(s){const i=this.videoBuffer;i&&this.mediaBuffer!==i&&(this.log("Switching on alternate audio, use video.buffered to schedule main fragment loading"),this.mediaBuffer=i)}this.altAudio=s?2:0,this.tick()}onBufferCreated(e,t){const s=t.tracks;let i,r,n=!1;for(const o in s){const c=s[o];if(c.id==="main"){if(r=o,i=c,o==="video"){const l=s[o];l&&(this.videoBuffer=l.buffer)}}else n=!0}n&&i?(this.log(`Alternate track found, use ${r}.buffered to schedule main fragment loading`),this.mediaBuffer=i.buffer):this.mediaBuffer=this.media}onFragBuffered(e,t){const{frag:s,part:i}=t,r=s.type===U.MAIN;if(r){if(this.fragContextChanged(s)){this.warn(`Fragment ${s.sn}${i?" p: "+i.index:""} of level ${s.level} finished buffering, but was aborted. state: ${this.state}`),this.state===C.PARSED&&(this.state=C.IDLE);return}const o=i?i.stats:s.stats;this.fragLastKbps=Math.round(8*o.total/(o.buffering.end-o.loading.first)),de(s)&&(this.fragPrevious=s),this.fragBufferedComplete(s,i)}const n=this.media;n&&(!this._hasEnoughToStart&&X.getBuffered(n).length&&(this._hasEnoughToStart=!0,this.seekToStartPos()),r&&this.tick())}get hasEnoughToStart(){return this._hasEnoughToStart}onError(e,t){var s;if(t.fatal){this.state=C.ERROR;return}switch(t.details){case R.FRAG_GAP:case R.FRAG_PARSING_ERROR:case R.FRAG_DECRYPT_ERROR:case R.FRAG_LOAD_ERROR:case R.FRAG_LOAD_TIMEOUT:case R.KEY_LOAD_ERROR:case R.KEY_LOAD_TIMEOUT:this.onFragmentOrKeyLoadError(U.MAIN,t);break;case R.LEVEL_LOAD_ERROR:case R.LEVEL_LOAD_TIMEOUT:case R.LEVEL_PARSING_ERROR:!t.levelRetry&&this.state===C.WAITING_LEVEL&&((s=t.context)==null?void 0:s.type)===J.LEVEL&&(this.state=C.IDLE);break;case R.BUFFER_ADD_CODEC_ERROR:case R.BUFFER_APPEND_ERROR:if(t.parent!=="main")return;this.reduceLengthAndFlushBuffer(t)&&this.resetLoadingState();break;case R.BUFFER_FULL_ERROR:if(t.parent!=="main")return;this.reduceLengthAndFlushBuffer(t)&&(!this.config.interstitialsController&&this.config.assetPlayerId?this._hasEnoughToStart=!0:this.flushMainBuffer(0,Number.POSITIVE_INFINITY));break;case R.INTERNAL_EXCEPTION:this.recoverWorkerError(t);break}}onFragLoadEmergencyAborted(){this.state=C.IDLE,this._hasEnoughToStart||(this.startFragRequested=!1,this.nextLoadPosition=this.lastCurrentTime),this.tickImmediate()}onBufferFlushed(e,{type:t}){if(t!==ae.AUDIO||!this.altAudio){const s=(t===ae.VIDEO?this.videoBuffer:this.mediaBuffer)||this.media;s&&(this.afterBufferFlushed(s,t,U.MAIN),this.tick())}}onLevelsUpdated(e,t){this.level>-1&&this.fragCurrent&&(this.level=this.fragCurrent.level,this.level===-1&&this.resetWhenMissingContext(this.fragCurrent)),this.levels=t.levels}swapAudioCodec(){this.audioCodecSwap=!this.audioCodecSwap}seekToStartPos(){const{media:e}=this;if(!e)return;const t=e.currentTime;let s=this.startPosition;if(s>=0&&t0&&(c{const{hls:i}=this,r=s==null?void 0:s.frag;if(!r||this.fragContextChanged(r))return;t.fragmentError=0,this.state=C.IDLE,this.startFragRequested=!1,this.bitrateTest=!1;const n=r.stats;n.parsing.start=n.parsing.end=n.buffering.start=n.buffering.end=self.performance.now(),i.trigger(m.FRAG_LOADED,s),r.bitrateTest=!1}).catch(s=>{this.state===C.STOPPED||this.state===C.ERROR||(this.warn(s),this.resetFragmentLoading(e))})}_handleTransmuxComplete(e){const t=this.playlistType,{hls:s}=this,{remuxResult:i,chunkMeta:r}=e,n=this.getCurrentContext(r);if(!n){this.resetWhenMissingContext(r);return}const{frag:o,part:c,level:l}=n,{video:h,text:d,id3:u,initSegment:f}=i,{details:g}=l,y=this.altAudio?void 0:i.audio;if(this.fragContextChanged(o)){this.fragmentTracker.removeFragment(o);return}if(this.state=C.PARSING,f){const p=f.tracks;if(p){const v=o.initSegment||o;if(this.unhandledEncryptionError(f,o))return;this._bufferInitSegment(l,p,v,r),s.trigger(m.FRAG_PARSING_INIT_SEGMENT,{frag:v,id:t,tracks:p})}const E=f.initPTS,T=f.timescale,S=this.initPTS[o.cc];if(B(E)&&(!S||S.baseTime!==E||S.timescale!==T)){const v=f.trackId;this.initPTS[o.cc]={baseTime:E,timescale:T,trackId:v},s.trigger(m.INIT_PTS_FOUND,{frag:o,id:t,initPTS:E,timescale:T,trackId:v})}}if(h&&g){y&&h.type==="audiovideo"&&this.logMuxedErr(o);const p=g.fragments[o.sn-1-g.startSN],E=o.sn===g.startSN,T=!p||o.cc>p.cc;if(i.independent!==!1){const{startPTS:S,endPTS:v,startDTS:x,endDTS:D}=h;if(c)c.elementaryStreams[h.type]={startPTS:S,endPTS:v,startDTS:x,endDTS:D};else if(h.firstKeyFrame&&h.independent&&r.id===1&&!T&&(this.couldBacktrack=!0),h.dropped&&h.independent){const A=this.getMainFwdBufferInfo(),_=(A?A.end:this.getLoadPosition())+this.config.maxBufferHole,b=h.firstKeyFramePTS?h.firstKeyFramePTS:S;if(!E&&_ys&&(o.gap=!0);o.setElementaryStreamInfo(h.type,S,v,x,D),this.backtrackFragment&&(this.backtrackFragment=o),this.bufferFragmentData(h,o,c,r,E||T)}else if(E||T)o.gap=!0;else{this.backtrack(o);return}}if(y){const{startPTS:p,endPTS:E,startDTS:T,endDTS:S}=y;c&&(c.elementaryStreams[ae.AUDIO]={startPTS:p,endPTS:E,startDTS:T,endDTS:S}),o.setElementaryStreamInfo(ae.AUDIO,p,E,T,S),this.bufferFragmentData(y,o,c,r)}if(g&&u!=null&&u.samples.length){const p={id:t,frag:o,details:g,samples:u.samples};s.trigger(m.FRAG_PARSING_METADATA,p)}if(g&&d){const p={id:t,frag:o,details:g,samples:d.samples};s.trigger(m.FRAG_PARSING_USERDATA,p)}}logMuxedErr(e){this.warn(`${de(e)?"Media":"Init"} segment with muxed audiovideo where only video expected: ${e.url}`)}_bufferInitSegment(e,t,s,i){if(this.state!==C.PARSING)return;this.audioOnly=!!t.audio&&!t.video,this.altAudio&&!this.audioOnly&&(delete t.audio,t.audiovideo&&this.logMuxedErr(s));const{audio:r,video:n,audiovideo:o}=t;if(r){const l=e.audioCodec;let h=hs(r.codec,l);h==="mp4a"&&(h="mp4a.40.5");const d=navigator.userAgent.toLowerCase();if(this.audioCodecSwitch){h&&(h.indexOf("mp4a.40.5")!==-1?h="mp4a.40.2":h="mp4a.40.5");const u=r.metadata;u&&"channelCount"in u&&(u.channelCount||1)!==1&&d.indexOf("firefox")===-1&&(h="mp4a.40.5")}h&&h.indexOf("mp4a.40.5")!==-1&&d.indexOf("android")!==-1&&r.container!=="audio/mpeg"&&(h="mp4a.40.2",this.log(`Android: force audio codec to ${h}`)),l&&l!==h&&this.log(`Swapping manifest audio codec "${l}" for "${h}"`),r.levelCodec=h,r.id=U.MAIN,this.log(`Init audio buffer, container:${r.container}, codecs[selected/level/parsed]=[${h||""}/${l||""}/${r.codec}]`),delete t.audiovideo}if(n){n.levelCodec=e.videoCodec,n.id=U.MAIN;const l=n.codec;if((l==null?void 0:l.length)===4)switch(l){case"hvc1":case"hev1":n.codec="hvc1.1.6.L120.90";break;case"av01":n.codec="av01.0.04M.08";break;case"avc1":n.codec="avc1.42e01e";break}this.log(`Init video buffer, container:${n.container}, codecs[level/parsed]=[${e.videoCodec||""}/${l}]${n.codec!==l?" parsed-corrected="+n.codec:""}${n.supplemental?" supplemental="+n.supplemental:""}`),delete t.audiovideo}o&&(this.log(`Init audiovideo buffer, container:${o.container}, codecs[level/parsed]=[${e.codecs}/${o.codec}]`),delete t.video,delete t.audio);const c=Object.keys(t);if(c.length){if(this.hls.trigger(m.BUFFER_CODECS,t),!this.hls)return;c.forEach(l=>{const d=t[l].initSegment;d!=null&&d.byteLength&&this.hls.trigger(m.BUFFER_APPENDING,{type:l,data:d,frag:s,part:null,chunkMeta:i,parent:s.type})})}this.tickImmediate()}getMainFwdBufferInfo(){const e=this.mediaBuffer&&this.altAudio===2?this.mediaBuffer:this.media;return this.getFwdBufferInfo(e,U.MAIN)}get maxBufferLength(){const{levels:e,level:t}=this,s=e==null?void 0:e[t];return s?this.getMaxBufferLength(s.maxBitrate):this.config.maxBufferLength}backtrack(e){this.couldBacktrack=!0,this.backtrackFragment=e,this.resetTransmuxer(),this.flushBufferGap(e),this.fragmentTracker.removeFragment(e),this.fragPrevious=null,this.nextLoadPosition=e.start,this.state=C.IDLE}checkFragmentChanged(){const e=this.media;let t=null;if(e&&e.readyState>1&&e.seeking===!1){const s=e.currentTime;if(X.isBuffered(e,s)?t=this.getAppendedFrag(s):X.isBuffered(e,s+.1)&&(t=this.getAppendedFrag(s+.1)),t){this.backtrackFragment=null;const i=this.fragPlaying,r=t.level;(!i||t.sn!==i.sn||i.level!==r)&&(this.fragPlaying=t,this.hls.trigger(m.FRAG_CHANGED,{frag:t}),(!i||i.level!==r)&&this.hls.trigger(m.LEVEL_SWITCHED,{level:r}))}}}get nextLevel(){const e=this.nextBufferedFrag;return e?e.level:-1}get currentFrag(){var e;if(this.fragPlaying)return this.fragPlaying;const t=((e=this.media)==null?void 0:e.currentTime)||this.lastCurrentTime;return B(t)?this.getAppendedFrag(t):null}get currentProgramDateTime(){var e;const t=((e=this.media)==null?void 0:e.currentTime)||this.lastCurrentTime;if(B(t)){const s=this.getLevelDetails(),i=this.currentFrag||(s?pt(null,s.fragments,t):null);if(i){const r=i.programDateTime;if(r!==null){const n=r+(t-i.start)*1e3;return new Date(n)}}}return null}get currentLevel(){const e=this.currentFrag;return e?e.level:-1}get nextBufferedFrag(){const e=this.currentFrag;return e?this.followingBufferedFrag(e):null}get forceStartLoad(){return this._forceStartLoad}}class au extends Oe{constructor(e,t){super("key-loader",t),this.config=void 0,this.keyIdToKeyInfo={},this.emeController=null,this.config=e}abort(e){for(const s in this.keyIdToKeyInfo){const i=this.keyIdToKeyInfo[s].loader;if(i){var t;if(e&&e!==((t=i.context)==null?void 0:t.frag.type))return;i.abort()}}}detach(){for(const e in this.keyIdToKeyInfo){const t=this.keyIdToKeyInfo[e];(t.mediaKeySessionContext||t.decryptdata.isCommonEncryption)&&delete this.keyIdToKeyInfo[e]}}destroy(){this.detach();for(const e in this.keyIdToKeyInfo){const t=this.keyIdToKeyInfo[e].loader;t&&t.destroy()}this.keyIdToKeyInfo={}}createKeyLoadError(e,t=R.KEY_LOAD_ERROR,s,i,r){return new Ze({type:Y.NETWORK_ERROR,details:t,fatal:!1,frag:e,response:r,error:s,networkDetails:i})}loadClear(e,t,s){if(this.emeController&&this.config.emeEnabled&&!this.emeController.getSelectedKeySystemFormats().length){if(t.length)for(let i=0,r=t.length;i{if(!this.emeController)return;n.setKeyFormat(o);const c=us(o);if(c)return this.emeController.getKeySystemAccess([c])})}if(this.config.requireKeySystemAccessOnStart){const i=Mt(this.config);if(i.length)return this.emeController.getKeySystemAccess(i)}}return null}load(e){return!e.decryptdata&&e.encrypted&&this.emeController&&this.config.emeEnabled?this.emeController.selectKeySystemFormat(e).then(t=>this.loadInternal(e,t)):this.loadInternal(e)}loadInternal(e,t){var s,i;t&&e.setKeyFormat(t);const r=e.decryptdata;if(!r){const l=new Error(t?`Expected frag.decryptdata to be defined after setting format ${t}`:`Missing decryption data on fragment in onKeyLoading (emeEnabled with controller: ${this.emeController&&this.config.emeEnabled})`);return Promise.reject(this.createKeyLoadError(e,R.KEY_LOAD_ERROR,l))}const n=r.uri;if(!n)return Promise.reject(this.createKeyLoadError(e,R.KEY_LOAD_ERROR,new Error(`Invalid key URI: "${n}"`)));const o=si(r);let c=this.keyIdToKeyInfo[o];if((s=c)!=null&&s.decryptdata.key)return r.key=c.decryptdata.key,Promise.resolve({frag:e,keyInfo:c});if(this.emeController&&(i=c)!=null&&i.keyLoadPromise)switch(this.emeController.getKeyStatus(c.decryptdata)){case"usable":case"usable-in-future":return c.keyLoadPromise.then(h=>{const{keyInfo:d}=h;return r.key=d.decryptdata.key,{frag:e,keyInfo:d}})}switch(this.log(`${this.keyIdToKeyInfo[o]?"Rel":"L"}oading${r.keyId?" keyId: "+ye(r.keyId):""} URI: ${r.uri} from ${e.type} ${e.level}`),c=this.keyIdToKeyInfo[o]={decryptdata:r,keyLoadPromise:null,loader:null,mediaKeySessionContext:null},r.method){case"SAMPLE-AES":case"SAMPLE-AES-CENC":case"SAMPLE-AES-CTR":return r.keyFormat==="identity"?this.loadKeyHTTP(c,e):this.loadKeyEME(c,e);case"AES-128":case"AES-256":case"AES-256-CTR":return this.loadKeyHTTP(c,e);default:return Promise.reject(this.createKeyLoadError(e,R.KEY_LOAD_ERROR,new Error(`Key supplied with unsupported METHOD: "${r.method}"`)))}}loadKeyEME(e,t){const s={frag:t,keyInfo:e};if(this.emeController&&this.config.emeEnabled){var i;if(!e.decryptdata.keyId&&(i=t.initSegment)!=null&&i.data){const n=Lo(t.initSegment.data);if(n.length){let o=n[0];o.some(c=>c!==0)?(this.log(`Using keyId found in init segment ${ye(o)}`),nt.setKeyIdForUri(e.decryptdata.uri,o)):(o=nt.addKeyIdForUri(e.decryptdata.uri),this.log(`Generating keyId to patch media ${ye(o)}`)),e.decryptdata.keyId=o}}if(!e.decryptdata.keyId&&!de(t))return Promise.resolve(s);const r=this.emeController.loadKey(s);return(e.keyLoadPromise=r.then(n=>(e.mediaKeySessionContext=n,s))).catch(n=>{throw e.keyLoadPromise=null,"data"in n&&(n.data.frag=t),n})}return Promise.resolve(s)}loadKeyHTTP(e,t){const s=this.config,i=s.loader,r=new i(s);return t.keyLoader=e.loader=r,e.keyLoadPromise=new Promise((n,o)=>{const c={keyInfo:e,frag:t,responseType:"arraybuffer",url:e.decryptdata.uri},l=s.keyLoadPolicy.default,h={loadPolicy:l,timeout:l.maxLoadTimeMs,maxRetry:0,retryDelay:0,maxRetryDelay:0},d={onSuccess:(u,f,g,y)=>{const{frag:p,keyInfo:E}=g,T=si(E.decryptdata);if(!p.decryptdata||E!==this.keyIdToKeyInfo[T])return o(this.createKeyLoadError(p,R.KEY_LOAD_ERROR,new Error("after key load, decryptdata unset or changed"),y));E.decryptdata.key=p.decryptdata.key=new Uint8Array(u.data),p.keyLoader=null,E.loader=null,n({frag:p,keyInfo:E})},onError:(u,f,g,y)=>{this.resetLoader(f),o(this.createKeyLoadError(t,R.KEY_LOAD_ERROR,new Error(`HTTP Error ${u.code} loading key ${u.text}`),g,ie({url:c.url,data:void 0},u)))},onTimeout:(u,f,g)=>{this.resetLoader(f),o(this.createKeyLoadError(t,R.KEY_LOAD_TIMEOUT,new Error("key loading timed out"),g))},onAbort:(u,f,g)=>{this.resetLoader(f),o(this.createKeyLoadError(t,R.INTERNAL_ABORTED,new Error("key loading aborted"),g))}};r.load(c,h,d)})}resetLoader(e){const{frag:t,keyInfo:s,url:i}=e,r=s.loader;t.keyLoader===r&&(t.keyLoader=null,s.loader=null);const n=si(s.decryptdata)||i;delete this.keyIdToKeyInfo[n],r&&r.destroy()}}function si(a){if(a.keyFormat!==Ee.FAIRPLAY){const e=a.keyId;if(e)return ye(e)}return a.uri}function En(a){const{type:e}=a;switch(e){case J.AUDIO_TRACK:return U.AUDIO;case J.SUBTITLE_TRACK:return U.SUBTITLE;default:return U.MAIN}}function ii(a,e){let t=a.url;return(t===void 0||t.indexOf("data:")===0)&&(t=e.url),t}class ou{constructor(e){this.hls=void 0,this.loaders=Object.create(null),this.variableList=null,this.onManifestLoaded=this.checkAutostartLoad,this.hls=e,this.registerListeners()}startLoad(e){}stopLoad(){this.destroyInternalLoaders()}registerListeners(){const{hls:e}=this;e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.LEVEL_LOADING,this.onLevelLoading,this),e.on(m.AUDIO_TRACK_LOADING,this.onAudioTrackLoading,this),e.on(m.SUBTITLE_TRACK_LOADING,this.onSubtitleTrackLoading,this),e.on(m.LEVELS_UPDATED,this.onLevelsUpdated,this)}unregisterListeners(){const{hls:e}=this;e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.LEVEL_LOADING,this.onLevelLoading,this),e.off(m.AUDIO_TRACK_LOADING,this.onAudioTrackLoading,this),e.off(m.SUBTITLE_TRACK_LOADING,this.onSubtitleTrackLoading,this),e.off(m.LEVELS_UPDATED,this.onLevelsUpdated,this)}createInternalLoader(e){const t=this.hls.config,s=t.pLoader,i=t.loader,r=s||i,n=new r(t);return this.loaders[e.type]=n,n}getInternalLoader(e){return this.loaders[e.type]}resetInternalLoader(e){this.loaders[e]&&delete this.loaders[e]}destroyInternalLoaders(){for(const e in this.loaders){const t=this.loaders[e];t&&t.destroy(),this.resetInternalLoader(e)}}destroy(){this.variableList=null,this.unregisterListeners(),this.destroyInternalLoaders()}onManifestLoading(e,t){const{url:s}=t;this.variableList=null,this.load({id:null,level:0,responseType:"text",type:J.MANIFEST,url:s,deliveryDirectives:null,levelOrTrack:null})}onLevelLoading(e,t){const{id:s,level:i,pathwayId:r,url:n,deliveryDirectives:o,levelInfo:c}=t;this.load({id:s,level:i,pathwayId:r,responseType:"text",type:J.LEVEL,url:n,deliveryDirectives:o,levelOrTrack:c})}onAudioTrackLoading(e,t){const{id:s,groupId:i,url:r,deliveryDirectives:n,track:o}=t;this.load({id:s,groupId:i,level:null,responseType:"text",type:J.AUDIO_TRACK,url:r,deliveryDirectives:n,levelOrTrack:o})}onSubtitleTrackLoading(e,t){const{id:s,groupId:i,url:r,deliveryDirectives:n,track:o}=t;this.load({id:s,groupId:i,level:null,responseType:"text",type:J.SUBTITLE_TRACK,url:r,deliveryDirectives:n,levelOrTrack:o})}onLevelsUpdated(e,t){const s=this.loaders[J.LEVEL];if(s){const i=s.context;i&&!t.levels.some(r=>r===i.levelOrTrack)&&(s.abort(),delete this.loaders[J.LEVEL])}}load(e){var t;const s=this.hls.config;let i=this.getInternalLoader(e);if(i){const l=this.hls.logger,h=i.context;if(h&&h.levelOrTrack===e.levelOrTrack&&(h.url===e.url||h.deliveryDirectives&&!e.deliveryDirectives)){h.url===e.url?l.log(`[playlist-loader]: ignore ${e.url} ongoing request`):l.log(`[playlist-loader]: ignore ${e.url} in favor of ${h.url}`);return}l.log(`[playlist-loader]: aborting previous loader for type: ${e.type}`),i.abort()}let r;if(e.type===J.MANIFEST?r=s.manifestLoadPolicy.default:r=ne({},s.playlistLoadPolicy.default,{timeoutRetry:null,errorRetry:null}),i=this.createInternalLoader(e),B((t=e.deliveryDirectives)==null?void 0:t.part)){let l;if(e.type===J.LEVEL&&e.level!==null?l=this.hls.levels[e.level].details:e.type===J.AUDIO_TRACK&&e.id!==null?l=this.hls.audioTracks[e.id].details:e.type===J.SUBTITLE_TRACK&&e.id!==null&&(l=this.hls.subtitleTracks[e.id].details),l){const h=l.partTarget,d=l.targetduration;if(h&&d){const u=Math.max(h*3,d*.8)*1e3;r=ne({},r,{maxTimeToFirstByteMs:Math.min(u,r.maxTimeToFirstByteMs),maxLoadTimeMs:Math.min(u,r.maxTimeToFirstByteMs)})}}}const n=r.errorRetry||r.timeoutRetry||{},o={loadPolicy:r,timeout:r.maxLoadTimeMs,maxRetry:n.maxNumRetry||0,retryDelay:n.retryDelayMs||0,maxRetryDelay:n.maxRetryDelayMs||0},c={onSuccess:(l,h,d,u)=>{const f=this.getInternalLoader(d);this.resetInternalLoader(d.type);const g=l.data;h.parsing.start=performance.now(),qe.isMediaPlaylist(g)||d.type!==J.MANIFEST?this.handleTrackOrLevelPlaylist(l,h,d,u||null,f):this.handleMasterPlaylist(l,h,d,u)},onError:(l,h,d,u)=>{this.handleNetworkError(h,d,!1,l,u)},onTimeout:(l,h,d)=>{this.handleNetworkError(h,d,!0,void 0,l)}};i.load(e,o,c)}checkAutostartLoad(){if(!this.hls)return;const{config:{autoStartLoad:e,startPosition:t},forceStartLoad:s}=this.hls;(e||s)&&(this.hls.logger.log(`${e?"auto":"force"} startLoad with configured startPosition ${t}`),this.hls.startLoad(t))}handleMasterPlaylist(e,t,s,i){const r=this.hls,n=e.data,o=ii(e,s),c=qe.parseMasterPlaylist(n,o);if(c.playlistParsingError){t.parsing.end=performance.now(),this.handleManifestParsingError(e,s,c.playlistParsingError,i,t);return}const{contentSteering:l,levels:h,sessionData:d,sessionKeys:u,startTimeOffset:f,variableList:g}=c;this.variableList=g,h.forEach(T=>{const{unknownCodecs:S}=T;if(S){const{preferManagedMediaSource:v}=this.hls.config;let{audioCodec:x,videoCodec:D}=T;for(let A=S.length;A--;){const _=S[A];Ut(_,"audio",v)?(T.audioCodec=x=x?`${x},${_}`:_,Pt.audio[x.substring(0,4)]=2,S.splice(A,1)):Ut(_,"video",v)&&(T.videoCodec=D=D?`${D},${_}`:_,Pt.video[D.substring(0,4)]=2,S.splice(A,1))}}});const{AUDIO:y=[],SUBTITLES:p,"CLOSED-CAPTIONS":E}=qe.parseMasterPlaylistMedia(n,o,c);y.length&&!y.some(S=>!S.url)&&h[0].audioCodec&&!h[0].attrs.AUDIO&&(this.hls.logger.log("[playlist-loader]: audio codec signaled in quality level, but no embedded audio track signaled, create one"),y.unshift({type:"main",name:"main",groupId:"main",default:!1,autoselect:!1,forced:!1,id:-1,attrs:new le({}),bitrate:0,url:""})),r.trigger(m.MANIFEST_LOADED,{levels:h,audioTracks:y,subtitles:p,captions:E,contentSteering:l,url:o,stats:t,networkDetails:i,sessionData:d,sessionKeys:u,startTimeOffset:f,variableList:g})}handleTrackOrLevelPlaylist(e,t,s,i,r){const n=this.hls,{id:o,level:c,type:l}=s,h=ii(e,s),d=B(c)?c:B(o)?o:0,u=En(s),f=qe.parseLevelPlaylist(e.data,h,d,u,0,this.variableList);if(l===J.MANIFEST){const g={attrs:new le({}),bitrate:0,details:f,name:"",url:h};f.requestScheduled=t.loading.start+Jn(f,0),n.trigger(m.MANIFEST_LOADED,{levels:[g],audioTracks:[],url:h,stats:t,networkDetails:i,sessionData:null,sessionKeys:null,contentSteering:null,startTimeOffset:null,variableList:null})}t.parsing.end=performance.now(),s.levelDetails=f,this.handlePlaylistLoaded(f,e,t,s,i,r)}handleManifestParsingError(e,t,s,i,r){this.hls.trigger(m.ERROR,{type:Y.NETWORK_ERROR,details:R.MANIFEST_PARSING_ERROR,fatal:t.type===J.MANIFEST,url:e.url,err:s,error:s,reason:s.message,response:e,context:t,networkDetails:i,stats:r})}handleNetworkError(e,t,s=!1,i,r){let n=`A network ${s?"timeout":"error"+(i?" (status "+i.code+")":"")} occurred while loading ${e.type}`;e.type===J.LEVEL?n+=`: ${e.level} id: ${e.id}`:(e.type===J.AUDIO_TRACK||e.type===J.SUBTITLE_TRACK)&&(n+=` id: ${e.id} group-id: "${e.groupId}"`);const o=new Error(n);this.hls.logger.warn(`[playlist-loader]: ${n}`);let c=R.UNKNOWN,l=!1;const h=this.getInternalLoader(e);switch(e.type){case J.MANIFEST:c=s?R.MANIFEST_LOAD_TIMEOUT:R.MANIFEST_LOAD_ERROR,l=!0;break;case J.LEVEL:c=s?R.LEVEL_LOAD_TIMEOUT:R.LEVEL_LOAD_ERROR,l=!1;break;case J.AUDIO_TRACK:c=s?R.AUDIO_TRACK_LOAD_TIMEOUT:R.AUDIO_TRACK_LOAD_ERROR,l=!1;break;case J.SUBTITLE_TRACK:c=s?R.SUBTITLE_TRACK_LOAD_TIMEOUT:R.SUBTITLE_LOAD_ERROR,l=!1;break}h&&this.resetInternalLoader(e.type);const d={type:Y.NETWORK_ERROR,details:c,fatal:l,url:e.url,loader:h,context:e,error:o,networkDetails:t,stats:r};if(i){const u=(t==null?void 0:t.url)||e.url;d.response=ie({url:u,data:void 0},i)}this.hls.trigger(m.ERROR,d)}handlePlaylistLoaded(e,t,s,i,r,n){const o=this.hls,{type:c,level:l,levelOrTrack:h,id:d,groupId:u,deliveryDirectives:f}=i,g=ii(t,i),y=En(i);let p=typeof i.level=="number"&&y===U.MAIN?l:void 0;const E=e.playlistParsingError;if(E){if(this.hls.logger.warn(`${E} ${e.url}`),!o.config.ignorePlaylistParsingErrors){o.trigger(m.ERROR,{type:Y.NETWORK_ERROR,details:R.LEVEL_PARSING_ERROR,fatal:!1,url:g,error:E,reason:E.message,response:t,context:i,level:p,parent:y,networkDetails:r,stats:s});return}e.playlistParsingError=null}if(!e.fragments.length){const T=e.playlistParsingError=new Error("No Segments found in Playlist");o.trigger(m.ERROR,{type:Y.NETWORK_ERROR,details:R.LEVEL_EMPTY_ERROR,fatal:!1,url:g,error:T,reason:T.message,response:t,context:i,level:p,parent:y,networkDetails:r,stats:s});return}switch(e.live&&n&&(n.getCacheAge&&(e.ageHeader=n.getCacheAge()||0),(!n.getCacheAge||isNaN(e.ageHeader))&&(e.ageHeader=0)),c){case J.MANIFEST:case J.LEVEL:if(p){if(!h)p=0;else if(h!==o.levels[p]){const T=o.levels.indexOf(h);T>-1&&(p=T)}}o.trigger(m.LEVEL_LOADED,{details:e,levelInfo:h||o.levels[0],level:p||0,id:d||0,stats:s,networkDetails:r,deliveryDirectives:f,withoutMultiVariant:c===J.MANIFEST});break;case J.AUDIO_TRACK:o.trigger(m.AUDIO_TRACK_LOADED,{details:e,track:h,id:d||0,groupId:u||"",stats:s,networkDetails:r,deliveryDirectives:f});break;case J.SUBTITLE_TRACK:o.trigger(m.SUBTITLE_TRACK_LOADED,{details:e,track:h,id:d||0,groupId:u||"",stats:s,networkDetails:r,deliveryDirectives:f});break}}}class Ye{static get version(){return Vt}static isMSESupported(){return Za()}static isSupported(){return su()}static getMediaSource(){return at()}static get Events(){return m}static get MetadataSchema(){return _e}static get ErrorTypes(){return Y}static get ErrorDetails(){return R}static get DefaultConfig(){return Ye.defaultConfig?Ye.defaultConfig:Hd}static set DefaultConfig(e){Ye.defaultConfig=e}constructor(e={}){this.config=void 0,this.userConfig=void 0,this.logger=void 0,this.coreComponents=void 0,this.networkControllers=void 0,this._emitter=new Mi,this._autoLevelCapping=-1,this._maxHdcpLevel=null,this.abrController=void 0,this.bufferController=void 0,this.capLevelController=void 0,this.latencyController=void 0,this.levelController=void 0,this.streamController=void 0,this.audioStreamController=void 0,this.subtititleStreamController=void 0,this.audioTrackController=void 0,this.subtitleTrackController=void 0,this.interstitialsController=void 0,this.gapController=void 0,this.emeController=void 0,this.cmcdController=void 0,this._media=null,this._url=null,this._sessionId=void 0,this.triggeringException=void 0,this.started=!1;const t=this.logger=fo(e.debug||!1,"Hls instance",e.assetPlayerId),s=this.config=Wd(Ye.DefaultConfig,e,t);this.userConfig=e,s.progressive&&qd(s,t);const{abrController:i,bufferController:r,capLevelController:n,errorController:o,fpsController:c}=s,l=new o(this),h=this.abrController=new i(this),d=new ll(this),u=s.interstitialsController,f=u?this.interstitialsController=new u(this,Ye):null,g=this.bufferController=new r(this,d),y=this.capLevelController=new n(this),p=new c(this),E=new ou(this),T=s.contentSteeringController,S=T?new T(this):null,v=this.levelController=new tu(this,S),x=new Jd(this),D=new au(this.config,this.logger),A=this.streamController=new nu(this,d,D),_=this.gapController=new Qd(this,d);y.setStreamController(A),p.setStreamController(A);const b=[E,v,A];f&&b.splice(1,0,f),S&&b.splice(1,0,S),this.networkControllers=b;const I=[h,g,_,y,p,x,d];this.audioTrackController=this.createController(s.audioTrackController,b);const P=s.audioStreamController;P&&b.push(this.audioStreamController=new P(this,d,D)),this.subtitleTrackController=this.createController(s.subtitleTrackController,b);const M=s.subtitleStreamController;M&&b.push(this.subtititleStreamController=new M(this,d,D)),this.createController(s.timelineController,I),D.emeController=this.emeController=this.createController(s.emeController,I),this.cmcdController=this.createController(s.cmcdController,I),this.latencyController=this.createController(eu,I),this.coreComponents=I,b.push(l);const G=l.onErrorOut;typeof G=="function"&&this.on(m.ERROR,G,l),this.on(m.MANIFEST_LOADED,E.onManifestLoaded,E)}createController(e,t){if(e){const s=new e(this);return t&&t.push(s),s}return null}on(e,t,s=this){this._emitter.on(e,t,s)}once(e,t,s=this){this._emitter.once(e,t,s)}removeAllListeners(e){this._emitter.removeAllListeners(e)}off(e,t,s=this,i){this._emitter.off(e,t,s,i)}listeners(e){return this._emitter.listeners(e)}emit(e,t,s){return this._emitter.emit(e,t,s)}trigger(e,t){if(this.config.debug)return this.emit(e,e,t);try{return this.emit(e,e,t)}catch(s){if(this.logger.error("An internal error happened while handling event "+e+'. Error message: "'+s.message+'". Here is a stacktrace:',s),!this.triggeringException){this.triggeringException=!0;const i=e===m.ERROR;this.trigger(m.ERROR,{type:Y.OTHER_ERROR,details:R.INTERNAL_EXCEPTION,fatal:i,event:e,error:s}),this.triggeringException=!1}}return!1}listenerCount(e){return this._emitter.listenerCount(e)}destroy(){this.logger.log("destroy"),this.trigger(m.DESTROYING,void 0),this.detachMedia(),this.removeAllListeners(),this._autoLevelCapping=-1,this._url=null,this.networkControllers.forEach(t=>t.destroy()),this.networkControllers.length=0,this.coreComponents.forEach(t=>t.destroy()),this.coreComponents.length=0;const e=this.config;e.xhrSetup=e.fetchSetup=void 0,this.userConfig=null}attachMedia(e){if(!e||"media"in e&&!e.media){const r=new Error(`attachMedia failed: invalid argument (${e})`);this.trigger(m.ERROR,{type:Y.OTHER_ERROR,details:R.ATTACH_MEDIA_ERROR,fatal:!0,error:r});return}this.logger.log("attachMedia"),this._media&&(this.logger.warn("media must be detached before attaching"),this.detachMedia());const t="media"in e,s=t?e.media:e,i=t?e:{media:s};this._media=s,this.trigger(m.MEDIA_ATTACHING,i)}detachMedia(){this.logger.log("detachMedia"),this.trigger(m.MEDIA_DETACHING,{}),this._media=null}transferMedia(){this._media=null;const e=this.bufferController.transferMedia();return this.trigger(m.MEDIA_DETACHING,{transferMedia:e}),e}loadSource(e){this.stopLoad();const t=this.media,s=this._url,i=this._url=Li.buildAbsoluteURL(self.location.href,e,{alwaysNormalize:!0});this._autoLevelCapping=-1,this._maxHdcpLevel=null,this.logger.log(`loadSource:${i}`),t&&s&&(s!==i||this.bufferController.hasSourceTypes())&&(this.detachMedia(),this.attachMedia(t)),this.trigger(m.MANIFEST_LOADING,{url:e})}get url(){return this._url}get hasEnoughToStart(){return this.streamController.hasEnoughToStart}get startPosition(){return this.streamController.startPositionValue}startLoad(e=-1,t){this.logger.log(`startLoad(${e+(t?", ":"")})`),this.started=!0,this.resumeBuffering();for(let s=0;s{e.resumeBuffering&&e.resumeBuffering()}))}pauseBuffering(){this.bufferingEnabled&&(this.logger.log("pause buffering"),this.networkControllers.forEach(e=>{e.pauseBuffering&&e.pauseBuffering()}))}get inFlightFragments(){const e={[U.MAIN]:this.streamController.inFlightFrag};return this.audioStreamController&&(e[U.AUDIO]=this.audioStreamController.inFlightFrag),this.subtititleStreamController&&(e[U.SUBTITLE]=this.subtititleStreamController.inFlightFrag),e}swapAudioCodec(){this.logger.log("swapAudioCodec"),this.streamController.swapAudioCodec()}recoverMediaError(){this.logger.log("recoverMediaError");const e=this._media,t=e==null?void 0:e.currentTime;this.detachMedia(),e&&(this.attachMedia(e),t&&this.startLoad(t))}removeLevel(e){this.levelController.removeLevel(e)}get sessionId(){let e=this._sessionId;return e||(e=this._sessionId=Qh()),e}get levels(){const e=this.levelController.levels;return e||[]}get latestLevelDetails(){return this.streamController.getLevelDetails()||null}get loadLevelObj(){return this.levelController.loadLevelObj}get currentLevel(){return this.streamController.currentLevel}set currentLevel(e){this.logger.log(`set currentLevel:${e}`),this.levelController.manualLevel=e,this.streamController.immediateLevelSwitch()}get nextLevel(){return this.streamController.nextLevel}set nextLevel(e){this.logger.log(`set nextLevel:${e}`),this.levelController.manualLevel=e,this.streamController.nextLevelSwitch()}get loadLevel(){return this.levelController.level}set loadLevel(e){this.logger.log(`set loadLevel:${e}`),this.levelController.manualLevel=e}get nextLoadLevel(){return this.levelController.nextLoadLevel}set nextLoadLevel(e){this.levelController.nextLoadLevel=e}get firstLevel(){return Math.max(this.levelController.firstLevel,this.minAutoLevel)}set firstLevel(e){this.logger.log(`set firstLevel:${e}`),this.levelController.firstLevel=e}get startLevel(){const e=this.levelController.startLevel;return e===-1&&this.abrController.forcedAutoLevel>-1?this.abrController.forcedAutoLevel:e}set startLevel(e){this.logger.log(`set startLevel:${e}`),e!==-1&&(e=Math.max(e,this.minAutoLevel)),this.levelController.startLevel=e}get capLevelToPlayerSize(){return this.config.capLevelToPlayerSize}set capLevelToPlayerSize(e){const t=!!e;t!==this.config.capLevelToPlayerSize&&(t?this.capLevelController.startCapping():(this.capLevelController.stopCapping(),this.autoLevelCapping=-1,this.streamController.nextLevelSwitch()),this.config.capLevelToPlayerSize=t)}get autoLevelCapping(){return this._autoLevelCapping}get bandwidthEstimate(){const{bwEstimator:e}=this.abrController;return e?e.getEstimate():NaN}set bandwidthEstimate(e){this.abrController.resetEstimator(e)}get abrEwmaDefaultEstimate(){const{bwEstimator:e}=this.abrController;return e?e.defaultEstimate:NaN}get ttfbEstimate(){const{bwEstimator:e}=this.abrController;return e?e.getEstimateTTFB():NaN}set autoLevelCapping(e){this._autoLevelCapping!==e&&(this.logger.log(`set autoLevelCapping:${e}`),this._autoLevelCapping=e,this.levelController.checkMaxAutoUpdated())}get maxHdcpLevel(){return this._maxHdcpLevel}set maxHdcpLevel(e){Wo(e)&&this._maxHdcpLevel!==e&&(this._maxHdcpLevel=e,this.levelController.checkMaxAutoUpdated())}get autoLevelEnabled(){return this.levelController.manualLevel===-1}get manualLevel(){return this.levelController.manualLevel}get minAutoLevel(){const{levels:e,config:{minAutoBitrate:t}}=this;if(!e)return 0;const s=e.length;for(let i=0;i=t)return i;return 0}get maxAutoLevel(){const{levels:e,autoLevelCapping:t,maxHdcpLevel:s}=this;let i;if(t===-1&&e!=null&&e.length?i=e.length-1:i=t,s)for(let r=i;r--;){const n=e[r].attrs["HDCP-LEVEL"];if(n&&n<=s)return r}return i}get firstAutoLevel(){return this.abrController.firstAutoLevel}get nextAutoLevel(){return this.abrController.nextAutoLevel}set nextAutoLevel(e){this.abrController.nextAutoLevel=e}get playingDate(){return this.streamController.currentProgramDateTime}get mainForwardBufferInfo(){return this.streamController.getMainFwdBufferInfo()}get maxBufferLength(){return this.streamController.maxBufferLength}setAudioOption(e){var t;return((t=this.audioTrackController)==null?void 0:t.setAudioOption(e))||null}setSubtitleOption(e){var t;return((t=this.subtitleTrackController)==null?void 0:t.setSubtitleOption(e))||null}get allAudioTracks(){const e=this.audioTrackController;return e?e.allAudioTracks:[]}get audioTracks(){const e=this.audioTrackController;return e?e.audioTracks:[]}get audioTrack(){const e=this.audioTrackController;return e?e.audioTrack:-1}set audioTrack(e){const t=this.audioTrackController;t&&(t.audioTrack=e)}get allSubtitleTracks(){const e=this.subtitleTrackController;return e?e.allSubtitleTracks:[]}get subtitleTracks(){const e=this.subtitleTrackController;return e?e.subtitleTracks:[]}get subtitleTrack(){const e=this.subtitleTrackController;return e?e.subtitleTrack:-1}get media(){return this._media}set subtitleTrack(e){const t=this.subtitleTrackController;t&&(t.subtitleTrack=e)}get subtitleDisplay(){const e=this.subtitleTrackController;return e?e.subtitleDisplay:!1}set subtitleDisplay(e){const t=this.subtitleTrackController;t&&(t.subtitleDisplay=e)}get lowLatencyMode(){return this.config.lowLatencyMode}set lowLatencyMode(e){this.config.lowLatencyMode=e}get liveSyncPosition(){return this.latencyController.liveSyncPosition}get latency(){return this.latencyController.latency}get maxLatency(){return this.latencyController.maxLatency}get targetLatency(){return this.latencyController.targetLatency}set targetLatency(e){this.latencyController.targetLatency=e}get drift(){return this.latencyController.drift}get forceStartLoad(){return this.streamController.forceStartLoad}get pathways(){return this.levelController.pathways}get pathwayPriority(){return this.levelController.pathwayPriority}set pathwayPriority(e){this.levelController.pathwayPriority=e}get bufferedToEnd(){var e;return!!((e=this.bufferController)!=null&&e.bufferedToEnd)}get interstitialsManager(){var e;return((e=this.interstitialsController)==null?void 0:e.interstitialsManager)||null}getMediaDecodingInfo(e,t=this.allAudioTracks){const s=Bn(t);return Mn(e,s,navigator.mediaCapabilities)}}Ye.defaultConfig=void 0;class lu{constructor({onState:e}){this.audio=new Audio,this.audio.preload="none",this.hls=null,this.station=null,this.onState=e||(()=>{}),this.audio.addEventListener("playing",()=>this.emit({playing:!0,loading:!1,error:null})),this.audio.addEventListener("pause",()=>this.emit({playing:!1,loading:!1})),this.audio.addEventListener("waiting",()=>this.emit({loading:!0})),this.audio.addEventListener("error",()=>{var r;const t=(r=this.audio.error)==null?void 0:r.code,i={1:"aborted",2:"network",3:"decode",4:"src not supported"}[t]||`code ${t}`;console.warn("[player] audio error",i,this.audio.currentSrc),this.emit({playing:!1,loading:!1,error:`stream error: ${i}`})})}emit(e){var t,s,i;this.onState({stationId:((t=this.station)==null?void 0:t.id)??null,stationName:((s=this.station)==null?void 0:s.name)??null,genres:((i=this.station)==null?void 0:i.genres)||[],volume:this.audio.volume,...e})}setVolume(e){this.audio.volume=Math.max(0,Math.min(1,e)),this.emit({})}stop(){this.audio.pause(),this.audio.removeAttribute("src"),this.audio.load(),this.hls&&(this.hls.destroy(),this.hls=null)}togglePause(){this.station&&(this.audio.paused?this.audio.play().catch(()=>{}):this.audio.pause())}async play(e){this.stop(),this.station=e,this.emit({playing:!1,loading:!0});let t;try{t=(await Te.post(`/api/stations/${e.id}/resolve`)).resolved}catch(i){this.emit({playing:!1,loading:!1,error:i.message});return}const s=t.url;t.format==="hls"?Ye.isSupported()?(this.hls=new Ye({enableWorker:!0}),this.hls.loadSource(s),this.hls.attachMedia(this.audio),this.hls.on(Ye.Events.MANIFEST_PARSED,()=>this.audio.play().catch(()=>{}))):this.audio.canPlayType("application/vnd.apple.mpegurl")?(this.audio.src=s,this.audio.play().catch(()=>{})):this.emit({playing:!1,loading:!1,error:"HLS not supported"}):(this.audio.src=s,this.audio.play().catch(()=>{}))}}const Rt=document.getElementById("app"),N={user:null,tab:"favorites",stations:[],categories:[],selectedCategory:null,favorites:[],history:[],query:"",sort:"hot",randomMode:localStorage.getItem("oradio.randomMode")==="favorites"?"favorites":"all",player:{stationId:null,stationName:null,genres:[],playing:!1,loading:!1,volume:.7,votes:null}},mt=new lu({onState:a=>{N.player={...N.player,...a},Ce()}});async function Ja(){try{N.user=await Te.get("/api/auth/me")}catch{du();return}await Xi(),io(hu),Ce(),vu()}async function Xi(){const[a,e,t,s]=await Promise.all([Te.get(`/api/stations?sort=${encodeURIComponent(N.sort)}`),Te.get("/api/me/favorites").catch(()=>[]),Te.get("/api/me/history").catch(()=>[]),Te.get("/api/v1/categories").catch(()=>[])]);N.stations=a,N.favorites=e,N.history=t,N.categories=s}async function cu(){N.stations=await Te.get(`/api/stations?sort=${encodeURIComponent(N.sort)}`)}function hu(a){if(a.type==="command")if(a.action==="play"&&a.stationId){const e=N.stations.find(t=>t.id===a.stationId);e&&qt(e)}else a.action==="pause"?mt.togglePause():a.action==="volume"?mt.setVolume(a.value):a.action==="stop"&&mt.stop()}function du(){Ii(Rt);const a=k("div",{class:"login"},k("form",{onSubmit:async e=>{e.preventDefault();const t=new FormData(e.target);try{N.user=await Te.post("/api/auth/login",{username:t.get("username"),password:t.get("password")}),await Ja()}catch(s){e.target.querySelector(".err").textContent=s.message}}},k("h1",{},"Sign in"),k("input",{name:"username",placeholder:"Username",autocomplete:"username",required:!0}),k("input",{name:"password",type:"password",placeholder:"Password",autocomplete:"current-password",required:!0}),k("div",{class:"err"}),k("button",{type:"submit"},"Continue")));Rt.appendChild(a)}let Ve=0;function Ce(){if(!N.user)return;const a=Rt.querySelector(".grid");a&&a.scrollTop>0&&(Ve=a.scrollTop),jt(),Ii(Rt);const e=N.player,t=new Set(N.favorites.map(l=>l.id)),s=e.votes,i=k("section",{class:"now"},k("div",{class:"meta"},k("div",{class:"name"},e.stationName||"Select a station"),k("div",{class:"sub"},e.loading?"Connecting…":e.playing?"On air":e.error?e.error:e.stationId?"Paused":"Idle"),k("div",{class:"tags"},...(e.genres||[]).slice(0,4).map(l=>k("span",{class:"tag"},l)))),k("div",{class:"controls"},k("div",{class:"vote-group",title:"Vote on current station"},k("button",{class:`vote up ${(s==null?void 0:s.myVote)===1?"on":""}`,disabled:!e.stationId,title:"Upvote",onClick:()=>Tn(1)},k("span",{class:"vote-icon"},"▲"),k("span",{class:"vote-count"},String((s==null?void 0:s.up)??0))),k("button",{class:`vote down ${(s==null?void 0:s.myVote)===-1?"on":""}`,disabled:!e.stationId,title:"Downvote",onClick:()=>Tn(-1)},k("span",{class:"vote-icon"},"▼"),k("span",{class:"vote-count"},String((s==null?void 0:s.down)??0)))),k("button",{class:`btn-play ${e.loading?"loading":""}`,title:e.playing?"Pause":"Play",onClick:()=>e.stationId?mt.togglePause():N.favorites[0]&&qt(N.favorites[0])},e.playing?"❚❚":"▶"),k("button",{class:"btn-stop",title:"Stop",disabled:!e.stationId,onClick:()=>mt.stop()},"■"),k("div",{class:"vol"},k("span",{class:"vol-icon"},e.volume===0?"🔇":e.volume<.5?"🔈":"🔊"),k("input",{type:"range",min:0,max:1,step:.05,value:e.volume,"aria-label":"Volume",onInput:l=>mt.setVolume(Number(l.target.value))}),k("span",{class:"val"},Math.round(e.volume*100))))),r=N.user.role==="admin",n=k("div",{class:"header"},k("div",{class:"tabs"},...["favorites","browse","recent"].map(l=>k("button",{class:`tab ${N.tab===l?"active":""}`,onClick:()=>{N.tab=l,Ve=0,Ce()}},l==="favorites"?"★ Favorites":l==="browse"?"🌐 Browse":"⏱ Recent"))),k("div",{class:"header-tools"},N.tab==="browse"?k("select",{class:"sort",title:"Sort browse list",onChange:l=>{N.sort=l.target.value,Ve=0,cu().then(Ce)}},k("option",{value:"hot",selected:N.sort==="hot"},"🔥 Hot (smart)"),k("option",{value:"top",selected:N.sort==="top"},"▲ Top voted"),k("option",{value:"plays",selected:N.sort==="plays"},"▶ Most played"),k("option",{value:"controversial",selected:N.sort==="controversial"},"⚡ Controversial"),k("option",{value:"name",selected:N.sort==="name"},"A → Z")):null,k("input",{class:"search",type:"search",placeholder:"Search…",value:N.query,onInput:l=>{N.query=l.target.value,gu()}}),k("button",{class:"btn-random",title:`Play random station (mode: ${N.randomMode}). Right-click to switch mode.`,onClick:yu,onContextMenu:l=>{l.preventDefault(),pu()}},k("span",{class:"rand-icon"},"🎲"),k("span",{class:"rand-mode"},N.randomMode==="favorites"?"★":"All")),k("a",{class:"btn-docs",href:"/docs/",target:"_blank",rel:"noopener",title:"Open API reference"},"API"),r?k("button",{class:"btn-add",title:"Add station",onClick:Su},"+"):null)),o=k("section",{class:"lib"},n);N.tab==="browse"&&N.categories.length&&o.appendChild(uu());const c=k("div",{class:"grid"});c.id="grid",c.addEventListener("scroll",()=>{Ve=c.scrollTop},{passive:!0}),o.appendChild(c),Rt.appendChild(i),Rt.appendChild(o),eo(c,t),Ve&&(c.scrollTop=Ve,requestAnimationFrame(()=>{Ve&&(c.scrollTop=Ve)}))}function uu(){return k("div",{class:"chips"},k("button",{class:`chip ${N.selectedCategory?"":"active"}`,onClick:()=>{N.selectedCategory=null,Ve=0,Ce()}},`All (${N.stations.length})`),...N.categories.filter(a=>a.count>0).map(a=>k("button",{class:`chip ${N.selectedCategory===a.id?"active":""}`,onClick:()=>{N.selectedCategory=a.id,Ve=0,Ce()}},`${a.icon||""} ${a.label} (${a.count})`.trim())))}function fu(){let a=[];if(N.tab==="favorites")a=N.favorites;else if(N.tab==="browse")a=N.stations,N.selectedCategory&&(a=a.filter(t=>t.category===N.selectedCategory));else if(N.tab==="recent"){const t=new Set;a=N.history.filter(s=>!t.has(s.station_id)&&t.add(s.station_id)).map(s=>N.stations.find(i=>i.id===s.station_id)).filter(Boolean)}const e=N.query.trim().toLowerCase();return e&&(a=a.filter(t=>t.name.toLowerCase().includes(e)||(t.country||"").toLowerCase().includes(e)||(t.genres||[]).some(s=>s.toLowerCase().includes(e)))),a}function gu(){const a=document.getElementById("grid");if(!a)return;const e=new Set(N.favorites.map(t=>t.id));eo(a,e)}function eo(a,e){Ii(a);const t=fu();if(!t.length){a.appendChild(k("div",{class:"empty"},N.tab==="favorites"?"No favorites yet — long-press or tap ★ on a station.":N.query?"No matches.":"Nothing here yet."));return}const s=N.player;for(const i of t){const r=typeof i.score=="number"?i.score:0,n=(i.up??0)-(i.down??0),o=n>0?"pos":n<0?"neg":"neu",c=k("div",{class:`card ${s.stationId===i.id?"playing":""}`,role:"button",tabindex:0,onClick:()=>qt(i),onContextMenu:l=>{l.preventDefault(),Sn(l.clientX,l.clientY,i)}},k("div",{class:"art"},i.image_url?k("img",{class:"art-img",src:i.image_url,alt:"",loading:"lazy",referrerpolicy:"no-referrer",onError:l=>{const h=l.target.parentNode;l.target.remove(),h&&h.appendChild(k("span",{class:"art-glyph"},"♪"))}}):k("span",{class:"art-glyph"},"♪")),k("div",{class:"card-body"},k("div",{class:"n"},i.name),k("div",{class:"g"},(i.genres||[]).slice(0,3).join(" · ")||i.country||"—")),k("div",{class:`score-badge ${o}`,title:`▲${i.up??0} · ▼${i.down??0} · ▶${i.plays??0} · score ${r.toFixed(2)}`},n>0?`+${n}`:String(n)),k("button",{class:`fav ${e.has(i.id)?"on":""}`,title:e.has(i.id)?"Remove favorite":"Add favorite",onClick:l=>{l.stopPropagation(),mu(i)}},e.has(i.id)?"★":"☆"),k("button",{class:"more",title:"API endpoints",onClick:l=>{l.stopPropagation();const h=l.currentTarget.getBoundingClientRect();Sn(h.right,h.bottom,i)}},"⋯"));a.appendChild(c)}}async function mu(a){N.favorites.some(t=>t.id===a.id)?await Te.del(`/api/me/favorites/${a.id}`):await Te.put(`/api/me/favorites/${a.id}`,{position:N.favorites.length}),N.favorites=await Te.get("/api/me/favorites"),Ce()}function pu(){N.randomMode=N.randomMode==="favorites"?"all":"favorites",localStorage.setItem("oradio.randomMode",N.randomMode),et(`Random mode: ${N.randomMode==="favorites"?"favorites only":"all stations"}`),Ce()}async function yu(){try{const a=N.randomMode==="favorites"?"/api/me/favorites/random":"/api/v1/stations/random",e=await Te.get(a);let t=e;if(t.id==null&&(t=N.stations.find(s=>s.uuid===e.uuid)||null),!t){et("Random station not in cache");return}qt(t)}catch(a){const e=N.randomMode==="favorites"?N.favorites:N.stations;if(!e.length){et(a.message||"No stations available");return}qt(e[Math.floor(Math.random()*e.length)])}}function Eu(a){N.history.unshift({station_id:a,started_at:new Date().toISOString()})}async function qt(a){N.player.votes=null,mt.play(a),Eu(a.id);try{const e=await Te.post(`/api/stations/${a.id}/play`);N.player.stationId===a.id&&(N.player.votes=e,Ai(a.id,e),Ce())}catch{try{const t=await Te.get(`/api/stations/${a.id}/votes`);N.player.stationId===a.id&&(N.player.votes=t,Ai(a.id,t),Ce())}catch{}}}async function Tn(a){var i;const e=N.player.stationId;if(!e)return;const s=(((i=N.player.votes)==null?void 0:i.myVote)||0)===a?0:a;try{const r=await Te.post(`/api/stations/${e}/vote`,{value:s});N.player.votes=r,Ai(e,r),Ce()}catch(r){et(r.message||"Vote failed")}}function Ai(a,e){const t=[N.stations,N.favorites];for(const s of t){const i=s.find(r=>r.id===a);i&&(i.up=e.up,i.down=e.down,i.plays=e.plays,i.score=e.score,i.my_vote=e.myVote)}}let Be=null;function jt(){Be&&(Be.remove(),Be=null)}function Tu(a){const e=location.origin,t=`${e}/api/v1`,s=[];return a.id!=null&&s.push({label:"Station (original)",url:`${e}/api/stations/${a.id}`}),a.uuid&&s.push({label:"Station detail",url:`${t}/stations/${a.uuid}`},{label:"Stream redirect",url:`${t}/stations/${a.uuid}/stream`},{label:"MP3 stream",url:`${t}/stations/${a.uuid}/stream?format=mp3`},{label:"AAC stream",url:`${t}/stations/${a.uuid}/stream?format=aac`},{label:"HLS stream",url:`${t}/stations/${a.uuid}/stream?format=hls`}),s.push({label:"All stations",url:`${t}/stations`},{label:"Health",url:`${t}/health`}),s}function Sn(a,e,t){jt();const s=Tu(t);Be=k("div",{class:"ctx-menu",role:"menu"},k("div",{class:"ctx-title"},t.name),k("div",{class:"ctx-sub"},t.uuid?`uuid · ${t.uuid}`:t.id!=null?`id · ${t.id} (no uuid — public v1 hidden)`:"no identifier"),...s.length?s.map(c=>k("div",{class:"ctx-row"},k("div",{class:"ctx-row-text"},k("div",{class:"ctx-label"},c.label),k("div",{class:"ctx-url"},c.url)),k("button",{class:"ctx-btn",title:"Copy",onClick:async l=>{l.stopPropagation();try{await navigator.clipboard.writeText(c.url),et("Copied")}catch{et("Copy failed")}}},"⧉"),k("button",{class:"ctx-btn",title:"Open",onClick:l=>{l.stopPropagation(),window.open(c.url,"_blank","noopener")}},"↗"))):[k("div",{class:"ctx-empty"},"No public API for this station yet (missing uuid).")],N.user.role==="admin"?k("button",{class:"ctx-danger",onClick:async()=>{if(jt(),!!confirm(`Delete ${t.name}?`))try{await Te.del(`/api/stations/${t.id}`),await Xi(),Ce(),et("Deleted")}catch(c){et(c.message||"Delete failed")}}},"🗑 Delete"):null),document.body.appendChild(Be);const i=Be.offsetWidth,r=Be.offsetHeight,n=Math.min(a,window.innerWidth-i-8),o=Math.min(e,window.innerHeight-r-8);Be.style.left=`${Math.max(8,n)}px`,Be.style.top=`${Math.max(8,o)}px`}document.addEventListener("click",a=>{Be&&!Be.contains(a.target)&&jt()});document.addEventListener("keydown",a=>{a.key==="Escape"&&jt()});async function Su(){const a=document.createElement("dialog");a.className="add-station";const e={name:"",country:"",genres:"",image_url:"",homepage:"",streamUrl:"",streamFormat:"mp3"},t=k("div",{class:"err"});a.appendChild(k("form",{method:"dialog",onSubmit:async s=>{s.preventDefault(),t.textContent="";const i={name:e.name.trim(),country:e.country.trim()||null,homepage:e.homepage.trim()||null,image_url:e.image_url.trim()||null,genres:e.genres.split(",").map(r=>r.trim()).filter(Boolean),streams:e.streamUrl.trim()?[{url:e.streamUrl.trim(),format:e.streamFormat,priority:0}]:[]};if(!i.name){t.textContent="Name is required.";return}try{await Te.post("/api/stations",i),a.close(),await Xi(),Ce(),et("Station added")}catch(r){t.textContent=r.message||"Failed to add station"}}},k("h2",{},"Add station"),k("label",{},"Name",k("input",{required:!0,autofocus:!0,onInput:s=>e.name=s.target.value})),k("div",{class:"row2"},k("label",{},"Country",k("input",{maxlength:4,placeholder:"NL",onInput:s=>e.country=s.target.value})),k("label",{},"Genres",k("input",{placeholder:"jazz, electronic",onInput:s=>e.genres=s.target.value}))),k("label",{},"Homepage",k("input",{type:"url",placeholder:"https://…",onInput:s=>e.homepage=s.target.value})),k("label",{},"Image URL",k("input",{type:"url",placeholder:"https://…/logo.png",onInput:s=>e.image_url=s.target.value})),k("div",{class:"row2"},k("label",{},"Stream URL",k("input",{type:"url",placeholder:"https://…/stream",onInput:s=>e.streamUrl=s.target.value})),k("label",{},"Format",k("select",{onChange:s=>e.streamFormat=s.target.value},...["mp3","aac","ogg","hls","m3u","pls","unknown"].map(s=>k("option",{value:s,selected:s==="mp3"},s))))),t,k("div",{class:"actions"},k("button",{class:"btn-ghost",type:"button",onClick:()=>a.close()},"Cancel"),k("button",{class:"btn-primary",type:"submit"},"Add")))),document.body.appendChild(a),a.showModal(),a.addEventListener("close",()=>a.remove())}let vn=null;function et(a){const e=document.querySelector(".toast");e&&e.remove();const t=k("div",{class:"toast"},a);document.body.appendChild(t),clearTimeout(vn),vn=setTimeout(()=>t.remove(),2200)}async function vu(){var a;try{await((a=navigator.wakeLock)==null?void 0:a.request("screen"))}catch{}document.addEventListener("visibilitychange",()=>{var e;document.visibilityState==="visible"&&((e=navigator.wakeLock)==null||e.request("screen").catch(()=>{}))})}document.addEventListener("contextmenu",a=>{window.matchMedia("(display-mode: fullscreen)").matches&&a.preventDefault()});Ja(); +`),l=[],h=e?fc(e.baseTime,e.timescale):0;let u="00:00.000",d=0,f=0,g,y=!0;o.oncue=function(p){const E=t[s];let T=t.ccOffset;const S=(d-h)/9e4;if(E!=null&&E.new&&(f!==void 0?T=t.ccOffset=E.start:au(t,s,S)),S){if(!e){g=new Error("Missing initPTS for VTT MPEGTS");return}T=S-t.presentationOffset}const v=p.endTime-p.startTime,x=Ie((p.startTime+T-f)*9e4,i*9e4)/9e4;p.startTime=Math.max(x,0),p.endTime=Math.max(x+v,0);const D=p.text.trim();p.text=decodeURIComponent(encodeURIComponent(D)),p.id||(p.id=Mi(p.startTime,p.endTime,D)),p.endTime>0&&l.push(p)},o.onparsingerror=function(p){g=p},o.onflush=function(){if(g){n(g);return}r(l)},c.forEach(p=>{if(y)if($s(p,"X-TIMESTAMP-MAP=")){y=!1,p.slice(16).split(",").forEach(E=>{$s(E,"LOCAL:")?u=E.slice(6):$s(E,"MPEGTS:")&&(d=parseInt(E.slice(7)))});try{f=nu(u)/1e3}catch(E){g=E}return}else p===""&&(y=!1);o.parse(p+` +`)}),o.flush()}const Gs="stpp.ttml.im1t",Ca=/^(\d{2,}):(\d{2}):(\d{2}):(\d{2})\.?(\d+)?$/,Pa=/^(\d*(?:\.\d*)?)(h|m|s|ms|f|t)$/,lu={left:"start",center:"center",right:"end",start:"start",end:"end"};function Xr(a,e,t,s){const i=z(new Uint8Array(a),["mdat"]);if(i.length===0){s(new Error("Could not parse IMSC1 mdat"));return}const r=i.map(o=>Re(o)),n=dc(e.baseTime,1,e.timescale);try{r.forEach(o=>t(cu(o,n)))}catch(o){s(o)}}function cu(a,e){const i=new DOMParser().parseFromString(a,"text/xml").getElementsByTagName("tt")[0];if(!i)throw new Error("Invalid ttml");const r={frameRate:30,subFrameRate:1,frameRateMultiplier:0,tickRate:0},n=Object.keys(r).reduce((u,d)=>(u[d]=i.getAttribute(`ttp:${d}`)||r[d],u),{}),o=i.getAttribute("xml:space")!=="preserve",c=zr(Ks(i,"styling","style")),l=zr(Ks(i,"layout","region")),h=Ks(i,"body","[begin]");return[].map.call(h,u=>{const d=ka(u,o);if(!d||!u.hasAttribute("begin"))return null;const f=Hs(u.getAttribute("begin"),n),g=Hs(u.getAttribute("dur"),n);let y=Hs(u.getAttribute("end"),n);if(f===null)throw Qr(u);if(y===null){if(g===null)throw Qr(u);y=f+g}const p=new Fi(f-e,y-e,d);p.id=Mi(p.startTime,p.endTime,p.text);const E=l[u.getAttribute("region")],T=c[u.getAttribute("style")],S=hu(E,T,c),{textAlign:v}=S;if(v){const x=lu[v];x&&(p.lineAlign=x),p.align=v}return ie(p,S),p}).filter(u=>u!==null)}function Ks(a,e,t){const s=a.getElementsByTagName(e)[0];return s?[].slice.call(s.querySelectorAll(t)):[]}function zr(a){return a.reduce((e,t)=>{const s=t.getAttribute("xml:id");return s&&(e[s]=t),e},{})}function ka(a,e){return[].slice.call(a.childNodes).reduce((t,s,i)=>{var r;return s.nodeName==="br"&&i?t+` +`:(r=s.childNodes)!=null&&r.length?ka(s,e):e?t+s.textContent.trim().replace(/\s+/g," "):t+s.textContent},"")}function hu(a,e,t){const s="http://www.w3.org/ns/ttml#styling";let i=null;const r=["displayAlign","textAlign","color","backgroundColor","fontSize","fontFamily"],n=a!=null&&a.hasAttribute("style")?a.getAttribute("style"):null;return n&&t.hasOwnProperty(n)&&(i=t[n]),r.reduce((o,c)=>{const l=Vs(e,s,c)||Vs(a,s,c)||Vs(i,s,c);return l&&(o[c]=l),o},{})}function Vs(a,e,t){return a&&a.hasAttributeNS(e,t)?a.getAttributeNS(e,t):null}function Qr(a){return new Error(`Could not parse ttml timestamp ${a}`)}function Hs(a,e){if(!a)return null;let t=ba(a);return t===null&&(Ca.test(a)?t=uu(a,e):Pa.test(a)&&(t=du(a,e))),t}function uu(a,e){const t=Ca.exec(a),s=(t[4]|0)+(t[5]|0)/e.subFrameRate;return(t[1]|0)*3600+(t[2]|0)*60+(t[3]|0)+s/e.frameRate}function du(a,e){const t=Pa.exec(a),s=Number(t[1]);switch(t[2]){case"h":return s*3600;case"m":return s*60;case"ms":return s*1e3;case"f":return s/e.frameRate;case"t":return s/e.tickRate}return s}class Qt{constructor(e,t){this.timelineController=void 0,this.cueRanges=[],this.trackName=void 0,this.startTime=null,this.endTime=null,this.screen=null,this.timelineController=e,this.trackName=t}dispatchCue(){this.startTime!==null&&(this.timelineController.addCues(this.trackName,this.startTime,this.endTime,this.screen,this.cueRanges),this.startTime=null)}newCue(e,t,s){(this.startTime===null||this.startTime>e)&&(this.startTime=e),this.endTime=t,this.screen=s,this.timelineController.createCaptionsTrack(this.trackName)}reset(){this.cueRanges=[],this.startTime=null}}class fu{constructor(e){this.hls=void 0,this.media=null,this.config=void 0,this.enabled=!0,this.Cues=void 0,this.textTracks=[],this.tracks=[],this.initPTS=[],this.unparsedVttFrags=[],this.captionsTracks={},this.nonNativeCaptionsTracks={},this.cea608Parser1=void 0,this.cea608Parser2=void 0,this.lastCc=-1,this.lastSn=-1,this.lastPartIndex=-1,this.prevCC=-1,this.vttCCs=Jr(),this.captionsProperties=void 0,this.hls=e,this.config=e.config,this.Cues=e.config.cueHandler,this.captionsProperties={textTrack1:{label:this.config.captionsTextTrack1Label,languageCode:this.config.captionsTextTrack1LanguageCode},textTrack2:{label:this.config.captionsTextTrack2Label,languageCode:this.config.captionsTextTrack2LanguageCode},textTrack3:{label:this.config.captionsTextTrack3Label,languageCode:this.config.captionsTextTrack3LanguageCode},textTrack4:{label:this.config.captionsTextTrack4Label,languageCode:this.config.captionsTextTrack4LanguageCode}},e.on(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.on(m.SUBTITLE_TRACKS_UPDATED,this.onSubtitleTracksUpdated,this),e.on(m.FRAG_LOADING,this.onFragLoading,this),e.on(m.FRAG_LOADED,this.onFragLoaded,this),e.on(m.FRAG_PARSING_USERDATA,this.onFragParsingUserdata,this),e.on(m.FRAG_DECRYPTED,this.onFragDecrypted,this),e.on(m.INIT_PTS_FOUND,this.onInitPtsFound,this),e.on(m.SUBTITLE_TRACKS_CLEARED,this.onSubtitleTracksCleared,this),e.on(m.BUFFER_FLUSHING,this.onBufferFlushing,this)}destroy(){const{hls:e}=this;e.off(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.off(m.SUBTITLE_TRACKS_UPDATED,this.onSubtitleTracksUpdated,this),e.off(m.FRAG_LOADING,this.onFragLoading,this),e.off(m.FRAG_LOADED,this.onFragLoaded,this),e.off(m.FRAG_PARSING_USERDATA,this.onFragParsingUserdata,this),e.off(m.FRAG_DECRYPTED,this.onFragDecrypted,this),e.off(m.INIT_PTS_FOUND,this.onInitPtsFound,this),e.off(m.SUBTITLE_TRACKS_CLEARED,this.onSubtitleTracksCleared,this),e.off(m.BUFFER_FLUSHING,this.onBufferFlushing,this),this.hls=this.config=this.media=null,this.cea608Parser1=this.cea608Parser2=void 0}initCea608Parsers(){const e=new Qt(this,"textTrack1"),t=new Qt(this,"textTrack2"),s=new Qt(this,"textTrack3"),i=new Qt(this,"textTrack4");this.cea608Parser1=new jr(1,e,t),this.cea608Parser2=new jr(3,s,i)}addCues(e,t,s,i,r){let n=!1;for(let o=r.length;o--;){const c=r[o],l=gu(c[0],c[1],t,s);if(l>=0&&(c[0]=Math.min(c[0],t),c[1]=Math.max(c[1],s),n=!0,l/(s-t)>.5))return}if(n||r.push([t,s]),this.config.renderTextTracksNatively){const o=this.captionsTracks[e];this.Cues.newCue(o,t,s,i)}else{const o=this.Cues.newCue(null,t,s,i);this.hls.trigger(m.CUES_PARSED,{type:"captions",cues:o,track:e})}}onInitPtsFound(e,{frag:t,id:s,initPTS:i,timescale:r,trackId:n}){const{unparsedVttFrags:o}=this;s===B.MAIN&&(this.initPTS[t.cc]={baseTime:i,timescale:r,trackId:n}),o.length&&(this.unparsedVttFrags=[],o.forEach(c=>{this.initPTS[c.frag.cc]?this.onFragLoaded(m.FRAG_LOADED,c):this.hls.trigger(m.SUBTITLE_FRAG_PROCESSED,{success:!1,frag:c.frag,error:new Error("Subtitle discontinuity domain does not match main")})}))}getExistingTrack(e,t){const{media:s}=this;if(s)for(let i=0;i{yt(i[r]),delete i[r]}),this.nonNativeCaptionsTracks={}}onManifestLoading(){this.lastCc=-1,this.lastSn=-1,this.lastPartIndex=-1,this.prevCC=-1,this.vttCCs=Jr(),this._cleanTracks(),this.tracks=[],this.captionsTracks={},this.nonNativeCaptionsTracks={},this.textTracks=[],this.unparsedVttFrags=[],this.initPTS=[],this.cea608Parser1&&this.cea608Parser2&&(this.cea608Parser1.reset(),this.cea608Parser2.reset())}_cleanTracks(){const{media:e}=this;if(!e)return;const t=e.textTracks;if(t)for(let s=0;sr.textCodec===Gs);if(this.config.enableWebVTT||i&&this.config.enableIMSC1){if(ca(this.tracks,s)){this.tracks=s;return}if(this.textTracks=[],this.tracks=s,this.config.renderTextTracksNatively){const n=this.media,o=n?as(n.textTracks):null;if(this.tracks.forEach((c,l)=>{let h;if(o){let u=null;for(let d=0;dl!==null).map(l=>l.label);c.length&&this.hls.logger.warn(`Media element contains unused subtitle tracks: ${c.join(", ")}. Replace media element for each source to clear TextTracks and captions menu.`)}}else if(this.tracks.length){const n=this.tracks.map(o=>({label:o.name,kind:o.type.toLowerCase(),default:o.default,subtitleTrack:o}));this.hls.trigger(m.NON_NATIVE_TEXT_TRACKS_FOUND,{tracks:n})}}}onManifestLoaded(e,t){this.config.enableCEA708Captions&&t.captions&&t.captions.forEach(s=>{const i=/(?:CC|SERVICE)([1-4])/.exec(s.instreamId);if(!i)return;const r=`textTrack${i[1]}`,n=this.captionsProperties[r];n&&(n.label=s.name,s.lang&&(n.languageCode=s.lang),n.media=s)})}closedCaptionsForLevel(e){const t=this.hls.levels[e.level];return t==null?void 0:t.attrs["CLOSED-CAPTIONS"]}onFragLoading(e,t){if(this.enabled&&t.frag.type===B.MAIN){var s,i;const{cea608Parser1:r,cea608Parser2:n,lastSn:o}=this,{cc:c,sn:l}=t.frag,h=(s=(i=t.part)==null?void 0:i.index)!=null?s:-1;r&&n&&(l!==o+1||l===o&&h!==this.lastPartIndex+1||c!==this.lastCc)&&(r.reset(),n.reset()),this.lastCc=c,this.lastSn=l,this.lastPartIndex=h}}onFragLoaded(e,t){const{frag:s,payload:i}=t;if(s.type===B.SUBTITLE)if(i.byteLength){const r=s.decryptdata,n="stats"in t;if(r==null||!r.encrypted||n){const o=this.tracks[s.level],c=this.vttCCs;c[s.cc]||(c[s.cc]={start:s.start,prevCC:this.prevCC,new:!0},this.prevCC=s.cc),o&&o.textCodec===Gs?this._parseIMSC1(s,i):this._parseVTTs(t)}}else this.hls.trigger(m.SUBTITLE_FRAG_PROCESSED,{success:!1,frag:s,error:new Error("Empty subtitle payload")})}_parseIMSC1(e,t){const s=this.hls;Xr(t,this.initPTS[e.cc],i=>{this._appendCues(i,e.level),s.trigger(m.SUBTITLE_FRAG_PROCESSED,{success:!0,frag:e})},i=>{s.logger.log(`Failed to parse IMSC1: ${i}`),s.trigger(m.SUBTITLE_FRAG_PROCESSED,{success:!1,frag:e,error:i})})}_parseVTTs(e){var t;const{frag:s,payload:i}=e,{initPTS:r,unparsedVttFrags:n}=this,o=r.length-1;if(!r[s.cc]&&o===-1){n.push(e);return}const c=this.hls,l=(t=s.initSegment)!=null&&t.data?De(s.initSegment.data,new Uint8Array(i)).buffer:i;ou(l,this.initPTS[s.cc],this.vttCCs,s.cc,s.start,h=>{this._appendCues(h,s.level),c.trigger(m.SUBTITLE_FRAG_PROCESSED,{success:!0,frag:s})},h=>{const u=h.message==="Missing initPTS for VTT MPEGTS";u?n.push(e):this._fallbackToIMSC1(s,i),c.logger.log(`Failed to parse VTT cue: ${h}`),!(u&&o>s.cc)&&c.trigger(m.SUBTITLE_FRAG_PROCESSED,{success:!1,frag:s,error:h})})}_fallbackToIMSC1(e,t){const s=this.tracks[e.level];s.textCodec||Xr(t,this.initPTS[e.cc],()=>{s.textCodec=Gs,this._parseIMSC1(e,t)},()=>{s.textCodec="wvtt"})}_appendCues(e,t){const s=this.hls;if(this.config.renderTextTracksNatively){const i=this.textTracks[t];if(!i||i.mode==="disabled")return;e.forEach(r=>Aa(i,r))}else{const i=this.tracks[t];if(!i)return;const r=i.default?"default":"subtitles"+t;s.trigger(m.CUES_PARSED,{type:"subtitles",cues:e,track:r})}}onFragDecrypted(e,t){const{frag:s}=t;s.type===B.SUBTITLE&&this.onFragLoaded(m.FRAG_LOADED,t)}onSubtitleTracksCleared(){this.tracks=[],this.captionsTracks={}}onFragParsingUserdata(e,t){if(!this.enabled||!this.config.enableCEA708Captions)return;const{frag:s,samples:i}=t;if(!(s.type===B.MAIN&&this.closedCaptionsForLevel(s)==="NONE"))for(let r=0;rci(o[c],t,s))}if(this.config.renderTextTracksNatively&&t===0&&i!==void 0){const{textTracks:o}=this;Object.keys(o).forEach(c=>ci(o[c],t,i))}}}extractCea608Data(e){const t=[[],[]],s=e[0]&31;let i=2;for(let r=0;r=16?c--:c++;const f=Da(l.trim()),g=Mi(e,t,f);a!=null&&(u=a.cues)!=null&&u.getCueById(g)||(n=new h(e,t,f),n.id=g,n.line=d+1,n.align="left",n.position=10+Math.min(80,Math.floor(c*8/32)*10),i.push(n))}return a&&i.length&&(i.sort((d,f)=>d.line==="auto"||f.line==="auto"?0:d.line>8&&f.line>8?f.line-d.line:d.line-f.line),i.forEach(d=>Aa(a,d))),i}};function yu(){if(self.fetch&&self.AbortController&&self.ReadableStream&&self.Request)try{return new self.ReadableStream({}),!0}catch{}return!1}const Eu=/(\d+)-(\d+)\/(\d+)/;class en{constructor(e){this.fetchSetup=void 0,this.requestTimeout=void 0,this.request=null,this.response=null,this.controller=void 0,this.context=null,this.config=null,this.callbacks=null,this.stats=void 0,this.loader=null,this.fetchSetup=e.fetchSetup||xu,this.controller=new self.AbortController,this.stats=new gi}destroy(){this.loader=this.callbacks=this.context=this.config=this.request=null,this.abortInternal(),this.response=null,this.fetchSetup=this.controller=this.stats=null}abortInternal(){this.controller&&!this.stats.loading.end&&(this.stats.aborted=!0,this.controller.abort())}abort(){var e;this.abortInternal(),(e=this.callbacks)!=null&&e.onAbort&&this.callbacks.onAbort(this.stats,this.context,this.response)}load(e,t,s){const i=this.stats;if(i.loading.start)throw new Error("Loader can only be used once.");i.loading.start=self.performance.now();const r=Tu(e,this.controller.signal),n=e.responseType==="arraybuffer",o=n?"byteLength":"length",{maxTimeToFirstByteMs:c,maxLoadTimeMs:l}=t.loadPolicy;this.context=e,this.config=t,this.callbacks=s,this.request=this.fetchSetup(e,r),self.clearTimeout(this.requestTimeout),t.timeout=c&&M(c)?c:l,this.requestTimeout=self.setTimeout(()=>{this.callbacks&&(this.abortInternal(),this.callbacks.onTimeout(i,e,this.response))},t.timeout),(Nt(this.request)?this.request.then(self.fetch):self.fetch(this.request)).then(u=>{var d;this.response=this.loader=u;const f=Math.max(self.performance.now(),i.loading.start);if(self.clearTimeout(this.requestTimeout),t.timeout=l,this.requestTimeout=self.setTimeout(()=>{this.callbacks&&(this.abortInternal(),this.callbacks.onTimeout(i,e,this.response))},l-(f-i.loading.start)),!u.ok){const{status:y,statusText:p}=u;throw new Au(p||"fetch, bad network response",y,u)}i.loading.first=f,i.total=vu(u.headers)||i.total;const g=(d=this.callbacks)==null?void 0:d.onProgress;return g&&M(t.highWaterMark)?this.loadProgressively(u,i,e,t.highWaterMark,g):n?u.arrayBuffer():e.responseType==="json"?u.json():u.text()}).then(u=>{var d,f;const g=this.response;if(!g)throw new Error("loader destroyed");self.clearTimeout(this.requestTimeout),i.loading.end=Math.max(self.performance.now(),i.loading.first);const y=u[o];y&&(i.loaded=i.total=y);const p={url:g.url,data:u,code:g.status},E=(d=this.callbacks)==null?void 0:d.onProgress;E&&!M(t.highWaterMark)&&E(i,e,u,g),(f=this.callbacks)==null||f.onSuccess(p,i,e,g)}).catch(u=>{var d;if(self.clearTimeout(this.requestTimeout),i.aborted)return;const f=u&&u.code||0,g=u?u.message:null;(d=this.callbacks)==null||d.onError({code:f,text:g},e,u?u.details:null,i)})}getCacheAge(){let e=null;if(this.response){const t=this.response.headers.get("age");e=t?parseFloat(t):null}return e}getResponseHeader(e){return this.response?this.response.headers.get(e):null}loadProgressively(e,t,s,i=0,r){const n=new Vn,o=e.body.getReader(),c=()=>o.read().then(l=>{if(l.done)return n.dataLength&&r(t,s,n.flush().buffer,e),Promise.resolve(new ArrayBuffer(0));const h=l.value,u=h.length;return t.loaded+=u,u=i&&r(t,s,n.flush().buffer,e)):r(t,s,h.buffer,e),c()}).catch(()=>Promise.reject());return c()}}function Tu(a,e){const t={method:"GET",mode:"cors",credentials:"same-origin",signal:e,headers:new self.Headers(ie({},a.headers))};return a.rangeEnd&&t.headers.set("Range","bytes="+a.rangeStart+"-"+String(a.rangeEnd-1)),t}function Su(a){const e=Eu.exec(a);if(e)return parseInt(e[2])-parseInt(e[1])+1}function vu(a){const e=a.get("Content-Range");if(e){const s=Su(e);if(M(s))return s}const t=a.get("Content-Length");if(t)return parseInt(t)}function xu(a,e){return new self.Request(a.url,e)}class Au extends Error{constructor(e,t,s){super(e),this.code=void 0,this.details=void 0,this.code=t,this.details=s}}const Iu=/^age:\s*[\d.]+\s*$/im;class Oa{constructor(e){this.xhrSetup=void 0,this.requestTimeout=void 0,this.retryTimeout=void 0,this.retryDelay=void 0,this.config=null,this.callbacks=null,this.context=null,this.loader=null,this.stats=void 0,this.xhrSetup=e&&e.xhrSetup||null,this.stats=new gi,this.retryDelay=0}destroy(){this.callbacks=null,this.abortInternal(),this.loader=null,this.config=null,this.context=null,this.xhrSetup=null}abortInternal(){const e=this.loader;self.clearTimeout(this.requestTimeout),self.clearTimeout(this.retryTimeout),e&&(e.onreadystatechange=null,e.onprogress=null,e.readyState!==4&&(this.stats.aborted=!0,e.abort()))}abort(){var e;this.abortInternal(),(e=this.callbacks)!=null&&e.onAbort&&this.callbacks.onAbort(this.stats,this.context,this.loader)}load(e,t,s){if(this.stats.loading.start)throw new Error("Loader can only be used once.");this.stats.loading.start=self.performance.now(),this.context=e,this.config=t,this.callbacks=s,this.loadInternal()}loadInternal(){const{config:e,context:t}=this;if(!e||!t)return;const s=this.loader=new self.XMLHttpRequest,i=this.stats;i.loading.first=0,i.loaded=0,i.aborted=!1;const r=this.xhrSetup;r?Promise.resolve().then(()=>{if(!(this.loader!==s||this.stats.aborted))return r(s,t.url)}).catch(n=>{if(!(this.loader!==s||this.stats.aborted))return s.open("GET",t.url,!0),r(s,t.url)}).then(()=>{this.loader!==s||this.stats.aborted||this.openAndSendXhr(s,t,e)}).catch(n=>{var o;(o=this.callbacks)==null||o.onError({code:s.status,text:n.message},t,s,i)}):this.openAndSendXhr(s,t,e)}openAndSendXhr(e,t,s){e.readyState||e.open("GET",t.url,!0);const i=t.headers,{maxTimeToFirstByteMs:r,maxLoadTimeMs:n}=s.loadPolicy;if(i)for(const o in i)e.setRequestHeader(o,i[o]);t.rangeEnd&&e.setRequestHeader("Range","bytes="+t.rangeStart+"-"+(t.rangeEnd-1)),e.onreadystatechange=this.readystatechange.bind(this),e.onprogress=this.loadprogress.bind(this),e.responseType=t.responseType,self.clearTimeout(this.requestTimeout),s.timeout=r&&M(r)?r:n,this.requestTimeout=self.setTimeout(this.loadtimeout.bind(this),s.timeout),e.send()}readystatechange(){const{context:e,loader:t,stats:s}=this;if(!e||!t)return;const i=t.readyState,r=this.config;if(!s.aborted&&i>=2&&(s.loading.first===0&&(s.loading.first=Math.max(self.performance.now(),s.loading.start),r.timeout!==r.loadPolicy.maxLoadTimeMs&&(self.clearTimeout(this.requestTimeout),r.timeout=r.loadPolicy.maxLoadTimeMs,this.requestTimeout=self.setTimeout(this.loadtimeout.bind(this),r.loadPolicy.maxLoadTimeMs-(s.loading.first-s.loading.start)))),i===4)){self.clearTimeout(this.requestTimeout),t.onreadystatechange=null,t.onprogress=null;const l=t.status,h=t.responseType==="text"?t.responseText:null;if(l>=200&&l<300){const g=h??t.response;if(g!=null){var n,o;s.loading.end=Math.max(self.performance.now(),s.loading.first);const y=t.responseType==="arraybuffer"?g.byteLength:g.length;s.loaded=s.total=y,s.bwEstimate=s.total*8e3/(s.loading.end-s.loading.first);const p=(n=this.callbacks)==null?void 0:n.onProgress;p&&p(s,e,g,t);const E={url:t.responseURL,data:g,code:l};(o=this.callbacks)==null||o.onSuccess(E,s,e,t);return}}const u=r.loadPolicy.errorRetry,d=s.retry,f={url:e.url,data:void 0,code:l};if(fs(u,d,!1,f))this.retry(u);else{var c;se.error(`${l} while loading ${e.url}`),(c=this.callbacks)==null||c.onError({code:l,text:t.statusText},e,t,s)}}}loadtimeout(){if(!this.config)return;const e=this.config.loadPolicy.timeoutRetry,t=this.stats.retry;if(fs(e,t,!0))this.retry(e);else{var s;se.warn(`timeout while loading ${(s=this.context)==null?void 0:s.url}`);const i=this.callbacks;i&&(this.abortInternal(),i.onTimeout(this.stats,this.context,this.loader))}}retry(e){const{context:t,stats:s}=this;this.retryDelay=Ei(e,s.retry),s.retry++,se.warn(`${status?"HTTP Status "+status:"Timeout"} while loading ${t==null?void 0:t.url}, retrying ${s.retry}/${e.maxNumRetry} in ${this.retryDelay}ms`),this.abortInternal(),this.loader=null,self.clearTimeout(this.retryTimeout),this.retryTimeout=self.setTimeout(this.loadInternal.bind(this),this.retryDelay)}loadprogress(e){const t=this.stats;t.loaded=e.loaded,e.lengthComputable&&(t.total=e.total)}getCacheAge(){let e=null;if(this.loader&&Iu.test(this.loader.getAllResponseHeaders())){const t=this.loader.getResponseHeader("age");e=t?parseFloat(t):null}return e}getResponseHeader(e){return this.loader&&new RegExp(`^${e}:\\s*[\\d.]+\\s*$`,"im").test(this.loader.getAllResponseHeaders())?this.loader.getResponseHeader(e):null}}const Lu={maxTimeToFirstByteMs:8e3,maxLoadTimeMs:2e4,timeoutRetry:null,errorRetry:null},Ru=te(te({autoStartLoad:!0,startPosition:-1,defaultAudioCodec:void 0,debug:!1,capLevelOnFPSDrop:!1,capLevelToPlayerSize:!1,ignoreDevicePixelRatio:!1,maxDevicePixelRatio:Number.POSITIVE_INFINITY,preferManagedMediaSource:!0,initialLiveManifestSize:1,maxBufferLength:30,backBufferLength:1/0,frontBufferFlushThreshold:1/0,startOnSegmentBoundary:!1,maxBufferSize:60*1e3*1e3,maxFragLookUpTolerance:.25,maxBufferHole:.1,detectStallWithCurrentTimeMs:1250,highBufferWatchdogPeriod:2,nudgeOffset:.1,nudgeMaxRetry:3,nudgeOnVideoHole:!0,liveSyncMode:"edge",liveSyncDurationCount:3,liveSyncOnStallIncrease:1,liveMaxLatencyDurationCount:1/0,liveSyncDuration:void 0,liveMaxLatencyDuration:void 0,maxLiveSyncPlaybackRate:1,liveDurationInfinity:!1,liveBackBufferLength:null,maxMaxBufferLength:600,enableWorker:!0,workerPath:null,enableSoftwareAES:!0,startLevel:void 0,startFragPrefetch:!1,fpsDroppedMonitoringPeriod:5e3,fpsDroppedMonitoringThreshold:.2,appendErrorMaxRetry:3,ignorePlaylistParsingErrors:!1,loader:Oa,fLoader:void 0,pLoader:void 0,xhrSetup:void 0,licenseXhrSetup:void 0,licenseResponseCallback:void 0,abrController:Bo,bufferController:_c,capLevelController:ki,errorController:Vo,fpsController:Dh,stretchShortVideoTrack:!1,maxAudioFramesDrift:1,forceKeyFrameOnDiscontinuity:!0,abrEwmaFastLive:3,abrEwmaSlowLive:9,abrEwmaFastVoD:3,abrEwmaSlowVoD:9,abrEwmaDefaultEstimate:5e5,abrEwmaDefaultEstimateMax:5e6,abrBandWidthFactor:.95,abrBandWidthUpFactor:.7,abrMaxWithRealBitrate:!1,maxStarvationDelay:4,maxLoadingDelay:4,minAutoBitrate:0,emeEnabled:!1,widevineLicenseUrl:void 0,drmSystems:{},drmSystemOptions:{},requestMediaKeySystemAccessFunc:kn,requireKeySystemAccessOnStart:!1,testBandwidth:!0,progressive:!1,lowLatencyMode:!0,cmcd:void 0,enableDateRangeMetadataCues:!0,enableEmsgMetadataCues:!0,enableEmsgKLVMetadata:!1,enableID3MetadataCues:!0,enableInterstitialPlayback:!0,interstitialAppendInPlace:!0,interstitialLiveLookAhead:10,useMediaCapabilities:!0,preserveManualLevelOnError:!1,certLoadPolicy:{default:Lu},keyLoadPolicy:{default:{maxTimeToFirstByteMs:8e3,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:1,retryDelayMs:1e3,maxRetryDelayMs:2e4,backoff:"linear"},errorRetry:{maxNumRetry:8,retryDelayMs:1e3,maxRetryDelayMs:2e4,backoff:"linear"}}},manifestLoadPolicy:{default:{maxTimeToFirstByteMs:1/0,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:2,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:1,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},playlistLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:2,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:2,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},fragLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:12e4,timeoutRetry:{maxNumRetry:4,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:6,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},steeringManifestLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:2,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:1,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},interstitialAssetListLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:3e4,timeoutRetry:{maxNumRetry:0,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:0,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},manifestLoadingTimeOut:1e4,manifestLoadingMaxRetry:1,manifestLoadingRetryDelay:1e3,manifestLoadingMaxRetryTimeout:64e3,levelLoadingTimeOut:1e4,levelLoadingMaxRetry:4,levelLoadingRetryDelay:1e3,levelLoadingMaxRetryTimeout:64e3,fragLoadingTimeOut:2e4,fragLoadingMaxRetry:6,fragLoadingRetryDelay:1e3,fragLoadingMaxRetryTimeout:64e3},bu()),{},{subtitleStreamController:Gh,subtitleTrackController:kh,timelineController:fu,audioStreamController:Ic,audioTrackController:Lc,emeController:St,cmcdController:Lh,contentSteeringController:bh,interstitialsController:$h});function bu(){return{cueHandler:pu,enableWebVTT:!0,enableIMSC1:!0,enableCEA708Captions:!0,captionsTextTrack1Label:"English",captionsTextTrack1LanguageCode:"en",captionsTextTrack2Label:"Spanish",captionsTextTrack2LanguageCode:"es",captionsTextTrack3Label:"Unknown CC",captionsTextTrack3LanguageCode:"",captionsTextTrack4Label:"Unknown CC",captionsTextTrack4LanguageCode:"",renderTextTracksNatively:!0}}function _u(a,e,t){if((e.liveSyncDurationCount||e.liveMaxLatencyDurationCount)&&(e.liveSyncDuration||e.liveMaxLatencyDuration))throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration");if(e.liveMaxLatencyDurationCount!==void 0&&(e.liveSyncDurationCount===void 0||e.liveMaxLatencyDurationCount<=e.liveSyncDurationCount))throw new Error('Illegal hls.js config: "liveMaxLatencyDurationCount" must be greater than "liveSyncDurationCount"');if(e.liveMaxLatencyDuration!==void 0&&(e.liveSyncDuration===void 0||e.liveMaxLatencyDuration<=e.liveSyncDuration))throw new Error('Illegal hls.js config: "liveMaxLatencyDuration" must be greater than "liveSyncDuration"');const s=ui(a),i=["manifest","level","frag"],r=["TimeOut","MaxRetry","RetryDelay","MaxRetryTimeout"];return i.forEach(n=>{const o=`${n==="level"?"playlist":n}LoadPolicy`,c=e[o]===void 0,l=[];r.forEach(h=>{const u=`${n}Loading${h}`,d=e[u];if(d!==void 0&&c){l.push(u);const f=s[o].default;switch(e[o]={default:f},h){case"TimeOut":f.maxLoadTimeMs=d,f.maxTimeToFirstByteMs=d;break;case"MaxRetry":f.errorRetry.maxNumRetry=d,f.timeoutRetry.maxNumRetry=d;break;case"RetryDelay":f.errorRetry.retryDelayMs=d,f.timeoutRetry.retryDelayMs=d;break;case"MaxRetryTimeout":f.errorRetry.maxRetryDelayMs=d,f.timeoutRetry.maxRetryDelayMs=d;break}}}),l.length&&t.warn(`hls.js config: "${l.join('", "')}" setting(s) are deprecated, use "${o}": ${ne(e[o])}`)}),te(te({},s),e)}function ui(a){return a&&typeof a=="object"?Array.isArray(a)?a.map(ui):Object.keys(a).reduce((e,t)=>(e[t]=ui(a[t]),e),{}):a}function Du(a,e){const t=a.loader;t!==en&&t!==Oa?(e.log("[config]: Custom loader detected, cannot enable progressive streaming"),a.progressive=!1):yu()&&(a.loader=en,a.progressive=!0,a.enableSoftwareAES=!0,e.log("[config]: Progressive streaming enabled, using FetchLoader"))}const os=2,Cu=.1,Pu=.05,ku=100;class wu extends bn{constructor(e,t){super("gap-controller",e.logger),this.hls=void 0,this.fragmentTracker=void 0,this.media=null,this.mediaSource=void 0,this.nudgeRetry=0,this.stallReported=!1,this.stalled=null,this.moved=!1,this.seeking=!1,this.buffered={},this.lastCurrentTime=0,this.ended=0,this.waiting=0,this.onMediaPlaying=()=>{this.ended=0,this.waiting=0},this.onMediaWaiting=()=>{var s;(s=this.media)!=null&&s.seeking||(this.waiting=self.performance.now(),this.tick())},this.onMediaEnded=()=>{if(this.hls){var s;this.ended=((s=this.media)==null?void 0:s.currentTime)||1,this.hls.trigger(m.MEDIA_ENDED,{stalled:!1})}},this.hls=e,this.fragmentTracker=t,this.registerListeners()}registerListeners(){const{hls:e}=this;e&&(e.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.BUFFER_APPENDED,this.onBufferAppended,this))}unregisterListeners(){const{hls:e}=this;e&&(e.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.BUFFER_APPENDED,this.onBufferAppended,this))}destroy(){super.destroy(),this.unregisterListeners(),this.media=this.hls=this.fragmentTracker=null,this.mediaSource=void 0}onMediaAttached(e,t){this.setInterval(ku),this.mediaSource=t.mediaSource;const s=this.media=t.media;Te(s,"playing",this.onMediaPlaying),Te(s,"waiting",this.onMediaWaiting),Te(s,"ended",this.onMediaEnded)}onMediaDetaching(e,t){this.clearInterval();const{media:s}=this;s&&(ve(s,"playing",this.onMediaPlaying),ve(s,"waiting",this.onMediaWaiting),ve(s,"ended",this.onMediaEnded),this.media=null),this.mediaSource=void 0}onBufferAppended(e,t){this.buffered=t.timeRanges}get hasBuffered(){return Object.keys(this.buffered).length>0}tick(){var e;if(!((e=this.media)!=null&&e.readyState)||!this.hasBuffered)return;const t=this.media.currentTime;this.poll(t,this.lastCurrentTime),this.lastCurrentTime=t}poll(e,t){var s,i;const r=(s=this.hls)==null?void 0:s.config;if(!r)return;const n=this.media;if(!n)return;const{seeking:o}=n,c=this.seeking&&!o,l=!this.seeking&&o,h=n.paused&&!o||n.ended||n.playbackRate===0;if(this.seeking=o,e!==t){t&&(this.ended=0),this.moved=!0,o||(this.nudgeRetry=0,r.nudgeOnVideoHole&&!h&&e>t&&this.nudgeOnVideoHole(e,t)),this.waiting===0&&this.stallResolved(e);return}if(l||c){c&&this.stallResolved(e);return}if(h){this.nudgeRetry=0,this.stallResolved(e),!this.ended&&n.ended&&this.hls&&(this.ended=e||1,this.hls.trigger(m.MEDIA_ENDED,{stalled:!1}));return}if(!q.getBuffered(n).length){this.nudgeRetry=0;return}const u=q.bufferInfo(n,e,0),d=u.nextStart||0,f=this.fragmentTracker;if(o&&f&&this.hls){const D=tn(this.hls.inFlightFragments,e),A=u.len>os,_=!d||D||d-e>os&&!f.getPartialFragment(e);if(A||_)return;this.moved=!1}const g=(i=this.hls)==null?void 0:i.latestLevelDetails;if(!this.moved&&this.stalled!==null&&f){if(!(u.len>0)&&!d)return;const A=Math.max(d,u.start||0)-e,b=!!(g!=null&&g.live)?g.targetduration*2:os,I=Zt(e,f);if(A>0&&(A<=b||I)){n.paused||this._trySkipBufferHole(I);return}}const y=r.detectStallWithCurrentTimeMs,p=self.performance.now(),E=this.waiting;let T=this.stalled;if(T===null)if(E>0&&p-E=y||E)&&this.hls){var v;if(((v=this.mediaSource)==null?void 0:v.readyState)==="ended"&&!(g!=null&&g.live)&&Math.abs(e-((g==null?void 0:g.edge)||0))<1){if(this.ended)return;this.ended=e||1,this.hls.trigger(m.MEDIA_ENDED,{stalled:!0});return}if(this._reportStall(u),!this.media||!this.hls)return}const x=q.bufferInfo(n,e,r.maxBufferHole);this._tryFixBufferStall(x,S,e)}stallResolved(e){const t=this.stalled;if(t&&this.hls&&(this.stalled=null,this.stallReported)){const s=self.performance.now()-t;this.log(`playback not stuck anymore @${e}, after ${Math.round(s)}ms`),this.stallReported=!1,this.waiting=0,this.hls.trigger(m.STALL_RESOLVED,{})}}nudgeOnVideoHole(e,t){var s;const i=this.buffered.video;if(this.hls&&this.media&&this.fragmentTracker&&(s=this.buffered.audio)!=null&&s.length&&i&&i.length>1&&e>i.end(0)){const r=q.bufferedInfo(q.timeRangesToArray(this.buffered.audio),e,0);if(r.len>1&&t>=r.start){const n=q.timeRangesToArray(i),o=q.bufferedInfo(n,t,0).bufferedIndex;if(o>-1&&oo)&&h-l<1&&e-l<2){const u=new Error(`nudging playhead to flush pipeline after video hole. currentTime: ${e} hole: ${l} -> ${h} buffered index: ${c}`);this.warn(u.message),this.media.currentTime+=1e-6;let d=Zt(e,this.fragmentTracker);d&&"fragment"in d?d=d.fragment:d||(d=void 0);const f=q.bufferInfo(this.media,e,0);this.hls.trigger(m.ERROR,{type:V.MEDIA_ERROR,details:R.BUFFER_SEEK_OVER_HOLE,fatal:!1,error:u,reason:u.message,frag:d,buffer:f.len,bufferInfo:f})}}}}}_tryFixBufferStall(e,t,s){var i,r;const{fragmentTracker:n,media:o}=this,c=(i=this.hls)==null?void 0:i.config;if(!o||!n||!c)return;const l=(r=this.hls)==null?void 0:r.latestLevelDetails,h=Zt(s,n);if((h||l!=null&&l.live&&s1&&e.len>c.maxBufferHole||e.nextStart&&(e.nextStart-sc.highBufferWatchdogPeriod*1e3||this.waiting)&&(this.warn("Trying to nudge playhead over buffer-hole"),this._tryNudgeBuffer(e))}adjacentTraversal(e,t){const s=this.fragmentTracker,i=e.nextStart;if(s&&i){const r=s.getFragAtPos(t,B.MAIN),n=s.getFragAtPos(i,B.MAIN);if(r&&n)return n.sn-r.sn<2}return!1}_reportStall(e){const{hls:t,media:s,stallReported:i,stalled:r}=this;if(!i&&r!==null&&s&&t){this.stallReported=!0;const n=new Error(`Playback stalling at @${s.currentTime} due to low buffer (${ne(e)})`);this.warn(n.message),t.trigger(m.ERROR,{type:V.MEDIA_ERROR,details:R.BUFFER_STALLED_ERROR,fatal:!1,error:n,buffer:e.len,bufferInfo:e,stalled:{start:r}})}}_trySkipBufferHole(e){var t;const{fragmentTracker:s,media:i}=this,r=(t=this.hls)==null?void 0:t.config;if(!i||!s||!r)return 0;const n=i.currentTime,o=q.bufferInfo(i,n,0),c=n0&&o.len<1&&i.readyState<3,d=c-n;if(d>0&&(h||u)){if(d>r.maxBufferHole){let g=!1;if(n===0){const y=s.getAppendedFrag(0,B.MAIN);y&&c"u"))return self.VTTCue||self.TextTrackCue}function Ys(a,e,t,s,i){let r=new a(e,t,"");try{r.value=s,i&&(r.type=i)}catch{r=new a(e,t,ne(i?te({type:i},s):s))}return r}const Jt=(()=>{const a=di();try{a&&new a(0,Number.POSITIVE_INFINITY,"")}catch{return Number.MAX_VALUE}return Number.POSITIVE_INFINITY})();class Fu{constructor(e){this.hls=void 0,this.id3Track=null,this.media=null,this.dateRangeCuesAppended={},this.removeCues=!0,this.assetCue=void 0,this.onEventCueEnter=()=>{this.hls&&this.hls.trigger(m.EVENT_CUE_ENTER,{})},this.hls=e,this._registerListeners()}destroy(){this._unregisterListeners(),this.id3Track=null,this.media=null,this.dateRangeCuesAppended={},this.hls=this.onEventCueEnter=null}_registerListeners(){const{hls:e}=this;e&&(e.on(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.FRAG_PARSING_METADATA,this.onFragParsingMetadata,this),e.on(m.BUFFER_FLUSHING,this.onBufferFlushing,this),e.on(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.on(m.LEVEL_PTS_UPDATED,this.onLevelPtsUpdated,this))}_unregisterListeners(){const{hls:e}=this;e&&(e.off(m.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.FRAG_PARSING_METADATA,this.onFragParsingMetadata,this),e.off(m.BUFFER_FLUSHING,this.onBufferFlushing,this),e.off(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.off(m.LEVEL_PTS_UPDATED,this.onLevelPtsUpdated,this))}onMediaAttaching(e,t){var s;this.media=t.media,((s=t.overrides)==null?void 0:s.cueRemoval)===!1&&(this.removeCues=!1)}onMediaAttached(){var e;const t=(e=this.hls)==null?void 0:e.latestLevelDetails;t&&this.updateDateRangeCues(t)}onMediaDetaching(e,t){this.media=null,!t.transferMedia&&(this.id3Track&&(this.removeCues&&yt(this.id3Track,this.onEventCueEnter),this.id3Track=null),this.dateRangeCuesAppended={})}onManifestLoading(){this.dateRangeCuesAppended={}}createTrack(e){const t=this.getID3Track(e.textTracks);return t.mode="hidden",t}getID3Track(e){if(this.media){for(let t=0;tJt&&(u=Jt),u-h<=0&&(u=h+Ou);for(let f=0;fh.type===Le.audioId3&&c:i==="video"?l=h=>h.type===Le.emsg&&o:l=h=>h.type===Le.audioId3&&c||h.type===Le.emsg&&o,ci(r,t,s,l)}}onLevelUpdated(e,{details:t}){this.updateDateRangeCues(t,!0)}onLevelPtsUpdated(e,t){Math.abs(t.drift)>.01&&this.updateDateRangeCues(t.details)}updateDateRangeCues(e,t){if(!this.hls||!this.media)return;const{assetPlayerId:s,timelineOffset:i,enableDateRangeMetadataCues:r,interstitialsController:n}=this.hls.config;if(!r)return;const o=di();if(s&&i&&!n){const{fragmentStart:y,fragmentEnd:p}=e;let E=this.assetCue;E?(E.startTime=y,E.endTime=p):o&&(E=this.assetCue=Ys(o,y,p,{assetPlayerId:this.hls.config.assetPlayerId},"hlsjs.interstitial.asset"),E&&(E.id=s,this.id3Track||(this.id3Track=this.createTrack(this.media)),this.id3Track.addCue(E),E.addEventListener("enter",this.onEventCueEnter)))}if(!e.hasProgramDateTime)return;const{id3Track:c}=this,{dateRanges:l}=e,h=Object.keys(l);let u=this.dateRangeCuesAppended;if(c&&t){var d;if((d=c.cues)!=null&&d.length){const y=Object.keys(u).filter(p=>!h.includes(p));for(let p=y.length;p--;){var f;const E=y[p],T=(f=u[E])==null?void 0:f.cues;delete u[E],T&&Object.keys(T).forEach(S=>{const v=T[S];if(v){v.removeEventListener("enter",this.onEventCueEnter);try{c.removeCue(v)}catch{}}})}}else u=this.dateRangeCuesAppended={}}const g=e.fragments[e.fragments.length-1];if(!(h.length===0||!M(g==null?void 0:g.programDateTime))){this.id3Track||(this.id3Track=this.createTrack(this.media));for(let y=0;y{if(F!==E.id){const U=l[F];if(U.class===E.class&&U.startDate>E.startDate&&(!P||E.startDate.01&&(F.startTime=T,F.endTime=D);else if(o){let U=E.attr[P];il(P)&&(U=on(U));const $=Ys(o,T,D,{key:P,data:U},Le.dateRange);$&&($.id=p,this.id3Track.addCue($),v[P]=$,n&&(P==="X-ASSET-LIST"||P==="X-ASSET-URL")&&$.addEventListener("enter",this.onEventCueEnter))}}u[p]={cues:v,dateRange:E,durationKnown:x}}}}}class Mu{constructor(e){this.hls=void 0,this.config=void 0,this.media=null,this.currentTime=0,this.stallCount=0,this._latency=null,this._targetLatencyUpdated=!1,this.onTimeupdate=()=>{const{media:t}=this,s=this.levelDetails;if(!t||!s)return;this.currentTime=t.currentTime;const i=this.computeLatency();if(i===null)return;this._latency=i;const{lowLatencyMode:r,maxLiveSyncPlaybackRate:n}=this.config;if(!r||n===1||!s.live)return;const o=this.targetLatency;if(o===null)return;const c=i-o,l=Math.min(this.maxLatency,o+s.targetduration);if(c.05&&this.forwardBufferLength>1){const u=Math.min(2,Math.max(1,n)),d=Math.round(2/(1+Math.exp(-.75*c-this.edgeStalled))*20)/20,f=Math.min(u,Math.max(1,d));this.changeMediaPlaybackRate(t,f)}else t.playbackRate!==1&&t.playbackRate!==0&&this.changeMediaPlaybackRate(t,1)},this.hls=e,this.config=e.config,this.registerListeners()}get levelDetails(){var e;return((e=this.hls)==null?void 0:e.latestLevelDetails)||null}get latency(){return this._latency||0}get maxLatency(){const{config:e}=this;if(e.liveMaxLatencyDuration!==void 0)return e.liveMaxLatencyDuration;const t=this.levelDetails;return t?e.liveMaxLatencyDurationCount*t.targetduration:0}get targetLatency(){const e=this.levelDetails;if(e===null||this.hls===null)return null;const{holdBack:t,partHoldBack:s,targetduration:i}=e,{liveSyncDuration:r,liveSyncDurationCount:n,lowLatencyMode:o}=this.config,c=this.hls.userConfig;let l=o&&s||t;(this._targetLatencyUpdated||c.liveSyncDuration||c.liveSyncDurationCount||l===0)&&(l=r!==void 0?r:n*i);const h=i;return l+Math.min(this.stallCount*this.config.liveSyncOnStallIncrease,h)}set targetLatency(e){this.stallCount=0,this.config.liveSyncDuration=e,this._targetLatencyUpdated=!0}get liveSyncPosition(){const e=this.estimateLiveEdge(),t=this.targetLatency;if(e===null||t===null)return null;const s=this.levelDetails;if(s===null)return null;const i=s.edge,r=e-t-this.edgeStalled,n=i-s.totalduration,o=i-(this.config.lowLatencyMode&&s.partTarget||s.targetduration);return Math.min(Math.max(n,r),o)}get drift(){const e=this.levelDetails;return e===null?1:e.drift}get edgeStalled(){const e=this.levelDetails;if(e===null)return 0;const t=(this.config.lowLatencyMode&&e.partTarget||e.targetduration)*3;return Math.max(e.age-t,0)}get forwardBufferLength(){const{media:e}=this,t=this.levelDetails;if(!e||!t)return 0;const s=e.buffered.length;return(s?e.buffered.end(s-1):t.edge)-this.currentTime}destroy(){this.unregisterListeners(),this.onMediaDetaching(),this.hls=null}registerListeners(){const{hls:e}=this;e&&(e.on(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.on(m.ERROR,this.onError,this))}unregisterListeners(){const{hls:e}=this;e&&(e.off(m.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(m.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.LEVEL_UPDATED,this.onLevelUpdated,this),e.off(m.ERROR,this.onError,this))}onMediaAttached(e,t){this.media=t.media,this.media.addEventListener("timeupdate",this.onTimeupdate)}onMediaDetaching(){this.media&&(this.media.removeEventListener("timeupdate",this.onTimeupdate),this.media=null)}onManifestLoading(){this._latency=null,this.stallCount=0}onLevelUpdated(e,{details:t}){t.advanced&&this.onTimeupdate(),!t.live&&this.media&&this.media.removeEventListener("timeupdate",this.onTimeupdate)}onError(e,t){var s;t.details===R.BUFFER_STALLED_ERROR&&(this.stallCount++,this.hls&&(s=this.levelDetails)!=null&&s.live&&this.hls.logger.warn("[latency-controller]: Stall detected, adjusting target latency"))}changeMediaPlaybackRate(e,t){var s,i;e.playbackRate!==t&&((s=this.hls)==null||s.logger.debug(`[latency-controller]: latency=${this.latency.toFixed(3)}, targetLatency=${(i=this.targetLatency)==null?void 0:i.toFixed(3)}, forwardBufferLength=${this.forwardBufferLength.toFixed(3)}: adjusting playback rate from ${e.playbackRate} to ${t}`),e.playbackRate=t)}estimateLiveEdge(){const e=this.levelDetails;return e===null?null:e.edge+e.age}computeLatency(){const e=this.estimateLiveEdge();return e===null?null:e-this.currentTime}}class Nu extends Pi{constructor(e,t){super(e,"level-controller"),this._levels=[],this._firstLevel=-1,this._maxAutoLevel=-1,this._startLevel=void 0,this.currentLevel=null,this.currentLevelIndex=-1,this.manualLevelIndex=-1,this.steering=void 0,this.onParsedComplete=void 0,this.steering=t,this._registerListeners()}_registerListeners(){const{hls:e}=this;e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.on(m.LEVEL_LOADED,this.onLevelLoaded,this),e.on(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.on(m.FRAG_BUFFERED,this.onFragBuffered,this),e.on(m.ERROR,this.onError,this)}_unregisterListeners(){const{hls:e}=this;e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.MANIFEST_LOADED,this.onManifestLoaded,this),e.off(m.LEVEL_LOADED,this.onLevelLoaded,this),e.off(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.off(m.FRAG_BUFFERED,this.onFragBuffered,this),e.off(m.ERROR,this.onError,this)}destroy(){this._unregisterListeners(),this.steering=null,this.resetLevels(),super.destroy()}stopLoad(){this._levels.forEach(t=>{t.loadError=0,t.fragmentError=0}),super.stopLoad()}resetLevels(){this._startLevel=void 0,this.manualLevelIndex=-1,this.currentLevelIndex=-1,this.currentLevel=null,this._levels=[],this._maxAutoLevel=-1}onManifestLoading(e,t){this.resetLevels()}onManifestLoaded(e,t){const s=this.hls.config.preferManagedMediaSource,i=[],r={},n={};let o=!1,c=!1,l=!1;t.levels.forEach(h=>{const u=h.attrs;let{audioCodec:d,videoCodec:f}=h;d&&(h.audioCodec=d=cs(d,s)||void 0),f&&(f=h.videoCodec=To(f));const{width:g,height:y,unknownCodecs:p}=h,E=(p==null?void 0:p.length)||0;if(o||(o=!!(g&&y)),c||(c=!!f),l||(l=!!d),E||d&&!this.isAudioSupported(d)||f&&!this.isVideoSupported(f)){this.log(`Some or all CODECS not supported "${u.CODECS}"`);return}const{CODECS:T,"FRAME-RATE":S,"HDCP-LEVEL":v,"PATHWAY-ID":x,RESOLUTION:D,"VIDEO-RANGE":A}=u,b=`${`${x||"."}-`}${h.bitrate}-${D}-${S}-${T}-${A}-${v}`;if(r[b])if(r[b].uri!==h.url&&!h.attrs["PATHWAY-ID"]){const I=n[b]+=1;h.attrs["PATHWAY-ID"]=new Array(I+1).join(".");const P=this.createLevel(h);r[b]=P,i.push(P)}else r[b].addGroupId("audio",u.AUDIO),r[b].addGroupId("text",u.SUBTITLES);else{const I=this.createLevel(h);r[b]=I,n[b]=1,i.push(I)}}),this.filterAndSortMediaOptions(i,t,o,c,l)}createLevel(e){const t=new Ot(e),s=e.supplemental;if(s!=null&&s.videoCodec&&!this.isVideoSupported(s.videoCodec)){const i=new Error(`SUPPLEMENTAL-CODECS not supported "${s.videoCodec}"`);this.log(i.message),t.supportedResult=Tn(i,[])}return t}isAudioSupported(e){return kt(e,"audio",this.hls.config.preferManagedMediaSource)}isVideoSupported(e){return kt(e,"video",this.hls.config.preferManagedMediaSource)}filterAndSortMediaOptions(e,t,s,i,r){var n;let o=[],c=[],l=e;const h=((n=t.stats)==null?void 0:n.parsing)||{};if((s||i)&&r&&(l=l.filter(({videoCodec:T,videoRange:S,width:v,height:x})=>(!!T||!!(v&&x))&&Do(S))),l.length===0){Promise.resolve().then(()=>{if(this.hls){let T="no level with compatible codecs found in manifest",S=T;t.levels.length&&(S=`one or more CODECS in variant not supported: ${ne(t.levels.map(x=>x.attrs.CODECS).filter((x,D,A)=>A.indexOf(x)===D))}`,this.warn(S),T+=` (${S})`);const v=new Error(T);this.hls.trigger(m.ERROR,{type:V.MEDIA_ERROR,details:R.MANIFEST_INCOMPATIBLE_CODECS_ERROR,fatal:!0,url:t.url,error:v,reason:S})}}),h.end=performance.now();return}t.audioTracks&&(o=t.audioTracks.filter(T=>!T.audioCodec||this.isAudioSupported(T.audioCodec)),rn(o)),t.subtitles&&(c=t.subtitles,rn(c));const u=l.slice(0);l.sort((T,S)=>{if(T.attrs["HDCP-LEVEL"]!==S.attrs["HDCP-LEVEL"])return(T.attrs["HDCP-LEVEL"]||"")>(S.attrs["HDCP-LEVEL"]||"")?1:-1;if(s&&T.height!==S.height)return T.height-S.height;if(T.frameRate!==S.frameRate)return T.frameRate-S.frameRate;if(T.videoRange!==S.videoRange)return hs.indexOf(T.videoRange)-hs.indexOf(S.videoRange);if(T.videoCodec!==S.videoCodec){const v=ji(T.videoCodec),x=ji(S.videoCodec);if(v!==x)return x-v}if(T.uri===S.uri&&T.codecSet!==S.codecSet){const v=ls(T.codecSet),x=ls(S.codecSet);if(v!==x)return x-v}return T.averageBitrate!==S.averageBitrate?T.averageBitrate-S.averageBitrate:0});let d=u[0];if(this.steering&&(l=this.steering.filterParsedLevels(l),l.length!==u.length)){for(let T=0;Tv&&v===this.hls.abrEwmaDefaultEstimate&&(this.hls.bandwidthEstimate=x)}break}const g=r&&!i,y=this.hls.config,p=!!(y.audioStreamController&&y.audioTrackController),E={levels:l,audioTracks:o,subtitleTracks:c,sessionData:t.sessionData,sessionKeys:t.sessionKeys,firstLevel:this._firstLevel,stats:t.stats,audio:r,video:i,altAudio:p&&!g&&o.some(T=>!!T.url)};h.end=performance.now(),this.hls.trigger(m.MANIFEST_PARSED,E)}get levels(){return this._levels.length===0?null:this._levels}get loadLevelObj(){return this.currentLevel}get level(){return this.currentLevelIndex}set level(e){const t=this._levels;if(t.length===0)return;if(e<0||e>=t.length){const h=new Error("invalid level idx"),u=e<0;if(this.hls.trigger(m.ERROR,{type:V.OTHER_ERROR,details:R.LEVEL_SWITCH_ERROR,level:e,fatal:u,error:h,reason:h.message}),u)return;e=Math.min(e,t.length-1)}const s=this.currentLevelIndex,i=this.currentLevel,r=i?i.attrs["PATHWAY-ID"]:void 0,n=t[e],o=n.attrs["PATHWAY-ID"];if(this.currentLevelIndex=e,this.currentLevel=n,s===e&&i&&r===o)return;this.log(`Switching to level ${e} (${n.height?n.height+"p ":""}${n.videoRange?n.videoRange+" ":""}${n.codecSet?n.codecSet+" ":""}@${n.bitrate})${o?" with Pathway "+o:""} from level ${s}${r?" with Pathway "+r:""}`);const c={level:e,attrs:n.attrs,details:n.details,bitrate:n.bitrate,averageBitrate:n.averageBitrate,maxBitrate:n.maxBitrate,realBitrate:n.realBitrate,width:n.width,height:n.height,codecSet:n.codecSet,audioCodec:n.audioCodec,videoCodec:n.videoCodec,audioGroups:n.audioGroups,subtitleGroups:n.subtitleGroups,loaded:n.loaded,loadError:n.loadError,fragmentError:n.fragmentError,name:n.name,id:n.id,uri:n.uri,url:n.url,urlId:0,audioGroupIds:n.audioGroupIds,textGroupIds:n.textGroupIds};this.hls.trigger(m.LEVEL_SWITCHING,c);const l=n.details;if(!l||l.live){const h=this.switchParams(n.uri,i==null?void 0:i.details,l);this.loadPlaylist(h)}}get manualLevel(){return this.manualLevelIndex}set manualLevel(e){this.manualLevelIndex=e,this._startLevel===void 0&&(this._startLevel=e),e!==-1&&(this.level=e)}get firstLevel(){return this._firstLevel}set firstLevel(e){this._firstLevel=e}get startLevel(){if(this._startLevel===void 0){const e=this.hls.config.startLevel;return e!==void 0?e:this.hls.firstAutoLevel}return this._startLevel}set startLevel(e){this._startLevel=e}get pathways(){return this.steering?this.steering.pathways():[]}get pathwayPriority(){return this.steering?this.steering.pathwayPriority:null}set pathwayPriority(e){if(this.steering){const t=this.steering.pathways(),s=e.filter(i=>t.indexOf(i)!==-1);if(e.length<1){this.warn(`pathwayPriority ${e} should contain at least one pathway from list: ${t}`);return}this.steering.pathwayPriority=s}}onError(e,t){t.fatal||!t.context||t.context.type===Q.LEVEL&&t.context.level===this.level&&this.checkRetry(t)}onFragBuffered(e,{frag:t}){if(t!==void 0&&t.type===B.MAIN){const s=t.elementaryStreams;if(!Object.keys(s).some(r=>!!s[r]))return;const i=this._levels[t.level];i!=null&&i.loadError&&(this.log(`Resetting level error count of ${i.loadError} on frag buffered`),i.loadError=0)}}onLevelLoaded(e,t){var s;const{level:i,details:r}=t,n=t.levelInfo;if(!n){var o;this.warn(`Invalid level index ${i}`),(o=t.deliveryDirectives)!=null&&o.skip&&(r.deltaUpdateFailed=!0);return}if(n===this.currentLevel||t.withoutMultiVariant){n.fragmentError===0&&(n.loadError=0);let c=n.details;c===t.details&&c.advanced&&(c=void 0),this.playlistLoaded(i,t,c)}else(s=t.deliveryDirectives)!=null&&s.skip&&(r.deltaUpdateFailed=!0)}loadPlaylist(e){super.loadPlaylist(),this.shouldLoadPlaylist(this.currentLevel)&&this.scheduleLoading(this.currentLevel,e)}loadingPlaylist(e,t){super.loadingPlaylist(e,t);const s=this.getUrlWithDirectives(e.uri,t),i=this.currentLevelIndex,r=e.attrs["PATHWAY-ID"],n=e.details,o=n==null?void 0:n.age;this.log(`Loading level index ${i}${(t==null?void 0:t.msn)!==void 0?" at sn "+t.msn+" part "+t.part:""}${r?" Pathway "+r:""}${o&&n.live?" age "+o.toFixed(1)+(n.type&&" "+n.type||""):""} ${s}`),this.hls.trigger(m.LEVEL_LOADING,{url:s,level:i,levelInfo:e,pathwayId:e.attrs["PATHWAY-ID"],id:0,deliveryDirectives:t||null})}get nextLoadLevel(){return this.manualLevelIndex!==-1?this.manualLevelIndex:this.hls.nextAutoLevel}set nextLoadLevel(e){this.level=e,this.manualLevelIndex===-1&&(this.hls.nextAutoLevel=e)}removeLevel(e){var t;if(this._levels.length===1)return;const s=this._levels.filter((r,n)=>n!==e?!0:(this.steering&&this.steering.removeLevel(r),r===this.currentLevel&&(this.currentLevel=null,this.currentLevelIndex=-1,r.details&&r.details.fragments.forEach(o=>o.level=-1)),!1));$n(s),this._levels=s,this.currentLevelIndex>-1&&(t=this.currentLevel)!=null&&t.details&&(this.currentLevelIndex=this.currentLevel.details.fragments[0].level),this.manualLevelIndex>-1&&(this.manualLevelIndex=this.currentLevelIndex);const i=s.length-1;this._firstLevel=Math.min(this._firstLevel,i),this._startLevel&&(this._startLevel=Math.min(this._startLevel,i)),this.hls.trigger(m.LEVELS_UPDATED,{levels:s})}onLevelsUpdated(e,{levels:t}){this._levels=t}checkMaxAutoUpdated(){const{autoLevelCapping:e,maxAutoLevel:t,maxHdcpLevel:s}=this.hls;this._maxAutoLevel!==t&&(this._maxAutoLevel=t,this.hls.trigger(m.MAX_AUTO_LEVEL_UPDATED,{autoLevelCapping:e,levels:this.levels,maxAutoLevel:t,minAutoLevel:this.hls.minAutoLevel,maxHdcpLevel:s}))}}function rn(a){const e={};a.forEach(t=>{const s=t.groupId||"";t.id=e[s]=e[s]||0,e[s]++})}function Fa(){return self.SourceBuffer||self.WebKitSourceBuffer}function Ma(){if(!Je())return!1;const e=Fa();return!e||e.prototype&&typeof e.prototype.appendBuffer=="function"&&typeof e.prototype.remove=="function"}function Bu(){if(!Ma())return!1;const a=Je();return typeof(a==null?void 0:a.isTypeSupported)=="function"&&(["avc1.42E01E,mp4a.40.2","av01.0.01M.08","vp09.00.50.08"].some(e=>a.isTypeSupported(wt(e,"video")))||["mp4a.40.2","fLaC"].some(e=>a.isTypeSupported(wt(e,"audio"))))}function Uu(){var a;const e=Fa();return typeof(e==null||(a=e.prototype)==null?void 0:a.changeType)=="function"}const $u=100;class Gu extends Ai{constructor(e,t,s){super(e,t,s,"stream-controller",B.MAIN),this.audioCodecSwap=!1,this.level=-1,this._forceStartLoad=!1,this._hasEnoughToStart=!1,this.altAudio=0,this.audioOnly=!1,this.fragPlaying=null,this.fragLastKbps=0,this.couldBacktrack=!1,this.backtrackFragment=null,this.audioCodecSwitch=!1,this.videoBuffer=null,this.onMediaPlaying=()=>{this.tick()},this.onMediaSeeked=()=>{const i=this.media,r=i?i.currentTime:null;if(r===null||!M(r)||(this.log(`Media seeked to ${r.toFixed(3)}`),!this.getBufferedFrag(r)))return;const n=this.getFwdBufferInfoAtPos(i,r,B.MAIN,0);if(n===null||n.len===0){this.warn(`Main forward buffer length at ${r} on "seeked" event ${n?n.len:"empty"})`);return}this.tick()},this.registerListeners()}registerListeners(){super.registerListeners();const{hls:e}=this;e.on(m.MANIFEST_PARSED,this.onManifestParsed,this),e.on(m.LEVEL_LOADING,this.onLevelLoading,this),e.on(m.LEVEL_LOADED,this.onLevelLoaded,this),e.on(m.FRAG_LOAD_EMERGENCY_ABORTED,this.onFragLoadEmergencyAborted,this),e.on(m.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),e.on(m.AUDIO_TRACK_SWITCHED,this.onAudioTrackSwitched,this),e.on(m.BUFFER_CREATED,this.onBufferCreated,this),e.on(m.BUFFER_FLUSHED,this.onBufferFlushed,this),e.on(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.on(m.FRAG_BUFFERED,this.onFragBuffered,this)}unregisterListeners(){super.unregisterListeners();const{hls:e}=this;e.off(m.MANIFEST_PARSED,this.onManifestParsed,this),e.off(m.LEVEL_LOADED,this.onLevelLoaded,this),e.off(m.FRAG_LOAD_EMERGENCY_ABORTED,this.onFragLoadEmergencyAborted,this),e.off(m.AUDIO_TRACK_SWITCHING,this.onAudioTrackSwitching,this),e.off(m.AUDIO_TRACK_SWITCHED,this.onAudioTrackSwitched,this),e.off(m.BUFFER_CREATED,this.onBufferCreated,this),e.off(m.BUFFER_FLUSHED,this.onBufferFlushed,this),e.off(m.LEVELS_UPDATED,this.onLevelsUpdated,this),e.off(m.FRAG_BUFFERED,this.onFragBuffered,this)}onHandlerDestroying(){this.onMediaPlaying=this.onMediaSeeked=null,this.unregisterListeners(),super.onHandlerDestroying()}startLoad(e,t){if(this.levels){const{lastCurrentTime:s,hls:i}=this;if(this.stopLoad(),this.setInterval($u),this.level=-1,!this.startFragRequested){let r=i.startLevel;r===-1&&(i.config.testBandwidth&&this.levels.length>1?(r=0,this.bitrateTest=!0):r=i.firstAutoLevel),i.nextLoadLevel=r,this.level=i.loadLevel,this._hasEnoughToStart=!!t}s>0&&e===-1&&!t&&(this.log(`Override startPosition with lastCurrentTime @${s.toFixed(3)}`),e=s),this.state=C.IDLE,this.nextLoadPosition=this.lastCurrentTime=e+this.timelineOffset,this.startPosition=t?-1:e,this.tick()}else this._forceStartLoad=!0,this.state=C.STOPPED}stopLoad(){this._forceStartLoad=!1,super.stopLoad()}doTick(){switch(this.state){case C.WAITING_LEVEL:{const{levels:e,level:t}=this,s=e==null?void 0:e[t],i=s==null?void 0:s.details;if(i&&(!i.live||this.levelLastLoaded===s&&!this.waitForLive(s))){if(this.waitForCdnTuneIn(i))break;this.state=C.IDLE;break}else if(this.hls.nextLoadLevel!==this.level){this.state=C.IDLE;break}break}case C.FRAG_LOADING_WAITING_RETRY:this.checkRetryDate();break}this.state===C.IDLE&&this.doTickIdle(),this.onTickEnd()}onTickEnd(){var e;super.onTickEnd(),(e=this.media)!=null&&e.readyState&&this.media.seeking===!1&&(this.lastCurrentTime=this.media.currentTime),this.checkFragmentChanged()}doTickIdle(){const{hls:e,levelLastLoaded:t,levels:s,media:i}=this;if(t===null||!i&&!this.primaryPrefetch&&(this.startFragRequested||!e.config.startFragPrefetch)||this.altAudio&&this.audioOnly)return;const r=this.buffering?e.nextLoadLevel:e.loadLevel;if(!(s!=null&&s[r]))return;const n=s[r],o=this.getMainFwdBufferInfo();if(o===null)return;const c=this.getLevelDetails();if(c&&this._streamEnded(o,c)){const y={};this.altAudio===2&&(y.type="video"),this.hls.trigger(m.BUFFER_EOS,y),this.state=C.ENDED;return}if(!this.buffering)return;e.loadLevel!==r&&e.manualLevel===-1&&this.log(`Adapting to level ${r} from level ${this.level}`),this.level=e.nextLoadLevel=r;const l=n.details;if(!l||this.state===C.WAITING_LEVEL||this.waitForLive(n)){this.level=r,this.state=C.WAITING_LEVEL,this.startFragRequested=!1;return}const h=o.len,u=this.getMaxBufferLength(n.maxBitrate);if(h>=u)return;this.backtrackFragment&&this.backtrackFragment.start>o.end&&(this.backtrackFragment=null);const d=this.backtrackFragment?this.backtrackFragment.start:o.end;let f=this.getNextFragment(d,l);if(this.couldBacktrack&&!this.fragPrevious&&f&&ce(f)&&this.fragmentTracker.getState(f)!==ue.OK){var g;const p=((g=this.backtrackFragment)!=null?g:f).sn-l.startSN,E=l.fragments[p-1];E&&f.cc===E.cc&&(f=E,this.fragmentTracker.removeFragment(E))}else this.backtrackFragment&&o.len&&(this.backtrackFragment=null);if(f&&this.isLoopLoading(f,d)){if(!f.gap){const p=this.audioOnly&&!this.altAudio?re.AUDIO:re.VIDEO,E=(p===re.VIDEO?this.videoBuffer:this.mediaBuffer)||this.media;E&&this.afterBufferFlushed(E,p,B.MAIN)}f=this.getNextFragmentLoopLoading(f,l,o,B.MAIN,u)}f&&(this.exceedsMaxBuffer(o,u,f)||(f.initSegment&&!f.initSegment.data&&!this.bitrateTest&&(f=f.initSegment),this.loadFragment(f,n,d)))}loadFragment(e,t,s){const i=this.fragmentTracker.getState(e);i===ue.NOT_LOADED||i===ue.PARTIAL?ce(e)?this.bitrateTest?(this.log(`Fragment ${e.sn} of level ${e.level} is being downloaded to test bitrate and will not be buffered`),this._loadBitrateTestFrag(e,t)):super.loadFragment(e,t,s):this._loadInitSegment(e,t):this.clearTrackerIfNeeded(e)}getBufferedFrag(e){return this.fragmentTracker.getBufferedFrag(e,B.MAIN)}followingBufferedFrag(e){return e?this.getBufferedFrag(e.end+.5):null}immediateLevelSwitch(){if(this.abortCurrentFrag(),this.flushMainBuffer(0,Number.POSITIVE_INFINITY),this.altAudio!==0){var e;(((e=this.getLevelDetails())==null?void 0:e.fragmentStart)||0)>this.lastCurrentTime&&super.flushMainBuffer(0,Number.POSITIVE_INFINITY,"audio")}}nextLevelSwitch(){const{levels:e,media:t}=this;if(t!=null&&t.readyState){let s;const i=this.getAppendedFrag(t.currentTime);i&&i.start>1&&this.flushMainBuffer(0,i.start-1);const r=this.getLevelDetails();if(r!=null&&r.live){const o=this.getMainFwdBufferInfo();if(!o||o.len=n-t.maxFragLookUpTolerance&&r<=o;if(i!==null&&s.duration>i&&(r{this.hls&&this.hls.trigger(m.AUDIO_TRACK_SWITCHED,t)}),s.trigger(m.BUFFER_FLUSHING,{startOffset:0,endOffset:Number.POSITIVE_INFINITY,type:null});return}s.trigger(m.AUDIO_TRACK_SWITCHED,t)}}onAudioTrackSwitched(e,t){const s=us(t.url,this.hls);if(s){const i=this.videoBuffer;i&&this.mediaBuffer!==i&&(this.log("Switching on alternate audio, use video.buffered to schedule main fragment loading"),this.mediaBuffer=i)}this.altAudio=s?2:0,this.tick()}onBufferCreated(e,t){const s=t.tracks;let i,r,n=!1;for(const o in s){const c=s[o];if(c.id==="main"){if(r=o,i=c,o==="video"){const l=s[o];l&&(this.videoBuffer=l.buffer)}}else n=!0}n&&i?(this.log(`Alternate track found, use ${r}.buffered to schedule main fragment loading`),this.mediaBuffer=i.buffer):this.mediaBuffer=this.media}onFragBuffered(e,t){const{frag:s,part:i}=t,r=s.type===B.MAIN;if(r){if(this.fragContextChanged(s)){this.warn(`Fragment ${s.sn}${i?" p: "+i.index:""} of level ${s.level} finished buffering, but was aborted. state: ${this.state}`),this.state===C.PARSED&&(this.state=C.IDLE);return}const o=i?i.stats:s.stats;this.fragLastKbps=Math.round(8*o.total/(o.buffering.end-o.loading.first)),ce(s)&&(this.fragPrevious=s),this.fragBufferedComplete(s,i)}const n=this.media;n&&(!this._hasEnoughToStart&&q.getBuffered(n).length&&(this._hasEnoughToStart=!0,this.seekToStartPos()),r&&this.tick())}get hasEnoughToStart(){return this._hasEnoughToStart}onError(e,t){var s;if(t.fatal){this.state=C.ERROR;return}switch(t.details){case R.FRAG_GAP:case R.FRAG_PARSING_ERROR:case R.FRAG_DECRYPT_ERROR:case R.FRAG_LOAD_ERROR:case R.FRAG_LOAD_TIMEOUT:case R.KEY_LOAD_ERROR:case R.KEY_LOAD_TIMEOUT:this.onFragmentOrKeyLoadError(B.MAIN,t);break;case R.LEVEL_LOAD_ERROR:case R.LEVEL_LOAD_TIMEOUT:case R.LEVEL_PARSING_ERROR:!t.levelRetry&&this.state===C.WAITING_LEVEL&&((s=t.context)==null?void 0:s.type)===Q.LEVEL&&(this.state=C.IDLE);break;case R.BUFFER_ADD_CODEC_ERROR:case R.BUFFER_APPEND_ERROR:if(t.parent!=="main")return;this.reduceLengthAndFlushBuffer(t)&&this.resetLoadingState();break;case R.BUFFER_FULL_ERROR:if(t.parent!=="main")return;this.reduceLengthAndFlushBuffer(t)&&(!this.config.interstitialsController&&this.config.assetPlayerId?this._hasEnoughToStart=!0:this.flushMainBuffer(0,Number.POSITIVE_INFINITY));break;case R.INTERNAL_EXCEPTION:this.recoverWorkerError(t);break}}onFragLoadEmergencyAborted(){this.state=C.IDLE,this._hasEnoughToStart||(this.startFragRequested=!1,this.nextLoadPosition=this.lastCurrentTime),this.tickImmediate()}onBufferFlushed(e,{type:t}){if(t!==re.AUDIO||!this.altAudio){const s=(t===re.VIDEO?this.videoBuffer:this.mediaBuffer)||this.media;s&&(this.afterBufferFlushed(s,t,B.MAIN),this.tick())}}onLevelsUpdated(e,t){this.level>-1&&this.fragCurrent&&(this.level=this.fragCurrent.level,this.level===-1&&this.resetWhenMissingContext(this.fragCurrent)),this.levels=t.levels}swapAudioCodec(){this.audioCodecSwap=!this.audioCodecSwap}seekToStartPos(){const{media:e}=this;if(!e)return;const t=e.currentTime;let s=this.startPosition;if(s>=0&&t0&&(c{const{hls:i}=this,r=s==null?void 0:s.frag;if(!r||this.fragContextChanged(r))return;t.fragmentError=0,this.state=C.IDLE,this.startFragRequested=!1,this.bitrateTest=!1;const n=r.stats;n.parsing.start=n.parsing.end=n.buffering.start=n.buffering.end=self.performance.now(),i.trigger(m.FRAG_LOADED,s),r.bitrateTest=!1}).catch(s=>{this.state===C.STOPPED||this.state===C.ERROR||(this.warn(s),this.resetFragmentLoading(e))})}_handleTransmuxComplete(e){const t=this.playlistType,{hls:s}=this,{remuxResult:i,chunkMeta:r}=e,n=this.getCurrentContext(r);if(!n){this.resetWhenMissingContext(r);return}const{frag:o,part:c,level:l}=n,{video:h,text:u,id3:d,initSegment:f}=i,{details:g}=l,y=this.altAudio?void 0:i.audio;if(this.fragContextChanged(o)){this.fragmentTracker.removeFragment(o);return}if(this.state=C.PARSING,f){const p=f.tracks;if(p){const v=o.initSegment||o;if(this.unhandledEncryptionError(f,o))return;this._bufferInitSegment(l,p,v,r),s.trigger(m.FRAG_PARSING_INIT_SEGMENT,{frag:v,id:t,tracks:p})}const E=f.initPTS,T=f.timescale,S=this.initPTS[o.cc];if(M(E)&&(!S||S.baseTime!==E||S.timescale!==T)){const v=f.trackId;this.initPTS[o.cc]={baseTime:E,timescale:T,trackId:v},s.trigger(m.INIT_PTS_FOUND,{frag:o,id:t,initPTS:E,timescale:T,trackId:v})}}if(h&&g){y&&h.type==="audiovideo"&&this.logMuxedErr(o);const p=g.fragments[o.sn-1-g.startSN],E=o.sn===g.startSN,T=!p||o.cc>p.cc;if(i.independent!==!1){const{startPTS:S,endPTS:v,startDTS:x,endDTS:D}=h;if(c)c.elementaryStreams[h.type]={startPTS:S,endPTS:v,startDTS:x,endDTS:D};else if(h.firstKeyFrame&&h.independent&&r.id===1&&!T&&(this.couldBacktrack=!0),h.dropped&&h.independent){const A=this.getMainFwdBufferInfo(),_=(A?A.end:this.getLoadPosition())+this.config.maxBufferHole,b=h.firstKeyFramePTS?h.firstKeyFramePTS:S;if(!E&&_os&&(o.gap=!0);o.setElementaryStreamInfo(h.type,S,v,x,D),this.backtrackFragment&&(this.backtrackFragment=o),this.bufferFragmentData(h,o,c,r,E||T)}else if(E||T)o.gap=!0;else{this.backtrack(o);return}}if(y){const{startPTS:p,endPTS:E,startDTS:T,endDTS:S}=y;c&&(c.elementaryStreams[re.AUDIO]={startPTS:p,endPTS:E,startDTS:T,endDTS:S}),o.setElementaryStreamInfo(re.AUDIO,p,E,T,S),this.bufferFragmentData(y,o,c,r)}if(g&&d!=null&&d.samples.length){const p={id:t,frag:o,details:g,samples:d.samples};s.trigger(m.FRAG_PARSING_METADATA,p)}if(g&&u){const p={id:t,frag:o,details:g,samples:u.samples};s.trigger(m.FRAG_PARSING_USERDATA,p)}}logMuxedErr(e){this.warn(`${ce(e)?"Media":"Init"} segment with muxed audiovideo where only video expected: ${e.url}`)}_bufferInitSegment(e,t,s,i){if(this.state!==C.PARSING)return;this.audioOnly=!!t.audio&&!t.video,this.altAudio&&!this.audioOnly&&(delete t.audio,t.audiovideo&&this.logMuxedErr(s));const{audio:r,video:n,audiovideo:o}=t;if(r){const l=e.audioCodec;let h=es(r.codec,l);h==="mp4a"&&(h="mp4a.40.5");const u=navigator.userAgent.toLowerCase();if(this.audioCodecSwitch){h&&(h.indexOf("mp4a.40.5")!==-1?h="mp4a.40.2":h="mp4a.40.5");const d=r.metadata;d&&"channelCount"in d&&(d.channelCount||1)!==1&&u.indexOf("firefox")===-1&&(h="mp4a.40.5")}h&&h.indexOf("mp4a.40.5")!==-1&&u.indexOf("android")!==-1&&r.container!=="audio/mpeg"&&(h="mp4a.40.2",this.log(`Android: force audio codec to ${h}`)),l&&l!==h&&this.log(`Swapping manifest audio codec "${l}" for "${h}"`),r.levelCodec=h,r.id=B.MAIN,this.log(`Init audio buffer, container:${r.container}, codecs[selected/level/parsed]=[${h||""}/${l||""}/${r.codec}]`),delete t.audiovideo}if(n){n.levelCodec=e.videoCodec,n.id=B.MAIN;const l=n.codec;if((l==null?void 0:l.length)===4)switch(l){case"hvc1":case"hev1":n.codec="hvc1.1.6.L120.90";break;case"av01":n.codec="av01.0.04M.08";break;case"avc1":n.codec="avc1.42e01e";break}this.log(`Init video buffer, container:${n.container}, codecs[level/parsed]=[${e.videoCodec||""}/${l}]${n.codec!==l?" parsed-corrected="+n.codec:""}${n.supplemental?" supplemental="+n.supplemental:""}`),delete t.audiovideo}o&&(this.log(`Init audiovideo buffer, container:${o.container}, codecs[level/parsed]=[${e.codecs}/${o.codec}]`),delete t.video,delete t.audio);const c=Object.keys(t);if(c.length){if(this.hls.trigger(m.BUFFER_CODECS,t),!this.hls)return;c.forEach(l=>{const u=t[l].initSegment;u!=null&&u.byteLength&&this.hls.trigger(m.BUFFER_APPENDING,{type:l,data:u,frag:s,part:null,chunkMeta:i,parent:s.type})})}this.tickImmediate()}getMainFwdBufferInfo(){const e=this.mediaBuffer&&this.altAudio===2?this.mediaBuffer:this.media;return this.getFwdBufferInfo(e,B.MAIN)}get maxBufferLength(){const{levels:e,level:t}=this,s=e==null?void 0:e[t];return s?this.getMaxBufferLength(s.maxBitrate):this.config.maxBufferLength}backtrack(e){this.couldBacktrack=!0,this.backtrackFragment=e,this.resetTransmuxer(),this.flushBufferGap(e),this.fragmentTracker.removeFragment(e),this.fragPrevious=null,this.nextLoadPosition=e.start,this.state=C.IDLE}checkFragmentChanged(){const e=this.media;let t=null;if(e&&e.readyState>1&&e.seeking===!1){const s=e.currentTime;if(q.isBuffered(e,s)?t=this.getAppendedFrag(s):q.isBuffered(e,s+.1)&&(t=this.getAppendedFrag(s+.1)),t){this.backtrackFragment=null;const i=this.fragPlaying,r=t.level;(!i||t.sn!==i.sn||i.level!==r)&&(this.fragPlaying=t,this.hls.trigger(m.FRAG_CHANGED,{frag:t}),(!i||i.level!==r)&&this.hls.trigger(m.LEVEL_SWITCHED,{level:r}))}}}get nextLevel(){const e=this.nextBufferedFrag;return e?e.level:-1}get currentFrag(){var e;if(this.fragPlaying)return this.fragPlaying;const t=((e=this.media)==null?void 0:e.currentTime)||this.lastCurrentTime;return M(t)?this.getAppendedFrag(t):null}get currentProgramDateTime(){var e;const t=((e=this.media)==null?void 0:e.currentTime)||this.lastCurrentTime;if(M(t)){const s=this.getLevelDetails(),i=this.currentFrag||(s?lt(null,s.fragments,t):null);if(i){const r=i.programDateTime;if(r!==null){const n=r+(t-i.start)*1e3;return new Date(n)}}}return null}get currentLevel(){const e=this.currentFrag;return e?e.level:-1}get nextBufferedFrag(){const e=this.currentFrag;return e?this.followingBufferedFrag(e):null}get forceStartLoad(){return this._forceStartLoad}}class Ku extends Ce{constructor(e,t){super("key-loader",t),this.config=void 0,this.keyIdToKeyInfo={},this.emeController=null,this.config=e}abort(e){for(const s in this.keyIdToKeyInfo){const i=this.keyIdToKeyInfo[s].loader;if(i){var t;if(e&&e!==((t=i.context)==null?void 0:t.frag.type))return;i.abort()}}}detach(){for(const e in this.keyIdToKeyInfo){const t=this.keyIdToKeyInfo[e];(t.mediaKeySessionContext||t.decryptdata.isCommonEncryption)&&delete this.keyIdToKeyInfo[e]}}destroy(){this.detach();for(const e in this.keyIdToKeyInfo){const t=this.keyIdToKeyInfo[e].loader;t&&t.destroy()}this.keyIdToKeyInfo={}}createKeyLoadError(e,t=R.KEY_LOAD_ERROR,s,i,r){return new We({type:V.NETWORK_ERROR,details:t,fatal:!1,frag:e,response:r,error:s,networkDetails:i})}loadClear(e,t,s){if(this.emeController&&this.config.emeEnabled&&!this.emeController.getSelectedKeySystemFormats().length){if(t.length)for(let i=0,r=t.length;i{if(!this.emeController)return;n.setKeyFormat(o);const c=ss(o);if(c)return this.emeController.getKeySystemAccess([c])})}if(this.config.requireKeySystemAccessOnStart){const i=_t(this.config);if(i.length)return this.emeController.getKeySystemAccess(i)}}return null}load(e){return!e.decryptdata&&e.encrypted&&this.emeController&&this.config.emeEnabled?this.emeController.selectKeySystemFormat(e).then(t=>this.loadInternal(e,t)):this.loadInternal(e)}loadInternal(e,t){var s,i;t&&e.setKeyFormat(t);const r=e.decryptdata;if(!r){const l=new Error(t?`Expected frag.decryptdata to be defined after setting format ${t}`:`Missing decryption data on fragment in onKeyLoading (emeEnabled with controller: ${this.emeController&&this.config.emeEnabled})`);return Promise.reject(this.createKeyLoadError(e,R.KEY_LOAD_ERROR,l))}const n=r.uri;if(!n)return Promise.reject(this.createKeyLoadError(e,R.KEY_LOAD_ERROR,new Error(`Invalid key URI: "${n}"`)));const o=Ws(r);let c=this.keyIdToKeyInfo[o];if((s=c)!=null&&s.decryptdata.key)return r.key=c.decryptdata.key,Promise.resolve({frag:e,keyInfo:c});if(this.emeController&&(i=c)!=null&&i.keyLoadPromise)switch(this.emeController.getKeyStatus(c.decryptdata)){case"usable":case"usable-in-future":return c.keyLoadPromise.then(h=>{const{keyInfo:u}=h;return r.key=u.decryptdata.key,{frag:e,keyInfo:u}})}switch(this.log(`${this.keyIdToKeyInfo[o]?"Rel":"L"}oading${r.keyId?" keyId: "+me(r.keyId):""} URI: ${r.uri} from ${e.type} ${e.level}`),c=this.keyIdToKeyInfo[o]={decryptdata:r,keyLoadPromise:null,loader:null,mediaKeySessionContext:null},r.method){case"SAMPLE-AES":case"SAMPLE-AES-CENC":case"SAMPLE-AES-CTR":return r.keyFormat==="identity"?this.loadKeyHTTP(c,e):this.loadKeyEME(c,e);case"AES-128":case"AES-256":case"AES-256-CTR":return this.loadKeyHTTP(c,e);default:return Promise.reject(this.createKeyLoadError(e,R.KEY_LOAD_ERROR,new Error(`Key supplied with unsupported METHOD: "${r.method}"`)))}}loadKeyEME(e,t){const s={frag:t,keyInfo:e};if(this.emeController&&this.config.emeEnabled){var i;if(!e.decryptdata.keyId&&(i=t.initSegment)!=null&&i.data){const n=ao(t.initSegment.data);if(n.length){let o=n[0];o.some(c=>c!==0)?(this.log(`Using keyId found in init segment ${me(o)}`),Ze.setKeyIdForUri(e.decryptdata.uri,o)):(o=Ze.addKeyIdForUri(e.decryptdata.uri),this.log(`Generating keyId to patch media ${me(o)}`)),e.decryptdata.keyId=o}}if(!e.decryptdata.keyId&&!ce(t))return Promise.resolve(s);const r=this.emeController.loadKey(s);return(e.keyLoadPromise=r.then(n=>(e.mediaKeySessionContext=n,s))).catch(n=>{throw e.keyLoadPromise=null,"data"in n&&(n.data.frag=t),n})}return Promise.resolve(s)}loadKeyHTTP(e,t){const s=this.config,i=s.loader,r=new i(s);return t.keyLoader=e.loader=r,e.keyLoadPromise=new Promise((n,o)=>{const c={keyInfo:e,frag:t,responseType:"arraybuffer",url:e.decryptdata.uri},l=s.keyLoadPolicy.default,h={loadPolicy:l,timeout:l.maxLoadTimeMs,maxRetry:0,retryDelay:0,maxRetryDelay:0},u={onSuccess:(d,f,g,y)=>{const{frag:p,keyInfo:E}=g,T=Ws(E.decryptdata);if(!p.decryptdata||E!==this.keyIdToKeyInfo[T])return o(this.createKeyLoadError(p,R.KEY_LOAD_ERROR,new Error("after key load, decryptdata unset or changed"),y));E.decryptdata.key=p.decryptdata.key=new Uint8Array(d.data),p.keyLoader=null,E.loader=null,n({frag:p,keyInfo:E})},onError:(d,f,g,y)=>{this.resetLoader(f),o(this.createKeyLoadError(t,R.KEY_LOAD_ERROR,new Error(`HTTP Error ${d.code} loading key ${d.text}`),g,te({url:c.url,data:void 0},d)))},onTimeout:(d,f,g)=>{this.resetLoader(f),o(this.createKeyLoadError(t,R.KEY_LOAD_TIMEOUT,new Error("key loading timed out"),g))},onAbort:(d,f,g)=>{this.resetLoader(f),o(this.createKeyLoadError(t,R.INTERNAL_ABORTED,new Error("key loading aborted"),g))}};r.load(c,h,u)})}resetLoader(e){const{frag:t,keyInfo:s,url:i}=e,r=s.loader;t.keyLoader===r&&(t.keyLoader=null,s.loader=null);const n=Ws(s.decryptdata)||i;delete this.keyIdToKeyInfo[n],r&&r.destroy()}}function Ws(a){if(a.keyFormat!==pe.FAIRPLAY){const e=a.keyId;if(e)return me(e)}return a.uri}function nn(a){const{type:e}=a;switch(e){case Q.AUDIO_TRACK:return B.AUDIO;case Q.SUBTITLE_TRACK:return B.SUBTITLE;default:return B.MAIN}}function qs(a,e){let t=a.url;return(t===void 0||t.indexOf("data:")===0)&&(t=e.url),t}class Vu{constructor(e){this.hls=void 0,this.loaders=Object.create(null),this.variableList=null,this.onManifestLoaded=this.checkAutostartLoad,this.hls=e,this.registerListeners()}startLoad(e){}stopLoad(){this.destroyInternalLoaders()}registerListeners(){const{hls:e}=this;e.on(m.MANIFEST_LOADING,this.onManifestLoading,this),e.on(m.LEVEL_LOADING,this.onLevelLoading,this),e.on(m.AUDIO_TRACK_LOADING,this.onAudioTrackLoading,this),e.on(m.SUBTITLE_TRACK_LOADING,this.onSubtitleTrackLoading,this),e.on(m.LEVELS_UPDATED,this.onLevelsUpdated,this)}unregisterListeners(){const{hls:e}=this;e.off(m.MANIFEST_LOADING,this.onManifestLoading,this),e.off(m.LEVEL_LOADING,this.onLevelLoading,this),e.off(m.AUDIO_TRACK_LOADING,this.onAudioTrackLoading,this),e.off(m.SUBTITLE_TRACK_LOADING,this.onSubtitleTrackLoading,this),e.off(m.LEVELS_UPDATED,this.onLevelsUpdated,this)}createInternalLoader(e){const t=this.hls.config,s=t.pLoader,i=t.loader,r=s||i,n=new r(t);return this.loaders[e.type]=n,n}getInternalLoader(e){return this.loaders[e.type]}resetInternalLoader(e){this.loaders[e]&&delete this.loaders[e]}destroyInternalLoaders(){for(const e in this.loaders){const t=this.loaders[e];t&&t.destroy(),this.resetInternalLoader(e)}}destroy(){this.variableList=null,this.unregisterListeners(),this.destroyInternalLoaders()}onManifestLoading(e,t){const{url:s}=t;this.variableList=null,this.load({id:null,level:0,responseType:"text",type:Q.MANIFEST,url:s,deliveryDirectives:null,levelOrTrack:null})}onLevelLoading(e,t){const{id:s,level:i,pathwayId:r,url:n,deliveryDirectives:o,levelInfo:c}=t;this.load({id:s,level:i,pathwayId:r,responseType:"text",type:Q.LEVEL,url:n,deliveryDirectives:o,levelOrTrack:c})}onAudioTrackLoading(e,t){const{id:s,groupId:i,url:r,deliveryDirectives:n,track:o}=t;this.load({id:s,groupId:i,level:null,responseType:"text",type:Q.AUDIO_TRACK,url:r,deliveryDirectives:n,levelOrTrack:o})}onSubtitleTrackLoading(e,t){const{id:s,groupId:i,url:r,deliveryDirectives:n,track:o}=t;this.load({id:s,groupId:i,level:null,responseType:"text",type:Q.SUBTITLE_TRACK,url:r,deliveryDirectives:n,levelOrTrack:o})}onLevelsUpdated(e,t){const s=this.loaders[Q.LEVEL];if(s){const i=s.context;i&&!t.levels.some(r=>r===i.levelOrTrack)&&(s.abort(),delete this.loaders[Q.LEVEL])}}load(e){var t;const s=this.hls.config;let i=this.getInternalLoader(e);if(i){const l=this.hls.logger,h=i.context;if(h&&h.levelOrTrack===e.levelOrTrack&&(h.url===e.url||h.deliveryDirectives&&!e.deliveryDirectives)){h.url===e.url?l.log(`[playlist-loader]: ignore ${e.url} ongoing request`):l.log(`[playlist-loader]: ignore ${e.url} in favor of ${h.url}`);return}l.log(`[playlist-loader]: aborting previous loader for type: ${e.type}`),i.abort()}let r;if(e.type===Q.MANIFEST?r=s.manifestLoadPolicy.default:r=ie({},s.playlistLoadPolicy.default,{timeoutRetry:null,errorRetry:null}),i=this.createInternalLoader(e),M((t=e.deliveryDirectives)==null?void 0:t.part)){let l;if(e.type===Q.LEVEL&&e.level!==null?l=this.hls.levels[e.level].details:e.type===Q.AUDIO_TRACK&&e.id!==null?l=this.hls.audioTracks[e.id].details:e.type===Q.SUBTITLE_TRACK&&e.id!==null&&(l=this.hls.subtitleTracks[e.id].details),l){const h=l.partTarget,u=l.targetduration;if(h&&u){const d=Math.max(h*3,u*.8)*1e3;r=ie({},r,{maxTimeToFirstByteMs:Math.min(d,r.maxTimeToFirstByteMs),maxLoadTimeMs:Math.min(d,r.maxTimeToFirstByteMs)})}}}const n=r.errorRetry||r.timeoutRetry||{},o={loadPolicy:r,timeout:r.maxLoadTimeMs,maxRetry:n.maxNumRetry||0,retryDelay:n.retryDelayMs||0,maxRetryDelay:n.maxRetryDelayMs||0},c={onSuccess:(l,h,u,d)=>{const f=this.getInternalLoader(u);this.resetInternalLoader(u.type);const g=l.data;h.parsing.start=performance.now(),Ge.isMediaPlaylist(g)||u.type!==Q.MANIFEST?this.handleTrackOrLevelPlaylist(l,h,u,d||null,f):this.handleMasterPlaylist(l,h,u,d)},onError:(l,h,u,d)=>{this.handleNetworkError(h,u,!1,l,d)},onTimeout:(l,h,u)=>{this.handleNetworkError(h,u,!0,void 0,l)}};i.load(e,o,c)}checkAutostartLoad(){if(!this.hls)return;const{config:{autoStartLoad:e,startPosition:t},forceStartLoad:s}=this.hls;(e||s)&&(this.hls.logger.log(`${e?"auto":"force"} startLoad with configured startPosition ${t}`),this.hls.startLoad(t))}handleMasterPlaylist(e,t,s,i){const r=this.hls,n=e.data,o=qs(e,s),c=Ge.parseMasterPlaylist(n,o);if(c.playlistParsingError){t.parsing.end=performance.now(),this.handleManifestParsingError(e,s,c.playlistParsingError,i,t);return}const{contentSteering:l,levels:h,sessionData:u,sessionKeys:d,startTimeOffset:f,variableList:g}=c;this.variableList=g,h.forEach(T=>{const{unknownCodecs:S}=T;if(S){const{preferManagedMediaSource:v}=this.hls.config;let{audioCodec:x,videoCodec:D}=T;for(let A=S.length;A--;){const _=S[A];kt(_,"audio",v)?(T.audioCodec=x=x?`${x},${_}`:_,xt.audio[x.substring(0,4)]=2,S.splice(A,1)):kt(_,"video",v)&&(T.videoCodec=D=D?`${D},${_}`:_,xt.video[D.substring(0,4)]=2,S.splice(A,1))}}});const{AUDIO:y=[],SUBTITLES:p,"CLOSED-CAPTIONS":E}=Ge.parseMasterPlaylistMedia(n,o,c);y.length&&!y.some(S=>!S.url)&&h[0].audioCodec&&!h[0].attrs.AUDIO&&(this.hls.logger.log("[playlist-loader]: audio codec signaled in quality level, but no embedded audio track signaled, create one"),y.unshift({type:"main",name:"main",groupId:"main",default:!1,autoselect:!1,forced:!1,id:-1,attrs:new ae({}),bitrate:0,url:""})),r.trigger(m.MANIFEST_LOADED,{levels:h,audioTracks:y,subtitles:p,captions:E,contentSteering:l,url:o,stats:t,networkDetails:i,sessionData:u,sessionKeys:d,startTimeOffset:f,variableList:g})}handleTrackOrLevelPlaylist(e,t,s,i,r){const n=this.hls,{id:o,level:c,type:l}=s,h=qs(e,s),u=M(c)?c:M(o)?o:0,d=nn(s),f=Ge.parseLevelPlaylist(e.data,h,u,d,0,this.variableList);if(l===Q.MANIFEST){const g={attrs:new ae({}),bitrate:0,details:f,name:"",url:h};f.requestScheduled=t.loading.start+Nn(f,0),n.trigger(m.MANIFEST_LOADED,{levels:[g],audioTracks:[],url:h,stats:t,networkDetails:i,sessionData:null,sessionKeys:null,contentSteering:null,startTimeOffset:null,variableList:null})}t.parsing.end=performance.now(),s.levelDetails=f,this.handlePlaylistLoaded(f,e,t,s,i,r)}handleManifestParsingError(e,t,s,i,r){this.hls.trigger(m.ERROR,{type:V.NETWORK_ERROR,details:R.MANIFEST_PARSING_ERROR,fatal:t.type===Q.MANIFEST,url:e.url,err:s,error:s,reason:s.message,response:e,context:t,networkDetails:i,stats:r})}handleNetworkError(e,t,s=!1,i,r){let n=`A network ${s?"timeout":"error"+(i?" (status "+i.code+")":"")} occurred while loading ${e.type}`;e.type===Q.LEVEL?n+=`: ${e.level} id: ${e.id}`:(e.type===Q.AUDIO_TRACK||e.type===Q.SUBTITLE_TRACK)&&(n+=` id: ${e.id} group-id: "${e.groupId}"`);const o=new Error(n);this.hls.logger.warn(`[playlist-loader]: ${n}`);let c=R.UNKNOWN,l=!1;const h=this.getInternalLoader(e);switch(e.type){case Q.MANIFEST:c=s?R.MANIFEST_LOAD_TIMEOUT:R.MANIFEST_LOAD_ERROR,l=!0;break;case Q.LEVEL:c=s?R.LEVEL_LOAD_TIMEOUT:R.LEVEL_LOAD_ERROR,l=!1;break;case Q.AUDIO_TRACK:c=s?R.AUDIO_TRACK_LOAD_TIMEOUT:R.AUDIO_TRACK_LOAD_ERROR,l=!1;break;case Q.SUBTITLE_TRACK:c=s?R.SUBTITLE_TRACK_LOAD_TIMEOUT:R.SUBTITLE_LOAD_ERROR,l=!1;break}h&&this.resetInternalLoader(e.type);const u={type:V.NETWORK_ERROR,details:c,fatal:l,url:e.url,loader:h,context:e,error:o,networkDetails:t,stats:r};if(i){const d=(t==null?void 0:t.url)||e.url;u.response=te({url:d,data:void 0},i)}this.hls.trigger(m.ERROR,u)}handlePlaylistLoaded(e,t,s,i,r,n){const o=this.hls,{type:c,level:l,levelOrTrack:h,id:u,groupId:d,deliveryDirectives:f}=i,g=qs(t,i),y=nn(i);let p=typeof i.level=="number"&&y===B.MAIN?l:void 0;const E=e.playlistParsingError;if(E){if(this.hls.logger.warn(`${E} ${e.url}`),!o.config.ignorePlaylistParsingErrors){o.trigger(m.ERROR,{type:V.NETWORK_ERROR,details:R.LEVEL_PARSING_ERROR,fatal:!1,url:g,error:E,reason:E.message,response:t,context:i,level:p,parent:y,networkDetails:r,stats:s});return}e.playlistParsingError=null}if(!e.fragments.length){const T=e.playlistParsingError=new Error("No Segments found in Playlist");o.trigger(m.ERROR,{type:V.NETWORK_ERROR,details:R.LEVEL_EMPTY_ERROR,fatal:!1,url:g,error:T,reason:T.message,response:t,context:i,level:p,parent:y,networkDetails:r,stats:s});return}switch(e.live&&n&&(n.getCacheAge&&(e.ageHeader=n.getCacheAge()||0),(!n.getCacheAge||isNaN(e.ageHeader))&&(e.ageHeader=0)),c){case Q.MANIFEST:case Q.LEVEL:if(p){if(!h)p=0;else if(h!==o.levels[p]){const T=o.levels.indexOf(h);T>-1&&(p=T)}}o.trigger(m.LEVEL_LOADED,{details:e,levelInfo:h||o.levels[0],level:p||0,id:u||0,stats:s,networkDetails:r,deliveryDirectives:f,withoutMultiVariant:c===Q.MANIFEST});break;case Q.AUDIO_TRACK:o.trigger(m.AUDIO_TRACK_LOADED,{details:e,track:h,id:u||0,groupId:d||"",stats:s,networkDetails:r,deliveryDirectives:f});break;case Q.SUBTITLE_TRACK:o.trigger(m.SUBTITLE_TRACK_LOADED,{details:e,track:h,id:u||0,groupId:d||"",stats:s,networkDetails:r,deliveryDirectives:f});break}}}class Ue{static get version(){return Ft}static isMSESupported(){return Ma()}static isSupported(){return Bu()}static getMediaSource(){return Je()}static get Events(){return m}static get MetadataSchema(){return Le}static get ErrorTypes(){return V}static get ErrorDetails(){return R}static get DefaultConfig(){return Ue.defaultConfig?Ue.defaultConfig:Ru}static set DefaultConfig(e){Ue.defaultConfig=e}constructor(e={}){this.config=void 0,this.userConfig=void 0,this.logger=void 0,this.coreComponents=void 0,this.networkControllers=void 0,this._emitter=new Ii,this._autoLevelCapping=-1,this._maxHdcpLevel=null,this.abrController=void 0,this.bufferController=void 0,this.capLevelController=void 0,this.latencyController=void 0,this.levelController=void 0,this.streamController=void 0,this.audioStreamController=void 0,this.subtititleStreamController=void 0,this.audioTrackController=void 0,this.subtitleTrackController=void 0,this.interstitialsController=void 0,this.gapController=void 0,this.emeController=void 0,this.cmcdController=void 0,this._media=null,this._url=null,this._sessionId=void 0,this.triggeringException=void 0,this.started=!1;const t=this.logger=ja(e.debug||!1,"Hls instance",e.assetPlayerId),s=this.config=_u(Ue.DefaultConfig,e,t);this.userConfig=e,s.progressive&&Du(s,t);const{abrController:i,bufferController:r,capLevelController:n,errorController:o,fpsController:c}=s,l=new o(this),h=this.abrController=new i(this),u=new Ho(this),d=s.interstitialsController,f=d?this.interstitialsController=new d(this,Ue):null,g=this.bufferController=new r(this,u),y=this.capLevelController=new n(this),p=new c(this),E=new Vu(this),T=s.contentSteeringController,S=T?new T(this):null,v=this.levelController=new Nu(this,S),x=new Fu(this),D=new Ku(this.config,this.logger),A=this.streamController=new Gu(this,u,D),_=this.gapController=new wu(this,u);y.setStreamController(A),p.setStreamController(A);const b=[E,v,A];f&&b.splice(1,0,f),S&&b.splice(1,0,S),this.networkControllers=b;const I=[h,g,_,y,p,x,u];this.audioTrackController=this.createController(s.audioTrackController,b);const P=s.audioStreamController;P&&b.push(this.audioStreamController=new P(this,u,D)),this.subtitleTrackController=this.createController(s.subtitleTrackController,b);const F=s.subtitleStreamController;F&&b.push(this.subtititleStreamController=new F(this,u,D)),this.createController(s.timelineController,I),D.emeController=this.emeController=this.createController(s.emeController,I),this.cmcdController=this.createController(s.cmcdController,I),this.latencyController=this.createController(Mu,I),this.coreComponents=I,b.push(l);const U=l.onErrorOut;typeof U=="function"&&this.on(m.ERROR,U,l),this.on(m.MANIFEST_LOADED,E.onManifestLoaded,E)}createController(e,t){if(e){const s=new e(this);return t&&t.push(s),s}return null}on(e,t,s=this){this._emitter.on(e,t,s)}once(e,t,s=this){this._emitter.once(e,t,s)}removeAllListeners(e){this._emitter.removeAllListeners(e)}off(e,t,s=this,i){this._emitter.off(e,t,s,i)}listeners(e){return this._emitter.listeners(e)}emit(e,t,s){return this._emitter.emit(e,t,s)}trigger(e,t){if(this.config.debug)return this.emit(e,e,t);try{return this.emit(e,e,t)}catch(s){if(this.logger.error("An internal error happened while handling event "+e+'. Error message: "'+s.message+'". Here is a stacktrace:',s),!this.triggeringException){this.triggeringException=!0;const i=e===m.ERROR;this.trigger(m.ERROR,{type:V.OTHER_ERROR,details:R.INTERNAL_EXCEPTION,fatal:i,event:e,error:s}),this.triggeringException=!1}}return!1}listenerCount(e){return this._emitter.listenerCount(e)}destroy(){this.logger.log("destroy"),this.trigger(m.DESTROYING,void 0),this.detachMedia(),this.removeAllListeners(),this._autoLevelCapping=-1,this._url=null,this.networkControllers.forEach(t=>t.destroy()),this.networkControllers.length=0,this.coreComponents.forEach(t=>t.destroy()),this.coreComponents.length=0;const e=this.config;e.xhrSetup=e.fetchSetup=void 0,this.userConfig=null}attachMedia(e){if(!e||"media"in e&&!e.media){const r=new Error(`attachMedia failed: invalid argument (${e})`);this.trigger(m.ERROR,{type:V.OTHER_ERROR,details:R.ATTACH_MEDIA_ERROR,fatal:!0,error:r});return}this.logger.log("attachMedia"),this._media&&(this.logger.warn("media must be detached before attaching"),this.detachMedia());const t="media"in e,s=t?e.media:e,i=t?e:{media:s};this._media=s,this.trigger(m.MEDIA_ATTACHING,i)}detachMedia(){this.logger.log("detachMedia"),this.trigger(m.MEDIA_DETACHING,{}),this._media=null}transferMedia(){this._media=null;const e=this.bufferController.transferMedia();return this.trigger(m.MEDIA_DETACHING,{transferMedia:e}),e}loadSource(e){this.stopLoad();const t=this.media,s=this._url,i=this._url=fi.buildAbsoluteURL(self.location.href,e,{alwaysNormalize:!0});this._autoLevelCapping=-1,this._maxHdcpLevel=null,this.logger.log(`loadSource:${i}`),t&&s&&(s!==i||this.bufferController.hasSourceTypes())&&(this.detachMedia(),this.attachMedia(t)),this.trigger(m.MANIFEST_LOADING,{url:e})}get url(){return this._url}get hasEnoughToStart(){return this.streamController.hasEnoughToStart}get startPosition(){return this.streamController.startPositionValue}startLoad(e=-1,t){this.logger.log(`startLoad(${e+(t?", ":"")})`),this.started=!0,this.resumeBuffering();for(let s=0;s{e.resumeBuffering&&e.resumeBuffering()}))}pauseBuffering(){this.bufferingEnabled&&(this.logger.log("pause buffering"),this.networkControllers.forEach(e=>{e.pauseBuffering&&e.pauseBuffering()}))}get inFlightFragments(){const e={[B.MAIN]:this.streamController.inFlightFrag};return this.audioStreamController&&(e[B.AUDIO]=this.audioStreamController.inFlightFrag),this.subtititleStreamController&&(e[B.SUBTITLE]=this.subtititleStreamController.inFlightFrag),e}swapAudioCodec(){this.logger.log("swapAudioCodec"),this.streamController.swapAudioCodec()}recoverMediaError(){this.logger.log("recoverMediaError");const e=this._media,t=e==null?void 0:e.currentTime;this.detachMedia(),e&&(this.attachMedia(e),t&&this.startLoad(t))}removeLevel(e){this.levelController.removeLevel(e)}get sessionId(){let e=this._sessionId;return e||(e=this._sessionId=wh()),e}get levels(){const e=this.levelController.levels;return e||[]}get latestLevelDetails(){return this.streamController.getLevelDetails()||null}get loadLevelObj(){return this.levelController.loadLevelObj}get currentLevel(){return this.streamController.currentLevel}set currentLevel(e){this.logger.log(`set currentLevel:${e}`),this.levelController.manualLevel=e,this.streamController.immediateLevelSwitch()}get nextLevel(){return this.streamController.nextLevel}set nextLevel(e){this.logger.log(`set nextLevel:${e}`),this.levelController.manualLevel=e,this.streamController.nextLevelSwitch()}get loadLevel(){return this.levelController.level}set loadLevel(e){this.logger.log(`set loadLevel:${e}`),this.levelController.manualLevel=e}get nextLoadLevel(){return this.levelController.nextLoadLevel}set nextLoadLevel(e){this.levelController.nextLoadLevel=e}get firstLevel(){return Math.max(this.levelController.firstLevel,this.minAutoLevel)}set firstLevel(e){this.logger.log(`set firstLevel:${e}`),this.levelController.firstLevel=e}get startLevel(){const e=this.levelController.startLevel;return e===-1&&this.abrController.forcedAutoLevel>-1?this.abrController.forcedAutoLevel:e}set startLevel(e){this.logger.log(`set startLevel:${e}`),e!==-1&&(e=Math.max(e,this.minAutoLevel)),this.levelController.startLevel=e}get capLevelToPlayerSize(){return this.config.capLevelToPlayerSize}set capLevelToPlayerSize(e){const t=!!e;t!==this.config.capLevelToPlayerSize&&(t?this.capLevelController.startCapping():(this.capLevelController.stopCapping(),this.autoLevelCapping=-1,this.streamController.nextLevelSwitch()),this.config.capLevelToPlayerSize=t)}get autoLevelCapping(){return this._autoLevelCapping}get bandwidthEstimate(){const{bwEstimator:e}=this.abrController;return e?e.getEstimate():NaN}set bandwidthEstimate(e){this.abrController.resetEstimator(e)}get abrEwmaDefaultEstimate(){const{bwEstimator:e}=this.abrController;return e?e.defaultEstimate:NaN}get ttfbEstimate(){const{bwEstimator:e}=this.abrController;return e?e.getEstimateTTFB():NaN}set autoLevelCapping(e){this._autoLevelCapping!==e&&(this.logger.log(`set autoLevelCapping:${e}`),this._autoLevelCapping=e,this.levelController.checkMaxAutoUpdated())}get maxHdcpLevel(){return this._maxHdcpLevel}set maxHdcpLevel(e){_o(e)&&this._maxHdcpLevel!==e&&(this._maxHdcpLevel=e,this.levelController.checkMaxAutoUpdated())}get autoLevelEnabled(){return this.levelController.manualLevel===-1}get manualLevel(){return this.levelController.manualLevel}get minAutoLevel(){const{levels:e,config:{minAutoBitrate:t}}=this;if(!e)return 0;const s=e.length;for(let i=0;i=t)return i;return 0}get maxAutoLevel(){const{levels:e,autoLevelCapping:t,maxHdcpLevel:s}=this;let i;if(t===-1&&e!=null&&e.length?i=e.length-1:i=t,s)for(let r=i;r--;){const n=e[r].attrs["HDCP-LEVEL"];if(n&&n<=s)return r}return i}get firstAutoLevel(){return this.abrController.firstAutoLevel}get nextAutoLevel(){return this.abrController.nextAutoLevel}set nextAutoLevel(e){this.abrController.nextAutoLevel=e}get playingDate(){return this.streamController.currentProgramDateTime}get mainForwardBufferInfo(){return this.streamController.getMainFwdBufferInfo()}get maxBufferLength(){return this.streamController.maxBufferLength}setAudioOption(e){var t;return((t=this.audioTrackController)==null?void 0:t.setAudioOption(e))||null}setSubtitleOption(e){var t;return((t=this.subtitleTrackController)==null?void 0:t.setSubtitleOption(e))||null}get allAudioTracks(){const e=this.audioTrackController;return e?e.allAudioTracks:[]}get audioTracks(){const e=this.audioTrackController;return e?e.audioTracks:[]}get audioTrack(){const e=this.audioTrackController;return e?e.audioTrack:-1}set audioTrack(e){const t=this.audioTrackController;t&&(t.audioTrack=e)}get allSubtitleTracks(){const e=this.subtitleTrackController;return e?e.allSubtitleTracks:[]}get subtitleTracks(){const e=this.subtitleTrackController;return e?e.subtitleTracks:[]}get subtitleTrack(){const e=this.subtitleTrackController;return e?e.subtitleTrack:-1}get media(){return this._media}set subtitleTrack(e){const t=this.subtitleTrackController;t&&(t.subtitleTrack=e)}get subtitleDisplay(){const e=this.subtitleTrackController;return e?e.subtitleDisplay:!1}set subtitleDisplay(e){const t=this.subtitleTrackController;t&&(t.subtitleDisplay=e)}get lowLatencyMode(){return this.config.lowLatencyMode}set lowLatencyMode(e){this.config.lowLatencyMode=e}get liveSyncPosition(){return this.latencyController.liveSyncPosition}get latency(){return this.latencyController.latency}get maxLatency(){return this.latencyController.maxLatency}get targetLatency(){return this.latencyController.targetLatency}set targetLatency(e){this.latencyController.targetLatency=e}get drift(){return this.latencyController.drift}get forceStartLoad(){return this.streamController.forceStartLoad}get pathways(){return this.levelController.pathways}get pathwayPriority(){return this.levelController.pathwayPriority}set pathwayPriority(e){this.levelController.pathwayPriority=e}get bufferedToEnd(){var e;return!!((e=this.bufferController)!=null&&e.bufferedToEnd)}get interstitialsManager(){var e;return((e=this.interstitialsController)==null?void 0:e.interstitialsManager)||null}getMediaDecodingInfo(e,t=this.allAudioTracks){const s=xn(t);return Sn(e,s,navigator.mediaCapabilities)}}Ue.defaultConfig=void 0;class Xu{constructor({onState:e}){this.audio=new Audio,this.audio.preload="none",this.hls=null,this.station=null,this.onState=e||(()=>{}),this.audio.addEventListener("playing",()=>this.emit({playing:!0,loading:!1,error:null})),this.audio.addEventListener("pause",()=>this.emit({playing:!1,loading:!1})),this.audio.addEventListener("waiting",()=>this.emit({loading:!0})),this.audio.addEventListener("error",()=>{var r;const t=(r=this.audio.error)==null?void 0:r.code,i={1:"aborted",2:"network",3:"decode",4:"src not supported"}[t]||`code ${t}`;console.warn("[player] audio error",i,this.audio.currentSrc),this.emit({playing:!1,loading:!1,error:`stream error: ${i}`})})}emit(e){var t,s,i;this.onState({stationId:((t=this.station)==null?void 0:t.id)??null,stationName:((s=this.station)==null?void 0:s.name)??null,genres:((i=this.station)==null?void 0:i.genres)||[],volume:this.audio.volume,...e})}setVolume(e){this.audio.volume=Math.max(0,Math.min(1,e)),this.emit({})}stop(){this.audio.pause(),this.audio.removeAttribute("src"),this.audio.load(),this.hls&&(this.hls.destroy(),this.hls=null)}togglePause(){this.station&&(this.audio.paused?this.audio.play().catch(()=>{}):this.audio.pause())}async play(e){this.stop(),this.station=e,this.emit({playing:!1,loading:!0});let t;try{t=(await Ua.post(`/api/stations/${e.id}/resolve`)).resolved}catch(i){this.emit({playing:!1,loading:!1,error:i.message});return}const s=t.url;t.format==="hls"?Ue.isSupported()?(this.hls=new Ue({enableWorker:!0}),this.hls.loadSource(s),this.hls.attachMedia(this.audio),this.hls.on(Ue.Events.MANIFEST_PARSED,()=>this.audio.play().catch(()=>{}))):this.audio.canPlayType("application/vnd.apple.mpegurl")?(this.audio.src=s,this.audio.play().catch(()=>{})):this.emit({playing:!1,loading:!1,error:"HLS not supported"}):(this.audio.src=s,this.audio.play().catch(()=>{}))}}export{Xu as P,Ua as a,Wu as c,Yu as e}; diff --git a/server/public/assets/ws-BM1PmMVd.js b/server/public/assets/ws-BM1PmMVd.js new file mode 100644 index 0000000..727b050 --- /dev/null +++ b/server/public/assets/ws-BM1PmMVd.js @@ -0,0 +1 @@ +function l(s,n={}){let e,r=0,c=!1;function i(){const a=location.protocol==="https:"?"wss":"ws",o=new URLSearchParams;n.room&&o.set("room",n.room),n.kind&&o.set("kind",n.kind);const d=o.toString();e=new WebSocket(`${a}://${location.host}/ws${d?"?"+d:""}`),e.addEventListener("open",()=>{var t;r=0,(t=n.onOpen)==null||t.call(n)}),e.addEventListener("message",t=>{try{s(JSON.parse(t.data))}catch{}}),e.addEventListener("close",()=>{var t;(t=n.onClose)==null||t.call(n),!c&&(r=Math.min(r+1,6),setTimeout(i,500*2**r))}),e.addEventListener("error",()=>e.close())}return i(),{send(a){(e==null?void 0:e.readyState)===WebSocket.OPEN&&e.send(JSON.stringify(a))},close(){c=!0,e==null||e.close()},get readyState(){return e==null?void 0:e.readyState}}}export{l as c}; diff --git a/server/public/docs/index.html b/server/public/docs/index.html index 9348808..1c4d2b2 100644 --- a/server/public/docs/index.html +++ b/server/public/docs/index.html @@ -21,4 +21,4 @@
- + \ No newline at end of file diff --git a/server/public/index.html b/server/public/index.html index 694cafa..97b23b8 100644 --- a/server/public/index.html +++ b/server/public/index.html @@ -5,10 +5,11 @@ Radio Kiosk - + - - + + + diff --git a/server/public/master/index.html b/server/public/master/index.html new file mode 100644 index 0000000..78062f9 --- /dev/null +++ b/server/public/master/index.html @@ -0,0 +1,19 @@ + + + + + + + Radio Master + + + + + + + + +
+ + + diff --git a/server/rooms.js b/server/rooms.js new file mode 100644 index 0000000..1b6204f --- /dev/null +++ b/server/rooms.js @@ -0,0 +1,142 @@ +// Room model: named multi-client listening sessions. +// +// Each user has an auto-provisioned "personal" room (slug = `u-`) so the +// kiosk Just Works on first login. Shared rooms are explicit creations and +// have a member list. + +import { getDb } from './db/index.js'; +import { slugify } from './stations.js'; + +function rowToRoom(row) { + if (!row) return null; + return { + id: row.id, + slug: row.slug, + name: row.name, + created_by: row.created_by, + created_at: row.created_at + }; +} + +export function getRoomBySlug(slug) { + return rowToRoom(getDb().prepare('SELECT * FROM rooms WHERE slug = ?').get(slug)); +} + +export function getRoomById(id) { + return rowToRoom(getDb().prepare('SELECT * FROM rooms WHERE id = ?').get(id)); +} + +export function isMember(roomId, userId) { + if (!roomId || !userId) return false; + const row = getDb().prepare( + 'SELECT 1 FROM room_members WHERE room_id = ? AND user_id = ?' + ).get(roomId, userId); + return !!row; +} + +export function listRoomsForUser(userId) { + return getDb().prepare(` + SELECT r.*, rm.role + FROM rooms r + JOIN room_members rm ON rm.room_id = r.id + WHERE rm.user_id = ? + ORDER BY r.name COLLATE NOCASE + `).all(userId).map((row) => ({ ...rowToRoom(row), role: row.role })); +} + +export function listMembers(roomId) { + return getDb().prepare(` + SELECT u.id, u.username, rm.role, rm.created_at + FROM room_members rm JOIN users u ON u.id = rm.user_id + WHERE rm.room_id = ? + ORDER BY u.username COLLATE NOCASE + `).all(roomId); +} + +function uniqueRoomSlug(base) { + const db = getDb(); + let slug = base, n = 1; + while (db.prepare('SELECT 1 FROM rooms WHERE slug = ?').get(slug)) { + n += 1; + slug = `${base}-${n}`; + } + return slug; +} + +export function createRoom({ name, slug, ownerId }) { + if (!name) throw new Error('name required'); + const db = getDb(); + const baseSlug = slug || slugify(name); + const finalSlug = uniqueRoomSlug(baseSlug); + const info = db.prepare( + 'INSERT INTO rooms (slug, name, created_by) VALUES (?, ?, ?)' + ).run(finalSlug, name, ownerId ?? null); + const id = info.lastInsertRowid; + if (ownerId) { + db.prepare( + "INSERT OR IGNORE INTO room_members (room_id, user_id, role) VALUES (?, ?, 'owner')" + ).run(id, ownerId); + } + db.prepare( + 'INSERT OR IGNORE INTO room_state (room_id, playing, volume) VALUES (?, 0, 0.7)' + ).run(id); + return getRoomById(id); +} + +export function addMember(roomId, userId, role = 'member') { + getDb().prepare( + 'INSERT OR IGNORE INTO room_members (room_id, user_id, role) VALUES (?, ?, ?)' + ).run(roomId, userId, role); +} + +export function removeMember(roomId, userId) { + return getDb().prepare( + 'DELETE FROM room_members WHERE room_id = ? AND user_id = ?' + ).run(roomId, userId).changes > 0; +} + +/** Idempotently ensure a personal room exists for the user, returning it. */ +export function ensurePersonalRoom(user) { + if (!user) return null; + const slug = `u-${user.id}`; + const existing = getRoomBySlug(slug); + if (existing) return existing; + const db = getDb(); + db.prepare( + 'INSERT INTO rooms (slug, name, created_by) VALUES (?, ?, ?)' + ).run(slug, `${user.username}'s room`, user.id); + const room = getRoomBySlug(slug); + db.prepare( + "INSERT OR IGNORE INTO room_members (room_id, user_id, role) VALUES (?, ?, 'owner')" + ).run(room.id, user.id); + db.prepare( + 'INSERT OR IGNORE INTO room_state (room_id, playing, volume) VALUES (?, 0, 0.7)' + ).run(room.id); + return room; +} + +export function getRoomState(roomId) { + const row = getDb().prepare('SELECT * FROM room_state WHERE room_id = ?').get(roomId); + if (!row) return { station_id: null, playing: false, volume: 0.7, updated_at: null }; + return { + station_id: row.station_id, + playing: !!row.playing, + volume: row.volume, + updated_at: row.updated_at + }; +} + +export function setRoomState(roomId, patch) { + const cur = getRoomState(roomId); + const next = { ...cur, ...patch }; + getDb().prepare(` + INSERT INTO room_state (room_id, station_id, playing, volume, updated_at) + VALUES (?, ?, ?, ?, datetime('now')) + ON CONFLICT(room_id) DO UPDATE SET + station_id = excluded.station_id, + playing = excluded.playing, + volume = excluded.volume, + updated_at = excluded.updated_at + `).run(roomId, next.station_id ?? null, next.playing ? 1 : 0, next.volume ?? 0.7); + return getRoomState(roomId); +} diff --git a/server/routes/admin.js b/server/routes/admin.js index 6b20d55..8f133c3 100644 --- a/server/routes/admin.js +++ b/server/routes/admin.js @@ -1,14 +1,29 @@ import { Router } from 'express'; +import express from 'express'; import { requireAdmin } from '../auth.js'; import { runHealthCheck } from '../streams/checker.js'; +import { probeStream } from '../streams/probe.js'; import { applySeedIfEmpty } from '../sources/seed.js'; import { getDb } from '../db/index.js'; import { scrapeIcon } from '../sources/iconScraper.js'; -import { listStations, getStation, updateStation } from '../stations.js'; +import { + listStations, getStation, updateStation, deleteStation, + getStreamsForStation, addStream, deleteStream +} from '../stations.js'; +import { + saveStationImageFromUrl, saveStationImageFromBuffer, + deleteStationImage, imageCacheStats +} from '../media/images.js'; +import { broadcastGlobal } from '../ws.js'; export const router = Router(); router.use(requireAdmin); +// Raw body parser used only by the image upload route. The global JSON +// parser is mounted before us so we have to opt-out for `image/*`. +const rawImageBody = express.raw({ type: ['image/*', 'application/octet-stream'], limit: '5mb' }); + + router.post('/health-check', async (_req, res) => { const n = await runHealthCheck(); res.json({ checked: n }); @@ -20,25 +35,31 @@ router.post('/reseed', (_req, res) => { router.get('/system', (_req, res) => { const db = getDb(); + const img = imageCacheStats(); res.json({ stations: db.prepare('SELECT COUNT(*) AS n FROM stations').get().n, streams: db.prepare('SELECT COUNT(*) AS n FROM streams').get().n, users: db.prepare('SELECT COUNT(*) AS n FROM users').get().n, favorites: db.prepare('SELECT COUNT(*) AS n FROM favorites').get().n, + image_cache: img, node: process.version, uptime_s: Math.round(process.uptime()) }); }); -// Scrape an icon for a single station. +// Scrape an icon for a single station and cache it locally. router.post('/stations/:id/scrape-icon', async (req, res) => { const id = Number(req.params.id); const st = getStation(id); if (!st) return res.status(404).json({ error: 'not found' }); const url = await scrapeIcon(st); if (!url) return res.status(404).json({ error: 'no icon found' }); - const updated = updateStation(id, { image_url: url }); - res.json({ id, image_url: url, station: updated }); + // Persist the remote URL as the canonical source... + updateStation(id, { image_url: url }); + // ...and try to cache it locally. Failure to cache is non-fatal. + const rel = await saveStationImageFromUrl(id, url, { source: 'scraped' }); + const station = getStation(id); + res.json({ id, image_url: url, image_path: rel, station }); }); // Bulk: scrape icons for every station (optionally only those missing one). @@ -56,8 +77,9 @@ router.post('/scrape-icons', async (req, res) => { const url = await scrapeIcon(s); if (url) { updateStation(s.id, { image_url: url }); + const rel = await saveStationImageFromUrl(s.id, url, { source: 'scraped' }); results.updated++; - results.items.push({ id: s.id, name: s.name, image_url: url }); + results.items.push({ id: s.id, name: s.name, image_url: url, image_path: rel }); } else { results.failed++; results.items.push({ id: s.id, name: s.name, image_url: null }); @@ -71,3 +93,213 @@ router.post('/scrape-icons', async (req, res) => { await Promise.all(Array.from({ length: concurrency }, worker)); res.json(results); }); + + +// ---------- Station edit (admin can override DB fields) ---------- +// Plain PATCH /api/stations/:id already exists for admins. We add a sibling +// here so the admin UI can hit /api/admin/stations/:id consistently. +router.patch('/stations/:id', (req, res) => { + const id = Number(req.params.id); + const st = updateStation(id, req.body || {}); + if (!st) return res.status(404).json({ error: 'not found' }); + broadcastGlobal({ type: 'station-updated', stationId: id }); + res.json(st); +}); + +router.delete('/stations/:id', (req, res) => { + const id = Number(req.params.id); + if (!deleteStation(id)) return res.status(404).json({ error: 'not found' }); + deleteStationImage(id); + broadcastGlobal({ type: 'station-deleted', stationId: id }); + res.json({ ok: true }); +}); + +// ---------- Image management ---------- +// Raw upload: PUT /api/admin/stations/:id/image (Content-Type: image/*) +router.put('/stations/:id/image', rawImageBody, (req, res) => { + const id = Number(req.params.id); + if (!getStation(id)) return res.status(404).json({ error: 'not found' }); + const buf = req.body; + if (!Buffer.isBuffer(buf) || !buf.length) return res.status(400).json({ error: 'no body' }); + const mime = req.get('content-type') || 'application/octet-stream'; + try { + const rel = saveStationImageFromBuffer(id, buf, mime, { source: 'upload' }); + broadcastGlobal({ type: 'station-updated', stationId: id }); + res.json({ id, image_path: rel, station: getStation(id) }); + } catch (err) { + res.status(400).json({ error: String(err.message || err) }); + } +}); + +// Re-download the current remote image_url into the local cache. +router.post('/stations/:id/image/refetch', async (req, res) => { + const id = Number(req.params.id); + const st = getStation(id); + if (!st) return res.status(404).json({ error: 'not found' }); + const target = (req.body && req.body.url) || st.image_url; + if (!target) return res.status(400).json({ error: 'no image_url to refetch' }); + if (req.body && req.body.url) updateStation(id, { image_url: target }); + const rel = await saveStationImageFromUrl(id, target, { source: 'remote' }); + if (!rel) return res.status(502).json({ error: 'download failed' }); + broadcastGlobal({ type: 'station-updated', stationId: id }); + res.json({ id, image_path: rel, station: getStation(id) }); +}); + +// Drop the local cache entry (keeps remote image_url). +router.delete('/stations/:id/image', (req, res) => { + const id = Number(req.params.id); + if (!getStation(id)) return res.status(404).json({ error: 'not found' }); + deleteStationImage(id); + broadcastGlobal({ type: 'station-updated', stationId: id }); + res.json({ ok: true, station: getStation(id) }); +}); + +// ---------- Streams CRUD ---------- +router.get('/stations/:id/streams', (req, res) => { + const id = Number(req.params.id); + if (!getStation(id)) return res.status(404).json({ error: 'not found' }); + res.json(getStreamsForStation(id)); +}); + +router.post('/stations/:id/streams', (req, res) => { + const id = Number(req.params.id); + if (!getStation(id)) return res.status(404).json({ error: 'not found' }); + res.status(201).json(addStream(id, req.body || {})); +}); + +router.patch('/streams/:streamId', (req, res) => { + const sid = Number(req.params.streamId); + const db = getDb(); + const cur = db.prepare('SELECT * FROM streams WHERE id = ?').get(sid); + if (!cur) return res.status(404).json({ error: 'not found' }); + const next = { ...cur, ...(req.body || {}) }; + db.prepare(`UPDATE streams SET url = ?, format = ?, bitrate = ?, label = ?, priority = ? WHERE id = ?`) + .run(next.url, next.format, next.bitrate || null, next.label || null, next.priority || 0, sid); + res.json(db.prepare('SELECT * FROM streams WHERE id = ?').get(sid)); +}); + +router.delete('/streams/:streamId', (req, res) => { + if (!deleteStream(Number(req.params.streamId))) return res.status(404).json({ error: 'not found' }); + res.json({ ok: true }); +}); + +// Probe a single stream on demand (admin UI uses this for a "test" button). +router.post('/streams/:streamId/probe', async (req, res) => { + const sid = Number(req.params.streamId); + const row = getDb().prepare('SELECT * FROM streams WHERE id = ?').get(sid); + if (!row) return res.status(404).json({ error: 'not found' }); + const status = await probeStream(row.url); + getDb().prepare(`UPDATE streams SET last_status = ?, last_checked_at = datetime('now') WHERE id = ?`).run(status, sid); + res.json({ id: sid, status }); +}); + +// ---------- Bulk ops ---------- +router.post('/stations/bulk', async (req, res) => { + const ids = Array.isArray(req.body?.ids) ? req.body.ids.map(Number).filter(Number.isFinite) : []; + const action = String(req.body?.action || ''); + if (!ids.length) return res.status(400).json({ error: 'ids required' }); + const results = { action, count: ids.length, ok: 0, failed: 0, items: [] }; + for (const id of ids) { + try { + switch (action) { + case 'delete': + if (deleteStation(id)) { deleteStationImage(id); results.ok++; } + else results.failed++; + break; + case 'enable': + case 'disable': + updateStation(id, { enabled: action === 'enable' }); + results.ok++; + break; + case 'scrape-icon': { + const st = getStation(id); + if (!st) { results.failed++; break; } + const url = await scrapeIcon(st); + if (url) { + updateStation(id, { image_url: url }); + await saveStationImageFromUrl(id, url, { source: 'scraped' }); + results.ok++; + } else results.failed++; + break; + } + case 'refetch-image': { + const st = getStation(id); + if (!st?.image_url) { results.failed++; break; } + const rel = await saveStationImageFromUrl(id, st.image_url, { source: 'remote' }); + if (rel) results.ok++; else results.failed++; + break; + } + default: + return res.status(400).json({ error: 'unknown action' }); + } + results.items.push({ id, ok: true }); + } catch (err) { + results.failed++; + results.items.push({ id, error: String(err.message || err) }); + } + } + broadcastGlobal({ type: 'bulk-completed', action }); + res.json(results); +}); + +// ---------- Moderation ---------- +router.delete('/stations/:id/votes', (req, res) => { + const id = Number(req.params.id); + if (!getStation(id)) return res.status(404).json({ error: 'not found' }); + const n = getDb().prepare('DELETE FROM station_votes WHERE station_id = ?').run(id).changes; + broadcastGlobal({ type: 'vote', stationId: id, stats: { up: 0, down: 0, score: 0 }, by: 'admin' }); + res.json({ ok: true, removed: n }); +}); + +router.delete('/stations/:id/plays', (req, res) => { + const id = Number(req.params.id); + if (!getStation(id)) return res.status(404).json({ error: 'not found' }); + const n = getDb().prepare('DELETE FROM station_plays WHERE station_id = ?').run(id).changes; + broadcastGlobal({ type: 'plays', stationId: id, plays: 0 }); + res.json({ ok: true, removed: n }); +}); + +router.get('/leaderboard', (req, res) => { + const db = getDb(); + const top = db.prepare(` + SELECT s.id, s.uuid, s.name, s.country, s.image_path, s.image_url, + COALESCE((SELECT COUNT(*) FROM station_votes v WHERE v.station_id = s.id AND v.value = 1), 0) AS up, + COALESCE((SELECT COUNT(*) FROM station_votes v WHERE v.station_id = s.id AND v.value = -1), 0) AS down, + COALESCE(p.plays, 0) AS plays, + COALESCE(p.sessions, 0) AS sessions, + COALESCE(p.total_play_ms, 0) AS total_play_ms, + p.last_played_at AS last_played_at + FROM stations s + LEFT JOIN station_plays p ON p.station_id = s.id + ORDER BY total_play_ms DESC, plays DESC, up DESC + LIMIT 50 + `).all(); + for (const r of top) { + r.avg_session_ms = r.sessions > 0 ? Math.round(r.total_play_ms / r.sessions) : 0; + // Mirror what listStations() does so admin UIs can use a single field. + r.image_display_url = r.image_path ? `/media/${r.image_path}` : (r.image_url || null); + } + res.json(top); +}); + +// ---------- Room admin ---------- +router.get('/rooms', (_req, res) => { + const db = getDb(); + const rows = db.prepare(` + SELECT r.id, r.slug, r.name, r.created_by, r.created_at, + (SELECT COUNT(*) FROM room_members m WHERE m.room_id = r.id) AS members, + (SELECT COUNT(*) FROM room_state rs WHERE rs.room_id = r.id AND rs.station_id IS NOT NULL) AS active + FROM rooms r + ORDER BY r.created_at DESC + `).all(); + res.json(rows); +}); + +router.delete('/rooms/:slug', (req, res) => { + const db = getDb(); + const row = db.prepare('SELECT id, slug FROM rooms WHERE slug = ?').get(req.params.slug); + if (!row) return res.status(404).json({ error: 'not found' }); + if (row.slug.startsWith('u-')) return res.status(400).json({ error: 'cannot delete personal rooms' }); + db.prepare('DELETE FROM rooms WHERE id = ?').run(row.id); + res.json({ ok: true }); +}); diff --git a/server/routes/rooms.js b/server/routes/rooms.js new file mode 100644 index 0000000..d5811eb --- /dev/null +++ b/server/routes/rooms.js @@ -0,0 +1,61 @@ +// /api/rooms — list/create rooms, manage members, fetch state. + +import { Router } from 'express'; +import { requireUser } from '../auth.js'; +import { + listRoomsForUser, getRoomBySlug, createRoom, + addMember, removeMember, listMembers, isMember, getRoomState, + ensurePersonalRoom +} from '../rooms.js'; +import { getStation } from '../stations.js'; + +export const router = Router(); +router.use(requireUser); + +router.get('/', (req, res) => { + // Guarantee a personal room exists for every authenticated user. + ensurePersonalRoom(req.user); + res.json(listRoomsForUser(req.user.id)); +}); + +router.post('/', (req, res) => { + const { name, slug } = req.body || {}; + if (!name || typeof name !== 'string') return res.status(400).json({ error: 'name required' }); + const room = createRoom({ name: name.trim(), slug: slug?.trim() || undefined, ownerId: req.user.id }); + res.status(201).json(room); +}); + +router.get('/:slug', (req, res) => { + const room = getRoomBySlug(req.params.slug); + if (!room) return res.status(404).json({ error: 'not found' }); + if (!isMember(room.id, req.user.id)) return res.status(403).json({ error: 'not a member' }); + const state = getRoomState(room.id); + const station = state.station_id ? getStation(state.station_id) : null; + res.json({ ...room, state: { ...state, station } }); +}); + +router.get('/:slug/members', (req, res) => { + const room = getRoomBySlug(req.params.slug); + if (!room) return res.status(404).json({ error: 'not found' }); + if (!isMember(room.id, req.user.id)) return res.status(403).json({ error: 'not a member' }); + res.json(listMembers(room.id)); +}); + +router.post('/:slug/members', (req, res) => { + const room = getRoomBySlug(req.params.slug); + if (!room) return res.status(404).json({ error: 'not found' }); + if (!isMember(room.id, req.user.id)) return res.status(403).json({ error: 'not a member' }); + const userId = Number(req.body?.user_id); + if (!userId) return res.status(400).json({ error: 'user_id required' }); + const role = req.body?.role === 'guest' ? 'guest' : 'member'; + addMember(room.id, userId, role); + res.json(listMembers(room.id)); +}); + +router.delete('/:slug/members/:userId', (req, res) => { + const room = getRoomBySlug(req.params.slug); + if (!room) return res.status(404).json({ error: 'not found' }); + if (!isMember(room.id, req.user.id)) return res.status(403).json({ error: 'not a member' }); + removeMember(room.id, Number(req.params.userId)); + res.json(listMembers(room.id)); +}); diff --git a/server/routes/stations.js b/server/routes/stations.js index 08c4ebe..0562a05 100644 --- a/server/routes/stations.js +++ b/server/routes/stations.js @@ -6,7 +6,8 @@ import { import { resolveStream } from '../streams/resolver.js'; import { requireAdmin, requireUser } from '../auth.js'; import * as radiobrowser from '../sources/radiobrowser.js'; -import { castVote, getStationStats, getStatsMap, recordPlay, sortByMode } from '../stats.js'; +import { castVote, getStationStats, getStatsMap, recordPlay, endPlaySession, sortByMode } from '../stats.js'; +import { broadcastGlobal } from '../ws.js'; export const router = Router(); @@ -51,15 +52,41 @@ router.post('/:id/vote', requireUser, (req, res) => { : raw === 0 || raw === '0' || raw === null || raw === 'clear' ? 0 : NaN; if (Number.isNaN(value)) return res.status(400).json({ error: 'value must be 1, -1 or 0' }); - res.json(castVote(req.user.id, id, value)); + const stats = castVote(req.user.id, id, value); + // Tell every open client so other panels' vote counts update live. + broadcastGlobal({ type: 'vote', stationId: id, stats: { up: stats.up, down: stats.down, score: stats.score }, by: req.user.username }); + res.json(stats); }); // Lightweight play-count ping (called when the kiosk actually starts a station). +// Opens a listening session in play_history; the returned `sessionId` should be +// echoed back to POST /api/stations/:id/play/end so we can credit total listen +// time toward the leaderboard score. router.post('/:id/play', requireUser, (req, res) => { const id = Number(req.params.id); if (!getStation(id)) return res.status(404).json({ error: 'not found' }); - recordPlay(id); - res.json(getStationStats(id, req.user.id)); + const streamId = Number.isFinite(Number(req.body?.streamId)) ? Number(req.body.streamId) : null; + const sessionId = recordPlay(id, req.user.id, streamId); + const stats = getStationStats(id, req.user.id); + broadcastGlobal({ type: 'plays', stationId: id, plays: stats.plays }); + res.json({ ...stats, sessionId }); +}); + +// Close a session opened by POST /:id/play. Idempotent — calling twice or with +// an unknown id silently no-ops. Accepts an optional `duration_ms` so a client +// that knows the real listened time (e.g. minus buffering stalls) can be honest. +router.post('/:id/play/end', requireUser, (req, res) => { + const id = Number(req.params.id); + if (!getStation(id)) return res.status(404).json({ error: 'not found' }); + const sessionId = Number(req.body?.sessionId); + if (!Number.isFinite(sessionId)) return res.status(400).json({ error: 'sessionId required' }); + const rawMs = req.body?.duration_ms; + const ms = rawMs == null ? null : Number(rawMs); + const closed = endPlaySession(sessionId, req.user.id, ms); + if (closed == null) return res.json({ ok: false }); + const stats = getStationStats(closed, req.user.id); + broadcastGlobal({ type: 'plays', stationId: closed, plays: stats.plays }); + res.json({ ok: true, ...stats }); }); router.post('/:id/resolve', requireUser, async (req, res) => { diff --git a/server/routes/v1.js b/server/routes/v1.js index de82bc5..fcf6f5b 100644 --- a/server/routes/v1.js +++ b/server/routes/v1.js @@ -50,7 +50,9 @@ function publicStation(s) { country: s.country, genres: s.genres, description: s.description, - image_url: s.image_url, + // Prefer the locally-cached file when available so public API consumers + // get a stable, fast URL on this host instead of upstream link rot. + image_url: s.image_display_url || s.image_url, category: s.category, enabled: s.enabled, up: s.up ?? 0, diff --git a/server/scripts/download-images.js b/server/scripts/download-images.js new file mode 100644 index 0000000..98eb20d --- /dev/null +++ b/server/scripts/download-images.js @@ -0,0 +1,65 @@ +// Backfill cover-art for every station missing a local image. +// +// node server/scripts/download-images.js # only stations missing a local file +// node server/scripts/download-images.js --all # re-download even cached stations +// node server/scripts/download-images.js --no-scrape # skip homepage scrape fallback +// +// Strategy per station: +// 1. Try downloading the existing image_url. +// 2. On failure (404, HTML, dead host, ...), call scrapeIcon() to find a +// fresh icon from Radio-Browser / the station homepage, persist the new +// URL, and try again. +// +// Safe to re-run. + +import 'dotenv/config'; +import { initDb } from '../db/index.js'; +import { listStations, updateStation } from '../stations.js'; +import { saveStationImageFromUrl, ensureImageDirs } from '../media/images.js'; +import { scrapeIcon } from '../sources/iconScraper.js'; + +const FORCE = process.argv.includes('--all'); +const NO_SCRAPE = process.argv.includes('--no-scrape'); +const CONCURRENCY = 4; + +initDb(process.env.DB_PATH || './data/db/oradio.sqlite'); +ensureImageDirs(); + +const all = listStations({ enabled: null }); +const todo = all.filter((s) => FORCE || !s.image_path); +console.log(`[images] ${todo.length} of ${all.length} stations to fetch (force=${FORCE}, scrape=${!NO_SCRAPE})`); + +let i = 0, ok = 0, scraped = 0, fail = 0; +async function worker() { + while (i < todo.length) { + const idx = i++; + const s = todo[idx]; + const label = `[${idx + 1}/${todo.length}] ${s.name}`; + + // 1. Try the existing remote URL. + let rel = s.image_url + ? await saveStationImageFromUrl(s.id, s.image_url, { source: s.image_source || 'remote' }) + : null; + + // 2. Fallback: scrape a fresh icon from the homepage / Radio-Browser. + if (!rel && !NO_SCRAPE) { + const found = await scrapeIcon(s); + if (found && found !== s.image_url) { + updateStation(s.id, { image_url: found }); + rel = await saveStationImageFromUrl(s.id, found, { source: 'scraped' }); + if (rel) scraped++; + } + } + + if (rel) { + ok++; + console.log(` ${label} -> ${rel}`); + } else { + fail++; + console.log(` ${label} ✗ (${s.image_url || 'no url'})`); + } + } +} +await Promise.all(Array.from({ length: CONCURRENCY }, worker)); +console.log(`[images] done. ok=${ok} (scraped=${scraped}) fail=${fail}`); +process.exit(0); diff --git a/server/sources/iconScraper.js b/server/sources/iconScraper.js index 152b23f..7db825f 100644 --- a/server/sources/iconScraper.js +++ b/server/sources/iconScraper.js @@ -7,7 +7,9 @@ // 3. HEAD-probe /favicon.ico at the homepage origin. // Returns the best absolute URL found, or null. -const UA = 'OnlineRadioExplorer/0.1 (+icon-scraper)'; +// Browser-like UA: many station homepages (Cloudflare, Wikimedia) block opaque bots. +const UA = process.env.IMAGE_FETCH_UA + || 'Mozilla/5.0 (compatible; OnlineRadioExplorer/0.1; +https://github.com/marcoheine/onlineRadioExplorer)'; const FETCH_TIMEOUT_MS = 8000; const MAX_HTML_BYTES = 256 * 1024; const RB_BASE = 'https://de1.api.radio-browser.info'; @@ -45,13 +47,47 @@ async function fetchText(url) { } async function head(url) { + // We can't trust real HEAD: many CDNs/SPAs return 200 for *every* path with + // HTML. So we issue a small ranged GET and check the response is actually + // an image (content-type AND/OR magic bytes). const t = withTimeout(FETCH_TIMEOUT_MS); try { - const res = await fetch(url, { method: 'HEAD', headers: { 'User-Agent': UA }, signal: t.signal, redirect: 'follow' }); - return res.ok; + const res = await fetch(url, { + method: 'GET', + headers: { 'User-Agent': UA, 'Accept': 'image/*', 'Range': 'bytes=0-1023' }, + signal: t.signal, + redirect: 'follow' + }); + if (!res.ok && res.status !== 206) return false; + const ct = (res.headers.get('content-type') || '').toLowerCase().split(';')[0].trim(); + if (ct.startsWith('text/') || ct.includes('html')) return false; + // Sniff the first chunk to make sure it's not HTML masquerading as image/*. + const reader = res.body?.getReader(); + if (!reader) return ct.startsWith('image/'); + const { value } = await reader.read(); + try { await reader.cancel(); } catch { } + const buf = value ? Buffer.from(value) : Buffer.alloc(0); + const head = buf.slice(0, 256).toString('utf8').trimStart().toLowerCase(); + if (head.startsWith(' accept. + return isImageMagic(buf); } catch { return false; } finally { t.done(); } } +function isImageMagic(buf) { + if (buf.length < 4) return false; + if (buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4E && buf[3] === 0x47) return true; // PNG + if (buf[0] === 0xFF && buf[1] === 0xD8 && buf[2] === 0xFF) return true; // JPEG + if (buf[0] === 0x47 && buf[1] === 0x49 && buf[2] === 0x46) return true; // GIF + if (buf.length >= 12 && buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 + && buf[8] === 0x57 && buf[9] === 0x45 && buf[10] === 0x42 && buf[11] === 0x50) return true; // WEBP + if (buf[0] === 0x00 && buf[1] === 0x00 && buf[2] === 0x01 && buf[3] === 0x00) return true; // ICO + const head = buf.slice(0, 256).toString('utf8').trimStart().toLowerCase(); + if (head.startsWith(' (s.name || '').toLowerCase().trim() === target); const pick = exact || list[0]; if (pick?.favicon) return pick.favicon; @@ -119,12 +157,23 @@ async function fromHomepage(homepage) { if (await head(c.href)) return c.href; } } - // last resort: /favicon.ico + // last resort on this host: /favicon.ico const ico = `${base.origin}/favicon.ico`; if (await head(ico)) return ico; return null; } +// Final fallback: Google's public favicon service. Returns a real PNG (the +// browser-side favicon Google has on file) for virtually any homepage, so +// even SPA/JS-only sites end up with *some* artwork. +function fromGoogleFavicon(homepage, size = 128) { + if (!homepage) return null; + let host; + try { host = new URL(homepage).hostname; } catch { return null; } + if (!host) return null; + return `https://www.google.com/s2/favicons?sz=${size}&domain=${encodeURIComponent(host)}`; +} + /** * Try to find an icon URL for a station. * @param {{ name?: string, homepage?: string|null, source?: string }} station @@ -135,7 +184,13 @@ export async function scrapeIcon(station) { // For non-RB stations, RB often still has an entry → cheap win. if (station.source !== 'radiobrowser') { const rb = await fromRadioBrowserByName(station.name); - if (rb) return rb; + if (rb && await head(rb)) return rb; } - return fromHomepage(station.homepage); + const fromPage = await fromHomepage(station.homepage); + if (fromPage) return fromPage; + // Last-ditch: ask Google's favicon service. It almost always returns a + // 128×128 PNG, even for SPA-only homepages where direct scraping fails. + const g = fromGoogleFavicon(station.homepage, 128); + if (g && await head(g)) return g; + return null; } diff --git a/server/stations.js b/server/stations.js index 34336f3..0ebdd24 100644 --- a/server/stations.js +++ b/server/stations.js @@ -3,6 +3,8 @@ import { getDb } from './db/index.js'; function rowToStation(row) { if (!row) return null; + const imagePath = row.image_path || null; + const remote = row.image_url || null; return { id: row.id, uuid: row.uuid, @@ -12,7 +14,12 @@ function rowToStation(row) { country: row.country, genres: row.genres ? JSON.parse(row.genres) : [], description: row.description, - image_url: row.image_url, + // image_url remains the remote/source URL (what admins edit). + // image_display_url is what UIs should render — prefers the local cache. + image_url: remote, + image_path: imagePath, + image_source: row.image_source || null, + image_display_url: imagePath ? `/media/${imagePath}` : remote, source: row.source, source_ref: row.source_ref, category: row.category, diff --git a/server/stats.js b/server/stats.js index 511f586..872a82f 100644 --- a/server/stats.js +++ b/server/stats.js @@ -1,23 +1,47 @@ // Vote + play stats and the ranking algorithm. // -// Score combines two signals: +// Score combines three signals: // - voteZ = (up - down) / sqrt(up + down + 1) z-like, penalizes small N // - playLog = log10(plays + 1) gentle popularity boost -// - score = voteZ + 0.5 * playLog +// - timeLog = log10(hours_listened + 1) rewards actual listen time +// - score = voteZ + 0.5 * playLog + 0.4 * timeLog // // Net effect: // * A handful of downvotes on an obscure station sinks it hard. // * One stray upvote on a brand new station barely moves it. -// * Popular stations float up only if they aren't being actively buried. +// * Pressing play and skipping immediately barely counts; sticking with a +// station for hours/days pushes it up the leaderboard. // * Established + positively-voted stations dominate the top. import { getDb } from './db/index.js'; -export function computeScore({ up = 0, down = 0, plays = 0 } = {}) { +// Sessions longer than this are almost certainly a forgotten-tab leak (laptop +// closed, browser put to sleep). Clamp so one user can't poison total_play_ms. +const MAX_SESSION_MS = 6 * 60 * 60 * 1000; // 6 hours +// Sessions shorter than this don't get credited toward listen time (people +// scrubbing through stations should still bump `plays`, but not `total_play_ms`). +const MIN_SESSION_MS = 3 * 1000; + +export function computeScore({ up = 0, down = 0, plays = 0, totalPlayMs = 0 } = {}) { const n = up + down; const voteZ = n === 0 ? 0 : (up - down) / Math.sqrt(n + 1); const playLog = Math.log10(plays + 1); - return voteZ + 0.5 * playLog; + const hours = totalPlayMs / 3600000; + const timeLog = Math.log10(hours + 1); + return voteZ + 0.5 * playLog + 0.4 * timeLog; +} + +function statsFromRow(r) { + const up = r.up || 0; + const down = r.down || 0; + const plays = r.plays || 0; + const sessions = r.sessions || 0; + const totalPlayMs = r.total_play_ms || 0; + const avgSessionMs = sessions > 0 ? Math.round(totalPlayMs / sessions) : 0; + return { + up, down, plays, sessions, totalPlayMs, avgSessionMs, + score: computeScore({ up, down, plays, totalPlayMs }) + }; } export function getStationStats(stationId, userId = null) { @@ -28,14 +52,15 @@ export function getStationStats(stationId, userId = null) { COALESCE(SUM(CASE WHEN value = -1 THEN 1 ELSE 0 END), 0) AS down FROM station_votes WHERE station_id = ? `).get(stationId) || { up: 0, down: 0 }; - const p = db.prepare('SELECT plays FROM station_plays WHERE station_id = ?').get(stationId); - const plays = p?.plays || 0; + const p = db.prepare(` + SELECT plays, sessions, total_play_ms FROM station_plays WHERE station_id = ? + `).get(stationId) || {}; let myVote = 0; if (userId) { const r = db.prepare('SELECT value FROM station_votes WHERE user_id = ? AND station_id = ?').get(userId, stationId); myVote = r?.value || 0; } - return { up: v.up, down: v.down, plays, myVote, score: computeScore({ up: v.up, down: v.down, plays }) }; + return { ...statsFromRow({ ...v, ...p }), myVote }; } // Bulk stats for many stations in one query. Returns a Map. @@ -46,7 +71,9 @@ export function getStatsMap(userId = null) { s.id AS station_id, COALESCE(v.up, 0) AS up, COALESCE(v.down, 0) AS down, - COALESCE(p.plays, 0) AS plays + COALESCE(p.plays, 0) AS plays, + COALESCE(p.sessions, 0) AS sessions, + COALESCE(p.total_play_ms, 0) AS total_play_ms FROM stations s LEFT JOIN ( SELECT station_id, @@ -65,11 +92,7 @@ export function getStatsMap(userId = null) { } const out = new Map(); for (const r of rows) { - const myVote = my.get(r.station_id) || 0; - out.set(r.station_id, { - up: r.up, down: r.down, plays: r.plays, myVote, - score: computeScore({ up: r.up, down: r.down, plays: r.plays }) - }); + out.set(r.station_id, { ...statsFromRow(r), myVote: my.get(r.station_id) || 0 }); } return out; } @@ -89,18 +112,67 @@ export function castVote(userId, stationId, value) { return getStationStats(stationId, userId); } -export function recordPlay(stationId) { - getDb().prepare(` - INSERT INTO station_plays (station_id, plays, last_played_at) VALUES (?, 1, datetime('now')) +// Record the start of a listening session. Bumps the play counter immediately +// (so spam-clickers still register as taps) and opens a play_history row that +// `endPlaySession` will close with a duration. Returns the new session id when +// a user is known, or null for anonymous plays (which still bump the counter). +export function recordPlay(stationId, userId = null, streamId = null) { + const db = getDb(); + db.prepare(` + INSERT INTO station_plays (station_id, plays, sessions, total_play_ms, last_played_at) + VALUES (?, 1, 0, 0, datetime('now')) ON CONFLICT(station_id) DO UPDATE SET plays = station_plays.plays + 1, last_played_at = datetime('now') `).run(stationId); + if (!userId) return null; + const info = db.prepare(` + INSERT INTO play_history (user_id, station_id, stream_id, started_at) + VALUES (?, ?, ?, datetime('now')) + `).run(userId, stationId, streamId || null); + return info.lastInsertRowid; +} + +// Close a session opened by recordPlay. `durationMs` is optional — when the +// client knows the real wall-clock listen time (e.g. an `audio.currentTime` +// derivative) it should pass it; otherwise we compute it from started_at. +// Returns the station_id we closed against, or null when the session is +// unknown / already closed / belongs to someone else. +export function endPlaySession(sessionId, userId, durationMs = null) { + const db = getDb(); + const row = db.prepare(` + SELECT id, station_id, user_id, started_at, ended_at + FROM play_history WHERE id = ? + `).get(sessionId); + if (!row || row.user_id !== userId || row.ended_at) return null; + + let ms = Number.isFinite(durationMs) && durationMs >= 0 + ? Math.floor(durationMs) + : Math.max(0, Date.now() - Date.parse(String(row.started_at).replace(' ', 'T') + 'Z')); + if (!Number.isFinite(ms) || ms < 0) ms = 0; + if (ms > MAX_SESSION_MS) ms = MAX_SESSION_MS; + + db.prepare(`UPDATE play_history SET ended_at = datetime('now') WHERE id = ?`).run(sessionId); + + // Only credit listen-time aggregates for "real" sessions; sub-second + // sessions don't earn the station any score, but they already bumped + // `plays` in recordPlay so they aren't completely free either. + if (ms >= MIN_SESSION_MS) { + db.prepare(` + INSERT INTO station_plays (station_id, plays, sessions, total_play_ms, last_played_at) + VALUES (?, 0, 1, ?, datetime('now')) + ON CONFLICT(station_id) DO UPDATE SET + sessions = station_plays.sessions + 1, + total_play_ms = station_plays.total_play_ms + excluded.total_play_ms, + last_played_at = datetime('now') + `).run(row.station_id, ms); + } + return row.station_id; } // Sort helper used by routes. Mutates the array. export function sortByMode(items, mode, statsMap) { - const s = (id) => statsMap.get(id) || { up: 0, down: 0, plays: 0, score: 0 }; + const s = (id) => statsMap.get(id) || { up: 0, down: 0, plays: 0, totalPlayMs: 0, score: 0 }; switch (mode) { case 'hot': items.sort((a, b) => s(b.id).score - s(a.id).score || a.name.localeCompare(b.name)); @@ -111,6 +183,9 @@ export function sortByMode(items, mode, statsMap) { case 'plays': items.sort((a, b) => s(b.id).plays - s(a.id).plays || a.name.localeCompare(b.name)); break; + case 'playtime': + items.sort((a, b) => s(b.id).totalPlayMs - s(a.id).totalPlayMs || a.name.localeCompare(b.name)); + break; case 'controversial': items.sort((a, b) => { const A = s(a.id), B = s(b.id); diff --git a/server/ws.js b/server/ws.js index 8261378..547f0f6 100644 --- a/server/ws.js +++ b/server/ws.js @@ -1,8 +1,102 @@ -import { WebSocketServer } from 'ws'; -import { getUserBySession, readSessionToken } from './auth.js'; +// Room-aware WebSocket hub. +// +// Connect to `/ws?room=&kind=display|controller|panel`. Auth via the +// session cookie. The server is the single source of truth for room state +// (now-playing, volume); clients send `command` (intent) and the elected +// display client emits `state` (truth) which is persisted to `room_state` +// and rebroadcast. +// +// Message envelope: `{ type, ...payload }`. Types: +// - hello server->client: { room, peers, state, role, you } +// - presence server->room: { peers } +// - command client->server: { action: play|pause|stop|volume|setSink, ... } +// server->room: forwarded as-is +// - state display->server: ground-truth playback snapshot +// server->room: persisted snapshot +// - devices display->server: { list, current } server->room: same +// - vote server->room: { stationId, stats } emitted after castVote +// - plays server->room: { stationId, plays } emitted after recordPlay -// per-user channel hub: any client of user U receives messages targeted to U. -const channels = new Map(); // userId -> Set +import { WebSocketServer } from 'ws'; +import { URL } from 'node:url'; +import { getUserBySession, readSessionToken } from './auth.js'; +import { + getRoomBySlug, ensurePersonalRoom, isMember, + getRoomState, setRoomState +} from './rooms.js'; +import { getStation } from './stations.js'; + +// roomSlug -> Set +const rooms = new Map(); +// userId -> Set +const byUser = new Map(); + +function addToIndex(map, key, ws) { + if (!map.has(key)) map.set(key, new Set()); + map.get(key).add(ws); +} +function removeFromIndex(map, key, ws) { + const set = map.get(key); + if (!set) return; + set.delete(ws); + if (!set.size) map.delete(key); +} + +function presenceFor(roomSlug) { + const set = rooms.get(roomSlug); + if (!set) return []; + const out = []; + for (const ws of set) { + out.push({ + user: { id: ws.user.id, username: ws.user.username }, + kind: ws.kind, + since: ws.since + }); + } + return out; +} + +function send(ws, msg) { + if (ws.readyState === ws.OPEN) ws.send(JSON.stringify(msg)); +} + +export function broadcastToRoom(roomSlug, msg, except) { + const set = rooms.get(roomSlug); + if (!set) return; + const payload = JSON.stringify(msg); + for (const ws of set) { + if (ws === except) continue; + if (ws.readyState === ws.OPEN) ws.send(payload); + } +} + +/** Send to every connection of the given user, across all their rooms. */ +export function broadcastToUser(userId, msg, except) { + const set = byUser.get(userId); + if (!set) return; + const payload = JSON.stringify(msg); + for (const ws of set) { + if (ws === except) continue; + if (ws.readyState === ws.OPEN) ws.send(payload); + } +} + +/** Broadcast to every open WS, regardless of room. Used for global events. */ +export function broadcastGlobal(msg) { + const payload = JSON.stringify(msg); + for (const set of rooms.values()) { + for (const ws of set) { + if (ws.readyState === ws.OPEN) ws.send(payload); + } + } +} + +function hasDisplay(roomSlug) { + const set = rooms.get(roomSlug); + if (!set) return false; + for (const ws of set) if (ws.kind === 'display') return true; + return false; +} export function attachWs(server) { const wss = new WebSocketServer({ noServer: true }); @@ -16,41 +110,110 @@ export function attachWs(server) { socket.destroy(); return; } + + const url = new URL(req.url, 'http://x'); + const slug = url.searchParams.get('room') || `u-${user.id}`; + let kindRaw = url.searchParams.get('kind') || 'controller'; + if (!['display', 'controller', 'panel'].includes(kindRaw)) kindRaw = 'controller'; + + // Resolve room. The personal room is auto-provisioned on demand. + let room = getRoomBySlug(slug); + if (!room && slug === `u-${user.id}`) room = ensurePersonalRoom(user); + if (!room) { + socket.write('HTTP/1.1 404 Not Found\r\n\r\n'); + socket.destroy(); + return; + } + if (!isMember(room.id, user.id)) { + socket.write('HTTP/1.1 403 Forbidden\r\n\r\n'); + socket.destroy(); + return; + } + + // One display per room: subsequent claimers are silently demoted + // to passive panels (no audio, no device picker). + let kind = kindRaw; + if (kind === 'display' && hasDisplay(room.slug)) kind = 'panel'; + wss.handleUpgrade(req, socket, head, (ws) => { ws.user = user; - addClient(user.id, ws); - ws.on('close', () => removeClient(user.id, ws)); + ws.kind = kind; + ws.room = room; + ws.since = Date.now(); + addToIndex(rooms, room.slug, ws); + addToIndex(byUser, user.id, ws); + + ws.on('close', () => { + removeFromIndex(rooms, room.slug, ws); + removeFromIndex(byUser, user.id, ws); + broadcastToRoom(room.slug, { type: 'presence', peers: presenceFor(room.slug) }); + }); + ws.on('message', (raw) => { let msg; try { msg = JSON.parse(raw.toString()); } catch { return; } - // Re-broadcast every message to all connections of the same user. - // (e.g. phone sends `{type:"command", action:"play", stationId:7}` → kiosk receives) - broadcastToUser(user.id, msg, ws); + handleClientMessage(ws, msg); }); - ws.send(JSON.stringify({ type: 'hello', user: { id: user.id, username: user.username, role: user.role } })); + + // Send hello snapshot. + const state = getRoomState(room.id); + const station = state.station_id ? getStation(state.station_id) : null; + send(ws, { + type: 'hello', + you: { id: user.id, username: user.username, role: user.role, kind }, + room: { id: room.id, slug: room.slug, name: room.name }, + state: { ...state, station }, + peers: presenceFor(room.slug) + }); + broadcastToRoom(room.slug, { type: 'presence', peers: presenceFor(room.slug) }, ws); }); }); return wss; } -function addClient(userId, ws) { - if (!channels.has(userId)) channels.set(userId, new Set()); - channels.get(userId).add(ws); -} -function removeClient(userId, ws) { - const set = channels.get(userId); - if (!set) return; - set.delete(ws); - if (!set.size) channels.delete(userId); -} +function handleClientMessage(ws, msg) { + if (!msg || typeof msg !== 'object') return; + const slug = ws.room.slug; -export function broadcastToUser(userId, msg, except) { - const set = channels.get(userId); - if (!set) return; - const payload = JSON.stringify(msg); - for (const ws of set) { - if (ws === except) continue; - if (ws.readyState === ws.OPEN) ws.send(payload); + switch (msg.type) { + case 'command': { + // Controllers express intent. Forward to all peers; the display + // is responsible for actually changing audio output. We also + // optimistically reflect simple intents into room_state so a + // late-joining peer sees the latest target station/volume even + // before the display emits a confirmation `state`. + if (msg.action === 'play' && Number.isFinite(msg.stationId)) { + setRoomState(ws.room.id, { station_id: Number(msg.stationId), playing: true }); + } else if (msg.action === 'stop') { + setRoomState(ws.room.id, { playing: false }); + } else if (msg.action === 'volume' && typeof msg.value === 'number') { + setRoomState(ws.room.id, { volume: Math.max(0, Math.min(1, msg.value)) }); + } + broadcastToRoom(slug, msg, null); // include sender so its UI mirrors + return; + } + case 'state': { + // Only the display's state messages are persisted as truth. + if (ws.kind !== 'display') return; + const patch = {}; + if ('stationId' in msg) patch.station_id = msg.stationId ?? null; + if ('playing' in msg) patch.playing = !!msg.playing; + if (typeof msg.volume === 'number') patch.volume = msg.volume; + const next = setRoomState(ws.room.id, patch); + const station = next.station_id ? getStation(next.station_id) : null; + broadcastToRoom(slug, { type: 'state', ...next, station }); + return; + } + case 'devices': { + if (ws.kind !== 'display') return; + broadcastToRoom(slug, { type: 'devices', list: msg.list || [], current: msg.current || null }); + return; + } + case 'ping': + send(ws, { type: 'pong', t: Date.now() }); + return; + default: + return; } } diff --git a/vite.config.js b/vite.config.js index 9f7d0c9..bfdab89 100644 --- a/vite.config.js +++ b/vite.config.js @@ -8,6 +8,10 @@ export default defineConfig({ port: 5173, proxy: { '/api': 'http://localhost:4173', + // Cover-art and other static media are served by the backend's + // express.static('/media') mount; the dev server has to proxy + // them or kiosk thumbnails 404 in `npm run dev`. + '/media': 'http://localhost:4173', '/ws': { target: 'ws://localhost:4173', ws: true } } }, @@ -18,7 +22,8 @@ export default defineConfig({ input: { kiosk: resolve(__dirname, 'web/index.html'), admin: resolve(__dirname, 'web/admin/index.html'), - docs: resolve(__dirname, 'web/docs/index.html') + docs: resolve(__dirname, 'web/docs/index.html'), + master: resolve(__dirname, 'web/master/index.html') } } } diff --git a/web/admin/main.js b/web/admin/main.js index c38bf9f..ad63d1e 100644 --- a/web/admin/main.js +++ b/web/admin/main.js @@ -1,9 +1,47 @@ +// Online Radio Explorer — Admin +// +// Views: +// - Stations: paginated list, search, bulk select, edit dialog with tabs. +// - Discover: search radio-browser, preview, bulk import. +// - Leaderboard: top stations by plays/votes + moderation actions. +// - Rooms: see who's connected to which named room, delete shared rooms. +// - Users: existing CRUD. +// - System: counters + cache stats. +// +// The station edit dialog has four tabs: Details / Streams / Image / Stats. +// Image tab supports drag-drop upload, refetch-from-URL, and clear-cache. +// A tiny per-station preview player lets the admin audition a stream +// without leaving the table. + import { api } from '../shared/api.js'; import { el, clear } from '../shared/dom.js'; +import { Player } from '../player.js'; const app = document.getElementById('app'); -const state = { user: null, view: 'stations', stations: [], users: [], system: null, search: '' }; +const state = { + user: null, + view: 'stations', + stations: [], + users: [], + rooms: [], + leaderboard: [], + system: null, + search: '', + sourceFilter: '', + selected: new Set(), + // Discover view scratch: + discoverResults: [], + discoverQuery: { q: '', country: '', tag: '' } +}; +// One shared preview player instance for the admin (so only one stream plays +// at a time across the whole UI). +const preview = new Player({ + onState: (s) => { Object.assign(previewState, s); paintPreviewButtons(); } +}); +const previewState = { stationId: null, playing: false, loading: false }; + +// ---------- bootstrap ---------- async function bootstrap() { try { state.user = await api.get('/api/auth/me'); } catch { return showLogin(); } @@ -19,10 +57,14 @@ async function refresh() { const tasks = [api.get('/api/stations?all=1')]; if (state.view === 'users') tasks.push(api.get('/api/auth/users')); if (state.view === 'system') tasks.push(api.get('/api/admin/system')); - const [stations, more1, more2] = await Promise.all(tasks); - state.stations = stations; - if (state.view === 'users') state.users = more1 || []; - if (state.view === 'system') state.system = more1 || more2 || null; + if (state.view === 'rooms') tasks.push(api.get('/api/admin/rooms')); + if (state.view === 'leaderboard') tasks.push(api.get('/api/admin/leaderboard')); + const results = await Promise.all(tasks); + state.stations = results[0]; + if (state.view === 'users') state.users = results[1] || []; + if (state.view === 'system') state.system = results[1] || null; + if (state.view === 'rooms') state.rooms = results[1] || []; + if (state.view === 'leaderboard') state.leaderboard = results[1] || []; } function showLogin() { @@ -48,194 +90,845 @@ function showLogin() { function render() { clear(app); + const views = ['stations', 'discover', 'leaderboard', 'rooms', 'users', 'system']; const side = el('aside', { class: 'side' }, - el('h1', {}, 'Online Radio Explorer'), - ...['stations', 'import', 'users', 'system'].map((v) => + el('h1', {}, 'OnlineRadio · Admin'), + ...views.map((v) => el('button', { class: `nav ${state.view === v ? 'active' : ''}`, - onClick: async () => { state.view = v; await refresh(); render(); } + onClick: async () => { state.view = v; state.selected.clear(); await refresh(); render(); } }, label(v))), - el('div', { class: 'me' }, `Signed in as ${state.user.username}`, + el('div', { class: 'me' }, + `Signed in as ${state.user.username}`, + el('br'), + el('a', { href: '/master', target: '_blank' }, 'Open master ↗'), + el('br'), + el('a', { href: '/', target: '_blank' }, 'Open kiosk ↗'), el('br'), el('a', { href: '#', onClick: async (e) => { e.preventDefault(); await api.post('/api/auth/logout'); location.reload(); } }, 'Sign out')) ); const main = el('main', { class: 'main' }); + // Append BEFORE delegating to the per-view renderers — they rely on + // document.getElementById() to find slots they just inserted into `main`, + // which only works once `main` is actually in the DOM. + app.appendChild(el('div', { class: 'shell' }, side, main)); if (state.view === 'stations') renderStations(main); - else if (state.view === 'import') renderImport(main); + else if (state.view === 'discover') renderDiscover(main); + else if (state.view === 'leaderboard') renderLeaderboard(main); + else if (state.view === 'rooms') renderRooms(main); else if (state.view === 'users') renderUsers(main); else if (state.view === 'system') renderSystem(main); - app.appendChild(el('div', { class: 'shell' }, side, main)); } -function label(v) { - return ({ stations: 'Stations', import: 'Import', users: 'Users', system: 'System' })[v]; -} +const label = (v) => ({ + stations: 'Stations', discover: 'Discover', leaderboard: 'Leaderboard', + rooms: 'Rooms', users: 'Users', system: 'System' +})[v]; -// ---------- Stations ---------- +// ============================================================ +// Stations view +// ============================================================ function renderStations(root) { root.appendChild(el('div', { class: 'bar' }, el('input', { - placeholder: 'Search…', value: state.search, + placeholder: 'Search name / country / genre…', value: state.search, onInput: (e) => { state.search = e.target.value; renderStationsTable(); } }), + el('select', { + onChange: (e) => { state.sourceFilter = e.target.value; renderStationsTable(); } + }, + el('option', { value: '' }, 'All sources'), + ...uniqueSources(state.stations).map((s) => el('option', { value: s, selected: state.sourceFilter === s }, s)) + ), el('button', { class: 'btn primary', onClick: () => openStationDialog() }, '+ Add station'), - el('button', { class: 'btn', onClick: async () => { await api.post('/api/admin/health-check'); alert('Health check finished'); await refresh(); render(); } }, 'Run health check') + el('button', { + class: 'btn', onClick: async () => { + if (!confirm('Run health check on every stream?')) return; + const r = await api.post('/api/admin/health-check'); + alert(`Checked ${r.checked} streams.`); + await refresh(); render(); + } + }, 'Health check'), )); - const tableWrap = el('div', { id: 'tableWrap' }); - root.appendChild(tableWrap); + root.appendChild(el('div', { id: 'bulkSlot' })); + root.appendChild(el('div', { id: 'tableWrap' })); renderStationsTable(); } +function uniqueSources(stations) { + return [...new Set(stations.map((s) => s.source).filter(Boolean))].sort(); +} + function renderStationsTable() { const wrap = document.getElementById('tableWrap'); - if (!wrap) return; - clear(wrap); + const bulkSlot = document.getElementById('bulkSlot'); + if (!wrap || !bulkSlot) return; + clear(wrap); clear(bulkSlot); + const q = state.search.toLowerCase(); + const src = state.sourceFilter; const filtered = state.stations.filter((s) => - !q || s.name.toLowerCase().includes(q) || (s.country || '').toLowerCase().includes(q) || - (s.genres || []).some((g) => g.toLowerCase().includes(q)) + (!src || s.source === src) && + (!q || s.name.toLowerCase().includes(q) || (s.country || '').toLowerCase().includes(q) || + (s.genres || []).some((g) => g.toLowerCase().includes(q))) ); + + if (state.selected.size) bulkSlot.appendChild(renderBulkBar(filtered)); + + const allOnPageSelected = filtered.length && filtered.every((s) => state.selected.has(s.id)); const table = el('table', {}, el('thead', {}, el('tr', {}, - el('th', {}, 'Name'), el('th', {}, 'Source'), el('th', {}, 'Genres'), - el('th', {}, 'Country'), el('th', {}, 'Enabled'), el('th', {}, 'Actions'))), - el('tbody', {}, ...filtered.map((s) => el('tr', {}, - el('td', {}, el('strong', {}, s.name), el('br'), el('small', {}, s.homepage || '')), - el('td', {}, s.source), - el('td', {}, ...(s.genres || []).slice(0, 4).map((g) => el('span', { class: 'tag' }, g))), - el('td', {}, s.country || ''), - el('td', {}, s.enabled ? '✅' : '⛔'), - el('td', {}, - el('button', { class: 'btn', onClick: () => openStationDialog(s.id) }, 'Edit'), - ' ', - el('button', { - class: 'btn danger', onClick: async () => { - if (confirm(`Delete ${s.name}?`)) { await api.del(`/api/stations/${s.id}`); await refresh(); render(); } + el('th', { style: { width: '32px' } }, el('input', { + type: 'checkbox', checked: allOnPageSelected, + onChange: (e) => { + if (e.target.checked) filtered.forEach((s) => state.selected.add(s.id)); + else filtered.forEach((s) => state.selected.delete(s.id)); + renderStationsTable(); + } + })), + el('th', {}, 'Name'), + el('th', {}, 'Source'), + el('th', {}, 'Genres'), + el('th', {}, 'Country'), + el('th', {}, 'Streams'), + el('th', {}, '▲/▼/▶'), + el('th', {}, 'On'), + el('th', {}, 'Actions'))), + el('tbody', {}, ...filtered.map((s) => { + const art = s.image_display_url || s.image_url; + return el('tr', { 'data-id': s.id }, + el('td', {}, el('input', { + type: 'checkbox', checked: state.selected.has(s.id), + onChange: (e) => { + if (e.target.checked) state.selected.add(s.id); + else state.selected.delete(s.id); + renderStationsTable(); } - }, 'Delete') - ) - ))) + })), + el('td', {}, el('div', { class: 'station-cell' }, + el('div', { class: 'station-art-thumb' + (art ? '' : ' empty') }, + art ? el('img', { + src: art, + alt: '', + loading: 'lazy', + referrerpolicy: 'no-referrer', + onError: (e) => { + const parent = e.target.parentNode; + e.target.remove(); + if (parent) parent.classList.add('empty'); + } + }) : null + ), + el('div', { class: 'meta' }, + el('strong', {}, s.name), + el('small', {}, s.homepage || s.uuid)) + )), + el('td', {}, s.source || ''), + el('td', {}, ...(s.genres || []).slice(0, 3).map((g) => el('span', { class: 'tag' }, g))), + el('td', {}, s.country || ''), + el('td', {}, String(s.stream_count ?? '—')), + el('td', {}, `${s.up || 0}/${s.down || 0}/${s.plays || 0}`), + el('td', {}, s.enabled ? '✓' : '✗'), + el('td', {}, + renderPreviewButton(s), + ' ', + el('button', { class: 'btn', onClick: () => openStationDialog(s.id) }, 'Edit'), + ' ', + el('button', { + class: 'btn danger', onClick: async () => { + if (!await confirmStationDelete({ stations: [s] })) return; + await api.del(`/api/admin/stations/${s.id}`); + await refresh(); render(); + } + }, '×') + ) + ); + })) ); wrap.appendChild(table); } -async function openStationDialog(id) { - const station = id ? await api.get(`/api/stations/${id}`) : { name: '', genres: [], streams: [], enabled: true }; - const dlg = el('dialog'); - const streamsBox = el('div', { class: 'streams' }); - - function paintStreams() { - clear(streamsBox); - streamsBox.appendChild(el('div', { style: { fontWeight: 600, marginBottom: '6px' } }, 'Streams')); - if (!station.streams?.length) streamsBox.appendChild(el('div', { style: { color: '#6b7280' } }, 'No streams yet.')); - for (const s of station.streams || []) { - streamsBox.appendChild(el('div', { class: 'stream-row' }, - el('select', { onChange: (e) => s.format = e.target.value }, - ...['mp3', 'aac', 'hls', 'm3u', 'pls', 'ogg', 'unknown'].map((f) => - el('option', { value: f, selected: s.format === f }, f))), - el('input', { value: s.url, placeholder: 'https://…', onInput: (e) => s.url = e.target.value }), - el('input', { type: 'number', placeholder: 'kbps', value: s.bitrate || '', onInput: (e) => s.bitrate = Number(e.target.value) || null }), - el('input', { value: s.label || '', placeholder: 'Label', onInput: (e) => s.label = e.target.value }), - s.last_status ? el('span', { class: `pill ${s.last_status === 'up' ? 'up' : 'down'}` }, s.last_status) : el('span'), - el('button', { class: 'btn danger', type: 'button', onClick: () => { station.streams = station.streams.filter((x) => x !== s); paintStreams(); } }, '×') - )); - } - streamsBox.appendChild(el('button', { - class: 'btn', type: 'button', onClick: () => { - station.streams = [...(station.streams || []), { url: '', format: 'mp3', priority: (station.streams?.length || 0) }]; - paintStreams(); - } - }, '+ Add stream')); +function renderBulkBar(filtered) { + const ids = [...state.selected]; + async function run(action, confirmMsg) { + if (confirmMsg && !confirm(`${confirmMsg} (${ids.length} stations)`)) return; + const r = await api.post('/api/admin/stations/bulk', { ids, action }); + alert(`${action}: ${r.ok} ok / ${r.failed} failed`); + state.selected.clear(); + await refresh(); render(); } - - const form = el('form', { - method: 'dialog', onSubmit: async (e) => { - e.preventDefault(); - const payload = { - name: station.name, homepage: station.homepage, country: station.country, - genres: station.genres, description: station.description, image_url: station.image_url, - enabled: station.enabled - }; - if (id) { - await api.patch(`/api/stations/${id}`, payload); - // sync streams: simple approach — delete all & re-add - const fresh = await api.get(`/api/stations/${id}`); - for (const s of fresh.streams || []) await api.del(`/api/stations/${id}/streams/${s.id}`); - for (const s of station.streams || []) if (s.url) await api.post(`/api/stations/${id}/streams`, s); - } else { - payload.streams = (station.streams || []).filter((s) => s.url); - await api.post('/api/stations', payload); - } - dlg.close(); - await refresh(); - render(); - } - }, - el('h2', {}, id ? 'Edit station' : 'Add station'), - el('div', { class: 'row' }, el('label', {}, 'Name'), el('input', { value: station.name, onInput: (e) => station.name = e.target.value, required: true })), - el('div', { class: 'row' }, el('label', {}, 'Homepage'), el('input', { value: station.homepage || '', onInput: (e) => station.homepage = e.target.value })), - el('div', { class: 'row' }, el('label', {}, 'Country'), el('input', { value: station.country || '', maxlength: 4, onInput: (e) => station.country = e.target.value })), - el('div', { class: 'row' }, el('label', {}, 'Genres'), el('input', { value: (station.genres || []).join(', '), onInput: (e) => station.genres = e.target.value.split(',').map((s) => s.trim()).filter(Boolean) })), - el('div', { class: 'row' }, el('label', {}, 'Image URL'), el('input', { value: station.image_url || '', onInput: (e) => station.image_url = e.target.value })), - el('div', { class: 'row col' }, el('textarea', { rows: 2, placeholder: 'Description', onInput: (e) => station.description = e.target.value }, station.description || '')), - el('div', { class: 'row' }, el('label', {}, 'Enabled'), el('input', { type: 'checkbox', checked: station.enabled, onChange: (e) => station.enabled = e.target.checked })), - streamsBox, - el('div', { class: 'actions' }, - el('button', { class: 'btn', type: 'button', onClick: () => dlg.close() }, 'Cancel'), - el('button', { class: 'btn primary', type: 'submit' }, 'Save')) + async function runDelete() { + const targets = state.stations.filter((s) => state.selected.has(s.id)); + if (!targets.length) return; + if (!await confirmStationDelete({ stations: targets })) return; + const r = await api.post('/api/admin/stations/bulk', { ids: targets.map((s) => s.id), action: 'delete' }); + alert(`delete: ${r.ok} ok / ${r.failed} failed`); + state.selected.clear(); + await refresh(); render(); + } + return el('div', { class: 'bulkbar' }, + el('span', { class: 'count' }, `${ids.length} selected`), + el('button', { class: 'btn', onClick: () => run('enable') }, 'Enable'), + el('button', { class: 'btn', onClick: () => run('disable') }, 'Disable'), + el('button', { class: 'btn', onClick: () => run('scrape-icon', 'Scrape icons for') }, 'Scrape icons'), + el('button', { class: 'btn', onClick: () => run('refetch-image', 'Refetch images for') }, 'Refetch images'), + el('button', { class: 'btn danger', onClick: () => runDelete() }, 'Delete'), + el('button', { class: 'btn', onClick: () => { state.selected.clear(); renderStationsTable(); } }, 'Clear'), ); - paintStreams(); - dlg.appendChild(form); +} + +function renderPreviewButton(station) { + const playing = previewState.stationId === station.id && previewState.playing; + return el('span', { + class: 'preview-player' + (playing ? ' playing' : ''), + 'data-preview-station': station.id + }, + el('button', { + title: 'Preview', + onClick: (e) => { + e.stopPropagation(); + if (previewState.stationId === station.id && previewState.playing) { + preview.stop(); + previewState.stationId = null; + previewState.playing = false; + } else { + previewState.stationId = station.id; + preview.play(station); + } + paintPreviewButtons(); + } + }, playing ? '❚❚' : '▶') + ); +} + +function paintPreviewButtons() { + document.querySelectorAll('.preview-player').forEach((nodeEl) => { + const id = Number(nodeEl.getAttribute('data-preview-station')); + const isPlaying = previewState.stationId === id && previewState.playing; + nodeEl.classList.toggle('playing', isPlaying); + const btn = nodeEl.querySelector('button'); + if (btn) btn.textContent = isPlaying ? '❚❚' : (previewState.stationId === id && previewState.loading ? '…' : '▶'); + }); +} + +// ============================================================ +// Station edit dialog (tabs) +// ============================================================ +async function openStationDialog(id) { + const station = id + ? await api.get(`/api/stations/${id}`) + : { name: '', genres: [], streams: [], enabled: true, image_url: '', country: '', homepage: '' }; + + const dlg = el('dialog', { class: 'wide' }); + let activeTab = 'details'; + + const body = el('div', { class: 'tab-body' }); + const tabs = el('div', { class: 'tabs' }, + ...[ + ['details', 'Details'], + ['streams', 'Streams'], + ['image', 'Image'], + ['stats', 'Stats'] + ].map(([key, lbl]) => el('button', { + type: 'button', + class: activeTab === key ? 'active' : '', + onClick: () => { activeTab = key; paintTabs(); } + }, lbl)) + ); + + function paintTabs() { + clear(body); + tabs.querySelectorAll('button').forEach((b, i) => { + const key = ['details', 'streams', 'image', 'stats'][i]; + b.classList.toggle('active', key === activeTab); + }); + if (activeTab === 'details') paintDetails(body, station); + else if (activeTab === 'streams') paintStreams(body, station); + else if (activeTab === 'image') paintImage(body, station, async () => { + // After upload/refetch/delete: re-fetch station so previews refresh. + if (id) Object.assign(station, await api.get(`/api/stations/${id}`)); + paintTabs(); + }); + else if (activeTab === 'stats') paintStats(body, station, id); + } + paintTabs(); + + const footer = el('div', { class: 'actions' }, + id ? el('button', { + class: 'btn danger', type: 'button', onClick: async () => { + if (!await confirmStationDelete({ stations: [station] })) return; + await api.del(`/api/admin/stations/${id}`); + dlg.close(); + await refresh(); render(); + } + }, 'Delete') : null, + el('button', { class: 'btn', type: 'button', onClick: () => dlg.close() }, 'Cancel'), + el('button', { + class: 'btn primary', type: 'button', onClick: async () => { + const payload = { + name: station.name, homepage: station.homepage, country: station.country, + genres: station.genres, description: station.description, image_url: station.image_url, + category: station.category, enabled: station.enabled + }; + if (id) { + await api.patch(`/api/admin/stations/${id}`, payload); + } else { + payload.streams = (station.streams || []).filter((s) => s.url); + const created = await api.post('/api/stations', payload); + Object.assign(station, created); + } + dlg.close(); + await refresh(); render(); + } + }, 'Save') + ); + + dlg.appendChild(el('form', { method: 'dialog', onSubmit: (e) => e.preventDefault() }, + el('h2', {}, id ? `Edit · ${station.name}` : 'Add station'), + tabs, body, footer + )); document.body.appendChild(dlg); dlg.showModal(); dlg.addEventListener('close', () => dlg.remove()); } -// ---------- Import (Radio-Browser) ---------- -function renderImport(root) { - let results = []; - const resultsBox = el('div'); - root.appendChild(el('h2', {}, 'Import from Radio-Browser')); - root.appendChild(el('div', { class: 'bar' }, - el('input', { id: 'rbq', placeholder: 'Search by name…' }), - el('input', { id: 'rbcountry', placeholder: 'Country (e.g. NL)', style: { minWidth: '120px' } }), - el('input', { id: 'rbtag', placeholder: 'Tag/genre' }), - el('button', { - class: 'btn primary', onClick: async () => { - const params = new URLSearchParams({ - q: document.getElementById('rbq').value, - country: document.getElementById('rbcountry').value, - tag: document.getElementById('rbtag').value - }); - results = await api.get(`/api/stations/sources/radiobrowser/search?${params}`); - paint(); - } - }, 'Search') - )); - root.appendChild(resultsBox); - function paint() { - clear(resultsBox); - if (!results.length) { resultsBox.appendChild(el('p', {}, 'No results yet.')); return; } - const table = el('table', {}, - el('thead', {}, el('tr', {}, el('th', {}, 'Name'), el('th', {}, 'Country'), el('th', {}, 'Tags'), el('th', {}, 'Stream'), el('th', {}, ''))), - el('tbody', {}, ...results.map((s) => el('tr', {}, - el('td', {}, s.name), - el('td', {}, s.country || ''), - el('td', {}, ...(s.genres || []).slice(0, 4).map((g) => el('span', { class: 'tag' }, g))), - el('td', {}, el('small', {}, (s.streams[0]?.format || '') + ' ' + (s.streams[0]?.bitrate || ''))), - el('td', {}, el('button', { - class: 'btn primary', onClick: async () => { - await api.post('/api/stations/sources/radiobrowser/import', s); - alert(`Imported ${s.name}`); - } - }, 'Import')) - ))) +function paintDetails(root, station) { + root.appendChild(el('div', { class: 'row' }, el('label', {}, 'Name'), + el('input', { value: station.name || '', onInput: (e) => station.name = e.target.value, required: true }))); + root.appendChild(el('div', { class: 'row' }, el('label', {}, 'Homepage'), + el('input', { value: station.homepage || '', onInput: (e) => station.homepage = e.target.value }))); + root.appendChild(el('div', { class: 'row' }, el('label', {}, 'Country'), + el('input', { value: station.country || '', maxlength: 4, onInput: (e) => station.country = e.target.value }))); + root.appendChild(el('div', { class: 'row' }, el('label', {}, 'Genres (CSV)'), + el('input', { + value: (station.genres || []).join(', '), + onInput: (e) => station.genres = e.target.value.split(',').map((s) => s.trim()).filter(Boolean) + }))); + root.appendChild(el('div', { class: 'row' }, el('label', {}, 'Category'), + el('input', { value: station.category || '', onInput: (e) => station.category = e.target.value }))); + root.appendChild(el('div', { class: 'row' }, el('label', {}, 'Description'), + el('textarea', { + rows: 4, placeholder: 'Short description shown to listeners', + onInput: (e) => station.description = e.target.value + }, station.description || ''))); + root.appendChild(el('div', { class: 'row' }, el('label', {}, 'Enabled'), + el('input', { type: 'checkbox', checked: station.enabled, onChange: (e) => station.enabled = e.target.checked }))); + + if (station.id) { + const meta = (k, v) => el('div', { class: 'meta-row' }, + el('span', { class: 'meta-k' }, k), + el('span', { class: 'meta-v mono' }, v == null || v === '' ? '—' : String(v)) ); - resultsBox.appendChild(table); + root.appendChild(el('div', { class: 'readonly-meta' }, + el('div', { class: 'readonly-meta-head' }, 'Read-only metadata (used by the public API)'), + meta('id', station.id), + meta('uuid', station.uuid), + meta('slug', station.slug), + meta('source', station.source), + meta('source_ref', station.source_ref), + meta('image_source', station.image_source), + meta('image_path', station.image_path), + meta('created_at', station.created_at), + meta('updated_at', station.updated_at), + )); } } -// ---------- Users ---------- +function paintStreams(root, station) { + if (!station.id) { + // Pre-create flow — work in-memory. + const box = el('div', { class: 'streams' }); + const repaint = () => { + clear(box); + box.appendChild(el('div', { style: { fontWeight: 700, marginBottom: '6px' } }, 'Streams')); + for (const s of station.streams || []) box.appendChild(renderStreamRow(s, () => { + station.streams = station.streams.filter((x) => x !== s); repaint(); + })); + box.appendChild(el('button', { + class: 'btn', type: 'button', onClick: () => { + station.streams = [...(station.streams || []), { url: '', format: 'mp3', priority: (station.streams?.length || 0) }]; + repaint(); + } + }, '+ Add stream')); + }; + repaint(); + root.appendChild(box); + return; + } + // Live mode: every change hits the server immediately. + const box = el('div', { class: 'streams' }); + const refreshStreams = async () => { + station.streams = await api.get(`/api/admin/stations/${station.id}/streams`); + repaint(); + }; + const repaint = () => { + clear(box); + box.appendChild(el('div', { style: { fontWeight: 700, marginBottom: '6px' } }, 'Streams')); + for (const s of station.streams || []) box.appendChild(renderStreamRow(s, async () => { + if (!confirm('Delete stream?')) return; + await api.del(`/api/admin/streams/${s.id}`); + await refreshStreams(); + }, async () => { + await api.patch(`/api/admin/streams/${s.id}`, { + url: s.url, format: s.format, bitrate: s.bitrate || null, + label: s.label || null, priority: s.priority || 0 + }); + }, async () => { + const r = await api.post(`/api/admin/streams/${s.id}/probe`); + s.last_status = r.status; + repaint(); + })); + box.appendChild(el('button', { + class: 'btn', type: 'button', onClick: async () => { + const newStream = await api.post(`/api/admin/stations/${station.id}/streams`, { + url: '', format: 'mp3', priority: (station.streams?.length || 0) + }); + station.streams = [...(station.streams || []), newStream]; + repaint(); + } + }, '+ Add stream')); + }; + repaint(); + root.appendChild(box); +} + +function renderStreamRow(s, onDelete, onSave, onProbe) { + const update = (k, v) => { s[k] = v; }; + return el('div', { class: 'stream-row' }, + el('select', { onChange: (e) => update('format', e.target.value) }, + ...['mp3', 'aac', 'hls', 'm3u', 'pls', 'ogg', 'unknown'].map((f) => + el('option', { value: f, selected: s.format === f }, f))), + el('input', { value: s.url || '', placeholder: 'https://…', onInput: (e) => update('url', e.target.value) }), + el('input', { type: 'number', placeholder: 'kbps', value: s.bitrate || '', onInput: (e) => update('bitrate', Number(e.target.value) || null) }), + el('input', { value: s.label || '', placeholder: 'Label', onInput: (e) => update('label', e.target.value) }), + s.last_status ? el('span', { class: `pill ${s.last_status === 'up' ? 'up' : s.last_status === 'down' ? 'down' : 'unknown'}` }, s.last_status) : el('span'), + el('span', { style: { display: 'flex', gap: '4px' } }, + onProbe ? el('button', { class: 'btn', type: 'button', onClick: onProbe }, 'Test') : null, + onSave ? el('button', { class: 'btn', type: 'button', onClick: onSave }, 'Save') : null, + el('button', { class: 'btn danger', type: 'button', onClick: onDelete }, '×') + ) + ); +} + +function paintImage(root, station, onChanged) { + if (!station.id) { + root.appendChild(el('p', {}, 'Save the station first, then come back to upload an image.')); + return; + } + const art = station.image_display_url || station.image_url; + const area = el('div', { class: 'image-area' }); + const preview = el('div', { + class: 'preview', + style: art ? { backgroundImage: `url("${art}")` } : {} + }, art ? '' : 'No image'); + const dropzone = el('div', { class: 'dropzone' }, 'Drop image file here, or click to upload'); + const fileInput = el('input', { type: 'file', accept: 'image/*', style: { display: 'none' } }); + + async function upload(file) { + if (!file) return; + if (file.size > 5 * 1024 * 1024) return alert('File is too large (5 MB max).'); + const buf = await file.arrayBuffer(); + const res = await fetch(`/api/admin/stations/${station.id}/image`, { + method: 'PUT', + headers: { 'Content-Type': file.type || 'application/octet-stream' }, + credentials: 'same-origin', + body: buf + }); + if (!res.ok) { alert('Upload failed: ' + res.status); return; } + await onChanged(); + } + + dropzone.addEventListener('click', () => fileInput.click()); + dropzone.addEventListener('dragover', (e) => { e.preventDefault(); dropzone.classList.add('over'); }); + dropzone.addEventListener('dragleave', () => dropzone.classList.remove('over')); + dropzone.addEventListener('drop', (e) => { + e.preventDefault(); + dropzone.classList.remove('over'); + upload(e.dataTransfer.files?.[0]); + }); + fileInput.addEventListener('change', () => upload(fileInput.files?.[0])); + + const actions = el('div', { class: 'actions-col' }, + el('div', { class: 'row' }, el('label', {}, 'Image URL'), + el('input', { value: station.image_url || '', onInput: (e) => station.image_url = e.target.value })), + dropzone, fileInput, + el('div', { style: { display: 'flex', gap: '6px', flexWrap: 'wrap' } }, + el('button', { + class: 'btn', type: 'button', onClick: async () => { + // Save image_url first, then refetch. + await api.patch(`/api/admin/stations/${station.id}`, { image_url: station.image_url }); + const r = await fetch(`/api/admin/stations/${station.id}/image/refetch`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + credentials: 'same-origin', + body: JSON.stringify({ url: station.image_url }) + }); + if (!r.ok) { alert('Refetch failed: ' + r.status); return; } + await onChanged(); + } + }, 'Refetch from URL'), + el('button', { + class: 'btn', type: 'button', onClick: async () => { + const r = await api.post(`/api/admin/stations/${station.id}/scrape-icon`).catch((e) => ({ error: e.message })); + if (r.error) alert('Scrape failed: ' + r.error); + await onChanged(); + } + }, 'Auto-scrape'), + el('button', { + class: 'btn danger', type: 'button', onClick: async () => { + if (!confirm('Drop the cached image?')) return; + await api.del(`/api/admin/stations/${station.id}/image`); + await onChanged(); + } + }, 'Clear cache') + ), + el('div', { style: { fontSize: '11px', color: 'var(--muted)' } }, + `Source: ${station.image_source || '—'} · Path: ${station.image_path || '—'}`) + ); + area.appendChild(preview); + area.appendChild(actions); + root.appendChild(area); +} + +function paintStats(root, station, id) { + if (!id) { root.appendChild(el('p', {}, 'Stats are available after the station is created.')); return; } + root.appendChild(el('div', { class: 'system-grid' }, + stat('Votes up', station.up || 0), + stat('Votes down', station.down || 0), + stat('Score', (station.score || 0).toFixed(2)), + stat('Plays', station.plays || 0), + stat('Streams', (station.streams || []).length) + )); + root.appendChild(el('div', { style: { marginTop: '12px', display: 'flex', gap: '8px', flexWrap: 'wrap' } }, + el('button', { + class: 'btn danger', onClick: async () => { + if (!confirm('Delete all votes for this station?')) return; + await api.del(`/api/admin/stations/${id}/votes`); + Object.assign(station, await api.get(`/api/stations/${id}`)); + paintStats(clearInline(root), station, id); + } + }, 'Reset votes'), + el('button', { + class: 'btn danger', onClick: async () => { + if (!confirm('Delete all plays for this station?')) return; + await api.del(`/api/admin/stations/${id}/plays`); + Object.assign(station, await api.get(`/api/stations/${id}`)); + paintStats(clearInline(root), station, id); + } + }, 'Reset plays'), + )); +} + +function clearInline(node) { clear(node); return node; } +function stat(k, v) { return el('div', { class: 'stat' }, el('div', { class: 'v' }, String(v)), el('div', { class: 'k' }, k)); } + +// Strong confirmation for destructive station removal. Forces the admin to +// type the station name (or the literal "DELETE" for bulk ops) and lays out +// exactly what API-visible state will disappear so we don't accidentally +// break clients that hard-code numeric ids or uuids. +function confirmStationDelete({ stations }) { + // `stations` is an array of {id, name, uuid?} so we can list them. + const list = Array.isArray(stations) ? stations : [stations]; + const single = list.length === 1 ? list[0] : null; + const expected = single ? single.name : 'DELETE'; + + return new Promise((resolve) => { + const dlg = el('dialog', { class: 'danger-confirm' }); + let typed = ''; + const input = el('input', { + placeholder: `Type "${expected}" to confirm`, + autocomplete: 'off', + onInput: (e) => { + typed = e.target.value; + confirmBtn.disabled = typed.trim() !== expected; + } + }); + const confirmBtn = el('button', { + class: 'btn danger', type: 'button', disabled: true, + onClick: () => { dlg.close(); resolve(true); } + }, single ? 'Permanently delete' : `Permanently delete ${list.length} stations`); + + dlg.appendChild(el('form', { method: 'dialog', onSubmit: (e) => e.preventDefault() }, + el('div', { class: 'danger-header' }, + el('div', { class: 'danger-icon' }, '⚠'), + el('h2', {}, + single ? `Delete "${single.name}"?` : `Delete ${list.length} stations?`) + ), + el('div', { class: 'danger-body' }, + el('p', { class: 'lede' }, + 'This is irreversible and ', + el('b', {}, 'will break the public API'), + ' for any client (kiosk, master, third-party integration, bookmarks, scripts) ', + 'that references these stations by id, uuid or slug.' + ), + el('ul', { class: 'impact' }, + el('li', {}, el('code', {}, 'GET /api/v1/stations/{id}'), ' will return 404'), + el('li', {}, el('code', {}, 'GET /api/v1/stations/{uuid}'), ' will return 404'), + el('li', {}, 'All streams, votes, plays and favorites attached to ', + single ? 'this station' : 'these stations', ' are dropped (cascade)'), + el('li', {}, 'Active listeners playing ', + single ? 'this station' : 'one of these', ' will receive a stop event'), + el('li', {}, 'Cached image files are unlinked from disk') + ), + list.length > 1 || single ? el('div', { class: 'impact-list' }, + el('div', { class: 'impact-list-head' }, 'Targets:'), + el('ul', {}, ...list.slice(0, 12).map((s) => + el('li', {}, el('b', {}, s.name), + s.uuid ? el('span', { class: 'mono' }, ` · ${s.uuid}`) : null, + el('span', { class: 'mono' }, ` · id=${s.id}`))), + list.length > 12 ? el('li', { class: 'more' }, `…and ${list.length - 12} more`) : null + ) + ) : null, + el('label', { class: 'type-to-confirm' }, + `Type `, el('code', {}, expected), ` to confirm:`, + input + ) + ), + el('div', { class: 'actions' }, + el('button', { + class: 'btn', type: 'button', + onClick: () => { dlg.close(); resolve(false); } + }, 'Cancel'), + confirmBtn + ) + )); + document.body.appendChild(dlg); + dlg.addEventListener('close', () => dlg.remove()); + dlg.showModal(); + setTimeout(() => input.focus(), 50); + }); +} + +// ============================================================ +// Discover view (Radio-Browser) +// ============================================================ +// Loads an initial list of popular Radio-Browser stations on tab open so the +// view doesn't feel empty. Same visual layout as the Stations table (with +// thumbnails, source column, etc.) — the only difference is the action column +// (Import) and the badge that flags entries already in our library. +function renderDiscover(root) { + root.appendChild(el('h2', {}, 'Discover · Radio-Browser')); + const q = state.discoverQuery; + + async function runSearch() { + const params = new URLSearchParams(); + if (q.q) params.set('q', q.q); + if (q.country) params.set('country', q.country); + if (q.tag) params.set('tag', q.tag); + params.set('limit', '50'); + const wrap = document.getElementById('discoverWrap'); + if (wrap) { clear(wrap); wrap.appendChild(el('p', { class: 'muted' }, 'Loading…')); } + try { + state.discoverResults = await api.get(`/api/stations/sources/radiobrowser/search?${params}`); + } catch (err) { + state.discoverResults = []; + if (wrap) { clear(wrap); wrap.appendChild(el('p', { class: 'err' }, err.message || 'Search failed')); } + return; + } + renderDiscoverTable(); + } + + root.appendChild(el('div', { class: 'bar' }, + el('input', { + placeholder: 'Name…', value: q.q, + onInput: (e) => q.q = e.target.value, + onKeyDown: (e) => { if (e.key === 'Enter') runSearch(); } + }), + el('input', { + placeholder: 'Country (e.g. NL)', value: q.country, + onInput: (e) => q.country = e.target.value, + onKeyDown: (e) => { if (e.key === 'Enter') runSearch(); }, + style: { minWidth: '120px' } + }), + el('input', { + placeholder: 'Tag/genre', value: q.tag, + onInput: (e) => q.tag = e.target.value, + onKeyDown: (e) => { if (e.key === 'Enter') runSearch(); } + }), + el('button', { class: 'btn primary', onClick: runSearch }, 'Search'), + el('button', { + class: 'btn', onClick: () => { + q.q = ''; q.country = ''; q.tag = ''; + renderDiscover(clearInline(root)); + } + }, 'Reset'), + el('button', { + class: 'btn', onClick: async () => { + const picks = state.discoverResults.filter((r) => r.__import); + if (!picks.length) return alert('Nothing selected.'); + if (!confirm(`Import ${picks.length} stations?`)) return; + for (const p of picks) { + await api.post('/api/stations/sources/radiobrowser/import', p).catch(() => { }); + } + alert('Done.'); + await refresh(); + await runSearch(); + } + }, 'Import selected'), + )); + root.appendChild(el('div', { id: 'discoverWrap' })); + + // Initial load: top-voted stations from Radio-Browser. + if (!state.discoverResults.length) runSearch(); + else renderDiscoverTable(); +} + +function renderDiscoverTable() { + const wrap = document.getElementById('discoverWrap'); + if (!wrap) return; + clear(wrap); + const rows = state.discoverResults; + if (!rows.length) { + wrap.appendChild(el('p', { class: 'muted' }, + 'No results. Try a different query — leave fields blank for the top stations on Radio-Browser.')); + return; + } + + // Dedupe against the library so the admin sees which entries already exist. + const existingUuids = new Set(state.stations.map((s) => s.uuid).filter(Boolean)); + + const allSelected = rows.length && rows.every((r) => r.__import); + wrap.appendChild(el('table', {}, + el('thead', {}, el('tr', {}, + el('th', { style: { width: '32px' } }, el('input', { + type: 'checkbox', checked: !!allSelected, + onChange: (e) => { + rows.forEach((r) => { r.__import = e.target.checked && !existingUuids.has(r.uuid); }); + renderDiscoverTable(); + } + })), + el('th', {}, 'Name'), + el('th', {}, 'Country'), + el('th', {}, 'Tags'), + el('th', {}, 'Stream'), + el('th', {}, 'Status'), + el('th', {}, ''))), + el('tbody', {}, ...rows.map((s) => { + const exists = existingUuids.has(s.uuid); + const art = s.image_url; + return el('tr', { class: exists ? 'discover-existing' : '' }, + el('td', {}, el('input', { + type: 'checkbox', checked: !!s.__import, disabled: exists, + onChange: (e) => { s.__import = e.target.checked; } + })), + el('td', {}, el('div', { class: 'station-cell' }, + el('div', { class: 'station-art-thumb' + (art ? '' : ' empty') }, + art ? el('img', { + src: art, alt: '', loading: 'lazy', referrerpolicy: 'no-referrer', + onError: (e) => { + const parent = e.target.parentNode; + e.target.remove(); + if (parent) parent.classList.add('empty'); + } + }) : null + ), + el('div', { class: 'meta' }, + el('strong', {}, s.name), + el('small', {}, s.homepage || s.uuid)) + )), + el('td', {}, s.country || ''), + el('td', {}, ...(s.genres || []).slice(0, 4).map((g) => el('span', { class: 'tag' }, g))), + el('td', {}, el('small', {}, + (s.streams[0]?.format || '') + ' ' + (s.streams[0]?.bitrate ? `· ${s.streams[0].bitrate}kbps` : ''))), + el('td', {}, exists + ? el('span', { class: 'pill up' }, 'in library') + : el('span', { class: 'pill unknown' }, 'new')), + el('td', {}, exists + ? el('button', { class: 'btn', disabled: true }, 'Imported') + : el('button', { + class: 'btn primary', onClick: async (e) => { + e.target.disabled = true; + try { + await api.post('/api/stations/sources/radiobrowser/import', s); + await refresh(); + renderDiscoverTable(); + } catch (err) { alert('Import failed: ' + err.message); } + } + }, 'Import')) + ); + })) + )); +} + +// ============================================================ +// Leaderboard view (moderation) +// ============================================================ +function renderLeaderboard(root) { + root.appendChild(el('h2', {}, 'Leaderboard')); + root.appendChild(el('p', { style: { color: 'var(--muted)', marginTop: 0 } }, + 'Top stations by total listen time. Use the reset buttons to moderate runaway counters.')); + const list = el('div', { class: 'leaderboard' }); + state.leaderboard.forEach((s, i) => { + const art = s.image_display_url || (s.image_path ? `/media/${s.image_path}` : s.image_url); + list.appendChild(el('div', { class: 'leader-row' }, + el('div', { class: 'rank' }, String(i + 1)), + el('div', { class: 'art' + (art ? '' : ' empty') }, + art ? el('img', { + src: art, alt: '', loading: 'lazy', referrerpolicy: 'no-referrer', + onError: (e) => { + const parent = e.target.parentNode; + e.target.remove(); + if (parent) parent.classList.add('empty'); + } + }) : null + ), + el('div', { class: 'name' }, el('b', {}, s.name), el('br'), el('small', {}, s.country || '')), + el('div', { class: 'stat-num', title: 'Total listen time' }, `⏱ ${formatDuration(s.total_play_ms)}`), + el('div', { class: 'stat-num', title: 'Average session length' }, `Ø ${formatDuration(s.avg_session_ms)}`), + el('div', { class: 'stat-num', title: 'Play taps' }, `▶ ${s.plays}`), + el('div', { class: 'stat-num', title: 'Sessions credited' }, `· ${s.sessions}`), + el('div', { class: 'stat-num' }, `▲ ${s.up}`), + el('div', { class: 'stat-num' }, `▼ ${s.down}`), + )); + }); + root.appendChild(list); +} + +// Compact human-readable duration: "42s", "7m12s", "3h08m", "2d04h". +function formatDuration(ms) { + const s = Math.max(0, Math.round((ms || 0) / 1000)); + if (s < 60) return `${s}s`; + const m = Math.floor(s / 60); + if (m < 60) return `${m}m${String(s % 60).padStart(2, '0')}s`; + const h = Math.floor(m / 60); + if (h < 24) return `${h}h${String(m % 60).padStart(2, '0')}m`; + const d = Math.floor(h / 24); + return `${d}d${String(h % 24).padStart(2, '0')}h`; +} + +// ============================================================ +// Rooms view +// ============================================================ +function renderRooms(root) { + root.appendChild(el('h2', {}, 'Rooms')); + root.appendChild(el('table', {}, + el('thead', {}, el('tr', {}, + el('th', {}, 'Slug'), el('th', {}, 'Name'), + el('th', {}, 'Members'), el('th', {}, 'Active station'), + el('th', {}, 'Created'), el('th', {}, ''))), + el('tbody', {}, ...state.rooms.map((r) => el('tr', {}, + el('td', {}, el('code', {}, r.slug)), + el('td', {}, r.name), + el('td', {}, String(r.members)), + el('td', {}, r.active ? '●' : '—'), + el('td', {}, el('small', {}, r.created_at)), + el('td', {}, + r.slug.startsWith('u-') ? el('small', { style: { color: 'var(--muted)' } }, 'personal') + : el('button', { + class: 'btn danger', onClick: async () => { + if (!confirm(`Delete room ${r.slug}?`)) return; + await api.del(`/api/admin/rooms/${r.slug}`); + await refresh(); render(); + } + }, 'Delete') + ) + ))) + )); +} + +// ============================================================ +// Users view (unchanged behaviour) +// ============================================================ function renderUsers(root) { root.appendChild(el('div', { class: 'bar' }, el('h2', { style: { margin: 0, flex: 1 } }, 'Users'), @@ -300,19 +993,39 @@ function openUserDialog() { dlg.addEventListener('close', () => dlg.remove()); } -// ---------- System ---------- +// ============================================================ +// System view +// ============================================================ function renderSystem(root) { - const s = state.system || {}; root.appendChild(el('h2', {}, 'System')); + const s = state.system || {}; root.appendChild(el('div', { class: 'system-grid' }, - stat('Stations', s.stations), stat('Streams', s.streams), stat('Users', s.users), - stat('Favorites', s.favorites), stat('Node', s.node), stat('Uptime (s)', s.uptime_s) + stat('Stations', s.stations || 0), + stat('Streams', s.streams || 0), + stat('Users', s.users || 0), + stat('Favorites', s.favorites || 0), + stat('Cached images', s.image_cache?.files || 0), + stat('Cache size (MB)', s.image_cache ? (s.image_cache.bytes / 1048576).toFixed(1) : '0'), + stat('Node', s.node || ''), + stat('Uptime (s)', s.uptime_s || 0) )); - root.appendChild(el('div', { class: 'bar', style: { marginTop: '16px' } }, - el('button', { class: 'btn', onClick: async () => { await api.post('/api/admin/health-check'); alert('Health check finished'); await refresh(); render(); } }, 'Run health check'), - el('button', { class: 'btn', onClick: async () => { const r = await api.post('/api/admin/reseed'); alert(JSON.stringify(r)); } }, 'Reseed (if empty)') + root.appendChild(el('div', { style: { marginTop: '16px', display: 'flex', gap: '8px' } }, + el('button', { + class: 'btn', onClick: async () => { + if (!confirm('Re-seed from data/seed/?')) return; + const r = await api.post('/api/admin/reseed'); + alert(JSON.stringify(r)); + await refresh(); render(); + } + }, 'Re-seed'), + el('button', { + class: 'btn', onClick: async () => { + const r = await api.post('/api/admin/scrape-icons?all=1'); + alert(`Updated ${r.updated}, failed ${r.failed}`); + await refresh(); render(); + } + }, 'Scrape all icons'), )); } -function stat(k, v) { return el('div', { class: 'stat' }, el('div', { class: 'k' }, k), el('div', { class: 'v' }, v ?? '—')); } bootstrap(); diff --git a/web/admin/style.css b/web/admin/style.css index 9d17e51..25ea62a 100644 --- a/web/admin/style.css +++ b/web/admin/style.css @@ -208,3 +208,236 @@ dialog .actions { padding-top: 12px; border-top: 1px solid #cccccc; } } .stat .v { font-weight: 900; letter-spacing: -0.01em; } .stat .k { font-weight: 700; letter-spacing: 0.08em; } + +/* ============================================================ + POWER-ADMIN ADDITIONS + ============================================================ */ +.tabs { display: flex; gap: 0; border-bottom: 1px solid var(--border); margin: 4px 0 12px; } +.tabs button { + background: var(--panel); border: 1px solid var(--border); border-bottom: 0; + padding: 8px 14px; font-size: 12px; font-weight: 700; + text-transform: uppercase; letter-spacing: 0.06em; margin-right: -1px; +} +.tabs button.active { background: var(--accent); color: #000; border-color: var(--accent); } + +.tab-body { padding: 6px 0; } + +.row.image-row { grid-template-columns: 1fr; } +.image-area { display: grid; grid-template-columns: 140px 1fr; gap: 16px; align-items: start; } +.image-area .preview { + width: 140px; height: 140px; border: 1px solid var(--border); + background-size: cover; background-position: center; background-color: #f5f5f5; + position: relative; display: grid; place-items: center; color: var(--muted); font-size: 11px; +} +.image-area .actions-col { display: grid; gap: 6px; align-content: start; } +.image-area .dropzone { + border: 2px dashed #999; padding: 10px 12px; font-size: 12px; color: var(--muted); + text-align: center; cursor: pointer; user-select: none; +} +.image-area .dropzone.over { border-color: var(--accent); color: var(--fg); background: #fff4ec; } + +.bulkbar { + position: sticky; top: 0; z-index: 2; + background: #000; color: #fff; padding: 8px 12px; margin-bottom: 8px; + display: flex; gap: 8px; align-items: center; flex-wrap: wrap; +} +.bulkbar .btn { background: #111 !important; color: #fff !important; border-color: #444 !important; } +.bulkbar .btn:hover { background: var(--accent) !important; color: #000 !important; border-color: var(--accent) !important; } +.bulkbar .count { font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; font-size: 12px; } + +.station-art-thumb { + width: 48px; height: 48px; background-color: #f3f3f3; + border: 1px solid var(--border); flex-shrink: 0; + overflow: hidden; position: relative; display: block; +} +.station-art-thumb img { + width: 100%; height: 100%; object-fit: cover; display: block; +} +.station-art-thumb.empty::after { + content: "\266A"; position: absolute; inset: 0; + display: grid; place-items: center; color: var(--muted); font-size: 22px; +} +.station-cell { display: flex; align-items: center; gap: 10px; } +.station-cell .meta { min-width: 0; } +.station-cell .meta small { color: var(--muted); display: block; max-width: 360px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + +.preview-player { + display: inline-flex; align-items: center; gap: 6px; font-size: 11px; + border: 1px solid var(--border); padding: 2px 6px; +} +.preview-player button { + background: transparent; border: 0; font-size: 14px; padding: 0 2px; cursor: pointer; +} +.preview-player.playing button { color: var(--accent); } + +/* Leaderboard view */ +.leaderboard { display: grid; gap: 8px; } +.leader-row { + display: grid; + grid-template-columns: 32px 60px 1fr repeat(6, auto); + align-items: center; gap: 10px; padding: 8px 12px; + border: 1px solid var(--border); background: var(--panel); +} +.leader-row .rank { font-weight: 900; font-size: 18px; } +.leader-row .art { + width: 48px; height: 48px; border-radius: 6px; overflow: hidden; + background: #f3f3f3; display: flex; align-items: center; justify-content: center; + flex: none; +} +.leader-row .art img { width: 100%; height: 100%; object-fit: cover; display: block; } +.leader-row .art.empty::after { content: '♪'; color: var(--muted); font-size: 22px; } +.leader-row .name b { font-size: 14px; } +.leader-row .stat-num { font-weight: 800; font-size: 13px; white-space: nowrap; } + +/* Wider dialog for the edit-station experience. */ +dialog.wide { max-width: 880px; } + +/* ---------- Strong delete confirmation (station removal warns about API impact) ---------- */ +dialog.danger-confirm { + border: 2px solid var(--bad); + max-width: 560px; + width: 92%; +} +dialog.danger-confirm form { + gap: 14px; + padding: 22px; +} +dialog.danger-confirm .danger-header { + display: flex; + align-items: center; + gap: 12px; +} +dialog.danger-confirm .danger-icon { + width: 44px; + height: 44px; + display: grid; + place-items: center; + background: var(--bad); + color: #fff; + font-size: 26px; + font-weight: 900; + flex-shrink: 0; +} +dialog.danger-confirm h2 { + margin: 0; + color: var(--bad); + text-transform: uppercase; + letter-spacing: 0.04em; + font-size: 20px; +} +dialog.danger-confirm .danger-body { + display: flex; + flex-direction: column; + gap: 12px; + font-size: 14px; +} +dialog.danger-confirm .lede { + margin: 0; + padding: 12px; + background: #fde7e6; + border-left: 4px solid var(--bad); + color: #2a0000; +} +dialog.danger-confirm .impact { + margin: 0; + padding-left: 22px; + font-size: 13px; + color: var(--fg); + line-height: 1.5; +} +dialog.danger-confirm .impact code, +dialog.danger-confirm .type-to-confirm code, +dialog.danger-confirm .mono { + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + background: #f0f1f5; + padding: 1px 6px; + font-size: 12px; +} +dialog.danger-confirm .impact-list { + background: #fafafc; + border: 1px solid var(--border); + padding: 8px 12px; + font-size: 12px; + max-height: 180px; + overflow: auto; +} +dialog.danger-confirm .impact-list-head { + font-weight: 700; + margin-bottom: 4px; + text-transform: uppercase; + letter-spacing: 0.06em; + font-size: 11px; + color: var(--muted); +} +dialog.danger-confirm .impact-list ul { + margin: 0; + padding-left: 18px; + list-style: square; +} +dialog.danger-confirm .impact-list li.more { + color: var(--muted); + font-style: italic; + list-style: none; + margin-left: -16px; +} +dialog.danger-confirm .type-to-confirm { + display: flex; + flex-direction: column; + gap: 6px; + font-size: 13px; +} +dialog.danger-confirm .type-to-confirm input { + border: 2px solid var(--bad); + font-size: 15px; + padding: 10px 12px; +} +dialog.danger-confirm .actions .btn.danger:disabled { + opacity: 0.35; + cursor: not-allowed; + background: var(--panel); + color: var(--bad); +} +dialog.danger-confirm .actions .btn.danger:not(:disabled) { + background: var(--bad); + color: #fff; + border-color: var(--bad); + font-weight: 700; +} + +/* ---------- Read-only metadata block in station detail editor ---------- */ +.readonly-meta { + margin-top: 8px; + padding: 10px 12px; + background: #fafafc; + border: 1px solid var(--border); + display: grid; + gap: 4px; + font-size: 12px; +} +.readonly-meta-head { + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--muted); + font-weight: 700; + margin-bottom: 4px; + font-size: 11px; +} +.readonly-meta .meta-row { + display: grid; + grid-template-columns: 140px 1fr; + gap: 8px; + align-items: center; +} +.readonly-meta .meta-k { + color: var(--muted); +} +.readonly-meta .meta-v.mono { + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: 11px; + word-break: break-all; +} + +/* ---------- Discover table: dim entries already in the library ---------- */ +tr.discover-existing { opacity: 0.55; } +tr.discover-existing td { background: #fafafc; } +.main .muted { color: var(--muted); } diff --git a/web/main.js b/web/main.js index 8420635..843cebb 100644 --- a/web/main.js +++ b/web/main.js @@ -15,7 +15,16 @@ const state = { query: '', sort: 'hot', // hot | top | plays | name | controversial — applied in Browse randomMode: localStorage.getItem('oradio.randomMode') === 'favorites' ? 'favorites' : 'all', - player: { stationId: null, stationName: null, genres: [], playing: false, loading: false, volume: 0.7, votes: null } + // Room sync. mode='play-here' uses local