@slashedcloud/player
Version:
A media player application utilizing Shaka Player for adaptive video streaming, capable of playing HLS, MPD and plain HTTP video streams.
949 lines (948 loc) • 39.1 kB
JavaScript
import './Slashedcloud-player.css';var ge = Object.defineProperty;
var J = Object.getOwnPropertySymbols;
var be = Object.prototype.hasOwnProperty, Ce = Object.prototype.propertyIsEnumerable;
var X = (o) => {
throw TypeError(o);
};
var W = (o, t, e) => t in o ? ge(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e, P = (o, t) => {
for (var e in t || (t = {}))
be.call(t, e) && W(o, e, t[e]);
if (J)
for (var e of J(t))
Ce.call(t, e) && W(o, e, t[e]);
return o;
};
var h = (o, t, e) => W(o, typeof t != "symbol" ? t + "" : t, e), K = (o, t, e) => t.has(o) || X("Cannot " + e);
var r = (o, t, e) => (K(o, t, "read from private field"), e ? e.call(o) : t.get(o)), g = (o, t, e) => t.has(o) ? X("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(o) : t.set(o, e), w = (o, t, e, i) => (K(o, t, "write to private field"), i ? i.call(o, e) : t.set(o, e), e), f = (o, t, e) => (K(o, t, "access private method"), e);
var Z = (o, t, e, i) => ({
set _(s) {
w(o, t, s, e);
},
get _() {
return r(o, t, i);
}
});
var b = (o, t, e) => new Promise((i, s) => {
var n = (c) => {
try {
l(e.next(c));
} catch (d) {
s(d);
}
}, a = (c) => {
try {
l(e.throw(c));
} catch (d) {
s(d);
}
}, l = (c) => c.done ? i(c.value) : Promise.resolve(c.value).then(n, a);
l((e = e.apply(o, t)).next());
});
import { a as A, s as y } from "./shaka-player.ui-CvkRFlcE.js";
import { l as ke, _ as ye } from "./Common-B3lKdzU9.js";
import { P as m, S as p } from "./PlayerError-JebC7rsX.js";
/*!
* SlashedCloud v0.1.2 (https://github.com/SlashedCloud/player#readme)
* Copyright 2024-2024 rogerio.jardim@fedrax.pt
* Licensed under Apache (https://github.com/SlashedCloud/player/blob/develop/LICENSE)
*/
const ee = {
RESOLUTION: "settings",
CHECKMARK: "done"
}, ve = {
Ids: {
AUTO_QUALITY: "AUTO_QUALITY",
RESOLUTION: "RESOLUTION",
QUALITY: "QUALITY"
}
};
var E;
class we extends A.ui.SettingsMenu {
constructor(e, i) {
super(e, i, ee.RESOLUTION);
g(this, E, []);
this.button.classList.add("shaka-resolution-button"), this.button.classList.add("shaka-tooltip-status"), this.menu.classList.add("shaka-resolutions"), this.eventManager.listen(i, "trackschanged", () => {
console.log("trackschanged"), this.updateResolutionSelection_();
}), this.updateResolutionSelection_();
}
/** @private */
updateResolutionSelection_() {
return b(this, null, function* () {
const e = se.get(this.controls);
e && w(this, E, e.srcSet);
const i = r(this, E).find((a) => a.active);
w(this, E, r(this, E).filter((a, l) => r(this, E).findIndex((d) => d.label == a.label && d.type == a.type && d.url == a.url) == l));
const s = this.menu.querySelector(".shaka-back-to-overflow-button");
A.util.Dom.removeAllChildren(this.menu), s && this.menu.appendChild(s);
const n = { abr: { enabled: !1 } };
this.player.configure(n);
for (const a of r(this, E)) {
const l = document.createElement("button");
l.setAttribute("type", "button"), l.classList.add("explicit-resolution"), this.eventManager.listen(l, "click", this.onTrackSelected_.bind(this, a));
const c = document.createElement("span");
c.textContent = a.label, l.appendChild(c), a == i && (l.ariaSelected = "true", l.appendChild(z.checkmarkIcon()), c.classList.add("shaka-chosen-item"), this.currentSelection.textContent = c.textContent), this.menu.appendChild(l);
}
z.focusOnTheChosenItem(this.menu), this.updateLocalizedStrings_(), z.setDisplay(this.button, r(this, E).length > 0);
});
}
/**
* @private
*/
updateLocalizedStrings_() {
const i = ve.Ids.RESOLUTION;
this.button.ariaLabel = this.localization.resolve(i), this.backButton.ariaLabel = this.localization.resolve(i), this.backSpan.textContent = this.localization.resolve(i), this.nameSpan.textContent = this.localization.resolve(i);
}
onTrackSelected_(e) {
return b(this, null, function* () {
const i = this.video.currentTime, s = this.video.paused;
if (this.video.src !== e.url) {
this.video.src = e.url, this.video.currentTime = i, s || (yield this.video.play());
for (const n of r(this, E)) n.active = !1;
e.active = !0, this.controls.dispatchEvent(new A.util.FakeEvent("resolutionselectionupdated")), this.updateResolutionSelection_();
}
});
}
}
E = new WeakMap();
const z = class {
/**
* @return {!Element}
*/
static checkmarkIcon() {
const o = document.createElement("i");
return o.classList.add("material-icons-round"), o.classList.add("shaka-chosen-item"), o.textContent = ee.CHECKMARK, o.ariaHidden = "true", o;
}
/**
* Finds a descendant of |menu| that has a 'shaka-chosen-item' class
* and focuses on its' parent.
*
* @param {HTMLElement} menu
*/
static focusOnTheChosenItem(o) {
if (!o) return;
const t = this.getDescendantIfExists(o, "shaka-chosen-item");
t && t.parentElement.focus();
}
/**
* @param {!HTMLElement} element
* @param {string} className
* @return {?Element}
*/
static getDescendantIfExists(o, t) {
const e = o.getElementsByClassName(t);
return e.length ? e[0] : null;
}
/**
* Depending on the value of display, sets/removes the css class of element to
* either display it or hide it.
*
* @param {Element} element
* @param {boolean} display
*/
static setDisplay(o, t) {
o && (t ? o.classList.remove("shaka-hidden") : o.classList.add("shaka-hidden"));
}
};
var L, x, U, Q;
class Ee extends A.ui.SeekBar {
constructor(e, i) {
super(e, i);
g(this, x);
h(this, "custumSeekBarActive", !1);
h(this, "isChaptersEnabled", !1);
h(this, "isMarkersEnabled", !1);
h(this, "isThumbnailEnabled", !1);
g(this, L);
h(this, "chapters", []);
h(this, "markers", []);
h(this, "thumbnailWrapper");
h(this, "thumbnailMarkerContainer");
h(this, "thumbnailMarkerText");
h(this, "thumbnailMarkerImage");
h(this, "thumbnailMarkerTime");
h(this, "markerContainer");
h(this, "chapterContainer");
h(this, "chapterContainerText");
h(this, "preloadedMarkerImages", /* @__PURE__ */ new Map());
h(this, "hideChapters");
h(this, "hideMarkers");
h(this, "thumbnailContainer");
h(this, "eventManager");
h(this, "controlsContainer");
const s = i.getLocalization(), [n] = s ? s.getCurrentLocales() : ["en"];
if (!this.player) throw new Error("Player is not available");
this.controlsContainer = i.getControlsContainer(), this.chapterContainerText = document.createElement("div"), this.chapterContainerText.id = "shaka-chapter-text", this.chapterContainer = document.createElement("div"), this.chapterContainer.classList.add("shaka-chapter-container"), this.chapterContainer.appendChild(this.chapterContainerText), this.markerContainer = document.createElement("div"), this.markerContainer.classList.add("shaka-marker-container"), this.thumbnailMarkerText = document.createElement("div"), this.thumbnailMarkerText.id = "shaka-player-ui-thumbnail-marker-text", this.thumbnailMarkerContainer = document.createElement("div"), this.thumbnailMarkerContainer.id = "shaka-player-ui-thumbnail-marker-container", this.thumbnailMarkerTime = document.createElement("div"), this.thumbnailMarkerTime.id = "shaka-player-ui-thumbnail-marker-time", this.thumbnailMarkerImage = document.createElement("img"), this.thumbnailMarkerImage.id = "shaka-player-ui-thumbnail-marker-image", this.thumbnailMarkerContainer.appendChild(this.thumbnailMarkerImage), this.thumbnailMarkerContainer.appendChild(this.thumbnailMarkerText), this.thumbnailMarkerContainer.appendChild(this.thumbnailMarkerTime), this.thumbnailWrapper = document.createElement("div"), this.thumbnailWrapper.id = "shaka-player-ui-thumbnail-wrapper", this.thumbnailWrapper.appendChild(this.thumbnailMarkerContainer), this.container.appendChild(this.thumbnailWrapper), window.innerWidth < 768 && this.thumbnailMarkerText.classList.add("mobile"), this.eventManager = new A.util.EventManager(), this.hideChapters = new A.util.Timer(() => {
this.hideChapters_();
}), this.hideMarkers = new A.util.Timer(() => {
this.hideMarkers_();
}), this.isThumbnailEnabled = this.player.getImageTracks().length > 0, this.thumbnailContainer = this.container.querySelector("#shaka-player-ui-thumbnail-container"), this.thumbnailContainer && this.thumbnailWrapper.appendChild(this.thumbnailContainer);
const c = this.player.getChaptersTracks().find((T) => T.language === n) ? this.player.getChapters(n) : this.player.getChapters("en");
c && c.length > 0 && this.registerChapters(c);
const d = this.player.getChapters("markers");
d && d.length > 0 && this.registerMarkers(d), this.eventManager.listen(this.container, "mouseleave", () => {
this.isChaptersEnabled && (this.hideChapters.stop(), this.hideChapters.tickAfter(
/* seconds= */
0.05
)), this.isMarkersEnabled && (this.hideMarkers.stop(), this.hideMarkers.tickAfter(
/* seconds= */
0.05
));
});
}
/**
* @override
*/
update() {
super.update(), this.isChaptersEnabled && this.updateChapters();
}
/**
* Called by the base class when user interaction with the input element
* ends.
*
* @override
*/
onChangeEnd() {
super.onChangeEnd(), this.isChaptersEnabled && (this.hideChapters.stop(), this.hideChapters.tickAfter(
/* seconds= */
0.25
)), this.isMarkersEnabled && (this.hideMarkers.stop(), this.hideMarkers.tickAfter(
/* seconds= */
0.25
));
}
/**
* Update the video element's state to match the input element's state.
* Called by the base class when the input element changes.
*
* @override
*/
onChange() {
super.onChange(), this.isChaptersEnabled && this.onChangeChapters();
}
changeTo(e) {
super.changeTo(e);
}
updateChapters() {
const e = this.controls.getConfig(), i = e.seekBarColors, s = this.getValue(), n = this.video.buffered.length, a = n ? this.video.buffered.start(0) : 0, l = n ? this.video.buffered.end(n - 1) : 0, c = this.player.seekRange();
if (n == 0) {
this.container.style.background = i.base;
return;
}
if (!this.chapterContainer) return;
const d = Math.max(a, c.start), T = Math.min(l, c.end), S = Math.min(Math.max(s, c.start), c.end), q = d - c.start, ue = T - c.start, me = S - c.start, pe = e.showUnbufferedStart ? i.base : i.played;
for (const v of this.chapters) {
if (!v.element) return;
if (s > v.endTime) {
v.element.style.background = i.played;
continue;
}
if (s < v.startTime) {
v.element.style.background = i.base;
continue;
}
const $ = v.endTime - v.startTime, H = (q - v.startTime) / $ || 0, G = (ue - v.startTime) / $ || 0, Y = (me - v.startTime) / $ || 0, fe = [
"to right",
this.makeColor_(pe, H),
this.makeColor_(i.played, H),
this.makeColor_(i.played, Y),
this.makeColor_(i.buffered, Y),
this.makeColor_(i.buffered, G),
this.makeColor_(i.base, G)
];
v.element.style.background = "linear-gradient(" + fe.join(",") + ")";
}
}
onChangeChapters() {
const e = parseFloat(this.bar.min), i = parseFloat(this.bar.max), s = this.bar.getBoundingClientRect(), n = Math.round(this.getValue()), a = (i - e) / s.width, l = (n - e) / a;
f(this, x, U).call(this, l, n);
}
setChapters(e) {
const i = this.player.seekRange(), s = i.end - i.start;
e = e.filter((a) => a.startTime >= i.start && a.startTime <= i.end), e = e.filter((a) => a.endTime <= i.end && a.endTime >= i.start);
for (const a in e) {
const l = e[a];
l.id = a;
const c = e[parseInt(a) + 1];
c && c.startTime > l.endTime && e.push({
id: `${a}-break`,
startTime: l.endTime,
endTime: c.startTime,
title: ""
});
}
e.sort((a, l) => a.startTime - l.startTime);
const n = e[e.length - 1];
if (n.endTime) {
const a = s - n.endTime;
n.endTime > i.end || a <= 1 ? n.endTime = i.end : e.push({
id: `${n.id}-break`,
startTime: n.endTime,
endTime: s,
title: ""
});
}
for (const a of e) {
const l = document.createElement("div");
l.classList.add("shaka-chapter"), l.id = `chapter-${a.id}`;
const c = this.calcFrac(a, i, s);
l.style.width = `calc(${(c.endFrac - c.startFrac) * 100}% - 4px)`;
const d = document.createElement("div");
d.classList.add("shaka-chapter-spacing"), d.style.width = "4px", this.chapterContainer.appendChild(l), this.chapterContainer.appendChild(d), a.element = l;
}
this.chapters = e, this.eventManager.listen(this.bar, "mousemove", (a) => b(this, null, function* () {
const l = this.bar.getBoundingClientRect(), c = parseFloat(this.bar.min), d = parseFloat(this.bar.max), T = a.clientX - l.left, S = (d - c) / l.width, q = Math.round(c + S * T);
f(this, x, U).call(this, T, q);
})), this.thumbnailWrapper.style.bottom = "25px";
}
calcFrac(e, i, s) {
const a = (e.startTime - i.start) / s || 0;
let l = a + 0.01;
return e.endTime && (l = (e.endTime - i.start) / s || 0), { startFrac: a, endFrac: l };
}
/**
* @param {string} color
* @param {number} fract
* @return {string}
* @private
*/
makeColor_(e, i) {
return e + " " + i * 100 + "%";
}
setMarkers(e) {
if (!e.length) {
this.markerContainer.style.background = "transparent";
return;
}
const i = this.player.seekRange(), s = i.end - i.start;
for (const n in e) {
const a = e[n];
if (a.time = Number(a.time), !(a.time >= i.start && a.time < i.end)) continue;
this.preloadImage(a.thumb, a.time);
const c = (a.time - i.start) / s || 0, d = document.createElement("div");
d.classList.add("shaka-marker"), d.id = `marker-${n}`, d.dataset.time = `${a.time}`, d.style.left = `${c * 100}%`, a.element = d, this.markerContainer.appendChild(d), this.eventManager.listen(d, "click", this.changeTo.bind(this, a.time)), this.eventManager.listen(d, "mousemove", f(this, x, Q).bind(this, a)), this.eventManager.listen(d, "mouseleave", () => {
this.hideMarkers.stop(), this.hideMarkers.tickNow();
}), this.eventManager.listen(d, "showMarker", f(this, x, Q).bind(this, a));
}
this.eventManager.listen(this.controlsContainer, "hideMarker", () => {
this.hideMarkers.stop(), this.hideMarkers.tickNow();
}), this.eventManager.listen(this.bar, "mousemove", () => {
this.hideMarkers.stop(), this.hideMarkers.tickNow();
}), this.markers = e;
}
/**
* Preload image
* @param {string} url
* @param {number} time
*/
preloadImage(e, i) {
return b(this, null, function* () {
if (this.preloadedMarkerImages.has(i)) return;
const s = new Image();
s.src = e, s.onload = () => this.preloadedMarkerImages.set(i, s);
});
}
/**
* Load image
* @param {string} url
* @param {string} alt
*/
loadImage(e, i) {
return b(this, null, function* () {
return new Promise((s, n) => {
this.thumbnailMarkerImage.onload = () => s(!0), this.thumbnailMarkerImage.onerror = n, this.thumbnailMarkerImage.src = e, this.thumbnailMarkerImage.alt = i;
});
});
}
/**
* @param {number} totalSeconds
* @private
*/
timeFormatter_(e) {
const i = Math.round(e), s = Math.floor(i / 3600);
let n = Math.floor((i - s * 3600) / 60), a = i - s * 3600 - n * 60;
return a < 10 && (a = "0" + a), s > 0 ? (n < 10 && (n = "0" + n), s + ":" + n + ":" + a) : n + ":" + a;
}
hideChapters_() {
var e;
if (this.isChaptersEnabled) {
this.chapterContainerText.style.visibility = "hidden";
for (const i of this.chapters) (e = i.element) == null || e.classList.remove("shaka-chapter-select");
this.controlsContainer.dispatchEvent(new CustomEvent("chapterHidden"));
}
}
hideMarkers_() {
var e;
if (this.isMarkersEnabled && r(this, L)) {
w(this, L, void 0), this.thumbnailMarkerContainer.style.visibility = "hidden", this.thumbnailMarkerImage.src = "", this.thumbnailMarkerImage.alt = "", this.thumbnailMarkerTime.textContent = "", this.thumbnailMarkerText.textContent = "";
for (const i of this.markers) (e = i.element) == null || e.classList.remove("active");
this.controlsContainer.dispatchEvent(new CustomEvent("markerHidden"));
}
}
// registerChapters(locale: string) {
registerChapters(e) {
if (!e || !e.length) throw new Error("Chapters are not available");
this.setChapters(e), this.container.insertBefore(this.chapterContainer, this.container.childNodes[0]), this.container.classList.add("shaka-no-background"), this.isChaptersEnabled = !0;
}
registerMarkers(e) {
return b(this, null, function* () {
const i = [];
for (const s in e) {
const n = e[s], [a, l] = n.title.split("#thumb#");
i.push({
time: n.startTime,
title: a,
thumb: l,
id: s
});
}
if (!i || !i.length) throw new Error("Markers are not available");
this.setMarkers(i), this.container.insertBefore(this.markerContainer, this.container.childNodes[0]), this.isMarkersEnabled = !0;
});
}
}
L = new WeakMap(), x = new WeakSet(), U = function(e, i) {
var d, T;
const s = this.player.seekRange(), n = Math.max(Math.ceil(s.start), Math.min(Math.floor(s.end), i));
this.chapterContainerText.style.visibility = "hidden";
for (const S of this.chapters) (d = S.element) == null || d.classList.remove("shaka-chapter-select");
const a = this.chapters.find((S) => S.startTime <= n && n <= S.endTime);
if (!a || !a.title) return;
(T = this.chapterContainer.querySelector(`#chapter-${a.id}`)) == null || T.classList.add("shaka-chapter-select"), this.chapterContainerText.textContent = a.title;
const l = this.chapterContainerText.clientWidth, c = Math.min(this.bar.offsetWidth - l, Math.max(0, e - l / 2));
this.chapterContainerText.style.left = c + "px", this.chapterContainerText.style.visibility = "visible", this.controlsContainer.dispatchEvent(new CustomEvent("chapterShown"));
}, Q = function(e) {
var a;
if (!e.element) throw new Error("Marker element is not defined");
if (r(this, L) === e.time) return;
w(this, L, e.time), this.isThumbnailEnabled && (this.thumbnailContainer.style.visibility = "hidden");
const i = e.element.offsetLeft, s = this.preloadedMarkerImages.get(e.time);
s && (e.thumb = s.src);
const n = this.loadImage(e.thumb, e.title);
for (const l of this.markers) (a = l.element) == null || a.classList.remove("active");
e.element.classList.add("active"), this.thumbnailMarkerText.textContent = e.title, this.thumbnailMarkerTime.textContent = this.timeFormatter_(e.time), n.then(() => {
const l = this.thumbnailMarkerContainer.offsetWidth, c = Math.min(this.bar.offsetWidth - l, Math.max(0, i - l / 2));
this.thumbnailMarkerContainer.style.left = c + "px", this.controlsContainer.dispatchEvent(new CustomEvent("markerShown")), this.thumbnailMarkerContainer.style.visibility = "visible";
}).catch(() => {
});
};
const Me = /* @__PURE__ */ new Map([
["adStart", y.ads.AdManager.AD_STARTED],
["adComplete", y.ads.AdManager.AD_COMPLETE],
["adAllCompleted", y.ads.AdManager.ALL_ADS_COMPLETED],
["adClick", y.ads.AdManager.AD_CLICKED],
["adSkip", y.ads.AdManager.AD_SKIPPED],
["adError", y.ads.AdManager.AD_ERROR]
]);
var O, te, ie;
class Te {
constructor(t, e) {
g(this, O);
h(this, "name", "ServerSideAdsInsertionPlugin");
h(this, "loadIm3", null);
h(this, "options");
h(this, "player");
h(this, "preventDoubleTrigger", []);
this.player = t, this.options = e;
}
/**
* Sets up the server-side ads insertion.
* @returns A promise that resolves to the stream request URL.
* @throws {Error} If the Google IMA SDK or Google IMA DAI SDK is not loaded, or if the ad manager is not available.
*/
setup() {
return b(this, null, function* () {
if (this.loadIm3 && (this.loadIm3 = yield ke("https://imasdk.googleapis.com/js/sdkloader/ima3_dai.js")), !window.google || !window.google.ima)
throw new m(this.name, p.ERROR, "IMA SDK Not Loaded.", {
description: "The Google IMA SDK is required to display ads."
});
if (!window.google.ima.dai)
throw new m(this.name, p.ERROR, "IMA DAI SDK Not Loaded.", {
description: "The Google IMA DAI SDK is required to display ads."
});
const t = this.player.basePlayer.getAdManager();
if (!t)
throw new m(this.name, p.ERROR, "Ad Manager Not Available", {
description: "The Ad Manager is currently unavailable."
});
const e = yield f(this, O, te).call(this, t);
return f(this, O, ie).call(this, t), e;
});
}
}
O = new WeakSet(), te = function(t) {
return b(this, null, function* () {
const e = this.player.controls.getServerSideAdContainer();
if (!e)
throw new m(this.name, p.ERROR, "Ad Container Not Available", {
reason: "The Server-side ad container is not available."
});
let i;
switch (this.options.type) {
case "ima-dai":
switch (this.options.stream) {
case "vod":
i = new google.ima.dai.api.VODStreamRequest(), this.options.contentSourceId && (i.contentSourceId = this.options.contentSourceId), this.options.videoId && (i.videoId = this.options.videoId);
break;
case "live":
i = new google.ima.dai.api.LiveStreamRequest(), this.options.assetKey && (i.assetKey = this.options.assetKey);
break;
default:
throw new m(this.name, p.ERROR, "Invalid stream type");
}
return t.initServerSide(e, this.player.videoElement), this.options.adTagParameters && (i.adTagParameters = this.options.adTagParameters), this.options.apiKey && (i.apiKey = this.options.apiKey), this.options.authToken && (i.authToken = this.options.authToken), this.options.format && (i.format = this.options.format), this.options.omidAccessModeRules && (i.omidAccessModeRules = this.options.omidAccessModeRules), this.options.streamActivityMonitorId && (i.streamActivityMonitorId = this.options.streamActivityMonitorId), yield t.requestServerSideStream(i);
case "media-tailor":
const s = this.player.basePlayer.getNetworkingEngine();
if (!s)
throw new m(this.name, p.ERROR, "Networking engine is not available", {
reason: "Networking engine is required for MediaTailor stream requests"
});
t.initMediaTailor(e, s, this.player.videoElement);
const n = {};
this.options.assetId && (n.assetId = this.options.assetId), this.options.podDuration && (n.podDuration = this.options.podDuration);
const a = Object.keys(n).length === 0 ? null : { adsParams: n };
return yield t.requestMediaTailorStream(this.options.url, a);
default:
throw new m(this.name, p.ERROR, "Invalid stream type");
}
});
}, /**
* Adds event listeners for ads events.
* @param {shaka.extern.IAdManager} adManager - The ad manager.
* @returns {void}
*/
ie = function(t) {
for (const [e, i] of Me)
t.addEventListener(i, () => {
switch (e) {
case "adStart":
if (this.preventDoubleTrigger.includes("adStart")) return;
this.preventDoubleTrigger.push(e);
break;
case "adComplete":
case "adAllCompleted":
case "adSkip":
case "adError":
const s = this.preventDoubleTrigger.indexOf("adStart");
s > -1 && this.preventDoubleTrigger.splice(s, 1);
break;
}
this.player.emit(e);
});
};
var M, D;
class Ie {
constructor() {
g(this, M, /* @__PURE__ */ new Map());
g(this, D, []);
h(this, "off", this.removeListener.bind(this));
}
on(t, e) {
if (Array.isArray(t)) {
const i = [];
for (const s of t) {
const n = this.on(s, e);
i.push(n);
}
return i;
}
return r(this, M).has(t) || r(this, M).set(t, []), r(this, M).get(t).push(e), () => this.removeListener(t, e);
}
once(t, e) {
if (Array.isArray(t))
return t.map((s) => this.once(s, e));
const i = this.on(t, (...s) => {
i(), e.apply(this, s);
});
return i;
}
/**
* Adds a listener to all events
* @param listener
*/
all(t) {
r(this, D).push(t);
}
/**
* Removes a listener from the event
* @param event
* @param listener
* @returns
*/
removeListener(t, e) {
if (Array.isArray(t)) {
for (const n of t) this.removeListener(n, e);
return;
}
if (!r(this, M).has(t)) return;
const i = r(this, M).get(t), s = i.indexOf(e);
s > -1 && i.splice(s, 1);
}
/**
* Removes all existing listeners
*/
removeAllListeners() {
r(this, M).clear();
}
/**
* Emits an event for all listeners
* @param event
* @param args
* @returns
*/
emit(t, ...e) {
const i = [];
r(this, M).has(t) && i.push(...r(this, M).get(t)), r(this, D).length && i.push(...r(this, D));
for (const s of i)
s.apply(this, [t, ...e]);
}
}
M = new WeakMap(), D = new WeakMap();
class Se {
constructor(t) {
h(this, "expiresIn");
h(this, "prefix");
this.prefix = (t == null ? void 0 : t.prefix) || "player_persister", this.expiresIn = (t == null ? void 0 : t.expiresIn) || 365 * 30 * 24 * 60 * 60 * 1e3;
}
get(t) {
const e = `${this.prefix}-${t}`, i = localStorage.getItem(e);
if (!i) return;
const s = JSON.parse(i);
return Date.now() >= s.expiresAt ? this.delete(t) : s.data;
}
set(t, e, i) {
const s = `${this.prefix}-${t}`, n = i || this.expiresIn, a = new Date((/* @__PURE__ */ new Date()).getTime() + n).getTime(), l = JSON.stringify({ expiresAt: a, data: e });
localStorage.setItem(s, l);
}
delete(t) {
const e = `${this.prefix}-${t}`;
localStorage.removeItem(e);
}
}
const xe = {
adStatisticsList: [],
addBigPlayButton: !1,
addSeekBar: !0,
castAndroidReceiverCompatible: !1,
castReceiverAppId: "",
clearBufferOnQualityChange: !0,
contextMenuElements: [],
controlPanelElements: [
"play_pause",
"mute",
"volume",
"time_and_duration",
"spacer",
"playback_rate",
// 'language',
// 'captions',
"recenter_vr",
"toggle_stereoscopic",
"quality",
"fullscreen"
],
customContextMenu: !1,
defaultVrProjectionMode: "equirectangular",
displayInVrMode: !1,
doubleClickForFullscreen: !0,
enableFullscreenOnRotation: !0,
enableKeyboardPlaybackControls: !0,
enableTooltips: !1,
fadeDelay: 0,
fastForwardRates: [2, 4, 8, 1],
forceLandscapeOnFullscreen: !0,
// fullScreenElement: document.createElement('div'),
keyboardLargeSeekDistance: 60,
keyboardSeekDistance: 5,
overflowMenuButtons: [],
playbackRates: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],
preferDocumentPictureInPicture: !0,
refreshTickInSeconds: 0.125,
rewindRates: [-1, -2, -4, -8],
seekBarColors: {
base: "rgba(255, 255, 255, 0.3)",
buffered: "rgba(255, 255, 255, 0.54)",
played: "rgb(255, 255, 255)",
adBreaks: "rgb(255, 204, 0)"
},
seekOnTaps: !0,
// setupMediaSession: true,
showAudioChannelCountVariants: !0,
showUnbufferedStart: !1,
singleClickForPlayAndPause: !0,
statisticsList: [],
tapSeekDistance: 10,
// textTrackLabelFormat: 'LANGUAGE',
// trackLabelFormat: 'LANGUAGE',
volumeBarColors: {
base: "rgba(255, 255, 255, 0.54)",
level: "rgb(255, 255, 255)"
}
};
y.polyfill.installAll();
if (!y.Player.isBrowserSupported())
throw console.error("Browser not supported!"), new Error("Browser not supported!");
y.ui.Controls.registerElement("customQualitySelector", {
create: (o, t) => new we(o, t)
});
y.ui.Controls.registerSeekBar({
create(o, t) {
return new Ee(o, t);
}
});
const se = /* @__PURE__ */ new Map();
var R, C, k, N, _, B, I, F, u, ae, ne, re, oe, V, le, j, he, ce, de;
class De {
constructor(t, e) {
g(this, u);
// Element ID of the container
h(this, "elementId");
h(this, "basePlayer");
h(this, "overlay");
h(this, "controls");
h(this, "localization");
h(this, "container");
h(this, "videoElement");
h(this, "options");
h(this, "uiConfig");
h(this, "language");
// Map of plugins
g(this, R, /* @__PURE__ */ new Map());
// Event emitter
g(this, C, new y.util.EventManager());
g(this, k, new Ie());
// Persister instance
g(this, N);
// Current volume of the video element
g(this, _);
// Flag to indicate that the source is server side ads
g(this, B, !1);
// Index of the current source in the sources array
g(this, I, 0);
// Index of the last error source in the sources array
g(this, F, -1);
// Event listeners (Bound to emitter)
h(this, "on", r(this, k).on.bind(r(this, k)));
h(this, "once", r(this, k).once.bind(r(this, k)));
h(this, "all", r(this, k).all.bind(r(this, k)));
h(this, "removeListener", r(this, k).removeListener.bind(r(this, k)));
h(this, "off", r(this, k).off.bind(r(this, k)));
h(this, "emit", r(this, k).emit.bind(r(this, k)));
var a, l;
if (!t) throw new m("Player", p.CRITICAL, "Element ID is required");
const i = document.getElementById(t);
if (!i) throw new m("Player", p.CRITICAL, `Element with ID '${t}' not found.`);
this.elementId = t, w(this, N, new Se(e.persister)), this.options = P({}, e), this.language = (l = (a = this.options.language) != null ? a : navigator.language) != null ? l : "en", this.container = i, this.uiConfig = ye(xe), f(this, u, oe).call(this), this.videoElement = f(this, u, ae).call(this);
const s = this.uiConfig.displayInVrMode ? f(this, u, ne).call(this) : null;
this.basePlayer = f(this, u, re).call(this), this.overlay = new y.ui.Overlay(this.basePlayer, i, this.videoElement, s), this.overlay.configure(this.uiConfig);
const n = this.overlay.getControls();
if (!n) throw new m("Player", p.CRITICAL, "Controls not found");
this.controls = n, this.localization = n.getLocalization(), this.localization && this.localization.changeLocale([this.language]), w(this, _, this.videoElement.volume);
}
initialize() {
return b(this, null, function* () {
try {
if (!this.options.src) throw new m("Player", p.CRITICAL, "No source provided");
f(this, u, de).call(this), yield this.basePlayer.attach(this.videoElement);
const t = yield f(this, u, V).call(this, this.options.src);
yield f(this, u, j).call(this, t), yield f(this, u, ce).call(this), this.overlay.configure(this.uiConfig), this.emit("ready"), this.emit("acknowledge");
} catch (t) {
let e = t;
t instanceof m || (e = new m("Player", p.CRITICAL, t.message, { reason: t })), this.emit("error", P({}, e.toObject()));
}
});
}
onError(t, e = !1) {
return b(this, null, function* () {
if (r(this, F) + 1 !== r(this, I)) return;
if (w(this, F, r(this, I)), !Array.isArray(this.options.src))
throw new m("Player", p.CRITICAL, t.message, { reason: t });
const i = r(this, I) + 1, s = yield f(this, u, V).call(this, this.options.src, i), n = new m("Player", p.WARNING, t.message, {
reason: t,
description: `Fallback to the next source... ${i}`
});
this.emit("error", P({}, n.toObject())), Z(this, I)._++, yield f(this, u, j).call(this, s);
});
}
loadPlugin(t, e) {
const i = new t(this, e);
return r(this, R).set(t, i), i;
}
/**
* Returns a loaded plugin instance
* @param PluginClass
* @returns
*/
getPlugin(t) {
if (!r(this, R).has(t))
throw new m("Player", p.WARNING, `Plugin ${t.name} not found`);
return r(this, R).get(t);
}
play() {
return b(this, null, function* () {
const t = this.videoElement.play();
t && (yield t.catch((e) => {
console.error("Play:", e);
}));
});
}
pause() {
this.videoElement.pause();
}
volume(t) {
(t < 0 || t > 1) && (t = 1), this.videoElement.volume = t;
}
mute() {
this.videoElement.muted = !0;
}
unmute() {
this.videoElement.muted = !1;
}
get persister() {
return r(this, N);
}
get currentSourceIndex() {
return r(this, I);
}
}
R = new WeakMap(), C = new WeakMap(), k = new WeakMap(), N = new WeakMap(), _ = new WeakMap(), B = new WeakMap(), I = new WeakMap(), F = new WeakMap(), u = new WeakSet(), ae = function() {
var e, i, s;
const t = document.createElement("video");
return t.id = "video-player", t.className = "shaka-video", t.crossOrigin = "anonymous", t.controls = !1, t.preload = "auto", t.autoplay = (e = this.options.autoplay) != null ? e : !1, t.muted = (i = this.options.muted) != null ? i : !1, t.playsInline = (s = this.options.playsInline) != null ? s : !1, t.setAttribute("data-shaka-player", ""), this.container.style.width = this.options.width ? `${this.options.width}px` : "100%", this.container.style.height = this.options.height ? `${this.options.height}px` : "100%", this.container.classList.add("shaka-theme", "youtube-theme"), this.container.appendChild(t), t;
}, ne = function() {
const t = document.createElement("canvas");
return t.className = "shaka-vr-canvas-container", this.container.appendChild(t), t;
}, re = function() {
const t = new y.Player();
return t.configure({
preferredTextLanguage: this.language,
preferredAudioLanguage: this.language,
streaming: {
// useNativeHlsOnSafari: true,
preferNativeHls: !0,
useNativeHlsForFairPlay: !0
},
abr: {
// TODO : review when is http
enabled: !0,
clearBufferSwitch: !0,
restrictToScreenSize: !0,
restrictions: {
maxHeight: window.screen.height,
maxWidth: window.screen.width
}
}
}), t;
}, oe = function() {
for (const t in this.uiConfig)
t in this.options && (this.uiConfig[t] = this.options[t]);
}, V = function(t, e = 0) {
return b(this, null, function* () {
if (Array.isArray(t)) {
if (e > t.length - 1)
throw new m("Player", p.CRITICAL, "All sources are played and none of them are working");
const i = t[e];
if (!i) throw new m("Player", p.CRITICAL, "No source provided");
return i;
}
return t;
});
}, le = function(t) {
return b(this, null, function* () {
var s;
let e, i;
if ((s = this.uiConfig.controlPanelElements) != null && s.length) {
const n = this.uiConfig.controlPanelElements.indexOf("customQualitySelector");
n !== -1 && (this.uiConfig.controlPanelElements[n] = "quality");
}
if (typeof t == "string")
e = t, i = null;
else
switch (t.type) {
case "multi-progressive":
({ url: e, type: i } = f(this, u, he).call(this, t));
break;
case "media-tailor":
case "ima-dai":
const a = yield new Te(this, t).setup();
w(this, B, !0), e = a, i = null;
break;
case "application/dash+xml":
case "dash":
case "mpd":
e = t.url, i = "application/dash+xml";
break;
case "application/x-mpegurl":
case "m3u8":
case "hls":
e = t.url, i = "application/x-mpegurl";
break;
default:
throw new m("Player", p.CRITICAL, "Invalid source type");
}
return this.basePlayer.load(e, null, i);
});
}, j = function(t) {
return b(this, null, function* () {
try {
const e = yield f(this, u, le).call(this, t);
return r(this, I) > 0 && this.emit("fallback", { source: t }), e;
} catch (e) {
yield this.onError(e);
}
});
}, /**
* Sets the custom quality selector for the player
* Replace the default quality selector with the custom quality selector
* Return the first source in the array
* @param src
* @returns string
*/
he = function(t) {
var s, n, a;
const e = t.srcSet;
if (!e.length) throw new m("Player", p.CRITICAL, "No source provided");
const i = (s = e.find((l) => l.active)) != null ? s : e[Math.floor(e.length / 2)];
if (i.active || (i.active = !0), ((n = this.uiConfig.controlPanelElements) == null ? void 0 : n.length) === 0) return i;
if (se.set(this.controls, t), ((a = this.uiConfig.controlPanelElements) == null ? void 0 : a.indexOf("customQualitySelector")) === -1) {
const l = this.uiConfig.controlPanelElements.indexOf("quality");
l === -1 ? this.uiConfig.controlPanelElements.push("customQualitySelector") : this.uiConfig.controlPanelElements[l] = "customQualitySelector";
}
return i;
}, ce = function() {
return b(this, null, function* () {
const t = [];
for (const e of r(this, R).values())
t.push(
e.setup().catch((i) => {
i instanceof m || (i = new m(e.name, p.WARNING, i.message, P({}, i))), this.emit("error", P({}, i.toObject()));
})
);
return Promise.all(t);
});
}, de = function() {
this.once("ready", () => {
r(this, C).listen(this.controls, "resolutionselectionupdated", () => this.emit("qualityChange"));
}), r(this, C).listenOnce(this.videoElement, "play", () => this.emit("firstPlay")), r(this, C).listen(this.videoElement, "play", () => this.emit("play")), r(this, C).listen(this.videoElement, "playing", () => this.emit("playing")), r(this, C).listen(this.videoElement, "pause", () => this.emit("pause")), r(this, C).listen(this.videoElement, "ended", () => this.emit("ended")), r(this, C).listen(this.videoElement, "seeking", () => this.emit("seeking")), r(this, C).listen(this.videoElement, "seeked", () => this.emit("seeked")), r(this, C).listen(this.container, "fullscreenchange", () => {
this.controls.isFullScreenEnabled() ? this.emit("fullScreenIn") : this.emit("fullScreenOut");
}), r(this, C).listen(this.videoElement, "volumechange", () => {
const t = this.videoElement.volume;
if (r(this, _) !== t)
return w(this, _, t), this.emit("volumeChange", { volume: t });
this.emit(this.videoElement.muted ? "mute" : "unmute");
}), r(this, C).listenOnce(this.videoElement, "play", () => {
const t = /* @__PURE__ */ new Date();
r(this, C).listenOnce(this.videoElement, "playing", () => {
const e = (/* @__PURE__ */ new Date()).getTime() - t.getTime();
this.emit("playAttempt", { attemptDuration: e });
});
}), r(this, C).listen(this.videoElement, "error", () => {
this.videoElement.error && this.emit("error", { error: this.videoElement.error });
}), this.container.addEventListener("error", (t) => {
this.emit("error", { error: t.error });
}), this.options.debug && this.all((t, ...e) => {
console.log("======= Debug ======="), console.log("Event sent:", t, ...e);
});
};
export {
De as default
};