@oddin-gg/havik-player 1.6.3 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/havik-player.global.js +2 -2
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +213 -186
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -95,27 +95,27 @@ function g(e) {
|
|
|
95
95
|
ceilMs: r,
|
|
96
96
|
imminentMs: i,
|
|
97
97
|
sanityFloorMs: a,
|
|
98
|
-
kickoffMs:
|
|
98
|
+
kickoffMs: ee(t.kickoffAt),
|
|
99
99
|
jitter: t.jitter ?? !0,
|
|
100
100
|
onState: t.onState
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
|
-
function
|
|
103
|
+
function ee(e) {
|
|
104
104
|
if (e == null) return;
|
|
105
105
|
if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
|
|
106
106
|
let t = Date.parse(e);
|
|
107
107
|
return Number.isFinite(t) ? t : void 0;
|
|
108
108
|
}
|
|
109
|
-
function
|
|
109
|
+
function te(e, t, n) {
|
|
110
110
|
return Math.min(n, Math.max(t, e));
|
|
111
111
|
}
|
|
112
|
-
function
|
|
112
|
+
function ne(e) {
|
|
113
113
|
return Math.round(e * (1 + .15 * Math.random()));
|
|
114
114
|
}
|
|
115
|
-
function
|
|
115
|
+
function _(e, t, n, r) {
|
|
116
116
|
let i = r ?? n.kickoffMs, a = i == null ? void 0 : Math.max(0, i - t), o = Math.max(n.floorMs, e ?? 0);
|
|
117
117
|
if (a == null || a <= n.imminentMs) return {
|
|
118
|
-
delay:
|
|
118
|
+
delay: te(e ?? n.floorMs, o, n.ceilMs),
|
|
119
119
|
ttkMs: a
|
|
120
120
|
};
|
|
121
121
|
let s = Math.min(Math.floor(a / 10), n.sanityFloorMs, a);
|
|
@@ -147,8 +147,8 @@ async function v(e, n, r) {
|
|
|
147
147
|
} catch (e) {
|
|
148
148
|
if (!(e instanceof t) || !i(e.code)) throw e;
|
|
149
149
|
c += 1, e.liveStartsAtMs != null && Number.isFinite(e.liveStartsAtMs) && (l = e.liveStartsAtMs);
|
|
150
|
-
let n = Date.now(), u =
|
|
151
|
-
if (a.jitter && (f =
|
|
150
|
+
let n = Date.now(), u = _(e.retryAfterMs, n, a, l), d = u.ttkMs, f = u.delay;
|
|
151
|
+
if (a.jitter && (f = ne(f)), n + f > s) throw new t("TIMEOUT", e.httpStatus, `timed out after ${a.timeoutMs}ms waiting for the stream to go live`, {
|
|
152
152
|
retryAfterMs: e.retryAfterMs,
|
|
153
153
|
cause: e
|
|
154
154
|
});
|
|
@@ -171,7 +171,7 @@ async function y(e) {
|
|
|
171
171
|
signal: e.signal
|
|
172
172
|
});
|
|
173
173
|
if (!n.ok) throw await ie(n);
|
|
174
|
-
return
|
|
174
|
+
return C(await n.json(), e.matchUrn);
|
|
175
175
|
}
|
|
176
176
|
function b(e) {
|
|
177
177
|
let t = () => y(e);
|
|
@@ -193,7 +193,7 @@ async function ie(e) {
|
|
|
193
193
|
liveStartsAtMs: c
|
|
194
194
|
});
|
|
195
195
|
}
|
|
196
|
-
var
|
|
196
|
+
var x = /* @__PURE__ */ new Set([
|
|
197
197
|
"matchUrn",
|
|
198
198
|
"protocol",
|
|
199
199
|
"drmEnabled",
|
|
@@ -203,7 +203,7 @@ var ae = /* @__PURE__ */ new Set([
|
|
|
203
203
|
"liveStartsAt",
|
|
204
204
|
"expiresAt"
|
|
205
205
|
]);
|
|
206
|
-
function
|
|
206
|
+
function S(e, n) {
|
|
207
207
|
let r;
|
|
208
208
|
try {
|
|
209
209
|
r = new URL(n);
|
|
@@ -213,29 +213,29 @@ function x(e, n) {
|
|
|
213
213
|
if (r.protocol !== "https:" && r.protocol !== "http:") throw new t("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
|
|
214
214
|
return n;
|
|
215
215
|
}
|
|
216
|
-
function
|
|
216
|
+
function C(e, n) {
|
|
217
217
|
if (!e.manifestUrl) throw new t("INTERNAL", 0, "playback response is missing manifestUrl");
|
|
218
218
|
let r = e.drmEnabled ?? !!e.drm, i = {
|
|
219
219
|
matchUrn: e.matchUrn ?? n,
|
|
220
220
|
protocol: "hls",
|
|
221
221
|
drmEnabled: r,
|
|
222
|
-
manifestUrl:
|
|
222
|
+
manifestUrl: S("manifestUrl", e.manifestUrl),
|
|
223
223
|
serverTime: e.serverTime ?? ""
|
|
224
224
|
};
|
|
225
225
|
if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), r && e.drm) {
|
|
226
226
|
let t = {};
|
|
227
|
-
e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl:
|
|
228
|
-
licenseUrl:
|
|
229
|
-
certificateUrl:
|
|
227
|
+
e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: S("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
|
|
228
|
+
licenseUrl: S("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
|
|
229
|
+
certificateUrl: S("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
|
|
230
230
|
}), (t.widevine || t.fairplay) && (i.drm = t);
|
|
231
231
|
}
|
|
232
232
|
let a = {};
|
|
233
|
-
for (let [t, n] of Object.entries(e))
|
|
233
|
+
for (let [t, n] of Object.entries(e)) x.has(t) || (a[t] = n);
|
|
234
234
|
return Object.keys(a).length > 0 && (i.extensions = a), i;
|
|
235
235
|
}
|
|
236
236
|
//#endregion
|
|
237
237
|
//#region src/core/catalog.ts
|
|
238
|
-
async function
|
|
238
|
+
async function w(e) {
|
|
239
239
|
let r = new URLSearchParams();
|
|
240
240
|
e.status && r.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && r.set("sport", e.sport);
|
|
241
241
|
let i = r.toString(), a = o(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), s = new Headers();
|
|
@@ -252,12 +252,12 @@ async function se(e) {
|
|
|
252
252
|
};
|
|
253
253
|
if (!l.ok) throw new t(n(l.status), l.status, `catalog request failed (HTTP ${l.status})`);
|
|
254
254
|
return {
|
|
255
|
-
tournaments:
|
|
255
|
+
tournaments: ae(await l.json()),
|
|
256
256
|
etag: l.headers.get("etag") ?? void 0,
|
|
257
257
|
notModified: !1
|
|
258
258
|
};
|
|
259
259
|
}
|
|
260
|
-
function
|
|
260
|
+
function ae(e) {
|
|
261
261
|
return (e.tournaments ?? []).map((e) => {
|
|
262
262
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
263
263
|
return {
|
|
@@ -277,7 +277,7 @@ function ce(e) {
|
|
|
277
277
|
};
|
|
278
278
|
});
|
|
279
279
|
}
|
|
280
|
-
async function
|
|
280
|
+
async function oe(e) {
|
|
281
281
|
let r = o(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
282
282
|
e.etag && i.set("If-None-Match", e.etag);
|
|
283
283
|
let a = await c(r, {
|
|
@@ -296,13 +296,13 @@ async function le(e) {
|
|
|
296
296
|
};
|
|
297
297
|
if (!a.ok) throw new t(n(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
298
298
|
return {
|
|
299
|
-
tournament:
|
|
299
|
+
tournament: se(await a.json()),
|
|
300
300
|
etag: a.headers.get("etag") ?? void 0,
|
|
301
301
|
notModified: !1,
|
|
302
302
|
notFound: !1
|
|
303
303
|
};
|
|
304
304
|
}
|
|
305
|
-
function
|
|
305
|
+
function se(e) {
|
|
306
306
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
307
307
|
return {
|
|
308
308
|
urn: t,
|
|
@@ -320,12 +320,12 @@ function S(e) {
|
|
|
320
320
|
}))
|
|
321
321
|
};
|
|
322
322
|
}
|
|
323
|
-
function
|
|
323
|
+
function ce(e) {
|
|
324
324
|
return e.tournaments.flatMap((e) => e.matches);
|
|
325
325
|
}
|
|
326
326
|
//#endregion
|
|
327
327
|
//#region src/core/poll.ts
|
|
328
|
-
function
|
|
328
|
+
function le(e) {
|
|
329
329
|
let r = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, s, l, u = !1, d = () => {
|
|
330
330
|
u || (a = setTimeout(f, r));
|
|
331
331
|
}, f = async () => {
|
|
@@ -480,11 +480,11 @@ function fe(e, t, n = {}) {
|
|
|
480
480
|
}
|
|
481
481
|
//#endregion
|
|
482
482
|
//#region src/core/drm/support.ts
|
|
483
|
-
var
|
|
483
|
+
var pe = 5e3, A = "video/mp4; codecs=\"avc1.42E01E\"", j = "audio/mp4; codecs=\"mp4a.40.2\"", M = {
|
|
484
484
|
widevine: ["com.widevine.alpha"],
|
|
485
485
|
fairplay: ["com.apple.fps"]
|
|
486
486
|
};
|
|
487
|
-
function
|
|
487
|
+
function N(e) {
|
|
488
488
|
return e === "fairplay" ? [{
|
|
489
489
|
initDataTypes: [
|
|
490
490
|
"sinf",
|
|
@@ -492,30 +492,30 @@ function P(e) {
|
|
|
492
492
|
"cenc"
|
|
493
493
|
],
|
|
494
494
|
videoCapabilities: [{
|
|
495
|
-
contentType:
|
|
495
|
+
contentType: A,
|
|
496
496
|
robustness: "",
|
|
497
497
|
encryptionScheme: "cbcs"
|
|
498
498
|
}],
|
|
499
499
|
audioCapabilities: [{
|
|
500
|
-
contentType:
|
|
500
|
+
contentType: j,
|
|
501
501
|
robustness: "",
|
|
502
502
|
encryptionScheme: "cbcs"
|
|
503
503
|
}]
|
|
504
504
|
}] : [{
|
|
505
505
|
initDataTypes: ["cenc"],
|
|
506
506
|
videoCapabilities: [{
|
|
507
|
-
contentType:
|
|
507
|
+
contentType: A,
|
|
508
508
|
robustness: "SW_SECURE_DECODE",
|
|
509
509
|
encryptionScheme: "cbcs"
|
|
510
510
|
}],
|
|
511
511
|
audioCapabilities: [{
|
|
512
|
-
contentType:
|
|
512
|
+
contentType: j,
|
|
513
513
|
robustness: "SW_SECURE_CRYPTO",
|
|
514
514
|
encryptionScheme: "cbcs"
|
|
515
515
|
}]
|
|
516
516
|
}];
|
|
517
517
|
}
|
|
518
|
-
function
|
|
518
|
+
function P(e, t) {
|
|
519
519
|
return new Promise((n, r) => {
|
|
520
520
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
521
521
|
e.then((e) => {
|
|
@@ -525,8 +525,8 @@ function F(e, t) {
|
|
|
525
525
|
});
|
|
526
526
|
});
|
|
527
527
|
}
|
|
528
|
-
async function
|
|
529
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
528
|
+
async function F(e = {}) {
|
|
529
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? pe, r = {};
|
|
530
530
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
531
531
|
verdict: "insecure-context",
|
|
532
532
|
detail: r
|
|
@@ -538,7 +538,7 @@ async function I(e = {}) {
|
|
|
538
538
|
};
|
|
539
539
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
540
540
|
for (let e of t) {
|
|
541
|
-
let t =
|
|
541
|
+
let t = M[e];
|
|
542
542
|
if (!t) {
|
|
543
543
|
r[e] = "unknown system";
|
|
544
544
|
continue;
|
|
@@ -549,7 +549,7 @@ async function I(e = {}) {
|
|
|
549
549
|
break;
|
|
550
550
|
}
|
|
551
551
|
try {
|
|
552
|
-
return await
|
|
552
|
+
return await P((await P(i(n, N(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
553
553
|
verdict: "supported",
|
|
554
554
|
system: e,
|
|
555
555
|
detail: r
|
|
@@ -573,17 +573,17 @@ async function I(e = {}) {
|
|
|
573
573
|
}
|
|
574
574
|
//#endregion
|
|
575
575
|
//#region src/core/manifest.ts
|
|
576
|
-
var
|
|
577
|
-
function
|
|
578
|
-
return
|
|
576
|
+
var I = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
577
|
+
function L(e) {
|
|
578
|
+
return I.test(e);
|
|
579
579
|
}
|
|
580
580
|
//#endregion
|
|
581
581
|
//#region src/core/stats.ts
|
|
582
|
-
var
|
|
583
|
-
function
|
|
582
|
+
var R = { droppedFrames: 0 };
|
|
583
|
+
function z(e) {
|
|
584
584
|
return e.getVideoPlaybackQuality?.()?.droppedVideoFrames ?? 0;
|
|
585
585
|
}
|
|
586
|
-
function
|
|
586
|
+
function B(e, t) {
|
|
587
587
|
let n = [
|
|
588
588
|
["playing", () => t("playing")],
|
|
589
589
|
["waiting", () => t("buffering")],
|
|
@@ -600,14 +600,27 @@ function V(e, t) {
|
|
|
600
600
|
}
|
|
601
601
|
//#endregion
|
|
602
602
|
//#region src/core/engine/native.ts
|
|
603
|
-
function
|
|
603
|
+
function me(e) {
|
|
604
|
+
try {
|
|
605
|
+
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
606
|
+
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
607
|
+
} catch {
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
function V(e) {
|
|
604
612
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
605
613
|
}
|
|
606
|
-
var
|
|
614
|
+
var H = class {
|
|
607
615
|
name = "native";
|
|
608
616
|
deps;
|
|
609
617
|
onLoaded;
|
|
610
618
|
onError;
|
|
619
|
+
onEncrypted;
|
|
620
|
+
fairplayLicenseUrl;
|
|
621
|
+
keySession = null;
|
|
622
|
+
fairplayArmed = !1;
|
|
623
|
+
fairplayKeyIV;
|
|
611
624
|
constructor(e) {
|
|
612
625
|
this.deps = e;
|
|
613
626
|
}
|
|
@@ -622,11 +635,7 @@ var U = class {
|
|
|
622
635
|
});
|
|
623
636
|
return;
|
|
624
637
|
}
|
|
625
|
-
|
|
626
|
-
type: "error",
|
|
627
|
-
error: new t("INTERNAL", 0, "the native HLS fallback engine does not drive FairPlay EME; relying on OS-trusted passthrough"),
|
|
628
|
-
fatal: !1
|
|
629
|
-
});
|
|
638
|
+
this.armFairPlay();
|
|
630
639
|
}
|
|
631
640
|
this.onLoaded = () => r({ type: "ready" }), this.onError = () => r({
|
|
632
641
|
type: "error",
|
|
@@ -634,7 +643,65 @@ var U = class {
|
|
|
634
643
|
fatal: !0
|
|
635
644
|
}), e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = n.manifestUrl, e.load();
|
|
636
645
|
}
|
|
637
|
-
|
|
646
|
+
armFairPlay() {
|
|
647
|
+
let { video: e, descriptor: n, credential: r, deviceId: i, userId: a, emit: o } = this.deps, s = n.drm?.fairplay;
|
|
648
|
+
if (!s) return;
|
|
649
|
+
this.fairplayLicenseUrl = s.licenseUrl;
|
|
650
|
+
let c = (e, n, r) => o({
|
|
651
|
+
type: "error",
|
|
652
|
+
error: new t(n === 403 ? "FORBIDDEN" : "INTERNAL", n, e),
|
|
653
|
+
fatal: r
|
|
654
|
+
});
|
|
655
|
+
this.onEncrypted = (t) => {
|
|
656
|
+
let o = t;
|
|
657
|
+
!o.initData || this.fairplayArmed || (this.fairplayArmed = !0, this.fairplayKeyIV = me(o.initData), (async () => {
|
|
658
|
+
try {
|
|
659
|
+
let t = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
660
|
+
initDataTypes: [o.initDataType],
|
|
661
|
+
videoCapabilities: [{
|
|
662
|
+
contentType: "application/vnd.apple.mpegurl",
|
|
663
|
+
robustness: ""
|
|
664
|
+
}],
|
|
665
|
+
distinctiveIdentifier: "not-allowed",
|
|
666
|
+
persistentState: "not-allowed",
|
|
667
|
+
sessionTypes: ["temporary"]
|
|
668
|
+
}])).createMediaKeys(), l = await fetch(s.certificateUrl, { headers: { "x-api-key": r.apiKey } });
|
|
669
|
+
if (!l.ok) throw Error(`certificate ${l.status}`);
|
|
670
|
+
await t.setServerCertificate(await l.arrayBuffer()), await e.setMediaKeys(t);
|
|
671
|
+
let u = t.createSession();
|
|
672
|
+
this.keySession = u, u.addEventListener("message", (e) => {
|
|
673
|
+
(async () => {
|
|
674
|
+
try {
|
|
675
|
+
let t = await fetch(this.fairplayLicenseUrl ?? s.licenseUrl, {
|
|
676
|
+
method: "POST",
|
|
677
|
+
body: e.message,
|
|
678
|
+
headers: {
|
|
679
|
+
"x-api-key": r.apiKey,
|
|
680
|
+
"X-Match-Urn": n.matchUrn,
|
|
681
|
+
"X-Device-Id": i,
|
|
682
|
+
...a ? { "X-User-Id": a } : {},
|
|
683
|
+
...this.fairplayKeyIV ? { "X-Key-Iv": this.fairplayKeyIV } : {}
|
|
684
|
+
}
|
|
685
|
+
});
|
|
686
|
+
if (!t.ok) {
|
|
687
|
+
c(`FairPlay license request failed: ${t.status}`, t.status, !0);
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
await u.update(new Uint8Array(await t.arrayBuffer()));
|
|
691
|
+
} catch (e) {
|
|
692
|
+
c(`FairPlay license request failed: ${String(e)}`, 0, !0);
|
|
693
|
+
}
|
|
694
|
+
})();
|
|
695
|
+
}), await u.generateRequest(o.initDataType, o.initData);
|
|
696
|
+
} catch (e) {
|
|
697
|
+
this.fairplayArmed = !1, c(`FairPlay key session failed: ${String(e)}`, 0, !0);
|
|
698
|
+
}
|
|
699
|
+
})());
|
|
700
|
+
}, e.addEventListener("encrypted", this.onEncrypted);
|
|
701
|
+
}
|
|
702
|
+
setLicenseUrls(e) {
|
|
703
|
+
e.fairplay && (this.fairplayLicenseUrl = e.fairplay);
|
|
704
|
+
}
|
|
638
705
|
getQualityLevels() {
|
|
639
706
|
return [];
|
|
640
707
|
}
|
|
@@ -679,7 +746,7 @@ var U = class {
|
|
|
679
746
|
e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
|
|
680
747
|
}
|
|
681
748
|
getStats() {
|
|
682
|
-
let e = this.deps.video, t = { droppedFrames:
|
|
749
|
+
let e = this.deps.video, t = { droppedFrames: z(e) };
|
|
683
750
|
return e.duration === Infinity && (t.isLive = !0, e.seekable.length > 0 && (t.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)), t;
|
|
684
751
|
}
|
|
685
752
|
stop() {
|
|
@@ -689,7 +756,7 @@ var U = class {
|
|
|
689
756
|
}
|
|
690
757
|
destroy() {
|
|
691
758
|
let { video: e } = this.deps;
|
|
692
|
-
this.onLoaded && e.removeEventListener("loadedmetadata", this.onLoaded), this.onError && e.removeEventListener("error", this.onError);
|
|
759
|
+
this.onLoaded && e.removeEventListener("loadedmetadata", this.onLoaded), this.onError && e.removeEventListener("error", this.onError), this.onEncrypted && e.removeEventListener("encrypted", this.onEncrypted), this.keySession?.close().catch(() => {}), this.keySession = null, this.fairplayArmed = !1, this.fairplayKeyIV = void 0;
|
|
693
760
|
try {
|
|
694
761
|
e.pause();
|
|
695
762
|
} catch {}
|
|
@@ -701,30 +768,28 @@ var U = class {
|
|
|
701
768
|
};
|
|
702
769
|
//#endregion
|
|
703
770
|
//#region src/core/engine/hls.ts
|
|
704
|
-
function
|
|
771
|
+
function he() {
|
|
705
772
|
return e.isSupported();
|
|
706
773
|
}
|
|
707
|
-
var
|
|
708
|
-
function
|
|
774
|
+
var ge = 3, _e = 5, ve = 3, ye = 3e4, be = 12e3, xe = 3e3, Se = 6e3, Ce = 2, we = 9, Te = .5;
|
|
775
|
+
function Ee(e) {
|
|
709
776
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
710
777
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
711
778
|
return;
|
|
712
779
|
}
|
|
713
|
-
e.liveSyncDuration ??=
|
|
714
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
715
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
780
|
+
e.liveSyncDuration ??= Ce;
|
|
781
|
+
let t = Math.max(12, e.liveSyncDuration + we);
|
|
782
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), De(e, e.liveSyncDuration);
|
|
716
783
|
}
|
|
717
|
-
function
|
|
784
|
+
function De(e, t) {
|
|
718
785
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
719
786
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
720
787
|
}
|
|
721
|
-
var
|
|
788
|
+
var U = class {
|
|
722
789
|
name = "hls";
|
|
723
790
|
hls = null;
|
|
724
791
|
deps;
|
|
725
792
|
licenseUrl;
|
|
726
|
-
fairplayLicenseUrl;
|
|
727
|
-
fairplayCertUrl;
|
|
728
793
|
detectedLowLatency = !1;
|
|
729
794
|
mediaRecoveries = 0;
|
|
730
795
|
networkRecoveries = 0;
|
|
@@ -743,14 +808,14 @@ var Te = class {
|
|
|
743
808
|
savedLiveMaxLatency;
|
|
744
809
|
savedMaxSyncRate;
|
|
745
810
|
constructor(e) {
|
|
746
|
-
this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl
|
|
811
|
+
this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl;
|
|
747
812
|
}
|
|
748
813
|
async load() {
|
|
749
|
-
let { descriptor: e, snapToLiveOnRefocus: n, video: r, emit: i } = this.deps, a =
|
|
750
|
-
if (e.drmEnabled && !o
|
|
814
|
+
let { descriptor: e, snapToLiveOnRefocus: n, video: r, emit: i } = this.deps, a = V(r), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
815
|
+
if (e.drmEnabled && !o) {
|
|
751
816
|
i({
|
|
752
817
|
type: "error",
|
|
753
|
-
error: new t("INTERNAL", 0, "DRM is required but none of the stream’s key systems is usable on this platform (WebKit takes FairPlay only; other browsers take Widevine only)"),
|
|
818
|
+
error: new t("INTERNAL", 0, e.drm?.fairplay?.licenseUrl && a ? "FairPlay cannot be played on the hls.js engine (WebKit binds keys via the media sinf box); use engine \"auto\" or \"native\"" : "DRM is required but none of the stream’s key systems is usable on this platform (WebKit takes FairPlay only; other browsers take Widevine only)"),
|
|
754
819
|
fatal: !0
|
|
755
820
|
});
|
|
756
821
|
return;
|
|
@@ -770,10 +835,10 @@ var Te = class {
|
|
|
770
835
|
let t = e.liveSyncPosition;
|
|
771
836
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
772
837
|
let { video: n } = this.deps;
|
|
773
|
-
n.currentTime <= t +
|
|
838
|
+
n.currentTime <= t + Te || (n.currentTime = t);
|
|
774
839
|
}
|
|
775
840
|
startHls() {
|
|
776
|
-
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps, u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d =
|
|
841
|
+
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps, u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d = {
|
|
777
842
|
debug: s === !0,
|
|
778
843
|
enableWorker: !o,
|
|
779
844
|
lowLatencyMode: o,
|
|
@@ -784,84 +849,44 @@ var Te = class {
|
|
|
784
849
|
capLevelToPlayerSize: !0,
|
|
785
850
|
...u ? {
|
|
786
851
|
emeEnabled: !0,
|
|
787
|
-
drmSystems: {
|
|
788
|
-
|
|
789
|
-
...d ? { "com.apple.fps": {
|
|
790
|
-
licenseUrl: this.fairplayLicenseUrl,
|
|
791
|
-
serverCertificateUrl: this.fairplayCertUrl,
|
|
792
|
-
generateRequest(e, t, n) {
|
|
793
|
-
if (t) return {
|
|
794
|
-
initDataType: e,
|
|
795
|
-
initData: t
|
|
796
|
-
};
|
|
797
|
-
let r = n.decryptdata?.uri;
|
|
798
|
-
return r?.startsWith("skd://") ? {
|
|
799
|
-
initDataType: "skd",
|
|
800
|
-
initData: new TextEncoder().encode(r).buffer
|
|
801
|
-
} : {
|
|
802
|
-
initDataType: e,
|
|
803
|
-
initData: t
|
|
804
|
-
};
|
|
805
|
-
}
|
|
806
|
-
} } : {}
|
|
807
|
-
},
|
|
808
|
-
drmSystemOptions: d ? {
|
|
809
|
-
videoEncryptionScheme: "cbcs",
|
|
810
|
-
audioEncryptionScheme: "cbcs"
|
|
811
|
-
} : {
|
|
852
|
+
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
853
|
+
drmSystemOptions: {
|
|
812
854
|
videoRobustness: "SW_SECURE_DECODE",
|
|
813
855
|
audioRobustness: "SW_SECURE_CRYPTO",
|
|
814
856
|
videoEncryptionScheme: "cbcs",
|
|
815
857
|
audioEncryptionScheme: "cbcs"
|
|
816
858
|
},
|
|
817
|
-
...d ? { requestMediaKeySystemAccessFunc: (e, t) => {
|
|
818
|
-
let n = e === "com.apple.fps" ? t.map((e) => ({
|
|
819
|
-
...e,
|
|
820
|
-
initDataTypes: [.../* @__PURE__ */ new Set([...e.initDataTypes ?? [], "skd"])]
|
|
821
|
-
})) : t;
|
|
822
|
-
return navigator.requestMediaKeySystemAccess(e, n);
|
|
823
|
-
} } : {},
|
|
824
859
|
licenseXhrSetup: (e, t) => {
|
|
825
|
-
|
|
826
|
-
e.open("POST", o, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a);
|
|
860
|
+
e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a);
|
|
827
861
|
}
|
|
828
862
|
} : {},
|
|
829
863
|
...c
|
|
830
864
|
};
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
let a = e?.(n, i), o = () => {
|
|
835
|
-
i === t() && (n.readyState === XMLHttpRequest.UNSENT && n.open("GET", i, !0), n.setRequestHeader("x-api-key", r.apiKey));
|
|
836
|
-
};
|
|
837
|
-
return a && typeof a.then == "function" ? a.then(() => o()) : (o(), a);
|
|
838
|
-
};
|
|
839
|
-
}
|
|
840
|
-
W(f);
|
|
841
|
-
let p = new e(f);
|
|
842
|
-
this.hls = p, p.on(e.Events.MANIFEST_PARSED, () => {
|
|
865
|
+
Ee(d);
|
|
866
|
+
let f = new e(d);
|
|
867
|
+
this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
843
868
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, l({ type: "ready" });
|
|
844
|
-
}),
|
|
869
|
+
}), f.on(e.Events.FRAG_BUFFERED, () => {
|
|
845
870
|
(this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
846
871
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.recoveryResetTimer = null;
|
|
847
|
-
},
|
|
848
|
-
}),
|
|
872
|
+
}, ye));
|
|
873
|
+
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
849
874
|
if (this.detectedLowLatency) return;
|
|
850
875
|
let n = t.details;
|
|
851
876
|
(n?.partList?.length || (n?.partTarget ?? 0) > 0) && (this.detectedLowLatency = !0, l({
|
|
852
877
|
type: "lowLatencyDetected",
|
|
853
878
|
value: !0
|
|
854
879
|
}));
|
|
855
|
-
}),
|
|
880
|
+
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog = setInterval(() => this.checkEndStale(), xe), f.on(e.Events.LEVEL_SWITCHED, (e, t) => l({
|
|
856
881
|
type: "qualitychange",
|
|
857
882
|
index: t.level
|
|
858
|
-
})),
|
|
883
|
+
})), f.on(e.Events.AUDIO_TRACK_SWITCHED, (e, t) => l({
|
|
859
884
|
type: "audiotrackchange",
|
|
860
885
|
id: t.id
|
|
861
|
-
})),
|
|
886
|
+
})), f.on(e.Events.SUBTITLE_TRACK_SWITCH, (e, t) => l({
|
|
862
887
|
type: "texttrackchange",
|
|
863
888
|
id: t.id
|
|
864
|
-
})),
|
|
889
|
+
})), f.on(e.Events.ERROR, (e, t) => this.onError(t)), f.loadSource(n.manifestUrl), f.attachMedia(t);
|
|
865
890
|
}
|
|
866
891
|
getQualityLevels() {
|
|
867
892
|
return this.hls ? this.hls.levels.map((e, t) => ({
|
|
@@ -917,11 +942,11 @@ var Te = class {
|
|
|
917
942
|
e && typeof e.liveSyncPosition == "number" && (this.deps.video.currentTime = e.liveSyncPosition);
|
|
918
943
|
}
|
|
919
944
|
setLicenseUrls(e) {
|
|
920
|
-
e.widevine && (this.licenseUrl = e.widevine)
|
|
945
|
+
e.widevine && (this.licenseUrl = e.widevine);
|
|
921
946
|
}
|
|
922
947
|
getStats() {
|
|
923
948
|
let e = this.hls, t = {
|
|
924
|
-
droppedFrames:
|
|
949
|
+
droppedFrames: z(this.deps.video),
|
|
925
950
|
lowLatency: this.detectedLowLatency
|
|
926
951
|
};
|
|
927
952
|
if (e) {
|
|
@@ -950,7 +975,7 @@ var Te = class {
|
|
|
950
975
|
return;
|
|
951
976
|
}
|
|
952
977
|
let e = Date.now() - this.lastAdvanceMs;
|
|
953
|
-
!this.chaseSuspended && e >
|
|
978
|
+
!this.chaseSuspended && e > Se && this.suspendChasing(), e > be && this.emitEnded("stalled");
|
|
954
979
|
}
|
|
955
980
|
suspendChasing() {
|
|
956
981
|
let e = this.hls;
|
|
@@ -992,7 +1017,7 @@ var Te = class {
|
|
|
992
1017
|
scheduleLicenseRetry(t) {
|
|
993
1018
|
if (!(t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED || t.details === e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED)) return !1;
|
|
994
1019
|
let n = t.response?.code ?? 0;
|
|
995
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1020
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= ve) return !1;
|
|
996
1021
|
this.licenseRecoveries += 1;
|
|
997
1022
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
998
1023
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1020,7 +1045,7 @@ var Te = class {
|
|
|
1020
1045
|
return;
|
|
1021
1046
|
}
|
|
1022
1047
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1023
|
-
if (this.networkRecoveries <
|
|
1048
|
+
if (this.networkRecoveries < _e) {
|
|
1024
1049
|
this.networkRecoveries += 1;
|
|
1025
1050
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1026
1051
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1036,7 +1061,7 @@ var Te = class {
|
|
|
1036
1061
|
return;
|
|
1037
1062
|
}
|
|
1038
1063
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1039
|
-
if (this.mediaRecoveries <
|
|
1064
|
+
if (this.mediaRecoveries < ge) {
|
|
1040
1065
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1041
1066
|
return;
|
|
1042
1067
|
}
|
|
@@ -1058,7 +1083,7 @@ var Te = class {
|
|
|
1058
1083
|
let r = e.response?.code ?? 0, i = e.details ?? e.type, a = e.reason ?? e.error?.message ?? "";
|
|
1059
1084
|
return new t(r === 401 ? "UNAUTHORIZED" : r === 403 || n === "DRM" ? "FORBIDDEN" : "INTERNAL", r, `${n} error: ${i}${a ? ` (${a})` : ""}`);
|
|
1060
1085
|
}
|
|
1061
|
-
},
|
|
1086
|
+
}, W = {
|
|
1062
1087
|
accent: "#E1B600",
|
|
1063
1088
|
accentText: "#1B1C23",
|
|
1064
1089
|
background: "#0e0f13",
|
|
@@ -1069,7 +1094,7 @@ var Te = class {
|
|
|
1069
1094
|
border: "rgba(255, 255, 255, 0.1)",
|
|
1070
1095
|
radius: "8px",
|
|
1071
1096
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
1072
|
-
},
|
|
1097
|
+
}, G = {
|
|
1073
1098
|
accent: "--havik-accent",
|
|
1074
1099
|
accentText: "--havik-accent-text",
|
|
1075
1100
|
background: "--havik-bg",
|
|
@@ -1081,25 +1106,25 @@ var Te = class {
|
|
|
1081
1106
|
radius: "--havik-radius",
|
|
1082
1107
|
fontFamily: "--havik-font"
|
|
1083
1108
|
};
|
|
1084
|
-
function
|
|
1109
|
+
function K(e, t) {
|
|
1085
1110
|
let n = {
|
|
1086
|
-
...
|
|
1111
|
+
...W,
|
|
1087
1112
|
...t
|
|
1088
1113
|
};
|
|
1089
|
-
for (let t of Object.keys(
|
|
1114
|
+
for (let t of Object.keys(G)) e.style.setProperty(G[t], n[t]);
|
|
1090
1115
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
1091
1116
|
}
|
|
1092
1117
|
//#endregion
|
|
1093
1118
|
//#region src/ui/styles.ts
|
|
1094
|
-
var
|
|
1095
|
-
function
|
|
1096
|
-
if (e.getElementById(
|
|
1119
|
+
var q = "havik-player-styles", Oe = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n.havik-spinner{width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:rgba(255,255,255,.3);border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:70px;opacity:1}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:12px;height:12px;border-radius:50%;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
|
|
1120
|
+
function ke(e = document) {
|
|
1121
|
+
if (e.getElementById(q)) return;
|
|
1097
1122
|
let t = e.createElement("style");
|
|
1098
|
-
t.id =
|
|
1123
|
+
t.id = q, t.textContent = Oe, e.head.appendChild(t);
|
|
1099
1124
|
}
|
|
1100
1125
|
//#endregion
|
|
1101
1126
|
//#region src/ui/icons.ts
|
|
1102
|
-
var
|
|
1127
|
+
var Ae = {
|
|
1103
1128
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
1104
1129
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
1105
1130
|
volumeHigh: "<path d=\"M3 10v4h4l5 5V5L7 10H3zm13.5 2a4.5 4.5 0 0 0-2.5-4v8a4.5 4.5 0 0 0 2.5-4zm-2.5-9v2.06A7 7 0 0 1 14 19v2a9 9 0 0 0 0-18z\"/>",
|
|
@@ -1112,21 +1137,21 @@ var Oe = {
|
|
|
1112
1137
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
1113
1138
|
retry: "<path d=\"M17.65 6.35A8 8 0 1 0 19.73 13h-2.08A6 6 0 1 1 12 6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"/>"
|
|
1114
1139
|
};
|
|
1115
|
-
function
|
|
1116
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
1140
|
+
function J(e) {
|
|
1141
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Ae[e]}</svg>`;
|
|
1117
1142
|
}
|
|
1118
1143
|
//#endregion
|
|
1119
1144
|
//#region src/ui/controls.ts
|
|
1120
|
-
var
|
|
1145
|
+
var je = 3e3, Me = /* @__PURE__ */ new Set([
|
|
1121
1146
|
"GONE",
|
|
1122
1147
|
"NOT_FOUND",
|
|
1123
1148
|
"INVALID_URN",
|
|
1124
1149
|
"UNAUTHORIZED"
|
|
1125
1150
|
]);
|
|
1126
|
-
function
|
|
1127
|
-
return new
|
|
1151
|
+
function Ne(e) {
|
|
1152
|
+
return new Pe(e);
|
|
1128
1153
|
}
|
|
1129
|
-
var
|
|
1154
|
+
var Pe = class {
|
|
1130
1155
|
root;
|
|
1131
1156
|
video;
|
|
1132
1157
|
player;
|
|
@@ -1166,7 +1191,7 @@ var Me = class {
|
|
|
1166
1191
|
scrubbing = !1;
|
|
1167
1192
|
offFns = [];
|
|
1168
1193
|
constructor(e) {
|
|
1169
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
1194
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? je, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.errorMessage = e.errorMessage, ke(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
|
|
1170
1195
|
let t = (e, t, n) => {
|
|
1171
1196
|
let r = this.doc.createElement(e);
|
|
1172
1197
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -1177,12 +1202,12 @@ var Me = class {
|
|
|
1177
1202
|
"aria-label": r,
|
|
1178
1203
|
title: r
|
|
1179
1204
|
});
|
|
1180
|
-
return i.innerHTML =
|
|
1205
|
+
return i.innerHTML = J(n), i;
|
|
1181
1206
|
};
|
|
1182
1207
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
1183
1208
|
type: "button",
|
|
1184
1209
|
"aria-label": "Play"
|
|
1185
|
-
}), this.center.innerHTML =
|
|
1210
|
+
}), this.center.innerHTML = J("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
|
|
1186
1211
|
role: "slider",
|
|
1187
1212
|
"aria-label": "Seek",
|
|
1188
1213
|
"aria-valuemin": "0",
|
|
@@ -1200,7 +1225,7 @@ var Me = class {
|
|
|
1200
1225
|
"aria-label": "Volume"
|
|
1201
1226
|
});
|
|
1202
1227
|
let a = t("div", "havik-vol");
|
|
1203
|
-
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML =
|
|
1228
|
+
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = J("liveDot");
|
|
1204
1229
|
let o = this.doc.createElement("span");
|
|
1205
1230
|
o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
|
|
1206
1231
|
let s = t("div", "havik-spacer");
|
|
@@ -1250,12 +1275,12 @@ var Me = class {
|
|
|
1250
1275
|
}
|
|
1251
1276
|
if (e === "preplay") {
|
|
1252
1277
|
let e = this.doc.createElement("button");
|
|
1253
|
-
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML =
|
|
1278
|
+
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = J("play"), e.addEventListener("click", () => void this.player.play()), t.append(e);
|
|
1254
1279
|
} else {
|
|
1255
1280
|
let n = this.doc.createElement("div");
|
|
1256
|
-
if (n.className = "havik-status__msg", n.textContent = e === "ended" ? this.endedMessage : e === "waiting" ? "Starting soon…" : this.errorMessage ?? this.lastError?.message ?? "Playback unavailable", t.append(n), e === "error" && this.lastError && !
|
|
1281
|
+
if (n.className = "havik-status__msg", n.textContent = e === "ended" ? this.endedMessage : e === "waiting" ? "Starting soon…" : this.errorMessage ?? this.lastError?.message ?? "Playback unavailable", t.append(n), e === "error" && this.lastError && !Me.has(this.lastError.code)) {
|
|
1257
1282
|
let e = this.doc.createElement("button");
|
|
1258
|
-
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${
|
|
1283
|
+
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${J("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), t.append(e);
|
|
1259
1284
|
}
|
|
1260
1285
|
}
|
|
1261
1286
|
this.root.append(t), this.statusBox = t, this.show();
|
|
@@ -1289,7 +1314,7 @@ var Me = class {
|
|
|
1289
1314
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
1290
1315
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
1291
1316
|
}
|
|
1292
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
1317
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Y(this.video.currentTime)} / ${Y(this.video.duration)}`);
|
|
1293
1318
|
}
|
|
1294
1319
|
syncLive() {
|
|
1295
1320
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -1339,17 +1364,17 @@ var Me = class {
|
|
|
1339
1364
|
renderQualityMenu() {
|
|
1340
1365
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
1341
1366
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
1342
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
1367
|
+
for (let n of e) this.menu.append(this.menuItem(Fe(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
1343
1368
|
}
|
|
1344
1369
|
renderAudioMenu() {
|
|
1345
1370
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
1346
1371
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
1347
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
1372
|
+
for (let t of e) this.menu.append(this.menuItem(Ie(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
1348
1373
|
}
|
|
1349
1374
|
renderCcMenu() {
|
|
1350
1375
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
1351
1376
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
1352
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
1377
|
+
for (let t of e) this.menu.append(this.menuItem(Le(t), !1, () => this.player.setTextTrack(t.id)));
|
|
1353
1378
|
}
|
|
1354
1379
|
onTracksChanged() {
|
|
1355
1380
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -1433,7 +1458,7 @@ var Me = class {
|
|
|
1433
1458
|
}
|
|
1434
1459
|
}
|
|
1435
1460
|
setIcon(e, t) {
|
|
1436
|
-
e.innerHTML =
|
|
1461
|
+
e.innerHTML = J(t);
|
|
1437
1462
|
}
|
|
1438
1463
|
destroy() {
|
|
1439
1464
|
this.hideTimer && clearTimeout(this.hideTimer);
|
|
@@ -1450,32 +1475,32 @@ var Me = class {
|
|
|
1450
1475
|
this.root.classList.remove("havik-player", "havik-hide");
|
|
1451
1476
|
}
|
|
1452
1477
|
};
|
|
1453
|
-
function
|
|
1478
|
+
function Y(e) {
|
|
1454
1479
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
1455
1480
|
let t = Math.floor(e % 60), n = Math.floor(e / 60 % 60), r = Math.floor(e / 3600), i = r > 0 ? String(n).padStart(2, "0") : String(n), a = String(t).padStart(2, "0");
|
|
1456
1481
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
1457
1482
|
}
|
|
1458
|
-
function
|
|
1483
|
+
function Fe(e) {
|
|
1459
1484
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
1460
1485
|
}
|
|
1461
|
-
function
|
|
1486
|
+
function Ie(e) {
|
|
1462
1487
|
return e.name || e.lang || `Track ${e.id}`;
|
|
1463
1488
|
}
|
|
1464
|
-
function
|
|
1489
|
+
function Le(e) {
|
|
1465
1490
|
return e.name || e.lang || `Track ${e.id}`;
|
|
1466
1491
|
}
|
|
1467
1492
|
//#endregion
|
|
1468
1493
|
//#region src/managed/index.ts
|
|
1469
|
-
var
|
|
1494
|
+
var Re = 6e3, X = 45e3, ze = 2e3, Z = 3, Be = 2e3, Ve = 480 * 1e3;
|
|
1470
1495
|
async function Q(e) {
|
|
1471
1496
|
if (!e.video || typeof e.video.play != "function") throw new t("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
1472
1497
|
if (!e.baseUrl) throw new t("INTERNAL", 0, "createPlayer: baseUrl is required");
|
|
1473
1498
|
if (!e.matchUrn) throw new t("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
1474
1499
|
if (!e.credential) throw new t("INTERNAL", 0, "createPlayer: credential is required");
|
|
1475
|
-
let n = new
|
|
1500
|
+
let n = new He(e);
|
|
1476
1501
|
return await n.start(), n;
|
|
1477
1502
|
}
|
|
1478
|
-
var
|
|
1503
|
+
var He = class {
|
|
1479
1504
|
opts;
|
|
1480
1505
|
abort = new AbortController();
|
|
1481
1506
|
listeners = {};
|
|
@@ -1552,7 +1577,7 @@ var Ve = class {
|
|
|
1552
1577
|
setTimeout(() => {
|
|
1553
1578
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
1554
1579
|
phase: "tooEarly",
|
|
1555
|
-
retryInMs:
|
|
1580
|
+
retryInMs: X,
|
|
1556
1581
|
attempt: 1,
|
|
1557
1582
|
elapsedMs: 0,
|
|
1558
1583
|
...d !== void 0 && d > Date.now() ? { ttkMs: d - Date.now() } : {}
|
|
@@ -1585,13 +1610,13 @@ var Ve = class {
|
|
|
1585
1610
|
!a && !f() && m();
|
|
1586
1611
|
}, e);
|
|
1587
1612
|
};
|
|
1588
|
-
g(
|
|
1613
|
+
g(Re), this.armingSub = T({
|
|
1589
1614
|
eventsBaseUrl: n,
|
|
1590
1615
|
matchUrn: this.opts.matchUrn,
|
|
1591
1616
|
credential: this.opts.credential,
|
|
1592
|
-
onAlive: () => g(
|
|
1617
|
+
onAlive: () => g(X),
|
|
1593
1618
|
onState: (e) => {
|
|
1594
|
-
a || f() || (e.state === "live" || e.state === "gone") && setTimeout(h, Math.random() *
|
|
1619
|
+
a || f() || (e.state === "live" || e.state === "gone") && setTimeout(h, Math.random() * ze);
|
|
1595
1620
|
},
|
|
1596
1621
|
onError: () => m()
|
|
1597
1622
|
});
|
|
@@ -1614,7 +1639,7 @@ var Ve = class {
|
|
|
1614
1639
|
let n = await a(this.opts.credential);
|
|
1615
1640
|
if (this.destroyed || t !== this.loadGen) return;
|
|
1616
1641
|
this.setState("loading");
|
|
1617
|
-
let r = this.createEngine(e, n), i =
|
|
1642
|
+
let r = this.createEngine(e, n), i = B(this.opts.video, (e) => {
|
|
1618
1643
|
this._state === "ended" || this._state === "error" || this.setState(e);
|
|
1619
1644
|
});
|
|
1620
1645
|
if (await r.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -1642,9 +1667,11 @@ var Ve = class {
|
|
|
1642
1667
|
hlsConfig: r,
|
|
1643
1668
|
emit: (e) => this.onEngineEvent(e)
|
|
1644
1669
|
}, a = this.opts.engine ?? "auto";
|
|
1645
|
-
if (a === "native") return new
|
|
1646
|
-
if (a === "hls"
|
|
1647
|
-
if (
|
|
1670
|
+
if (a === "native") return new H(i);
|
|
1671
|
+
if (a === "hls") return new U(i);
|
|
1672
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && V(this.opts.video)) return new H(i);
|
|
1673
|
+
if (he()) return new U(i);
|
|
1674
|
+
if (V(this.opts.video)) return new H(i);
|
|
1648
1675
|
throw new t("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
1649
1676
|
}
|
|
1650
1677
|
onEngineEvent(e) {
|
|
@@ -1689,7 +1716,7 @@ var Ve = class {
|
|
|
1689
1716
|
r = 0, i = !1;
|
|
1690
1717
|
},
|
|
1691
1718
|
onError: () => {
|
|
1692
|
-
this.destroyed || e !== this.loadGen || i || (r += 1, r >=
|
|
1719
|
+
this.destroyed || e !== this.loadGen || i || (r += 1, r >= Z && (i = !0, this.emit("warning", new t("NETWORK", 0, `live-state events unreachable at ${n} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
|
|
1693
1720
|
}
|
|
1694
1721
|
});
|
|
1695
1722
|
}
|
|
@@ -1711,7 +1738,7 @@ var Ve = class {
|
|
|
1711
1738
|
}
|
|
1712
1739
|
t.controls = !1;
|
|
1713
1740
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
1714
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
1741
|
+
r && r.insertBefore(n, t), n.appendChild(t), K(n, this.opts.theme), this.container = n, this.controlBar = Ne({
|
|
1715
1742
|
root: n,
|
|
1716
1743
|
video: t,
|
|
1717
1744
|
player: this,
|
|
@@ -1734,7 +1761,7 @@ var Ve = class {
|
|
|
1734
1761
|
}
|
|
1735
1762
|
startStats() {
|
|
1736
1763
|
this.stopStats();
|
|
1737
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
1764
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Be);
|
|
1738
1765
|
this.statsTimer = setInterval(() => {
|
|
1739
1766
|
this.engine && this.emit("stats", this.engine.getStats());
|
|
1740
1767
|
}, e);
|
|
@@ -1744,7 +1771,7 @@ var Ve = class {
|
|
|
1744
1771
|
}
|
|
1745
1772
|
scheduleLicenseRefresh() {
|
|
1746
1773
|
this.stopRefresh();
|
|
1747
|
-
let e = this.opts.licenseRefreshMs ??
|
|
1774
|
+
let e = this.opts.licenseRefreshMs ?? Ve;
|
|
1748
1775
|
!e || !this._descriptor?.drmEnabled || (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
1749
1776
|
}
|
|
1750
1777
|
stopRefresh() {
|
|
@@ -1781,7 +1808,7 @@ var Ve = class {
|
|
|
1781
1808
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
1782
1809
|
}
|
|
1783
1810
|
getStats() {
|
|
1784
|
-
return this.engine?.getStats() ??
|
|
1811
|
+
return this.engine?.getStats() ?? R;
|
|
1785
1812
|
}
|
|
1786
1813
|
getQualityLevels() {
|
|
1787
1814
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -1882,7 +1909,7 @@ function $(e) {
|
|
|
1882
1909
|
}
|
|
1883
1910
|
//#endregion
|
|
1884
1911
|
//#region src/embed/host.ts
|
|
1885
|
-
function
|
|
1912
|
+
function Ue(e) {
|
|
1886
1913
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
1887
1914
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
1888
1915
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -1941,8 +1968,8 @@ function He(e) {
|
|
|
1941
1968
|
}
|
|
1942
1969
|
//#endregion
|
|
1943
1970
|
//#region src/embed/page.ts
|
|
1944
|
-
var
|
|
1945
|
-
function
|
|
1971
|
+
var We = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
1972
|
+
function Ge() {
|
|
1946
1973
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
1947
1974
|
if (e) return {
|
|
1948
1975
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -1964,9 +1991,9 @@ function We() {
|
|
|
1964
1991
|
waitForLive: !0
|
|
1965
1992
|
};
|
|
1966
1993
|
}
|
|
1967
|
-
async function
|
|
1968
|
-
let e =
|
|
1969
|
-
|
|
1994
|
+
async function Ke() {
|
|
1995
|
+
let e = Ge();
|
|
1996
|
+
Je();
|
|
1970
1997
|
let n = document.createElement("video");
|
|
1971
1998
|
n.setAttribute("playsinline", ""), n.muted = e.muted ?? !0, n.style.cssText = "width:100%;height:100%;object-fit:contain;background:#000;aspect-ratio:auto", document.body.appendChild(n);
|
|
1972
1999
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -2021,7 +2048,7 @@ async function Ge() {
|
|
|
2021
2048
|
code: e.code,
|
|
2022
2049
|
message: e.message
|
|
2023
2050
|
})), e.on("autoplayblocked", () => {
|
|
2024
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
2051
|
+
i({ type: "oddin:autoplayblocked" }), qe(n, e);
|
|
2025
2052
|
});
|
|
2026
2053
|
}, s = async (r) => {
|
|
2027
2054
|
a?.destroy(), a = null;
|
|
@@ -2087,7 +2114,7 @@ async function Ge() {
|
|
|
2087
2114
|
a?.retry();
|
|
2088
2115
|
break;
|
|
2089
2116
|
case "oddin:load":
|
|
2090
|
-
typeof e.matchUrn == "string" &&
|
|
2117
|
+
typeof e.matchUrn == "string" && We.test(e.matchUrn) && s(e.matchUrn);
|
|
2091
2118
|
break;
|
|
2092
2119
|
case "oddin:destroy":
|
|
2093
2120
|
c();
|
|
@@ -2101,18 +2128,18 @@ async function Ge() {
|
|
|
2101
2128
|
protocol: 1
|
|
2102
2129
|
});
|
|
2103
2130
|
}
|
|
2104
|
-
function
|
|
2131
|
+
function qe(e, t) {
|
|
2105
2132
|
if (document.getElementById("havik-tap")) return;
|
|
2106
2133
|
let n = document.createElement("button");
|
|
2107
2134
|
n.id = "havik-tap", n.textContent = "▶ Tap to play", n.style.cssText = "position:fixed;inset:0;width:100%;height:100%;border:0;background:rgba(0,0,0,.55);color:#fff;font:600 18px system-ui,sans-serif;cursor:pointer;z-index:9", n.addEventListener("click", () => {
|
|
2108
2135
|
n.remove(), t.play();
|
|
2109
2136
|
}), document.body.appendChild(n);
|
|
2110
2137
|
}
|
|
2111
|
-
function
|
|
2138
|
+
function Je() {
|
|
2112
2139
|
let e = document.createElement("style");
|
|
2113
2140
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
2114
2141
|
}
|
|
2115
2142
|
//#endregion
|
|
2116
|
-
export {
|
|
2143
|
+
export { W as ODDIN_THEME, t as PlaybackError, K as applyTheme, Ke as bootEmbed, ue as clearDeviceId, Q as createPlayer, E as deriveEventsBaseUrl, F as detectDrmSupport, w as fetchCatalog, oe as fetchTournament, ce as flattenMatches, k as getDeviceId, L as isLowLatencyManifest, $ as isOddinMessage, fe as licenseRequestHeaders, Ue as mountEmbed, v as pollToLive, b as resolveStream, T as subscribeLiveState, le as watchStatus };
|
|
2117
2144
|
|
|
2118
2145
|
//# sourceMappingURL=index.js.map
|