@oplayer/core
Version:
Oh! Another HTML5 video player.
1,133 lines (1,132 loc) • 35.5 kB
JavaScript
/**
* name: @oplayer/core
* version: v1.2.38-beta.2
* description: Oh! Another HTML5 video player.
* author: shiyiya
* homepage: https://github.com/shiyiya/oplayer
*/
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
function hashify(str) {
return hash(str).toString(36);
}
function hash(str) {
let seed = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 0;
let m = 1540483477;
let r = 24;
let h = seed ^ str.length;
let length = str.length;
let currentIndex = 0;
while (length >= 4) {
let k = UInt32(str, currentIndex);
k = Umul32(k, m);
k ^= k >>> r;
k = Umul32(k, m);
h = Umul32(h, m);
h ^= k;
currentIndex += 4;
length -= 4;
}
switch (length) {
case 3:
h ^= UInt16(str, currentIndex);
h ^= str.charCodeAt(currentIndex + 2) << 16;
h = Umul32(h, m);
break;
case 2:
h ^= UInt16(str, currentIndex);
h = Umul32(h, m);
break;
case 1:
h ^= str.charCodeAt(currentIndex);
h = Umul32(h, m);
break;
}
h ^= h >>> 13;
h = Umul32(h, m);
h ^= h >>> 15;
return h >>> 0;
}
function UInt32(str, pos) {
return str.charCodeAt(pos++) + (str.charCodeAt(pos++) << 8) + (str.charCodeAt(pos++) << 16) + (str.charCodeAt(pos) << 24);
}
function UInt16(str, pos) {
return str.charCodeAt(pos++) + (str.charCodeAt(pos++) << 8);
}
function Umul32(n, m) {
n = n | 0;
m = m | 0;
let nlo = n & 65535;
let nhi = n >>> 16;
let res = nlo * m + ((nhi * m & 65535) << 16) | 0;
return res;
}
function isObject(item) {
return Boolean(item && typeof item === "object" && !Array.isArray(item));
}
function mergeDeep(target) {
for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
sources[_key - 1] = arguments[_key];
}
if (!sources.length) return target;
const source = sources.shift();
if (isObject(target) && isObject(source)) {
for (const key in source) {
if (isObject(source[key])) {
if (!target[key]) Object.assign(target, {
[key]: {}
});
mergeDeep(target[key], source[key]);
} else {
Object.assign(target, {
[key]: source[key]
});
}
}
}
return mergeDeep.apply(void 0, [target].concat(sources));
}
function isPlainObject(obj) {
if (typeof obj !== "object" || obj === null) return false;
let proto = obj;
while (Object.getPrototypeOf(proto) !== null) {
proto = Object.getPrototypeOf(proto);
}
return Object.getPrototypeOf(obj) === proto;
}
function isSelector(key) {
let possibles = [":", ".", "[", ">", " "], found = false, ch = key.charAt(0);
for (let i = 0; i < possibles.length; i++) {
if (ch === possibles[i]) {
found = true;
break;
}
}
return found || key.indexOf("&") >= 0;
}
var selectorTokenizer = /[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g;
function splitSelector(selector) {
if (selector.indexOf(",") === -1) {
return [selector];
}
var indices = [], res = [], inParen = 0, o;
while (o = selectorTokenizer.exec(selector)) {
switch (o[0]) {
case "(":
inParen++;
break;
case ")":
inParen--;
break;
case ",":
if (inParen) break;
indices.push(o.index);
}
}
for (o = indices.length; o--; ) {
res.unshift(selector.slice(indices[o] + 1));
selector = selector.slice(0, indices[o]);
}
res.unshift(selector);
return res;
}
function joinSelectors(a, b) {
let as = splitSelector(a);
let bs = splitSelector(b).map((b2) => !(b2.indexOf("&") >= 0) ? "&" + b2 : b2);
return bs.reduce((arr, b2) => arr.concat(as.map((a2) => b2.replace(/\&/g, a2))), []).join(",");
}
function joinMediaQueries(a, b) {
return a ? "@media " + a.substring(6) + " and " + b.substring(6) : b;
}
function isMediaQuery(key) {
return key.indexOf("@media") === 0;
}
function isKeyframes(key) {
return key.indexOf("@keyframes") === 0;
}
function isGlobal(key) {
return key.indexOf("@global") === 0;
}
function build(selector, _ref) {
var _a2;
let rules = _ref.rules, mediaQuery = _ref.mediaQuery, globalSelector = _ref.globalSelector;
let css2 = {};
if (globalSelector) selector = globalSelector;
(_a2 = Object.keys(rules)) == null ? void 0 : _a2.forEach((key) => {
if (isGlobal(key)) {
const rawKey = key;
key = key.substring(8);
const selfKey = key.indexOf("&");
let _selector;
if (selfKey != -1) {
_selector = joinSelectors(selector, key);
globalSelector = key.substring(0, selfKey - 1).trim();
} else {
_selector = key;
}
mergeDeep(css2, build(_selector, {
mediaQuery,
rules: rules[rawKey],
globalSelector: _selector
}));
} else if (isSelector(key)) {
mergeDeep(css2, build(joinSelectors(selector, key), {
rules: rules[key],
mediaQuery
}));
} else if (isMediaQuery(key)) {
mergeDeep(css2, build(selector, {
mediaQuery: joinMediaQueries(mediaQuery, key),
rules: rules[key]
}));
} else {
if (mediaQuery) {
var _css2$mediaQuery, _css2$mediaQuery2, _selector2, _css2$mediaQuery2$_se;
(_css2$mediaQuery = css2[mediaQuery]) !== null && _css2$mediaQuery !== void 0 ? _css2$mediaQuery : css2[mediaQuery] = {};
(_css2$mediaQuery2$_se = (_css2$mediaQuery2 = css2[mediaQuery])[_selector2 = selector]) !== null && _css2$mediaQuery2$_se !== void 0 ? _css2$mediaQuery2$_se : _css2$mediaQuery2[_selector2] = {};
css2[mediaQuery][selector][key] = rules[key];
} else {
if (isKeyframes(key)) {
css2[key] = rules[key];
} else {
var _selector3, _css2$_selector;
(_css2$_selector = css2[_selector3 = selector]) !== null && _css2$_selector !== void 0 ? _css2$_selector : css2[_selector3] = {};
css2[selector][key] = rules[key];
}
}
}
});
return css2;
}
function deepStyleString(style) {
let v = [];
for (const key in style) {
if (Object.hasOwnProperty.call(style, key)) {
const element = style[key];
if (isObject(element)) {
v.push(key + "{" + deepStyleString(element) + "}");
} else {
v.push(key + ":" + element);
}
}
}
return /^\d%/.test(v[0]) ? v.join(" ") : v.join(";");
}
function styleString(style) {
let str = [];
for (const key in style) {
if (Object.hasOwnProperty.call(style, key)) {
const element = style[key];
if (isMediaQuery(key)) {
str.push(key + "{" + styleString(element) + "}");
} else if (isKeyframes(key)) {
str.push(key + "{" + deepStyleString(element) + "}");
} else {
const v = Object.entries(element).map((_ref2) => {
let k = _ref2[0], v2 = _ref2[1];
return k + ":" + v2;
}).join(";");
str.push(key + "{" + v + "}");
}
}
}
return str;
}
function css(css2, selector) {
return styleString(build(selector, {
rules: css2
}));
}
var $;
(($2) => {
$2.create = function(t) {
let attrs = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
let tpl = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "";
const isIdSelector = t.indexOf("#") !== -1;
const isClassSelector = t.indexOf(".") !== -1;
const _ref3 = isIdSelector ? t.split("#") : isClassSelector ? t.split(".") : [t], tag = _ref3[0], selector = _ref3[1];
const dom = document.createElement(tag);
if (isIdSelector) dom.id = selector;
if (isClassSelector) dom.classList.add(selector);
tpl && (dom.innerHTML = tpl);
Object.keys(attrs).forEach((key) => {
const attr = attrs[key];
if ((tag === "video" || tag === "audio") && typeof attr === "boolean") {
attr && dom.setAttribute(key, "");
} else {
if (typeof attr !== "undefined") {
dom.setAttribute(key, "" + attr);
}
}
});
return dom;
};
$2.render = (elm, container) => {
return container.appendChild(elm);
};
$2.isBrowser = () => Boolean(typeof globalThis !== "undefined" && globalThis.document && globalThis.document.documentElement);
function createSheet(key) {
if (!(0, $2.isBrowser)()) return null;
let tag = document.createElement("style");
tag.setAttribute("data-" + key, "");
tag.appendChild(document.createTextNode(""));
(document.head || document.getElementsByTagName("head")[0]).appendChild(tag);
for (let i = 0; i < document.styleSheets.length; i++) {
if (document.styleSheets[i].ownerNode === tag) {
return document.styleSheets.item(i);
}
}
return null;
}
$2.createSheet = createSheet;
const createSelector = /* @__PURE__ */ (() => {
const cachedCss = /* @__PURE__ */ Object.create({});
return (s) => {
const key = typeof s == "object" ? JSON.stringify(s) : s;
if (!cachedCss[key]) {
cachedCss[key] = "css-" + hashify(key);
}
return cachedCss[key];
};
})();
$2.createCss = (_ref4) => {
let sheet = _ref4.sheet, ssrData = _ref4.ssrData;
return function() {
var _a2;
for (var _len2 = arguments.length, arg = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
arg[_key2] = arguments[_key2];
}
const isRaw = Boolean(arg[0] && arg[0].length && arg[0].raw);
let stringify = "";
if (isRaw) {
let strings = arg[0];
stringify += strings[0];
for (let i = 1; i < arg.length; i++) {
stringify += typeof arg[i] !== "string" ? "" : arg[i];
stringify += strings[i];
}
} else if (typeof arg[0] == "string") {
stringify = arg[0];
} else {
stringify = JSON.stringify(arg[0]);
}
const cls2 = createSelector(stringify);
if (sheet) {
for (let i = 0; i < sheet.cssRules.length; i++) {
if (((_a2 = sheet.cssRules[i]) == null ? void 0 : _a2.selectorText) == "." + cls2) {
return cls2;
}
}
}
let styles = ["." + cls2 + "{" + stringify + "}"];
if (!isRaw && typeof arg[0] == "object") {
styles = css(arg[0], "." + cls2);
}
if (sheet) {
styles.forEach((rule) => {
sheet.insertRule(rule, sheet.cssRules.length);
});
} else {
ssrData = ssrData.concat(styles);
}
return cls2;
};
};
$2.createStyled = () => {
const ssrData = [];
const sheet = createSheet("oplayer");
return {
css: (0, $2.createCss)({
sheet,
ssrData
}),
getCssValue: () => ssrData
};
};
var _ref5 = (0, $2.createStyled)();
$2.css = _ref5.css;
$2.getCssValue = _ref5.getCssValue;
$2.cls = (str) => "css-" + hashify(str);
})($ || ($ = {}));
const $$1 = $;
const isiPad = /(iPad)/gi.test((_a = globalThis.navigator) == null ? void 0 : _a.userAgent) || // chrome
/Macintosh/i.test((_b = globalThis.navigator) == null ? void 0 : _b.userAgent) && // safari - iPad on iOS 13 detection
Boolean((_c = globalThis.navigator) == null ? void 0 : _c.maxTouchPoints) && ((_d = globalThis.navigator) == null ? void 0 : _d.maxTouchPoints) >= 1;
const isiPhone = /iPhone/gi.test((_e = globalThis.navigator) == null ? void 0 : _e.userAgent);
const isSafari = /^((?!chrome|android).)*safari/i.test((_f = globalThis.navigator) == null ? void 0 : _f.userAgent);
const isIOS = isiPhone || isiPad;
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i.test((_g = globalThis.navigator) == null ? void 0 : _g.userAgent) || isIOS;
const isQQBrowser = /mqqbrowser/i.test((_h = globalThis.navigator) == null ? void 0 : _h.userAgent) && !/ qq/i.test((_i = globalThis.navigator) == null ? void 0 : _i.userAgent);
const loadScript = (src, onLoad, onError) => {
var _a2;
const script = document.createElement("script");
script.src = src;
script.onload = onLoad;
script.onerror = onError;
const firstScriptTag = document.getElementsByTagName("script")[0];
(_a2 = firstScriptTag == null ? void 0 : firstScriptTag.parentNode) == null ? void 0 : _a2.insertBefore(script, firstScriptTag);
};
const pendingSDKRequests = {};
const isUndefined = (value) => typeof value === "undefined";
const loadSDK = function(url, sdkGlobalVar, sdkReadyVar) {
let isLoaded = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : () => true;
let loadScriptFn = arguments.length > 4 && arguments[4] !== void 0 ? arguments[4] : loadScript;
const getGlobal = (key) => {
if (!isUndefined(window[key])) return window[key];
if (window.exports && window.exports[key]) return window.exports[key];
if (window.module && window.module.exports && window.module.exports[key]) {
return window.module.exports[key];
}
return void 0;
};
const existingGlobal = getGlobal(sdkGlobalVar);
if (existingGlobal && isLoaded(existingGlobal)) {
return Promise.resolve(existingGlobal);
}
return new Promise((resolve, reject) => {
if (!isUndefined(pendingSDKRequests[url])) {
pendingSDKRequests[url].push({
resolve,
reject
});
return;
}
pendingSDKRequests[url] = [{
resolve,
reject
}];
const onLoaded = (sdk) => {
var _a2;
(_a2 = pendingSDKRequests[url]) == null ? void 0 : _a2.forEach((request) => request.resolve(sdk));
};
if (!isUndefined(sdkReadyVar)) {
const previousOnReady = window[sdkReadyVar];
window[sdkReadyVar] = function() {
if (!isUndefined(previousOnReady)) previousOnReady.apply(void 0, arguments);
onLoaded(getGlobal(sdkGlobalVar));
};
}
loadScriptFn(url, () => {
if (isUndefined(sdkReadyVar)) onLoaded(getGlobal(sdkGlobalVar));
}, (e) => {
var _a2;
(_a2 = pendingSDKRequests[url]) == null ? void 0 : _a2.forEach((request) => {
request.reject(e);
});
delete pendingSDKRequests[url];
});
});
};
const VIDEO_EVENTS = ["abort", "canplay", "canplaythrough", "durationchange", "emptied", "ended", "error", "loadeddata", "loadedmetadata", "loadstart", "pause", "play", "playing", "progress", "ratechange", "seeked", "seeking", "stalled", "suspend", "timeupdate", "volumechange", "waiting", "encrypted", "waitingforkey", "enterpictureinpicture", "leavepictureinpicture"];
const PLAYER_EVENTS = ["contextmenu"];
const OH_EVENTS = [
"loadedplugin",
"videoqualitychange",
"videosourcechange",
// 'posterchange',
"destroy"
];
[].concat(VIDEO_EVENTS, PLAYER_EVENTS, OH_EVENTS);
class EventEmitter {
constructor() {
this.events = /* @__PURE__ */ Object.create(null);
}
on(name, callback) {
if (!this.events[name]) {
this.events[name] = [];
}
this.events[name].push(callback);
}
onAny(names, callback) {
names.forEach((name) => this.on(name, callback));
}
once(name, callback) {
const once = (event) => {
callback({
type: name,
payload: event.payload
});
};
once.raw = callback;
this.on(name, once);
}
off(name, callback) {
if (!this.events[name]) return;
for (let i = 0; i < this.events[name].length; i++) {
const queue = this.events[name][i];
if (queue == callback || callback == queue.raw) {
this.events[name].splice(i, 1);
}
}
}
offAny(name) {
this.events[name] = [];
}
offAll() {
this.events = /* @__PURE__ */ Object.create(null);
}
emit(name, payload) {
var _a2, _b2;
const onceOffQueue = [];
(_a2 = this.events[name]) == null ? void 0 : _a2.forEach((callback) => {
callback({
type: name,
payload
});
if (callback.raw) onceOffQueue.push(callback);
});
(_b2 = this.events["*"]) == null ? void 0 : _b2.forEach((callback) => {
callback({
type: name,
payload
});
if (callback.raw) onceOffQueue.push(callback);
});
onceOffQueue.forEach((it) => {
this.off(name, it);
});
}
}
const Play$2 = "播放";
const Pause$2 = "暂停";
const Loop$2 = "循环播放";
const Volume$2 = "音量";
const Mute$2 = "静音";
const Speed$2 = "播放速度";
const LIVE$2 = "直播";
const Language$2 = "语言";
const Screenshot$2 = "截图";
const Subtitle$2 = "字幕";
const Quality$2 = "画质";
const Fullscreen$2 = "全屏";
const Settings$2 = "设置";
const Danmaku$2 = "弹幕";
const Display$2 = "显示";
const Opacity$2 = "透明度";
const FontSize$2 = "字体大小";
const Off$2 = "关闭";
const Auto$2 = "自动";
const Default$2 = "默认";
const Normal$2 = "正常";
const Close$2 = "关闭";
const CN = {
Play: Play$2,
Pause: Pause$2,
Loop: Loop$2,
Volume: Volume$2,
"Volume: %s": "音量:%s",
Mute: Mute$2,
Speed: Speed$2,
LIVE: LIVE$2,
Language: Language$2,
Screenshot: Screenshot$2,
Subtitle: Subtitle$2,
Quality: Quality$2,
Fullscreen: Fullscreen$2,
Settings: Settings$2,
"Picture in Picture": "画中画",
Danmaku: Danmaku$2,
Display: Display$2,
Opacity: Opacity$2,
FontSize: FontSize$2,
"Display Area": "显示区域",
Off: Off$2,
Auto: Auto$2,
Default: Default$2,
Normal: Normal$2,
"%ss": "%s秒",
Close: Close$2,
"Can be closed after %ss": "%s秒后可关闭广告"
};
const Play$1 = "پخش";
const Next$1 = "بعدی";
const Previous$1 = "قبلی";
const Pause$1 = "توقف";
const Loop$1 = "تکرار";
const Volume$1 = "حجم صدا";
const Mute$1 = "بیصدا کردن";
const Speed$1 = "سرعت";
const LIVE$1 = "زنده";
const WebFullscreen$1 = "تمام صفحه وب";
const Chromecast$1 = "کروم کاست";
const AirPlay$1 = "ایر پلی";
const Playlist$1 = "پلیلیست";
const Heatmap$1 = "نقشهٔ حرارتی";
const Language$1 = "زبان";
const Screenshot$1 = "عکس صفحه";
const Subtitle$1 = "زیرنویس";
const Quality$1 = "کیفیت";
const Fullscreen$1 = "تمام صفحه";
const Settings$1 = "تنظیمات";
const Danmaku$1 = "دانماکو";
const Display$1 = "نمایش";
const Opacity$1 = "شفافیت";
const FontSize$1 = "اندازه فونت";
const Off$1 = "خاموش";
const Auto$1 = "خودکار";
const Default$1 = "پیشفرض";
const Normal$1 = "عادی";
const Close$1 = "بستن";
const FA = {
Play: Play$1,
Next: Next$1,
Previous: Previous$1,
Pause: Pause$1,
Loop: Loop$1,
Volume: Volume$1,
"Volume: %s": "حجم صدا: %s",
Mute: Mute$1,
Speed: Speed$1,
LIVE: LIVE$1,
WebFullscreen: WebFullscreen$1,
Chromecast: Chromecast$1,
AirPlay: AirPlay$1,
Playlist: Playlist$1,
Heatmap: Heatmap$1,
Language: Language$1,
Screenshot: Screenshot$1,
Subtitle: Subtitle$1,
Quality: Quality$1,
Fullscreen: Fullscreen$1,
Settings: Settings$1,
"Picture in Picture": "تصویر در تصویر",
Danmaku: Danmaku$1,
Display: Display$1,
Opacity: Opacity$1,
FontSize: FontSize$1,
"Display Area": "ناحیه نمایش",
Off: Off$1,
Auto: Auto$1,
Default: Default$1,
Normal: Normal$1,
"%ss": "%s ثانیه",
Close: Close$1,
"Can be closed after %ss": "قابل بستن پس از %s ثانیه"
};
const Play = "پلېکول";
const Next = "بل";
const Previous = "مخکېنی";
const Pause = "تم کول";
const Loop = "تکرار";
const Volume = "غږ";
const Mute = "غلی کول";
const Speed = "چټکتیا";
const LIVE = "ژوندی";
const WebFullscreen = "د تمام صفحه وب";
const Chromecast = "کروم کاسټ";
const AirPlay = "ایر پلی";
const Playlist = "پلېلسټ";
const Heatmap = "د ډېرو کتلو نقشه";
const Language = "ژبه";
const Screenshot = "سکرین شاټ";
const Subtitle = "لاندې لیک";
const Quality = "کیفیت";
const Fullscreen = "پوره پرده";
const Settings = "ترتیبات";
const Danmaku = "دانماکو";
const Display = "ښکاره کول";
const Opacity = "روڼوالی";
const FontSize = "د خط اندازه";
const Off = "بند";
const Auto = "خودکار";
const Default = "پېل شوی";
const Normal = "عادي";
const Close = "بندول";
const PA = {
Play,
Next,
Previous,
Pause,
Loop,
Volume,
"Volume: %s": "غږ: %s",
Mute,
Speed,
LIVE,
WebFullscreen,
Chromecast,
AirPlay,
Playlist,
Heatmap,
Language,
Screenshot,
Subtitle,
Quality,
Fullscreen,
"": "د متن ډیکوډر ملاتړ نه لري",
Settings,
"Picture in Picture": "انځور په انځور",
Danmaku,
Display,
Opacity,
FontSize,
"Display Area": "د ښودلو ساحه",
Off,
Auto,
Default,
Normal,
"%ss": "%s ثانیه",
Close,
"Can be closed after %ss": "د %s ثانیو وروسته تړل کېدای شي"
};
class I18n {
constructor(defaultLang) {
this.languages = {
zh: CN,
"zh-CN": CN,
fa: FA,
pa: PA,
en: Object.keys(CN).reduce((previous, current) => (previous[current] = current, previous), {})
};
this.lang = defaultLang === "auto" ? navigator.language : defaultLang;
if (!this.languages[this.lang]) {
navigator.languages.some((lang) => {
if (this.languages[lang]) {
this.lang = lang;
return true;
}
if (lang.indexOf("-") !== -1) {
const short = lang.split("-")[0];
if (short && this.languages[short]) {
this.lang = short;
return true;
}
}
return false;
});
}
if (!this.languages[this.lang]) this.lang = "en";
}
get(key) {
for (var _len3 = arguments.length, arg = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
arg[_key3 - 1] = arguments[_key3];
}
const result = this.languages[this.lang][key];
if (result == void 0) return key;
let i = 0;
return result.replace(/%s/gi, () => {
var _arg$i;
return (_arg$i = arg[i++]) !== null && _arg$i !== void 0 ? _arg$i : "";
});
}
update(languages) {
mergeDeep(this.languages, languages);
}
}
const defaultOptions = {
autoplay: false,
muted: false,
loop: false,
volume: 1,
preload: "metadata",
playbackRate: 1,
playsinline: true,
lang: "auto",
source: {},
videoAttr: {},
isLive: false,
autopause: true,
isNativeUI: () => isQQBrowser
};
const _Player = class _Player {
constructor(el, options) {
this.plugins = [];
this.context = {};
this.listeners = /* @__PURE__ */ Object.create(null);
this.hasError = false;
this.isSourceChanging = false;
this.container = typeof el == "string" ? document.querySelector(el) : el;
if (!this.container) throw new Error((typeof el == "string" ? el : "Element") + "does not exist");
this.options = Object.assign({}, defaultOptions, typeof options === "string" ? {
source: {
src: options
}
} : options);
this.locales = new I18n(this.options.lang);
this.eventEmitter = new EventEmitter();
}
static make(el, options) {
return new _Player(el, options);
}
use(plugins) {
plugins.forEach((plugin) => {
this.plugins.push(plugin);
});
return this;
}
create() {
this.render();
this.initEvent();
this.plugins.forEach((plugin) => this.applyPlugin(plugin, true));
if (this.options.source.src) this.load(this.options.source);
_Player.players.push(this);
return this;
}
initEvent() {
const errorHandler = (payload) => {
if (this.$video.error) {
this.hasError = true;
this.eventEmitter.emit("error", payload);
}
};
this.listeners["error"] = errorHandler;
this.$video.addEventListener("error", (e) => this.listeners["error"](e));
const eventHandler = (eventName, payload) => {
this.eventEmitter.emit(eventName, payload);
};
[[this.$video, ["fullscreenchange", "webkitbeginfullscreen", "webkitendfullscreen"], ["fullscreenerror", "webkitfullscreenerror", "mozfullscreenerror"]], [this.$root, ["fullscreenchange", "webkitfullscreenchange"], ["fullscreenerror", "webkitfullscreenerror", "mozfullscreenerror"]]].forEach((it) => {
const target = it[0], eventNames = it.slice(1);
eventNames.forEach((eventName) => {
const polyfillName = eventName[0];
this.listeners[polyfillName] = eventHandler;
eventName.forEach((name) => {
target.addEventListener(name, (e) => {
this.listeners[polyfillName](polyfillName, e);
}, {
passive: true
});
});
});
});
[[this.$video, VIDEO_EVENTS], [this.$root, PLAYER_EVENTS]].forEach((_ref6) => {
let target = _ref6[0], events = _ref6[1];
events.forEach((eventName) => {
if (!this.listeners[eventName]) {
this.listeners[eventName] = eventHandler;
target.addEventListener(eventName, (e) => {
var _a2;
(_a2 = this.listeners) == null ? void 0 : _a2[eventName](eventName, e);
}, {
passive: true
});
}
});
});
}
render() {
this.$video = $$1.create("video." + $$1.css("\n width: 100%;\n height: 100%;\n display: block;\n position: relative;\n "), Object.assign({
autoplay: this.options.autoplay,
loop: this.options.loop,
playsinline: this.options.playsinline,
"webkit-playsinline": this.options.playsinline,
"x5-playsinline": this.options.playsinline,
preload: this.options.preload,
poster: this.options.source.poster
}, this.options.videoAttr));
const _this$options = this.options, muted = _this$options.muted, volume = _this$options.volume, playbackRate = _this$options.playbackRate;
if (!!muted) this.mute();
this.$video.volume = volume;
setTimeout(() => {
if (this.$root) this.setPlaybackRate(playbackRate);
});
this.$root = $$1.create("div." + $$1.css("\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n background-color: #000;\n "));
$$1.render(this.$video, this.$root);
$$1.render(this.$root, this.container);
}
async load(source) {
var _a2;
await ((_a2 = this.loader) == null ? void 0 : _a2.destroy());
this.loader = void 0;
for (const plugin of this.plugins) {
if (plugin.load) {
const returned = await plugin.load(this, source);
if (returned != false && !this.loader) {
this.loader = returned;
this.emit("loaderchange", returned);
break;
}
}
}
if (!this.loader) {
this.$video.src = source.src;
}
return source;
}
applyPlugin(plugin) {
let init = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
const name = plugin.name, key = plugin.key;
if (this.context[plugin.key || plugin.name]) {
throw new Error("duplicate plugin");
}
if (!init) this.plugins.push(plugin);
const returned = plugin.apply(this);
if (returned) {
this.context[key || name] = returned;
}
}
on(name, listener) {
if (typeof name === "string") {
this.eventEmitter.on(name, listener);
} else if (Array.isArray(name)) {
this.eventEmitter.onAny(name, listener);
} else if (typeof name === "function") {
this.eventEmitter.on("*", name);
}
return this;
}
once(name, listener) {
this.eventEmitter.once(name, listener);
}
off(name, listener) {
this.eventEmitter.off(name, listener);
}
emit(name, payload) {
this.eventEmitter.emit(name, payload);
}
setPoster(poster) {
this.$video.poster = poster;
}
play() {
if (!this.$video.src && !this.$video.currentSrc || this.isSourceChanging) return;
if (this.options.autopause) {
for (let i = 0; i < _Player.players.length; i++) {
const player = _Player.players[i];
if (player != this) player.pause();
}
}
return this.$video.play();
}
pause() {
return this.$video.pause();
}
togglePlay() {
if (this.isPlaying) {
return this.pause();
} else {
return this.play();
}
}
mute() {
this.$video.muted = true;
}
unmute() {
this.$video.muted = false;
}
toggleMute() {
if (this.isMuted) {
this.unmute();
} else {
this.mute();
}
}
setVolume(volume) {
this.$video.volume = volume > 1 ? 1 : volume < 0 ? 0 : volume;
if (this.$video.volume > 0 && this.isMuted) {
this.unmute();
}
}
setPlaybackRate(rate) {
this.$video.playbackRate = rate;
}
seek(time) {
this.$video.currentTime = time;
}
setLoop(loop) {
this.$video.loop = loop;
}
async enterFullscreen() {
if (this.isInPip) await this.exitPip();
if (this._requestFullscreen) {
this._requestFullscreen.call(this.$root, {
navigationUI: "hide"
});
} else {
this.$video.webkitEnterFullscreen();
}
}
exitFullscreen() {
return this._exitFullscreen.call(document);
}
get isFullscreenEnabled() {
return document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled || this.$video.webkitEnterFullscreen;
}
get isFullScreen() {
return Boolean((document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) === this.$root || //ios
this.$video.webkitDisplayingFullscreen);
}
toggleFullScreen() {
if (this.isFullScreen) {
return this.exitFullscreen();
} else {
return this.enterFullscreen();
}
}
get isPipEnabled() {
return document.pictureInPictureEnabled;
}
enterPip() {
return this.$video.requestPictureInPicture();
}
exitPip() {
if (this.isInPip) {
return document.exitPictureInPicture();
}
return false;
}
get isInPip() {
return document.pictureInPictureElement == this.$video;
}
togglePip() {
if (this.isInPip) {
return this.exitPip();
} else {
return this.enterPip();
}
}
changeQuality(source) {
return this._loader(source, {
keepPlaying: true,
keepTime: true,
preEvent: "videoqualitychange",
event: "videoqualitychanged",
brokenEvent: "qualitychangeerror"
});
}
changeSource(source) {
let keepPlaying = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
return this._loader(source, {
keepPlaying,
preEvent: "videosourcechange",
event: "videosourcechanged",
brokenEvent: "sourcechangeerror"
});
}
_loader(sourceLike, options) {
return new Promise((resolve, reject) => {
if (this.isSourceChanging) return reject(Error("Previous Source is Changing."));
const isPlaying = this.isPlaying, currentTime = this.currentTime, volume = this.volume, playbackRate = this.playbackRate;
this.pause();
this.hasError = false;
this.isSourceChanging = true;
this.emit(options.preEvent, sourceLike);
const keepPlaying = options.keepPlaying, keepTime = options.keepTime;
const isPreloadNone = this.options.preload == "none";
const canplay = isPreloadNone ? "loadstart" : "loadedmetadata";
const shouldPlay = keepPlaying && isPlaying;
let finalSource;
const errorHandler = (err) => {
if (!this.$root) return;
this.off(canplay, canplayHandler);
this.emit(options.brokenEvent, {
source: finalSource || sourceLike,
error: err
});
if (options.event == "videosourcechanged") {
this.isSourceChanging = false;
} else {
this.load(this.options.source).then(rollback).finally(() => {
this.isSourceChanging = false;
});
}
reject(err);
};
const rollback = () => {
if (volume != this.volume) this.setVolume(volume);
if (playbackRate != this.playbackRate) this.setPlaybackRate(playbackRate);
if (isPreloadNone && keepTime) this.$video.load();
if (keepTime && !this.options.isLive) this.seek(currentTime);
if (shouldPlay && !this.isPlaying) this.$video.play();
Object.assign(this.options.source, finalSource);
};
const canplayHandler = () => {
if (!this.$root) return;
this.off("error", errorHandler);
rollback();
this.isSourceChanging = false;
this.emit(options.event, finalSource);
resolve();
};
return (sourceLike instanceof Promise ? sourceLike : Promise.resolve(sourceLike)).then((source) => {
if (!source.src) throw new Error("Empty Source");
finalSource = source;
this.$video.poster = source.poster || "";
this.once("error", errorHandler);
this.once(canplay, canplayHandler);
return source;
}).then((source) => this.load(source)).catch(errorHandler);
});
}
destroy() {
_Player.players.splice(_Player.players.indexOf(this), 1);
const eventEmitter = this.eventEmitter, loader = this.loader, plugins = this.plugins, container = this.container, $root = this.$root, $video = this.$video, isPlaying = this.isPlaying, isFullScreen = this.isFullScreen, isInPip = this.isInPip;
eventEmitter.emit("destroy");
eventEmitter.offAll();
loader == null ? void 0 : loader.destroy();
plugins.forEach((it) => {
var _a2;
return !it.load && ((_a2 = it.destroy) == null ? void 0 : _a2.call(it));
});
if (isPlaying) this.pause();
if (isFullScreen) this.exitFullscreen();
if (isInPip) this.exitPip();
if ($video.src) URL.revokeObjectURL($video.src);
container.removeChild($root);
this.eventEmitter = this.locales = this.options = this.listeners = this.context = this.plugins = this.container = this.$root = this.$video = this.loader = void 0;
}
get isNativeUI() {
return this.options.isNativeUI();
}
get state() {
return this.$video.readyState;
}
get isPlaying() {
return !this.$video.paused;
}
get isMuted() {
return this.$video.muted;
}
get isEnded() {
return this.$video.ended;
}
get isLoop() {
return this.$video.loop;
}
get isAutoPlay() {
return this.$video.autoplay;
}
get duration() {
return this.$video.duration;
}
get buffered() {
return this.$video.buffered;
}
get currentTime() {
return this.$video.currentTime;
}
get volume() {
return this.$video.volume;
}
get playbackRate() {
return this.$video.playbackRate;
}
get _requestFullscreen() {
return HTMLElement.prototype.requestFullscreen || HTMLElement.prototype.webkitRequestFullscreen || HTMLElement.prototype.mozRequestFullScreen || HTMLElement.prototype.msRequestFullscreen;
}
get _exitFullscreen() {
return Document.prototype.exitFullscreen || Document.prototype.webkitExitFullscreen || Document.prototype.cancelFullScreen || Document.prototype.mozCancelFullScreen || Document.prototype.msExitFullscreen;
}
static get version() {
return "1.2.38-beta.2";
}
};
_Player.players = [];
let Player = _Player;
if (globalThis.window) {
console.log("%cOPlayer%c v%s\n %c\nOh! Another HTML5 video player.\nhttps://github.com/shiyiya/oplayer\n", "font-size:32px;", "font-size:12px;color:#999999;", Player.version, "font-size:14px;");
}
export {
$,
Player,
Player as default,
isIOS,
isMobile,
isObject,
isPlainObject,
isQQBrowser,
isSafari,
isUndefined,
isiPad,
isiPhone,
loadSDK,
loadScript,
mergeDeep
};