UNPKG

@asicupv/paella-core

Version:
1,578 lines 214 kB
const h = Object.freeze({ PLAY: "paella:play", PAUSE: "paella:pause", STOP: "paella:stop", ENDED: "paella:ended", SEEK: "paella:seek", FULLSCREEN_CHANGED: "paella:fullscreenchanged", ENTER_FULLSCREEN: "paella:enterfullscreen", EXIT_FULLSCREEN: "paella:exitfullscreen", VOLUME_CHANGED: "paella:volumeChanged", TIMEUPDATE: "paella:timeupdate", TRIMMING_CHANGED: "paella:trimmingChanged", CAPTIONS_CHANGED: "paella:captionsChanged", CAPTIONS_ENABLED: "paella:captionsEnabled", CAPTIONS_DISABLED: "paella:captionsDisabled", BUTTON_PRESS: "paella:buttonPress", SHOW_POPUP: "paella:showPopUp", HIDE_POPUP: "paella:hidePopUp", MANIFEST_LOADED: "paella:manifestLoaded", STREAM_LOADED: "paella:streamLoaded", PLAYER_LOADED: "paella:playerLoaded", PLAYER_UNLOADED: "paella:playerUnloaded", RESIZE: "paella:resize", RESIZE_END: "paella:resizeEnd", LAYOUT_CHANGED: "paella:layoutChanged", PLAYBACK_RATE_CHANGED: "paella:playbackRateChanged", VIDEO_QUALITY_CHANGED: "paella:videoQualityChanged", HIDE_UI: "paella:hideUI", SHOW_UI: "paella:showUI", COOKIE_CONSENT_CHANGED: "paella:cookieConsentChanged", LOG: "paella:log" }); function T(i, e, t, n = !0) { return i.__eventListeners__ = i.__eventListeners__ || {}, Array.isArray(e) || (e = [e]), e.forEach((s) => { i.__eventListeners__[s] = i.__eventListeners__[s] || [], i.__eventListeners__[s].push({ callback: t, unregisterOnUnload: n }); }), t; } function b(i, e, t = {}) { i.__eventListeners__ && i.__eventListeners__[e] && i.__eventListeners__[e].forEach((n) => n.callback(t)); } function H(i, e, t = {}) { i.ready && b(i, e, t); } function ri(i) { if (i.__eventListeners__) for (const e in i.__eventListeners__) i.__eventListeners__[e] = i.__eventListeners__[e].filter((t) => t.unregisterOnUnload == !1), i.log.debug("Unregister event: " + i.__eventListeners__[e]); } function gt(i) { return new Promise((e, t) => { fetch(i).then((n) => n.text()).then((n) => { e(n); }).catch((n) => t(n)); }); } function Re(i) { return typeof i != "string" ? !1 : /<svg[^>]*>/i.test(i); } function mt(i) { const e = new URLSearchParams(window.location.search); return e.has(i) ? e.get(i) : null; } function ft(i) { const e = window.location.hash.replace("#", "?"), t = new URLSearchParams(e); return t.has(i) ? t.get(i) : null; } function M(i, e) { const t = e || "/"; return i = i.map((n, s) => (s && (n = n.replace(new RegExp("^" + t), "")), s !== i.length - 1 && (n = n.replace(new RegExp(t + "$"), "")), n)), i.join(t); } function yt(i) { return new RegExp("^([a-z]+://|//)", "i").test(i) || /^\//.test(i); } function ce(i) { try { return new URL(i).pathname.split("/").pop(); } catch { return i.split("/").pop(); } } function vt(i) { return i.split(".").reduce((e, t, n, s) => n < s.length - 1 ? e !== "" ? `${e}.${t}` : t : e, ""); } function $e(i) { const e = (t) => { const n = t.split("/").reduce((s, a, r, o) => r < o.length - 1 ? s !== "" ? `${s}/${a}` : a : s, ""); return (t[0] === "/" ? `/${n}` : n) + "/"; }; try { const t = new URL(i); return t.origin + e(t.pathname); } catch { return e(i); } } function Ve(i) { return ce(i).split(".").pop(); } function U(i, e) { return yt(e) ? e : M([i.manifestUrl, e]); } function _t(i) { i.__hideTimerPaused__ = !0; } function Ue(i) { i.__hideTimerPaused__ = !1; } function wt(i, e = "hideUiTime") { i.__hideTimer__ = null; const t = async () => i.__hideTimerPaused__ ? (i.log.debug("UI not hidden because the auto hide timer is paused"), !1) : n() ? (i.log.debug("UI not hidden because there is a focused element"), !1) : (await i.hideUserInterface(), !0); i.config.ui?.hideOnMouseLeave && i.containerElement.addEventListener("mouseleave", () => { t(); }); const n = () => { const a = document.activeElement, r = document.querySelector(":focus-visible"); return (i.playbackBar.element.contains(a) || i.videoContainer.element.contains(a)) && [ "input", "textarea", "button" ].find((o) => a.tagName.toLowerCase(o)) !== -1 && r; }, s = async () => { i.__hideTimer__ && clearTimeout(i.__hideTimer__), await i.showUserInterface(), i.__hideTimer__ = setTimeout(async () => { i.__hideTimer__ = null, t() || s(); }, i[e]); }; i.containerElement.addEventListener("mousemove", async (a) => { s(); }), T(i, h.PLAY, async () => { s(); }), T(i, h.PAUSE, async () => { await i.showUserInterface(); }), T(i, h.ENDED, async () => { await i.showUserInterface(); }), document.addEventListener("keydown", async () => { s(); }); } function Ct(i) { i.__hideTimer__ && (clearTimeout(i.__hideTimer__), delete i.__hideTimer__); } function B(i) { const e = Math.floor(i / 60 / 60), t = Math.floor(i / 60) - e * 60, n = Math.floor(i % 60); return (e > 0 ? e.toString().padStart(2, "0") + ":" : "") + t.toString().padStart(2, "0") + ":" + n.toString().padStart(2, "0"); } function le(i) { const t = /^(?:(\d+):){0,1}(\d+):(\d+)(\.\d+)?$/.exec(i); if (t) { const n = t[1] !== void 0 ? Number(t[1]) : 0, s = Number(t[2]), a = Number(t[3]); return n * 3600 + s * 60 + a; } return null; } function Le(i) { const t = /^(?:(\d+):){0,1}(\d+):(\d+)\.(\d+)?$/.exec(i); if (t) { const n = t[1] !== void 0 ? Number(t[1]) : 0, s = Number(t[2]), a = Number(t[3]), r = t[4] && Number(t[4]) || 0; return n * 36e5 + s * 6e4 + a * 1e3 + r; } return null; } function O(i, e, t = 365) { let n = /* @__PURE__ */ new Date(); n.setTime(n.getTime() + t * 24 * 60 * 60 * 1e3); let s = `expires=${n.toUTCString()}`; document.cookie = `${i}=${e};${s};path=/;SameSite=None;` + (/Apple/.test(navigator.vendor) ? "" : "Secure;"); } function bt(i, e, t, n, s = 365) { i.cookieConsent.getConsentForType(e) && O(t, n, s); } function V(i) { let e = i + "=", n = decodeURIComponent(document.cookie).split(";"); for (let s = 0; s < n.length; ++s) { let a = n[s]; for (; a.charAt(0) == " "; ) a = a.substring(1); if (a.indexOf(e) == 0) return a.substring(e.length, a.length); } return ""; } function oi(i) { const e = V(i), t = Number(e); return e !== "" && !isNaN(t) ? t : null; } function li(i) { try { return JSON.parse(V(i)); } catch { return null; } } function Ne(i, e = !0) { return new Promise((t) => { const n = document.createElement("link"); n.setAttribute("rel", "stylesheet"), n.setAttribute("href", i), n.onload = () => t(n); const s = document.getElementsByTagName("head")[0]; e && s.appendChild(n), t(); }); } function Lt(i) { if (!i) return; document.getElementsByTagName("head")[0].removeChild(i); } function te(i, e, t = !0) { for (const n in e) { const s = i[n]; let a = e[n]; t && Array.isArray(s) && Array.isArray(a) ? (s.forEach((r) => { a = a.filter((o) => typeof r == "object" && typeof o == "object" && r.id === o.id ? (te(r, o, t), !1) : !0); }), a.forEach((r) => { s.push(r); })) : typeof s == "object" && a ? te(s, a, t) : i[n] = e[n]; } } function Pe(i, { excludedTags: e = null } = {}) { const t = document.createElement("div"); t.innerHTML = i; const n = ["script"]; return e && n.push(...e), n.flatMap((s) => Array.from(t.getElementsByTagName(s))).forEach((s) => { s.parentElement.removeChild(s); }), t.innerHTML; } let oe = null; function Fe(i) { if (!i) return !1; oe || (oe = document.createElement("video")); let e = oe.canPlayType(i); if (e === "maybe" || e === "probably") return !0; if (/video\/mp4/i.test(i)) return e = oe.canPlayType("video/mp4"), e === "maybe" || e === "probably"; } const Po = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, clearAutoHideTimer: Ct, getCookie: V, getFileExtension: Ve, getHashParameter: ft, getJSONCookie: li, getNumericCookie: oi, getUrlFileName: ce, getUrlParameter: mt, isAbsoluteUrl: yt, isSvgString: Re, joinPath: M, loadStyle: Ne, loadSvgIcon: gt, mergeObjects: te, pauseAutoHideUiTimer: _t, removeExtension: vt, removeFileName: $e, resolveResourcePath: U, resumeAutoHideUiTimer: Ue, sanitizeHTML: Pe, secondsToTime: B, setCookie: O, setCookieIfAllowed: bt, setupAutoHideUiTimer: wt, supportsVideoType: Fe, timeToMilliseconds: Le, timeToSeconds: le, unloadStyle: Lt }, Symbol.toStringTag, { value: "Module" })); async function ci(i, e) { return e.log.debug("Using default configuration loading function."), (await fetch(i)).json(); } async function ui(i, e) { return e.log.debug("Using default getVideoId function"), ft("id") || mt("id") || i.fallbackId; } async function di(i, e, t, n) { return n.log.debug("Using default getManifestUrl function"), M([i, e]); } async function hi(i, e, t, n) { return n.log.debug("Using default getManifestFileUrl function"), M([i, e]); } async function pi(i, e, t) { t.log.debug("Using default loadVideoManifest function"); const n = await fetch(i); if (n.ok) try { return await n.json(); } catch { throw new Error(t.translate("Error parsing video manifest. Unexpected file format.")); } else throw new Error(t.translate("Error loading video manifest: $1 $2", [n.status, n.statusText])); } class q { #t = null; constructor(e) { this.#t = e; } get player() { return this.#t; } } function Pt({ tag: i = "div", attributes: e = {}, children: t = "", innerText: n = "", parent: s = null }) { const a = document.createElement(i); a.innerText = n; for (let r in e) a.setAttribute(r, e[r]); return a.innerHTML = t, s && s.appendChild(a), a; } function _(i, e = null) { const t = document.createElement("div"); t.innerHTML = i; const n = t.children[0]; return e && e.appendChild(n), n; } class R extends q { #t = null; constructor(e, { tag: t = "div", attributes: n = [], children: s = "", parent: a = null }) { super(e), this.#t = Pt({ tag: t, attributes: n, children: s, parent: a }), Object.defineProperty(this, t, { get: () => this.#t }); } get element() { return this.#t; } get parent() { return this.#t.parentElement; } hide() { this.element.style.display = "none"; } show(e = "block") { this.element.style.display = null; } get isVisible() { const e = window.getComputedStyle(this.element); return e.display !== "none" && e.display !== ""; } setAttribute(e, t) { this.#t.setAttribute(e, t); } removeFromParent() { this.#t.parentElement?.removeChild(this.#t); } setParent(e) { this.removeFromParent(), e.appendChild(this.#t); } } const gi = `<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"> <g transform="matrix(1,0,0,1,3,-3.88857)"> <path d="M128,35.819C65.633,35.819 14.999,86.453 14.999,148.82C14.999,163.127 17.663,176.817 22.549,189.403L22.475,189.447C11.612,170.791 5.889,149.588 5.889,128C5.889,60.56 60.56,5.889 128,5.889L128,35.819Z" style="fill:url(#_Linear1);"/> </g> <g transform="matrix(-1,1.22465e-16,-1.22465e-16,-1,258,251.914)"> <path d="M128,35.819C65.633,35.819 14.999,86.453 14.999,148.82C14.999,163.127 17.663,176.817 22.549,189.403L22.475,189.447C11.612,170.791 5.889,149.588 5.889,128C5.889,60.56 60.56,5.889 128,5.889L128,35.819Z" style="fill:url(#_Linear2);"/> </g> <defs> <linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-89.3028,140.734,-140.734,-89.3028,144.417,48.7125)"><stop offset="0" style="stop-color:rgb(13,13,13);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(175,175,175);stop-opacity:0.5"/></linearGradient> <linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-89.3028,140.734,-140.734,-89.3028,144.417,48.7125)"><stop offset="0" style="stop-color:rgb(13,13,13);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(175,175,175);stop-opacity:0.5"/></linearGradient> </defs> </svg> `; class mi extends R { constructor(e) { super(e, { parent: e.containerElement }), this.element.className = "loader-container"; } async create() { _(`<i>${gi}</i>`, this.element); } get debug() { return !1; } } const fi = `<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"> <g id="Cancel" transform="matrix(5.54545,6.8353e-32,6.8353e-32,5.54545,-2567.37,-10735.5)"> <path d="M486.05,1937C498.192,1937 508.05,1946.86 508.05,1959C508.05,1971.14 498.192,1981 486.05,1981C473.908,1981 464.05,1971.14 464.05,1959C464.05,1946.86 473.908,1937 486.05,1937ZM478.979,1950.52L477.565,1951.93L484.636,1959L477.565,1966.07L478.979,1967.49L486.05,1960.41L493.121,1967.49L494.535,1966.07L487.464,1959L494.535,1951.93L493.121,1950.52L486.05,1957.59L478.979,1950.52Z" style="fill:rgb(210,0,0);"/> </g> </svg> `; class ye extends R { constructor(e, t = "") { super(e, { parent: e.containerElement }), this.element.className = "error-container", _(` <div> <i>${fi}</i> <p>${t}</p> </div>`, this.element); } } class j extends q { constructor(e, t) { super(e), this._name = t; } getPluginModuleInstance() { return null; } get config() { return this._config; } get type() { return "none"; } get order() { return this._config?.order || 0; } get description() { return this._config?.description || ""; } get name() { return this._name; } async isEnabled() { return this.config?.enabled; } async load() { } async unload() { } } class pe extends j { get type() { return "video"; } get streamType() { return "mp4"; } async isCompatible() { return !1; } async getVideoInstance() { return null; } getCompatibleFileExtensions() { return []; } getManifestData(e) { } } const ue = []; async function yi(i) { await A(i, "video", (e) => { ue.push(e); }); } async function vi(i) { ue.slice(0); } function Et(i) { if (ue.length === 0) throw Error("No video plugins loaded. Note that `loadVideoPlugins()` must to be called before using `getVideoPlugins()`."); return ue; } function _i(i, e) { const t = Ve(e); return Et().find((s) => s.getCompatibleFileExtensions().indexOf(t) !== -1); } async function wi(i, e) { const t = Et(); let n = null; for (const s of t) if (await s.isCompatible(e)) { n = s; break; } return n; } async function Ci() { return await new Promise((e) => { const t = document.createElement("audio"), n = setTimeout(() => e(!1), 100); t.addEventListener("volumechange", (s) => { clearTimeout(n), e(!0); }), t.volume = 0.5; }); } class Be extends R { constructor(e, t, n) { const s = { class: "video-player" }; super(t, { tag: e, attributes: s, parent: n }), this._streamProvider = null, this._streamData = null, this._ready = !1; } async isVolumeApiAvailable() { return await Ci(); } get streamData() { return this._streamData; } get ready() { return this._ready; } async load(e, t) { return this._streamProvider = t, this._streamData = e, await this.loadStreamData(e); } get isMainAudioPlayer() { return this._streamProvider.mainAudioPlayer === this; } // The player must call _videoEndedCallback when the video is ended onVideoEnded(e) { this._videoEndedCallback = e; } // The video instance must implement the following functions and properties async play() { return !1; } async pause() { return !1; } async duration() { return -1; } get currentTimeSync() { return -1; } async currentTime() { return -1; } async setCurrentTime() { return !1; } async volume() { return -1; } async setVolume() { return !1; } initVolume(e) { this._initialVolume = e; } async paused() { return !0; } async playbackRate() { return -1; } async setPlaybackRate() { return !1; } async getQualities() { return null; } async setQuality() { return !1; } get currentQuality() { return null; } async getDimensions() { return null; } async supportsMultiaudio() { return !1; } async getAudioTracks() { return null; } async setCurrentAudioTrack() { } get currentAudioTrack() { return null; } async loadStreamData(e) { return !1; } get isEnabled() { return this._enabled; } async enable() { this._enabled = !0; } async disable() { this._enabled = !1; } } class ge extends q { get moduleName() { return this.player.log.warn(`Incomplete player module definition: '${__filename}.moduleName'`), "-"; } get moduleVersion() { return this.player.log.warn(`Incomplete player module definition: '${__filename}.moduleVersion'`), "0.0.0"; } async getDictionaries() { return null; } } const bi = "@asicupv/paella-core", Li = { ".": "./dist/paella-core.js", "./src/": "./src/", "./paella-core.css": "./dist/paella-core.css" }, Pi = "2.3.2", Ei = "Multi stream HTML video player", Si = "./dist/paella-core.js", Ti = ["dist/paella-core.css", "dist/paella-core.js", "dist/paella-core.js.map", "dist/paella-core.d.ts"], Ii = "./dist/paella-core.js", ki = "module", Di = { dev: "vite build --watch", build: "vite build --emptyOutDir" }, Ai = { type: "git", url: "git+https://github.com/polimediaupv/paella-player.git" }, xi = ["html", "player", "video", "hls"], Mi = "Fernando Serrano Carpena <ferserc1@gmail.com>", Ri = "ECL-2.0", $i = { url: "https://github.com/polimediaupv/paella-player/issues" }, Vi = "https://github.com/polimediaupv/paella-player#readme", Ui = { typescript: "^5.8.3", vite: "^7.0.0", "vite-plugin-static-copy": "^3.0.0" }, Ni = { "@ferserc1/input-style-unifier": "^0.0.2" }, ne = { name: bi, exports: Li, version: Pi, description: Ei, main: Si, files: Ti, module: Ii, type: ki, scripts: Di, repository: Ai, keywords: xi, author: Mi, license: Ri, bugs: $i, homepage: Vi, devDependencies: Ui, dependencies: Ni }; let ve = null; class W extends ge { static Get() { return ve || (ve = new W()), ve; } get moduleName() { return "paella-core default video formats"; } get moduleVersion() { return ne.version; } } function Fi(i) { return new Promise((e, t) => { const n = new Image(); n.addEventListener("load", (s) => { e(n); }), n.addEventListener("error", (s) => { t(new Error("Could not load preview image. The preview image is required in audio only streams")); }), n.src = i; }); } function Bi(i, e, t) { return new Promise((n, s) => { e.oncanplay = () => n(), e.onerror = () => s(new Error(i.translate("Error loading audio: $1", [t]))), e.src = U(i, t), n(); }); } class Oi extends Be { constructor(e, t, n) { super("audio", e, t), this.isMainAudio = n, this._ready = !1; } get streamType() { return "audio"; } waitForLoaded() { return new Promise((e) => { const t = () => { this._ready ? e() : setTimeout(t, 100); }; t(); }); } async play() { await this.waitForLoaded(), this.audio.play(); } async pause() { await this.waitForLoaded(), this.audio.pause(); } async duration() { return await this.waitForLoaded(), this.audio.duration; } get currentTimeSync() { return this.audio?.currentTime || 0; } async currentTime() { return await this.waitForLoaded(), this.audio.currentTime; } async setCurrentTime(e) { await this.waitForLoaded(), this.audio.currentTime = e; } async volume() { return await this.waitForLoaded(), this.audio.volume; } async setVolume(e) { await this.waitForLoaded(), this.audio.volume = e; } async paused() { return await this.waitForLoaded(), this.audio.paused; } async playbackRate() { return await this.waitForLoaded(), this.audio.playbackRate; } async setPlaybackRate(e) { await this.waitForLoaded(), this.audio.playbackRate = e; } // getQualities(), setQuality(q), get currentQuality(): audio format does not support multiquality async getDimensions() { return { w: this._previewImage.width, h: this._previewImage.height }; } async loadStreamData(e = null) { this._streamData = this._streamData || e, this.player.log.debug("es.upv.paella.audioVideoFormat: loadStreamData"); const t = this.player.videoManifest.metadata.preview; if (!t || t == null) throw new Error("Invalid video manifest data: preview image is required"); if (this._previewImage = await Fi(t), this._imageContainer = document.createElement("div"), this._imageContainer.className = "image-container", this.parent.appendChild(this._imageContainer), this._imageContainer.appendChild(this._previewImage), this._source = e.sources.audio && e.sources.audio[0], !this._source) throw new Error("Invalid source in audio only video stream"); if (!this.isMainAudioPlayer) throw new Error("Audio only video stream must be main audio player. Check the role property at video manifest"); await Bi(this.player, this.audio, this._source.src); const n = () => { const s = this.player.videoContainer.baseVideoRect.offsetWidth / this.player.videoContainer.baseVideoRect.offsetHeight, a = this._previewImage.width / this._previewImage.height; s > a ? (this._previewImage.classList.add("landscape"), this._previewImage.classList.remove("portrait")) : (this._previewImage.classList.add("portrait"), this._previewImage.classList.remove("landscape")); }; this.player.frameList.frames.length > 0 && this.audio.addEventListener("timeupdate", (s) => { const a = this.player.frameList.getImage(s.target.currentTime, !0); this._previewImage.src != a.url && (this._previewImage.src = a.url, this._previewImage.onload = () => n()); }), window.addEventListener("resize", (s) => n()), n(), this._ready = !0; } } class zi extends pe { getPluginModuleInstance() { return W.Get(); } get name() { return super.name || "es.upv.paella.audioVideoFormat"; } get streamType() { return "audio"; } async isCompatible(e) { return e.sources.audio != null; } async getVideoInstance(e, t) { return new Oi(this.player, e, t); } getCompatibleFileExtensions() { return ["m4a", "mp3"]; } getManifestData(e) { return { audio: e.map((t) => ({ src: t })) }; } } class St extends Be { constructor(e, t, n, s) { super("video", e, t), this._config = s || {}; const a = this._config.crossOrigin ?? ""; this.element.setAttribute("playsinline", ""), a !== !1 && this.element.setAttribute("crossorigin", a), this.isMainAudio = n, this.element.setAttribute("autoplay", ""), this.element.autoplay = !0, n || (this.element.muted = !0), this._videoEnabled = !0; } async play() { if (this._videoEnabled) try { return await this.waitForLoaded(), this.video.play(); } catch { } else this._disabledProperties.paused = !1; } async pause() { if (this._videoEnabled) return await this.waitForLoaded(), this.video.pause(); this._disabledProperties.paused = !0; } async duration() { return this._videoEnabled ? (await this.waitForLoaded(), this.video.duration) : this._disabledProperties.duration; } get currentTimeSync() { return this._videoEnabled ? this.ready ? this.video.currentTime : -1 : this._disabledProperties.currentTime; } async currentTime() { return this._videoEnabled ? (await this.waitForLoaded(), this.currentTimeSync) : this._disabledProperties.currentTime; } async setCurrentTime(e) { return this._videoEnabled ? (await this.waitForLoaded(), this.video.currentTime = e) : (this._disabledProperties.currentTime = e, e); } async volume() { return this._videoEnabled ? (await this.waitForLoaded(), this.video.volume) : this._disabledProperties.volume; } async setVolume(e) { return this._videoEnabled ? (await this.waitForLoaded(), e === 0 ? this.video.setAttribute("muted", "") : this.video.removeAttribute("muted"), this.video.volume = e) : (this._disabledProperties.volume = e, e); } async paused() { return this._videoEnabled ? (await this.waitForLoaded(), this.video.paused) : this._disabledProperties.paused; } async playbackRate() { return this._videoEnabled ? (await this.waitForLoaded(), await this.video.playbackRate) : this._disabledProperties.playbackRate; } async setPlaybackRate(e) { return this._videoEnabled ? (await this.waitForLoaded(), this.video.playbackRate = e) : (this._disabledProperties.playbackRate = e, e); } async getQualities() { } async setQuality() { } get currentQuality() { return 0; } async getDimensions() { return this._videoEnabled ? (await this.waitForLoaded(), { w: this.video.videoWidth, h: this.video.videoHeight }) : { w: this._disabledProperties.videoWidth, h: this._disabledProperties.videoHeight }; } saveDisabledProperties(e) { this._disabledProperties = { duration: e.duration, volume: e.volume, videoWidth: e.videoWidth, videoHeight: e.videoHeight, playbackRate: e.playbackRate, paused: e.paused, currentTime: e.currentTime }; } async loadStreamData(e = null) { this._streamData = this._streamData || e, this.player.log.debug("es.upv.paella.htmlVideoFormat: loadStreamData"), this._sources = e.sources.html, this._currentQuality = 0, this.isMainAudioPlayer || (this.video.muted = !0), this._sources.forEach(({ src: t, mimetype: n }) => { t = U(this.player, t); const s = document.createElement("source"); s.src = t, s.type = n, this.video.appendChild(s); }), this._endedCallback = this._endedCallback || (() => { typeof this._videoEndedCallback == "function" && this._videoEndedCallback(); }), this.video.addEventListener("ended", this._endedCallback); try { await this.video.play(); } catch { } await this.waitForLoaded(), this.player.log.debug(`es.upv.paella.htmlVideoFormat (${this.streamData.content}): video loaded and ready.`), this.saveDisabledProperties(this.video); } async clearStreamData() { this.video.src = "", this.video.removeEventListener("ended", this._endedCallback), this.video.removeEventListener("loadeddata", this._handleLoadedCallback), this._ready = !1; } get isEnabled() { return this._videoEnabled; } async enable() { this._videoEnabled = !0; } async disable() { return this.isMainAudio ? this.player.log.debug("video.disable() - the video is not disabled because it is the main audio source.") : this._videoEnabled = !1, this._videoEnabled; } waitForLoaded() { return new Promise((e, t) => { this.video.readyState >= 2 && (this._ready = !0), this.ready ? e() : (this._handleLoadedCallback = (n) => { this.video.readyState >= 2 && (this.video.pause(), this._ready = !0, e()); }, this.video.addEventListener("loadeddata", this._handleLoadedCallback)); }); } } class Hi extends pe { getPluginModuleInstance() { return W.Get(); } get name() { return super.name || "es.upv.paella.htmlVideoFormat"; } get streamType() { return "html"; } async isCompatible(e) { const { html: t } = e.sources; return t && t.some((n) => Fe(n.mimetype)); } async getVideoInstance(e, t) { return new St(this.player, e, t, this.config); } getCompatibleFileExtensions() { return ["m4v", "mp4", "ogg", "webm", "ogv"]; } getManifestData(e) { const t = (n) => { switch (Ve(n)) { case "mp4": case "m4v": return "video/mp4"; case "webm": return "video/webm"; case "ogg": case "ogv": return "video/ogg"; default: return null; } }; return { html: e.map((n) => ({ src: n, mimetype: t(n) })) }; } } class Gi { constructor({ label: e, shortLabel: t, isAuto: n = !1, index: s = 0, src: a = "", width: r = -1, height: o = -1, bitrate: l = -1 }) { this._label = e, this._shortLabel = t, this._index = s, this._src = a, this._res = { w: r, h: o }, this._bitrate = l, this._isAuto = n; } get label() { return this._label; } get shortLabel() { return this._shortLabel; } get index() { return this._index; } get src() { return this._src; } get res() { return this._res; } get bitrate() { return this._bitrate; } get isAuto() { return this._isAuto; } get quality() { return this._res.w !== -1 && this._res.h !== -1 ? this._res.w * this._res.h : this._bitrate; } compare(e) { return e.quality - this.quality; } } function Tt(i) { let e = this._currentSource.frames[0]; this._currentSource.frames.some((t) => { if (t.time <= this._currentTime) e = t; else return !0; }), this.img.src = e.src; } function Ki() { this._startTimestamp = Date.now(); const i = () => { this._timer = setTimeout(i, 250); const e = Date.now(), t = e - this._startTimestamp; this._currentTime += t / 1e3, this._startTimestamp = e, Tt.apply(this, [this._currentTime]); }; i(); } function qi() { this._timer && (clearTimeout(this._timer), this._timer = null); } class ji extends Be { constructor(e, t) { super("img", e, t), this._currentTime = 0, this._startTimesamp = 0, this._playbackRate = 1, this._timer = null, this.video = this.domElement; } async play() { Ki.apply(this); } async pause() { qi.apply(this); } async duration() { return this._currentSource.duration; } get currentTimeSync() { return this._currentTime; } async currentTime() { return this._currentTime; } async setCurrentTime(e) { this._currentTime = e, Tt.apply(this, [e]); } async volume() { return 0; } async setVolume(e) { } async paused() { return this._timer === null; } async playbackRate() { return this._playbackRate; } async setPlaybackRate(e) { this._playbackRate = e; } async getQualities() { return this._qualities; } async setQuality() { } get currentQuality() { return this._currentQuality; } async getDimensions() { return this._currentSource.res; } async loadStreamData(e) { return this._sources = e.sources.image, this._qualities = this._sources.map((t) => new Gi({ src: t.frames[0].src, label: `${t.res.w}x${t.res.h}`, shortLabel: `${t.res.h}p`, width: t.res.w, height: t.res.h })), this._currentQuality = this._qualities.length - 1, this._qualities.forEach((t, n) => { this._qualities[this._currentQuality].compare(t) > 0 && (this._currentQuality = n); }), this._currentSource = this._sources[this._currentQuality], this._sources.forEach((t) => { t.frames.sort((n, s) => n.time - s.time); }), !0; } } class Wi extends pe { getPluginModuleInstance() { return W.Get(); } get name() { return super.name || "es.upv.paella.imageVideoFormat"; } get streamType() { return "image"; } async isCompatible(e) { return e.sources.image != null; } async getVideoInstance(e, t) { return new ji(this.player, e, this.config, t); } } class Qi extends St { constructor(e, t, n, s) { super(e, t, n, s); } // This function is called when the player loads, and it should // make everything ready for video playback to begin. async loadStreamData(e = null) { this._streamData = this._streamData || e, this.player.log.debug("es.upv.paella.mp4VideoFormat: loadStreamData"), this._currentSource || (this._sources = null, this._currentQuality = 0, this._sources = e.sources.mp4, this._sources.sort((t, n) => Number(t.res.w) - Number(n.res.w)), this._currentQuality = this._sources.length - 1, this._currentSource = this._sources[this._currentQuality]), this.isMainAudioPlayer || (this.video.muted = !0), this._initialVolume && (this.video.volume = this._initialVolume, this._initialVolume === 0 && (this.video.muted = !0)), this.video.src = U(this.player, this._currentSource.src), this._endedCallback = this._endedCallback || (() => { typeof this._videoEndedCallback == "function" && this._videoEndedCallback(); }), this.video.addEventListener("ended", this._endedCallback); try { await this.video.play(); } catch { } await this.waitForLoaded(), this.player.log.debug(`es.upv.paella.mp4VideoFormat (${this.streamData.content}): video loaded and ready.`), this.saveDisabledProperties(this.video); } } class Zi extends pe { getPluginModuleInstance() { return W.Get(); } get name() { return super.name || "es.upv.paella.mp4VideoFormat"; } get streamType() { return "mp4"; } isCompatible(e) { const { mp4: t } = e.sources; return t && Fe(t[0]?.mimetype); } async getVideoInstance(e, t) { return new Qi(this.player, e, t, this.config); } getCompatibleFileExtensions() { return ["m4v", "mp4"]; } getManifestData(e) { return { mp4: e.map((t) => ({ src: t, mimetype: "video/mp4" })) }; } } async function Yi(i) { const e = []; await A(i, "captions", async (t) => { e.push(t); }); for (let t in e) { const s = await e[t].getCaptions(), a = i.captionsCanvas; s.forEach((r) => a.addCaptions(r)); } } class It extends j { get type() { return "captions"; } async load() { this.player.log.debug("load captions plugin"); } async getCaptions() { return this.player.log.warn(`CaptionsPlugin ${this.name}: getCaptions() is not implemented.`), []; } } class kt { get cues() { return this._cues; } get label() { return this._label; } get language() { return this._lang; } set label(e) { this._label = e; } set language(e) { this._lang = e; } constructor(e = "", t = "") { this._cues = [], this._label = e, this._lang = t; } addCue({ label: e = "", start: t, end: n, captions: s }) { const a = { label: e }; if (typeof s == "string") a.captions = [s]; else if (Array.isArray(s)) a.captions = s; else throw Error("Invalid cue caption format: must be an array of strings or a string"); if (typeof t == "string") a.start = le(t), a.startString = t; else if (typeof t == "number") a.start = t, a.startString = B(t); else throw Error("Invalid cue timestamp format: must be a valid time string or a number of seconds"); if (typeof n == "string") a.end = le(n), a.endString = n; else if (typeof n == "number") a.end = n, a.endString = B(n); else throw Error("Invalid cue timestamp format: must be a valid time string or a number of seconds"); return this._cues.push(a), a; } getCue(e) { if (typeof e == "string") e = le(e); else if (typeof e != "number") throw Error("Invalid time instant format getting cue"); let t = null; return this._cues.some((n) => { if (e >= n.start && e <= n.end) return t = n, !0; }), t; } } function Ye(i, e) { const t = {}, s = new DOMParser().parseFromString(e, "text/xml"); return Array.from(s.getElementsByTagName("div")).forEach((a) => { const r = a.getAttribute("xml:lang") || "unknonw"; t[r] = t[r] || new kt(i.translate(r), r), Array.from(a.getElementsByTagName("p")).forEach((o) => { const l = Le(o.getAttribute("begin")); t[r].addCue({ label: `caption_${o.getAttribute("xml:id") || l}`, start: l / 1e3, end: Le(o.getAttribute("end")) / 1e3, captions: o.innerHTML }); }); }), t; } class Ji { constructor(e, t = "") { this.player = e, this._text = t, this._captions = Ye(this.player, t); } get text() { return this._text; } set text(e) { this._text = e, this._captions = Ye(e); } get captions() { return this._captions; } } let _e = null; class Q extends ge { static Get() { return _e || (_e = new Q()), _e; } get moduleName() { return "paella-core default plugins"; } get moduleVersion() { return ne.version; } getDictionaries() { return { es: { "playPauseButtonHelp.title": "Ayuda del botón de reproducción/pausa", "playPauseButtonHelp.description": "Este botón permite reproducir o pausar el video." }, en: { "playPauseButtonHelp.title": "Play/Pause button help", "playPauseButtonHelp.description": "This button allows you to play or pause the video." } }; } } class Xi extends It { getPluginModuleInstance() { return Q.Get(); } get name() { return super.name || "es.upv.paella.dfxpManifestCaptionsPlugin"; } async isEnabled() { return await super.isEnabled() && this.player.videoManifest.captions && this.player.videoManifest.captions.length > 0; } async getCaptions() { const e = [], t = []; return this.player.videoManifest.captions.forEach((n) => { t.push(new Promise(async (s, a) => { if (/dfxp/i.test(n.format)) { const r = U(this.player, n.url), o = await fetch(r); if (o.ok) { let l = await o.text(); l = l.replace(/[^\x09\x0A\x0D\x20-\xFF\x85\xA0-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]/gm, ""), l = l.replace(/&\w+;/gmi, ""), l = l.replaceAll("<br>", ""); const c = new Ji(this.player, l); Object.entries(c.captions).forEach(([u, d]) => { e.push(d); }), s(); } else a(); } else a(); })); }), await Promise.allSettled(t), e; } } class Oe extends j { constructor(e, t, n) { super(e, t, n), this.__uiPlugin = !0; } async getDictionaries() { return null; } async getHelp() { return null; } async getTranslatedHelp() { const e = await this.getHelp(); return e ? { title: this.player.translate(e.title), description: this.player.translate(e.description) } : null; } } let ze = "en", Dt = ""; const G = {}; function Ee(i) { const e = G[ze] || {}, t = G[Dt] || {}; return e[i] || t[i] || i; } function Se(i) { ze = i; } function Te() { return ze; } function Ie(i, e) { G[i] = G[i] || {}; for (const t in e) { const n = e[t]; G[i][t] = n; } } function ke() { return G; } function De(i) { return i.config.defaultLanguage || navigator.language; } let At = Ee, xt = Se, Mt = Te, Rt = Ie, $t = ke, Vt = De; function ie(i, e = null) { const t = At(i); if (Array.isArray(e)) { let n = t; return e.forEach((s, a) => { const r = `$${a + 1}`; n = n.replace(r, s); }), n; } else return t; } function Je(i) { xt(i); } function en() { return Mt(); } function X(i, e) { Rt(i, e); } function tn() { return $t(); } function Ut(i) { return Vt(i); } function Xe(i) { At = i; } function et(i) { xt = i; } function tt(i) { Mt = i; } function it(i) { Rt = i; } function nt(i) { $t = i; } function st(i) { Vt = i; } function nn(i) { Dt = Ut(i); } async function de(i, e) { const t = _("<li></li>", e); t.plugin = i; const n = ie(i.ariaLabel), s = ie(i.description), a = i.dynamicWidth ? "dynamic-width" : "fixed-width", r = i.id ? `id="${i.id}" ` : "", o = i.buttonName ? `name="${i.buttonName}" ` : `name="${i.name}" `, l = i.tabIndex ? ` tabindex="${i.tabIndex}" ` : ""; if (i.interactive) { const c = _(` <button type="button" ${r}${o}class="${a}"${l}aria-label="${n}" title="${s}"> </button> `, t); i.className !== "" && c.classList.add(i.className), i._button = c, i._container = t, c._pluginData = i, t._pluginData = i, c.addEventListener("click", (y) => { const P = c._pluginData; b(P.player, h.BUTTON_PRESS, { plugin: P }), P.action(y, null), y.stopPropagation(), y.pageX !== 0 && y.pageY !== 0 && document.activeElement.blur(); }); let u = null; const d = () => { u && (clearTimeout(u), u = null); }, p = () => { d(), u = setTimeout(() => { i.leftSideContainerPresent && i.leftSideContainer.classList.add("hidden"), i.rightSideContainerPresent && i.rightSideContainer.classList.add("hidden"), u = null; }, 300); }, E = () => { d(), i.leftSideContainerPresent && i.leftSideContainer.classList.remove("hidden"), i.rightSideContainerPresent && i.rightSideContainer.classList.remove("hidden"); }; c.addEventListener("focus", E), c.addEventListener("mouseover", E), c.addEventListener("mouseout", p), c.addEventListener("blur", p), (i.player.config.accessibility?.clickWithSpacebar !== void 0 ? i.player.config.accessibility?.clickWithSpacebar : !0) || (c.addEventListener("keyup", (y) => { y.keyCode == 32 && y.preventDefault(); }), c.addEventListener("keydown", (y) => { y.keyCode == 32 && y.preventDefault(); })), i.className !== "" && c.classList.add(i.className); } else { const c = _(` <div ${r}${o} class="non-interactive ${a}" title="${s}"> </div> `, t); i._button = c, i._container = t, c._pluginData = i, t._pluginData = i, i.className !== "" && c.classList.add(i.className); } } const at = () => { const i = document.createElement("span"); return i.classList.add("side-container"), i.classList.add("hidden"), i; }; class sn { onIconChanged(e, t, n) { } onTitleChanged(e, t, n) { } onStateChanged(e, t, n, s, a) { } } class He extends Oe { get type() { return "button"; } // _container and _button are loaded in PlaybackBar get container() { return this._container; } get button() { return this._button; } get interactive() { return !0; } get dynamicWidth() { return !1; } getId() { return null; } get id() { return this.config.id || this.getId(); } getButtonName() { return null; } get buttonName() { return this.config.name || this.getButtonName() || this.name; } get ariaLabel() { return this.config.ariaLabel || this.getAriaLabel(); } getAriaLabel() { return ""; } get tabIndex() { return this.config.tabIndex || this.getTabIndex(); } getTabIndex() { return null; } getDescription() { return ""; } get description() { return this.config.description || this.getDescription(); } get minContainerSize() { return this.config.minContainerSize || this.getMinContainerSize(); } getMinContainerSize() { return 0; } setObserver(e) { if (e instanceof sn) this._observer = e; else if (typeof e.onIconChanged == "function" || typeof e.onTitleChanged == "function" || typeof e.onStateChanged == "function") this._observer = e; else throw new Error("Invalid observer for ButtonPlugin"); } #t() { const e = this.isMenuButton ? this._menuIcon : this._icon, t = this.isMenuButton && this.haveMenuIcon ? this.menuIcon : this.icon; if (t && this._button instanceof HTMLElement) { const n = this._button.querySelector("i") || _("<i></i>", this._button); n.innerHTML = t; } else if (this._button instanceof HTMLElement) { const n = this._button.querySelector("i"); n && this._button.removeChild(n); } this._observer?.onIconChanged && this._observer.onIconChanged(this, e, t); } get icon() { return this._icon || (this._icon = ""), this._icon; } set icon(e) { typeof e == "string" && (e = Pe(e)), this._icon = e, this.#t(); } get haveIcon() { return this.icon !== ""; } get menuIcon() { return this._menuIcon || (this._menuIcon = ""), this._menuIcon; } set menuIcon(e) { typeof e == "string" && (e = Pe(e)), this._menuIcon = e, this.#t(); } get haveMenuIcon() { return this.menuIcon !== ""; } get isMenuButton() { const e = this.config?.parentContainer === "playbackBar" || !this.config?.parentContainer, t = this.config?.parentContainer === "videoContainer"; return !e && !t; } get title() { return this._title || ""; } set title(e) { if (this._title = e, e && this._button instanceof HTMLElement) { const t = this._button.querySelector("span") || _(`<span class="button-title-${this.titleSize}"></span>`, this._button); t.innerHTML = e; } else if (this._button instanceof HTMLElement) { const t = this._button.querySelector("span"); t && this._button.removeChild(t); } this._observer?.onTitleChanged && this._observer.onTitleChanged(this, this._title, e); } // "small", "medium", "large" get titleSize() { return "medium"; } // "left" or "right" get side() { return this.config?.side || "left"; } get closePopUps() { return this.config.closePopUps || this.getClosePopUps(); } getClosePopUps() { return !0; } // "playbackBar" or "videoContainer" get parentContainer() { return this.config?.parentContainer || "playbackBar"; } get className() { return ""; } enable() { this._enabled = !0, this.show(); } disable() { this._enabled = !1, this.hide(); } hide() { this._button && (this._button.style.display = "none"); } show() { if (this._enabled === !1) return; const { width: e } = this.player.playbackBar.containerSize; this._button && (e > this.minContainerSize || this.parentContainer !== "playbackBar") && (this._button.style.display = null); } get hidden() { return this._button.style.display === "none"; } #e = null; get leftSideContainer() { return this.#e || (this.#e = at(), this.container.appendChild(this.#e)), this.#e; } get leftSideContainerPresent() { return this.#e !== null; } #i = null; get rightSideContainer() { return this.#i || (this.#i = at(), this.container.appendChild(this.#i)), this.#i; } get rightSideContainerPresent() { return this.#i !== null; } get stateText() { return null; } get stateIcon() { return null; } setState({ text: e = null, icon: t = null } = {}) { const n = this._statusText, s = this._statusIcon; this._statusText = e, this._statusIcon = t, this.#n.forEach((a) => a(this)), this._statusIcon && (this.icon = this._statusIcon, this.menuIcon = this._statusIcon), this._statusText && (this.title = this._statusText), this._observer?.onStateChanged?.(this, n, e, s, t); } #n = []; onStateChange(e) { typeof e == "function" ? this.#n.push(e) : this.player.log.warn("Invalid callback for ButtonPlugin.onStateChange"); } async action(e, t = null) { } onResize({ width: e, height: t }) { e < this.minContainerSize ? this.hide() : this.show(); } focus() { this.button?.focus(); } blur() { this.button?.blur(); } isFocus() { return this.button === document.activeElement; } } const an = `<svg width="100%" height="100%" viewBox="0 0 24 24" style="stroke:none;fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"> <g id="play"> <path d="M19.662,11.155C19.952,11.338 20.128,11.657 20.128,12C20.128,12.343 19.952,12.662 19.662,12.845C16.249,15 7.228,20.698 3.572,23.007C3.257,23.206 2.857,23.218 2.53,23.038C2.203,22.858 2,22.514 2,22.14C2,17.638 2,6.199 2,1.78C2,1.423 2.194,1.094 2.508,0.921C2.821,0.748 3.203,0.76 3.505,0.951C7.117,3.232 16.228,8.986 19.662,11.155Z" /> </g> </svg> `, rn = `<svg width="100%" height="100%" viewBox="0 0 26 24" style="stroke:none;fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"> <path d="M10,1.353L10,20.647C10,21.394 9.394,22 8.647,22L1.353,22C0.606,22 0,21.394 0,20.647L0,1.353C0,0.606 0.606,0 1.353,0L8.647,0C9.394,0 10,0.606 10,1.353Z" /> <path d="M24,1.353L24,20.647C24,21.394 23.394,22 22.647,22L15.353,22C14.606,22 14,21.394 14,20.647L14,1.353C14,0.606 14.606,0 15.353,0L22.647,0C23.394,0 24,0.606 24,1.353Z" /> </svg>`, on = `<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="100%" height="100%" viewBox="0 0 40 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"> <g transform="matrix(1.94013e-16,0.689169,-0.784942,2.23746e-16,110.436,-203.562)"> <g id="play"> <path d="M304.588,115.214C304.588,105.205 313.901,97.079 325.373,97.079C336.844,97.079 346.157,105.205 346.157,115.214C346.157,125.223 336.844,133.349 325.373,133.349L325.373,128.287C333.642,128.287 340.356,122.43 340.356,115.214C340.356,107.999 333.642,102.141 325.373,102.141C317.103,102.141 310.39,107.999 310.39,115.214L304.588,115.214Z"/> <g transform="matrix(-2.33361,-6.00363e-16,1.21708e-15,-2.59724,320.246,134.358)"> <path d="M5.454,3.35L9.398,7.505L1.511,7.505L5.454,3.35Z"/> </g> </g> </g> </svg> `; class ln extends He { getPluginModuleInstance() { re