@asicupv/paella-core
Version:
Multi stream HTML video player
1,578 lines • 214 kB
JavaScript
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