@oddin-gg/havik-player 2.23.4 → 2.25.0
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/README.md +2 -0
- package/dist/havik-player.global.js +15 -15
- 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.d.cts +44 -1
- package/dist/index.d.ts +44 -1
- package/dist/index.js +573 -433
- package/dist/index.js.map +1 -1
- package/docs/API.md +101 -57
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -309,42 +309,42 @@ function ge(e, t) {
|
|
|
309
309
|
}
|
|
310
310
|
//#endregion
|
|
311
311
|
//#region src/core/fullscreen.ts
|
|
312
|
-
function
|
|
312
|
+
function _e(e) {
|
|
313
313
|
return e.ownerDocument ?? document;
|
|
314
314
|
}
|
|
315
|
-
function
|
|
315
|
+
function ve(e) {
|
|
316
316
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
317
317
|
}
|
|
318
|
-
function
|
|
319
|
-
let n = _e(
|
|
318
|
+
function ye(e, t) {
|
|
319
|
+
let n = ve(_e(e));
|
|
320
320
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
321
321
|
}
|
|
322
|
-
function
|
|
323
|
-
let n = t ?? e, r =
|
|
322
|
+
function x(e, t) {
|
|
323
|
+
let n = t ?? e, r = _e(e);
|
|
324
324
|
if (typeof n.requestFullscreen == "function") return r.fullscreenEnabled !== !1;
|
|
325
325
|
if (typeof n.webkitRequestFullscreen == "function") return r.webkitFullscreenEnabled !== !1;
|
|
326
326
|
let i = e;
|
|
327
327
|
return i.webkitSupportsFullscreen === !0 && typeof i.webkitEnterFullscreen == "function" || e.readyState < 1;
|
|
328
328
|
}
|
|
329
|
-
async function
|
|
329
|
+
async function S(e, t) {
|
|
330
330
|
let n = t ?? e;
|
|
331
331
|
if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
|
|
332
332
|
if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
|
|
333
333
|
let r = e;
|
|
334
334
|
return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
|
|
335
335
|
}
|
|
336
|
-
async function
|
|
336
|
+
async function C(e, t) {
|
|
337
337
|
let n = e;
|
|
338
338
|
if (n.webkitDisplayingFullscreen) {
|
|
339
339
|
n.webkitExitFullscreen?.();
|
|
340
340
|
return;
|
|
341
341
|
}
|
|
342
|
-
let r =
|
|
342
|
+
let r = _e(e), i = ve(r);
|
|
343
343
|
i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
|
|
344
344
|
}
|
|
345
345
|
//#endregion
|
|
346
346
|
//#region src/core/catalog.ts
|
|
347
|
-
async function
|
|
347
|
+
async function be(e) {
|
|
348
348
|
let t = new URLSearchParams();
|
|
349
349
|
e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
|
|
350
350
|
let i = t.toString(), a = f(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
|
|
@@ -362,12 +362,12 @@ async function ve(e) {
|
|
|
362
362
|
};
|
|
363
363
|
if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
|
|
364
364
|
return {
|
|
365
|
-
tournaments:
|
|
365
|
+
tournaments: xe(await s.json()),
|
|
366
366
|
etag: s.headers.get("etag") ?? void 0,
|
|
367
367
|
notModified: !1
|
|
368
368
|
};
|
|
369
369
|
}
|
|
370
|
-
function
|
|
370
|
+
function xe(e) {
|
|
371
371
|
return (e.tournaments ?? []).map((e) => {
|
|
372
372
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
373
373
|
return {
|
|
@@ -389,7 +389,7 @@ function ye(e) {
|
|
|
389
389
|
};
|
|
390
390
|
});
|
|
391
391
|
}
|
|
392
|
-
async function
|
|
392
|
+
async function Se(e) {
|
|
393
393
|
let t = f(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
394
394
|
e.etag && i.set("If-None-Match", e.etag);
|
|
395
395
|
let a = await m(t, {
|
|
@@ -409,13 +409,13 @@ async function be(e) {
|
|
|
409
409
|
};
|
|
410
410
|
if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
411
411
|
return {
|
|
412
|
-
tournament:
|
|
412
|
+
tournament: Ce(await a.json()),
|
|
413
413
|
etag: a.headers.get("etag") ?? void 0,
|
|
414
414
|
notModified: !1,
|
|
415
415
|
notFound: !1
|
|
416
416
|
};
|
|
417
417
|
}
|
|
418
|
-
function
|
|
418
|
+
function Ce(e) {
|
|
419
419
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
420
420
|
return {
|
|
421
421
|
urn: t,
|
|
@@ -435,18 +435,18 @@ function xe(e) {
|
|
|
435
435
|
}))
|
|
436
436
|
};
|
|
437
437
|
}
|
|
438
|
-
function
|
|
438
|
+
function we(e) {
|
|
439
439
|
return e.tournaments.flatMap((e) => e.matches);
|
|
440
440
|
}
|
|
441
441
|
//#endregion
|
|
442
442
|
//#region src/core/poll.ts
|
|
443
|
-
var
|
|
443
|
+
var Te = /* @__PURE__ */ new Set([
|
|
444
444
|
"NOT_FOUND",
|
|
445
445
|
"GEO_DENIED",
|
|
446
446
|
"GONE",
|
|
447
447
|
"INVALID_URN"
|
|
448
448
|
]);
|
|
449
|
-
function
|
|
449
|
+
function Ee(e) {
|
|
450
450
|
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, c = !1, d = () => {
|
|
451
451
|
c || (a = setTimeout(p, t));
|
|
452
452
|
}, p = async () => {
|
|
@@ -479,7 +479,7 @@ function we(e) {
|
|
|
479
479
|
} catch (t) {
|
|
480
480
|
if (!i.signal.aborted) {
|
|
481
481
|
let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
|
|
482
|
-
|
|
482
|
+
Te.has(r.code) && (c = !0), e.onError?.(r);
|
|
483
483
|
}
|
|
484
484
|
} finally {
|
|
485
485
|
d();
|
|
@@ -491,16 +491,16 @@ function we(e) {
|
|
|
491
491
|
}
|
|
492
492
|
//#endregion
|
|
493
493
|
//#region src/core/events.ts
|
|
494
|
-
var
|
|
494
|
+
var De = 45e3, w = class extends Error {
|
|
495
495
|
status;
|
|
496
496
|
terminal;
|
|
497
497
|
constructor(e) {
|
|
498
498
|
let t = e === 410;
|
|
499
499
|
super(t ? `live-state subscribe failed: HTTP ${e} — match is gone, not retrying` : e === 404 ? `live-state subscribe failed: HTTP ${e} — match not in the catalog, retrying slowly` : `live-state subscribe failed: HTTP ${e}`), this.name = "LiveStateHttpError", this.status = e, this.terminal = t;
|
|
500
500
|
}
|
|
501
|
-
},
|
|
502
|
-
function
|
|
503
|
-
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = Math.max(t, e.notFoundRetryMs ??
|
|
501
|
+
}, Oe = 3e5;
|
|
502
|
+
function T(e) {
|
|
503
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = Math.max(t, e.notFoundRetryMs ?? Oe), i = e.idleTimeoutMs ?? De, a = Number.isFinite(i) && i > 0 ? i : 0, o = new AbortController(), s = !1, l = (e) => new Promise((t) => {
|
|
504
504
|
if (o.signal.aborted) return t();
|
|
505
505
|
let n = setTimeout(t, e);
|
|
506
506
|
o.signal.addEventListener("abort", () => {
|
|
@@ -567,7 +567,7 @@ function D(e) {
|
|
|
567
567
|
});
|
|
568
568
|
if (clearTimeout(_), s) return;
|
|
569
569
|
if (!o.ok || !o.body) {
|
|
570
|
-
let t = new
|
|
570
|
+
let t = new w(o.status);
|
|
571
571
|
h = t.terminal, g = o.status === 404, e.onError?.(t);
|
|
572
572
|
} else await p(o.body, () => {
|
|
573
573
|
i = t;
|
|
@@ -585,7 +585,7 @@ function D(e) {
|
|
|
585
585
|
s || (s = !0, o.abort());
|
|
586
586
|
} };
|
|
587
587
|
}
|
|
588
|
-
function
|
|
588
|
+
function E(e) {
|
|
589
589
|
try {
|
|
590
590
|
let t = new URL(e);
|
|
591
591
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -595,27 +595,27 @@ function O(e) {
|
|
|
595
595
|
}
|
|
596
596
|
//#endregion
|
|
597
597
|
//#region src/core/drm/deviceId.ts
|
|
598
|
-
var
|
|
599
|
-
function
|
|
600
|
-
if (
|
|
598
|
+
var D = "havik.player.deviceId", O;
|
|
599
|
+
function k() {
|
|
600
|
+
if (O) return O;
|
|
601
601
|
try {
|
|
602
|
-
let e = globalThis.localStorage?.getItem(
|
|
603
|
-
if (e) return
|
|
602
|
+
let e = globalThis.localStorage?.getItem(D);
|
|
603
|
+
if (e) return O = e, e;
|
|
604
604
|
} catch {}
|
|
605
|
-
let e =
|
|
606
|
-
|
|
605
|
+
let e = Ae();
|
|
606
|
+
O = e;
|
|
607
607
|
try {
|
|
608
|
-
globalThis.localStorage?.setItem(
|
|
608
|
+
globalThis.localStorage?.setItem(D, e);
|
|
609
609
|
} catch {}
|
|
610
610
|
return e;
|
|
611
611
|
}
|
|
612
|
-
function
|
|
613
|
-
|
|
612
|
+
function ke() {
|
|
613
|
+
O = void 0;
|
|
614
614
|
try {
|
|
615
|
-
globalThis.localStorage?.removeItem(
|
|
615
|
+
globalThis.localStorage?.removeItem(D);
|
|
616
616
|
} catch {}
|
|
617
617
|
}
|
|
618
|
-
function
|
|
618
|
+
function Ae() {
|
|
619
619
|
let e = globalThis.crypto;
|
|
620
620
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
621
621
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -627,32 +627,32 @@ function Oe() {
|
|
|
627
627
|
}
|
|
628
628
|
//#endregion
|
|
629
629
|
//#region src/core/drm/headers.ts
|
|
630
|
-
function
|
|
630
|
+
function je(e, t, n = {}) {
|
|
631
631
|
let r = {
|
|
632
632
|
"x-api-key": t.apiKey,
|
|
633
633
|
"X-Match-Urn": e.matchUrn,
|
|
634
|
-
"X-Device-Id": n.deviceId ??
|
|
634
|
+
"X-Device-Id": n.deviceId ?? k(),
|
|
635
635
|
"Content-Type": "application/octet-stream"
|
|
636
636
|
};
|
|
637
637
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
638
638
|
}
|
|
639
639
|
//#endregion
|
|
640
640
|
//#region src/core/bandwidthMemory.ts
|
|
641
|
-
var
|
|
642
|
-
function
|
|
641
|
+
var A = "havik.player.bandwidth", Me = .8, Ne = 2e7, Pe = 3e5;
|
|
642
|
+
function Fe() {
|
|
643
643
|
return globalThis.navigator?.connection;
|
|
644
644
|
}
|
|
645
|
-
function
|
|
646
|
-
let e =
|
|
645
|
+
function Ie() {
|
|
646
|
+
let e = Fe()?.type;
|
|
647
647
|
return typeof e == "string" && e !== "" && e !== "unknown" ? e : "any";
|
|
648
648
|
}
|
|
649
|
-
function
|
|
650
|
-
let e =
|
|
649
|
+
function Le() {
|
|
650
|
+
let e = Fe()?.downlink;
|
|
651
651
|
return typeof e == "number" && Number.isFinite(e) && e > 0 ? e * 1e6 : void 0;
|
|
652
652
|
}
|
|
653
|
-
function
|
|
653
|
+
function Re() {
|
|
654
654
|
try {
|
|
655
|
-
let e = globalThis.localStorage?.getItem(
|
|
655
|
+
let e = globalThis.localStorage?.getItem(A);
|
|
656
656
|
if (!e) return {};
|
|
657
657
|
let t = JSON.parse(e);
|
|
658
658
|
return t && typeof t == "object" && !Array.isArray(t) ? t : {};
|
|
@@ -660,36 +660,36 @@ function Ie() {
|
|
|
660
660
|
return {};
|
|
661
661
|
}
|
|
662
662
|
}
|
|
663
|
-
function
|
|
664
|
-
let t =
|
|
663
|
+
function ze(e = Date.now()) {
|
|
664
|
+
let t = Re()[Ie()];
|
|
665
665
|
if (!t || typeof t.bps != "number" || typeof t.at != "number" || !Number.isFinite(t.bps) || t.bps <= 0) return;
|
|
666
666
|
let n = e - t.at;
|
|
667
667
|
if (n < 0 || n > 2592e5) return;
|
|
668
|
-
let r =
|
|
669
|
-
return Math.round(Math.min(
|
|
668
|
+
let r = Le(), i = r === void 0 ? t.bps : Math.min(t.bps, r);
|
|
669
|
+
return Math.round(Math.min(Ne, Math.max(Pe, i * Me)));
|
|
670
670
|
}
|
|
671
|
-
function
|
|
671
|
+
function Be(e, t = Date.now()) {
|
|
672
672
|
if (!Number.isFinite(e) || e <= 0) return;
|
|
673
|
-
let n =
|
|
674
|
-
n[
|
|
673
|
+
let n = Re();
|
|
674
|
+
n[Ie()] = {
|
|
675
675
|
bps: Math.round(e),
|
|
676
676
|
at: t
|
|
677
677
|
};
|
|
678
678
|
try {
|
|
679
|
-
globalThis.localStorage?.setItem(
|
|
679
|
+
globalThis.localStorage?.setItem(A, JSON.stringify(n));
|
|
680
680
|
} catch {}
|
|
681
681
|
}
|
|
682
|
-
function
|
|
682
|
+
function Ve() {
|
|
683
683
|
try {
|
|
684
|
-
globalThis.localStorage?.removeItem(
|
|
684
|
+
globalThis.localStorage?.removeItem(A);
|
|
685
685
|
} catch {}
|
|
686
686
|
}
|
|
687
687
|
//#endregion
|
|
688
688
|
//#region src/core/drm/cdm.ts
|
|
689
|
-
var
|
|
690
|
-
function
|
|
691
|
-
let n =
|
|
692
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
689
|
+
var He = /* @__PURE__ */ new WeakMap();
|
|
690
|
+
function Ue(e, t) {
|
|
691
|
+
let n = He.get(e);
|
|
692
|
+
n || (n = /* @__PURE__ */ new Map(), He.set(e, n));
|
|
693
693
|
let r = n.get(t.keySystem);
|
|
694
694
|
if (r) return r;
|
|
695
695
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -697,22 +697,22 @@ function Ve(e, t) {
|
|
|
697
697
|
});
|
|
698
698
|
return n.set(t.keySystem, i), i;
|
|
699
699
|
}
|
|
700
|
-
function
|
|
700
|
+
function j() {
|
|
701
701
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
702
702
|
}
|
|
703
|
-
var
|
|
704
|
-
function
|
|
703
|
+
var M = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
704
|
+
function We(e) {
|
|
705
705
|
return e.startsWith("com.widevine");
|
|
706
706
|
}
|
|
707
|
-
function
|
|
708
|
-
if (!
|
|
707
|
+
function N(e, t) {
|
|
708
|
+
if (!We(e)) return t;
|
|
709
709
|
let n = (e, t) => {
|
|
710
710
|
let n = e.videoCapabilities;
|
|
711
711
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
712
|
-
let n =
|
|
713
|
-
return n === -1 ||
|
|
712
|
+
let n = M.indexOf(e.robustness);
|
|
713
|
+
return n === -1 || M.indexOf(t) > n;
|
|
714
714
|
});
|
|
715
|
-
}, r =
|
|
715
|
+
}, r = M.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
716
716
|
...t,
|
|
717
717
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
718
718
|
...t,
|
|
@@ -721,53 +721,53 @@ function F(e, t) {
|
|
|
721
721
|
})));
|
|
722
722
|
return [...t, ...r];
|
|
723
723
|
}
|
|
724
|
-
function
|
|
725
|
-
return (t, n) =>
|
|
724
|
+
function Ge(e) {
|
|
725
|
+
return (t, n) => j() ? navigator.requestMediaKeySystemAccess(t, N(t, n)).then((t) => ({
|
|
726
726
|
keySystem: t.keySystem,
|
|
727
727
|
getConfiguration: () => t.getConfiguration(),
|
|
728
|
-
createMediaKeys: () =>
|
|
728
|
+
createMediaKeys: () => Ue(e, t)
|
|
729
729
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
730
730
|
}
|
|
731
|
-
var
|
|
731
|
+
var P = {
|
|
732
732
|
video: "SW_SECURE_DECODE",
|
|
733
733
|
audio: "SW_SECURE_CRYPTO",
|
|
734
734
|
scheme: "cbcs"
|
|
735
735
|
};
|
|
736
|
-
function
|
|
737
|
-
if (!
|
|
736
|
+
function Ke(e) {
|
|
737
|
+
if (!j()) return;
|
|
738
738
|
let t = (e, t) => ({
|
|
739
739
|
contentType: e,
|
|
740
740
|
robustness: t,
|
|
741
|
-
encryptionScheme:
|
|
741
|
+
encryptionScheme: P.scheme
|
|
742
742
|
});
|
|
743
|
-
|
|
743
|
+
Ge(e)("com.widevine.alpha", [{
|
|
744
744
|
initDataTypes: ["cenc"],
|
|
745
745
|
distinctiveIdentifier: "optional",
|
|
746
746
|
persistentState: "optional",
|
|
747
747
|
sessionTypes: ["temporary"],
|
|
748
|
-
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"",
|
|
749
|
-
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"",
|
|
748
|
+
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", P.audio)],
|
|
749
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", P.video)]
|
|
750
750
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
751
751
|
}
|
|
752
|
-
function
|
|
753
|
-
let t =
|
|
752
|
+
function F(e) {
|
|
753
|
+
let t = I(e);
|
|
754
754
|
if (/^avc[13]/.test(t)) return "avc";
|
|
755
755
|
if (/^(hvc1|hev1)/.test(t)) return "hevc";
|
|
756
756
|
if (/^(dvh1|dvhe)/.test(t)) return "dv";
|
|
757
757
|
if (t.startsWith("av01")) return "av1";
|
|
758
758
|
if (/^vp0?9/.test(t)) return "vp9";
|
|
759
759
|
}
|
|
760
|
-
function
|
|
760
|
+
function I(e) {
|
|
761
761
|
return (e ?? "").trim().toLowerCase();
|
|
762
762
|
}
|
|
763
|
-
var
|
|
763
|
+
var qe = {
|
|
764
764
|
hevc: "hvc1.1.6.L93.90",
|
|
765
765
|
dv: "dvh1.05.06",
|
|
766
766
|
av1: "av01.0.05M.08",
|
|
767
767
|
vp9: "vp09.00.10.08"
|
|
768
|
-
},
|
|
769
|
-
function
|
|
770
|
-
let t =
|
|
768
|
+
}, Je = /* @__PURE__ */ new Map(), L = /* @__PURE__ */ new Map();
|
|
769
|
+
function Ye(e) {
|
|
770
|
+
let t = I(e), n = Je.get(t);
|
|
771
771
|
if (n) return n;
|
|
772
772
|
let r = {
|
|
773
773
|
initDataTypes: ["cenc"],
|
|
@@ -776,32 +776,32 @@ function qe(e) {
|
|
|
776
776
|
sessionTypes: ["temporary"],
|
|
777
777
|
videoCapabilities: [{
|
|
778
778
|
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
779
|
-
robustness:
|
|
780
|
-
encryptionScheme:
|
|
779
|
+
robustness: P.video,
|
|
780
|
+
encryptionScheme: P.scheme
|
|
781
781
|
}]
|
|
782
782
|
}, i = (async () => {
|
|
783
783
|
try {
|
|
784
|
-
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha",
|
|
784
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", N("com.widevine.alpha", [r])), !0;
|
|
785
785
|
} catch {
|
|
786
786
|
return !1;
|
|
787
787
|
}
|
|
788
|
-
})().then((e) => (
|
|
789
|
-
return
|
|
788
|
+
})().then((e) => (L.set(t, e), e));
|
|
789
|
+
return Je.set(t, i), i;
|
|
790
790
|
}
|
|
791
|
-
function
|
|
792
|
-
if (
|
|
791
|
+
function Xe() {
|
|
792
|
+
if (j()) for (let e of Object.values(qe)) Ye(e);
|
|
793
793
|
}
|
|
794
|
-
function
|
|
795
|
-
let t =
|
|
796
|
-
if (t) return t === "avc" ? !0 :
|
|
794
|
+
function Ze(e) {
|
|
795
|
+
let t = F(e);
|
|
796
|
+
if (t) return t === "avc" ? !0 : L.get(I(e)) ?? L.get(I(qe[t]));
|
|
797
797
|
}
|
|
798
798
|
//#endregion
|
|
799
799
|
//#region src/core/drm/support.ts
|
|
800
|
-
var
|
|
800
|
+
var Qe = 5e3, $e = "video/mp4; codecs=\"avc1.42E01E\"", et = "audio/mp4; codecs=\"mp4a.40.2\"", tt = {
|
|
801
801
|
widevine: ["com.widevine.alpha"],
|
|
802
802
|
fairplay: ["com.apple.fps"]
|
|
803
803
|
};
|
|
804
|
-
function
|
|
804
|
+
function nt(e) {
|
|
805
805
|
return e === "fairplay" ? [{
|
|
806
806
|
initDataTypes: [
|
|
807
807
|
"sinf",
|
|
@@ -809,30 +809,30 @@ function et(e) {
|
|
|
809
809
|
"cenc"
|
|
810
810
|
],
|
|
811
811
|
videoCapabilities: [{
|
|
812
|
-
contentType:
|
|
812
|
+
contentType: $e,
|
|
813
813
|
robustness: "",
|
|
814
814
|
encryptionScheme: "cbcs"
|
|
815
815
|
}],
|
|
816
816
|
audioCapabilities: [{
|
|
817
|
-
contentType:
|
|
817
|
+
contentType: et,
|
|
818
818
|
robustness: "",
|
|
819
819
|
encryptionScheme: "cbcs"
|
|
820
820
|
}]
|
|
821
|
-
}] :
|
|
821
|
+
}] : N("com.widevine.alpha", [{
|
|
822
822
|
initDataTypes: ["cenc"],
|
|
823
823
|
videoCapabilities: [{
|
|
824
|
-
contentType:
|
|
825
|
-
robustness:
|
|
826
|
-
encryptionScheme:
|
|
824
|
+
contentType: $e,
|
|
825
|
+
robustness: P.video,
|
|
826
|
+
encryptionScheme: P.scheme
|
|
827
827
|
}],
|
|
828
828
|
audioCapabilities: [{
|
|
829
|
-
contentType:
|
|
830
|
-
robustness:
|
|
831
|
-
encryptionScheme:
|
|
829
|
+
contentType: et,
|
|
830
|
+
robustness: P.audio,
|
|
831
|
+
encryptionScheme: P.scheme
|
|
832
832
|
}]
|
|
833
833
|
}]);
|
|
834
834
|
}
|
|
835
|
-
function
|
|
835
|
+
function rt(e, t) {
|
|
836
836
|
return new Promise((n, r) => {
|
|
837
837
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
838
838
|
e.then((e) => {
|
|
@@ -842,8 +842,8 @@ function tt(e, t) {
|
|
|
842
842
|
});
|
|
843
843
|
});
|
|
844
844
|
}
|
|
845
|
-
async function
|
|
846
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
845
|
+
async function it(e = {}) {
|
|
846
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Qe, r = {};
|
|
847
847
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
848
848
|
verdict: "insecure-context",
|
|
849
849
|
detail: r
|
|
@@ -855,7 +855,7 @@ async function nt(e = {}) {
|
|
|
855
855
|
};
|
|
856
856
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
857
857
|
for (let e of t) {
|
|
858
|
-
let t =
|
|
858
|
+
let t = tt[e];
|
|
859
859
|
if (!t) {
|
|
860
860
|
r[e] = "unknown system";
|
|
861
861
|
continue;
|
|
@@ -866,7 +866,7 @@ async function nt(e = {}) {
|
|
|
866
866
|
break;
|
|
867
867
|
}
|
|
868
868
|
try {
|
|
869
|
-
return await
|
|
869
|
+
return await rt((await rt(i(n, nt(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
870
870
|
verdict: "supported",
|
|
871
871
|
system: e,
|
|
872
872
|
detail: r
|
|
@@ -890,49 +890,70 @@ async function nt(e = {}) {
|
|
|
890
890
|
}
|
|
891
891
|
//#endregion
|
|
892
892
|
//#region src/core/manifest.ts
|
|
893
|
-
var
|
|
894
|
-
function
|
|
895
|
-
return
|
|
893
|
+
var at = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
894
|
+
function ot(e) {
|
|
895
|
+
return at.test(e);
|
|
896
896
|
}
|
|
897
897
|
//#endregion
|
|
898
898
|
//#region src/core/env.ts
|
|
899
|
-
var
|
|
899
|
+
var st = {
|
|
900
900
|
integration: "https://feed-dev.oddin-video.gg",
|
|
901
901
|
production: "https://feed.oddin-video.gg"
|
|
902
902
|
};
|
|
903
|
-
function
|
|
904
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
903
|
+
function ct(e) {
|
|
904
|
+
let t = Object.prototype.hasOwnProperty.call(st, e) ? st[e] : void 0;
|
|
905
905
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
906
906
|
return t;
|
|
907
907
|
}
|
|
908
908
|
//#endregion
|
|
909
|
+
//#region src/core/connectivity.ts
|
|
910
|
+
function R() {
|
|
911
|
+
return typeof navigator > "u" || navigator.onLine !== !1;
|
|
912
|
+
}
|
|
913
|
+
function lt() {
|
|
914
|
+
let e = /* @__PURE__ */ new Set(), t = (t) => {
|
|
915
|
+
for (let n of Array.from(e)) n(t);
|
|
916
|
+
}, n = () => t(!0), r = () => t(!1), i = typeof window < "u" && typeof window.addEventListener == "function";
|
|
917
|
+
return i && (window.addEventListener("online", n), window.addEventListener("offline", r)), {
|
|
918
|
+
isOnline: R,
|
|
919
|
+
onChange(t) {
|
|
920
|
+
return e.add(t), () => {
|
|
921
|
+
e.delete(t);
|
|
922
|
+
};
|
|
923
|
+
},
|
|
924
|
+
destroy() {
|
|
925
|
+
e.clear(), i && (window.removeEventListener("online", n), window.removeEventListener("offline", r));
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
//#endregion
|
|
909
930
|
//#region src/core/stats.ts
|
|
910
|
-
var
|
|
911
|
-
function
|
|
931
|
+
var ut = { droppedFrames: 0 };
|
|
932
|
+
function dt(e) {
|
|
912
933
|
try {
|
|
913
934
|
return new URL(e).host;
|
|
914
935
|
} catch {
|
|
915
936
|
return "";
|
|
916
937
|
}
|
|
917
938
|
}
|
|
918
|
-
var
|
|
919
|
-
function
|
|
939
|
+
var ft = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
940
|
+
function pt(e) {
|
|
920
941
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
921
942
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
922
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
923
|
-
let e =
|
|
943
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || ft.test(i.name)) && i.startTime >= n) {
|
|
944
|
+
let e = dt(i.name);
|
|
924
945
|
e && (t = e, n = i.startTime);
|
|
925
946
|
}
|
|
926
947
|
return t;
|
|
927
948
|
}
|
|
928
|
-
function
|
|
949
|
+
function z(e) {
|
|
929
950
|
let t = e.getVideoPlaybackQuality?.();
|
|
930
951
|
return {
|
|
931
952
|
dropped: t?.droppedVideoFrames ?? 0,
|
|
932
953
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
933
954
|
};
|
|
934
955
|
}
|
|
935
|
-
var
|
|
956
|
+
var mt = class {
|
|
936
957
|
video;
|
|
937
958
|
baseFrames = 0;
|
|
938
959
|
baseDropped = 0;
|
|
@@ -942,7 +963,7 @@ var dt = class {
|
|
|
942
963
|
this.video = e;
|
|
943
964
|
}
|
|
944
965
|
read() {
|
|
945
|
-
let e =
|
|
966
|
+
let e = z(this.video);
|
|
946
967
|
return e.totalFrames < this.lastFrames && (this.baseFrames += this.lastFrames), e.dropped < this.lastDropped && (this.baseDropped += this.lastDropped), this.lastFrames = e.totalFrames, this.lastDropped = e.dropped, {
|
|
947
968
|
dropped: this.baseDropped + e.dropped,
|
|
948
969
|
totalFrames: this.baseFrames + e.totalFrames
|
|
@@ -955,7 +976,7 @@ var dt = class {
|
|
|
955
976
|
};
|
|
956
977
|
}
|
|
957
978
|
};
|
|
958
|
-
function
|
|
979
|
+
function ht(e, t) {
|
|
959
980
|
let n = [
|
|
960
981
|
["playing", () => t("playing")],
|
|
961
982
|
["waiting", () => t("buffering")],
|
|
@@ -972,8 +993,8 @@ function ft(e, t) {
|
|
|
972
993
|
}
|
|
973
994
|
//#endregion
|
|
974
995
|
//#region src/core/engine/native.ts
|
|
975
|
-
var
|
|
976
|
-
function
|
|
996
|
+
var gt = 2e3, _t = 3, B = 500, vt = 6e3, yt = .25, bt = 250, xt = .05, St = 4, Ct = 12e3, wt = .25, Tt = 1e3;
|
|
997
|
+
function Et(e) {
|
|
977
998
|
try {
|
|
978
999
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
979
1000
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -981,20 +1002,20 @@ function Ct(e) {
|
|
|
981
1002
|
return;
|
|
982
1003
|
}
|
|
983
1004
|
}
|
|
984
|
-
function
|
|
1005
|
+
function V(e) {
|
|
985
1006
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
986
1007
|
}
|
|
987
|
-
function
|
|
1008
|
+
function H() {
|
|
988
1009
|
if (typeof window > "u") return !1;
|
|
989
1010
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
990
1011
|
return e || t;
|
|
991
1012
|
}
|
|
992
|
-
function
|
|
993
|
-
if (typeof navigator > "u" || !
|
|
1013
|
+
function Dt() {
|
|
1014
|
+
if (typeof navigator > "u" || !H()) return !1;
|
|
994
1015
|
let e = navigator.userAgent ?? "";
|
|
995
1016
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
996
1017
|
}
|
|
997
|
-
var
|
|
1018
|
+
var U = class {
|
|
998
1019
|
name = "native";
|
|
999
1020
|
deps;
|
|
1000
1021
|
onLoaded;
|
|
@@ -1024,7 +1045,7 @@ var W = class {
|
|
|
1024
1045
|
frameCounter;
|
|
1025
1046
|
detachFrames = null;
|
|
1026
1047
|
constructor(e) {
|
|
1027
|
-
this.deps = e, this.frameCounter = new
|
|
1048
|
+
this.deps = e, this.frameCounter = new mt(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
|
|
1028
1049
|
}
|
|
1029
1050
|
async load() {
|
|
1030
1051
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1043,9 +1064,9 @@ var W = class {
|
|
|
1043
1064
|
let i = !this.loadStarted;
|
|
1044
1065
|
this.onLoaded = i ? void 0 : () => r({ type: "ready" }), this.onError = () => r({
|
|
1045
1066
|
type: "error",
|
|
1046
|
-
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
1067
|
+
error: R() ? new n("INTERNAL", 0, "native HLS playback error") : new n("NETWORK", 0, "native HLS playback error while offline"),
|
|
1047
1068
|
fatal: !0
|
|
1048
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
1069
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = kt(t.manifestUrl, t.analytics?.sid), e.load();
|
|
1049
1070
|
}
|
|
1050
1071
|
startLoad() {
|
|
1051
1072
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -1073,7 +1094,7 @@ var W = class {
|
|
|
1073
1094
|
};
|
|
1074
1095
|
this.onEncrypted = (n) => {
|
|
1075
1096
|
let a = n;
|
|
1076
|
-
a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
1097
|
+
a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Et(a.initData), (async () => {
|
|
1077
1098
|
try {
|
|
1078
1099
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
1079
1100
|
initDataTypes: [a.initDataType],
|
|
@@ -1173,10 +1194,10 @@ var W = class {
|
|
|
1173
1194
|
droppedFrames: t.dropped,
|
|
1174
1195
|
decodedFrames: t.totalFrames
|
|
1175
1196
|
};
|
|
1176
|
-
if (this.cdnHost ||=
|
|
1197
|
+
if (this.cdnHost ||= pt(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1177
1198
|
n.isLive = !0;
|
|
1178
1199
|
let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
|
|
1179
|
-
Number.isFinite(r) && (n.atLiveEdge = r <=
|
|
1200
|
+
Number.isFinite(r) && (n.atLiveEdge = r <= St, !e.paused && r >= 0 && (n.latencySeconds = r));
|
|
1180
1201
|
} else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
|
|
1181
1202
|
return n;
|
|
1182
1203
|
}
|
|
@@ -1188,30 +1209,30 @@ var W = class {
|
|
|
1188
1209
|
}
|
|
1189
1210
|
watchRefocus() {
|
|
1190
1211
|
this.deps.snapToLiveOnRefocus === !1 || typeof document > "u" || this.onVisibility || (this.onVisibility = () => {
|
|
1191
|
-
let e =
|
|
1212
|
+
let e = W();
|
|
1192
1213
|
if (document.visibilityState === "hidden") {
|
|
1193
1214
|
this.hiddenSince = e, this.cancelRefocus();
|
|
1194
1215
|
return;
|
|
1195
1216
|
}
|
|
1196
1217
|
let t = this.hiddenSince;
|
|
1197
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1218
|
+
this.hiddenSince = null, t != null && e - t >= gt && this.armRefocus();
|
|
1198
1219
|
}, this.onPageShow = (e) => {
|
|
1199
1220
|
e.persisted && this.armRefocus();
|
|
1200
1221
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
1201
1222
|
}
|
|
1202
1223
|
armRefocus() {
|
|
1203
1224
|
if (this.cancelRefocus(), Number.isFinite(this.deps.video.duration)) return;
|
|
1204
|
-
let e = this.liveEnd(), t =
|
|
1225
|
+
let e = this.liveEnd(), t = W, n = t(), r = 0, i = () => {
|
|
1205
1226
|
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1206
|
-
r +=
|
|
1207
|
-
let a = this.liveEnd(), o = a != null && (e == null || a >= e +
|
|
1227
|
+
r += B;
|
|
1228
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + yt), s = Math.max(r, t() - n) >= vt;
|
|
1208
1229
|
if (o || s && a != null) {
|
|
1209
1230
|
this.snapToLive();
|
|
1210
1231
|
return;
|
|
1211
1232
|
}
|
|
1212
|
-
this.refocusTimer = setTimeout(i,
|
|
1233
|
+
this.refocusTimer = setTimeout(i, B);
|
|
1213
1234
|
};
|
|
1214
|
-
this.refocusTimer = setTimeout(i,
|
|
1235
|
+
this.refocusTimer = setTimeout(i, B);
|
|
1215
1236
|
}
|
|
1216
1237
|
cancelRefocus() {
|
|
1217
1238
|
this.refocusTimer != null && clearTimeout(this.refocusTimer), this.refocusTimer = null;
|
|
@@ -1224,24 +1245,24 @@ var W = class {
|
|
|
1224
1245
|
}, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
|
|
1225
1246
|
if (e.duration !== Infinity) return;
|
|
1226
1247
|
this.checkEndStale();
|
|
1227
|
-
let t =
|
|
1228
|
-
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >=
|
|
1229
|
-
},
|
|
1248
|
+
let t = Ot(e, e.currentTime);
|
|
1249
|
+
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= xt) && (this.bufferedAdvancedAt = W()), this.lastBufferedEnd = t);
|
|
1250
|
+
}, bt);
|
|
1230
1251
|
}
|
|
1231
1252
|
checkEndStale() {
|
|
1232
1253
|
if (this.endedEmitted) return;
|
|
1233
|
-
let e =
|
|
1254
|
+
let e = W(), t = this.lastTickAt == null ? 0 : e - this.lastTickAt;
|
|
1234
1255
|
this.lastTickAt = e;
|
|
1235
1256
|
let n = this.liveEnd();
|
|
1236
1257
|
if (n == null) return;
|
|
1237
|
-
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >=
|
|
1258
|
+
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= wt;
|
|
1238
1259
|
this.lastSeekableEnd = n;
|
|
1239
1260
|
let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
|
|
1240
|
-
if (r || t >
|
|
1261
|
+
if (r || t > Tt || a || i.paused) {
|
|
1241
1262
|
this.edgeStampedAt = e;
|
|
1242
1263
|
return;
|
|
1243
1264
|
}
|
|
1244
|
-
e - (this.edgeStampedAt ?? e) >
|
|
1265
|
+
e - (this.edgeStampedAt ?? e) > Ct && (this.endedEmitted = !0, this.deps.emit({
|
|
1245
1266
|
type: "ended",
|
|
1246
1267
|
reason: "stalled"
|
|
1247
1268
|
}));
|
|
@@ -1255,9 +1276,9 @@ var W = class {
|
|
|
1255
1276
|
liveEdgeEstimate() {
|
|
1256
1277
|
let e = this.deps.video;
|
|
1257
1278
|
if (e.duration !== Infinity) return null;
|
|
1258
|
-
let t = this.liveEnd(), n =
|
|
1279
|
+
let t = this.liveEnd(), n = Ot(e, e.currentTime) ?? this.lastBufferedEnd;
|
|
1259
1280
|
if (n != null) {
|
|
1260
|
-
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (
|
|
1281
|
+
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (W() - e) / 1e3));
|
|
1261
1282
|
(t == null || r > t) && (t = r);
|
|
1262
1283
|
}
|
|
1263
1284
|
return t != null && Number.isFinite(t) ? t : null;
|
|
@@ -1271,7 +1292,7 @@ var W = class {
|
|
|
1271
1292
|
snapToLive() {
|
|
1272
1293
|
let e = this.deps.video, t = this.liveEnd();
|
|
1273
1294
|
if (t == null) return;
|
|
1274
|
-
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t -
|
|
1295
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - _t, r);
|
|
1275
1296
|
try {
|
|
1276
1297
|
e.currentTime = i;
|
|
1277
1298
|
} catch {}
|
|
@@ -1289,10 +1310,10 @@ var W = class {
|
|
|
1289
1310
|
} catch {}
|
|
1290
1311
|
}
|
|
1291
1312
|
};
|
|
1292
|
-
function
|
|
1313
|
+
function W() {
|
|
1293
1314
|
return typeof performance < "u" ? performance.now() : Date.now();
|
|
1294
1315
|
}
|
|
1295
|
-
function
|
|
1316
|
+
function Ot(e, t) {
|
|
1296
1317
|
let n = e.buffered;
|
|
1297
1318
|
if (!n || !Number.isFinite(t)) return null;
|
|
1298
1319
|
for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
|
|
@@ -1301,12 +1322,12 @@ function Tt(e, t) {
|
|
|
1301
1322
|
}
|
|
1302
1323
|
return null;
|
|
1303
1324
|
}
|
|
1304
|
-
function
|
|
1325
|
+
function kt(e, t) {
|
|
1305
1326
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1306
1327
|
}
|
|
1307
1328
|
//#endregion
|
|
1308
1329
|
//#region src/core/drm/signedUrl.ts
|
|
1309
|
-
function
|
|
1330
|
+
function G(e, t = Date.now()) {
|
|
1310
1331
|
if (!e) return !1;
|
|
1311
1332
|
let n;
|
|
1312
1333
|
try {
|
|
@@ -1318,13 +1339,13 @@ function K(e, t = Date.now()) {
|
|
|
1318
1339
|
}
|
|
1319
1340
|
//#endregion
|
|
1320
1341
|
//#region src/core/drm/xhrBody.ts
|
|
1321
|
-
var
|
|
1322
|
-
function
|
|
1342
|
+
var At = 4096;
|
|
1343
|
+
function jt(e) {
|
|
1323
1344
|
if (!e || typeof e != "object") return;
|
|
1324
1345
|
let { response: t } = e;
|
|
1325
1346
|
if (typeof t == "string") return t;
|
|
1326
1347
|
let n;
|
|
1327
|
-
if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength >
|
|
1348
|
+
if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength > At)) try {
|
|
1328
1349
|
return new TextDecoder().decode(n);
|
|
1329
1350
|
} catch {
|
|
1330
1351
|
return;
|
|
@@ -1332,8 +1353,8 @@ function Ot(e) {
|
|
|
1332
1353
|
}
|
|
1333
1354
|
//#endregion
|
|
1334
1355
|
//#region src/core/engine/prefetch.ts
|
|
1335
|
-
var
|
|
1336
|
-
function
|
|
1356
|
+
var Mt = 15e3, Nt = 5e3, Pt = 6, Ft = 4e3, It = 2;
|
|
1357
|
+
function K(e) {
|
|
1337
1358
|
try {
|
|
1338
1359
|
let t = new URL(e);
|
|
1339
1360
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1341,17 +1362,23 @@ function Mt(e) {
|
|
|
1341
1362
|
return e;
|
|
1342
1363
|
}
|
|
1343
1364
|
}
|
|
1344
|
-
var
|
|
1365
|
+
var Lt = class {
|
|
1345
1366
|
cmcd;
|
|
1346
1367
|
entries = /* @__PURE__ */ new Map();
|
|
1347
1368
|
keyed = /* @__PURE__ */ new Set();
|
|
1348
1369
|
perTrack = /* @__PURE__ */ new Map();
|
|
1370
|
+
hints = /* @__PURE__ */ new Map();
|
|
1349
1371
|
stats = {
|
|
1350
1372
|
started: 0,
|
|
1351
1373
|
served: 0,
|
|
1352
1374
|
missed: 0,
|
|
1353
1375
|
failed: 0,
|
|
1354
|
-
expired: 0
|
|
1376
|
+
expired: 0,
|
|
1377
|
+
hintStarted: 0,
|
|
1378
|
+
hintServed: 0,
|
|
1379
|
+
hintFailed: 0,
|
|
1380
|
+
hintExpired: 0,
|
|
1381
|
+
hintDropped: 0
|
|
1355
1382
|
};
|
|
1356
1383
|
constructor(e = {}) {
|
|
1357
1384
|
this.cmcd = e;
|
|
@@ -1364,32 +1391,58 @@ var Nt = class {
|
|
|
1364
1391
|
}
|
|
1365
1392
|
prefetch(e, t, n) {
|
|
1366
1393
|
if (!this.isActive(t)) return;
|
|
1367
|
-
let r =
|
|
1394
|
+
let r = K(e);
|
|
1368
1395
|
if (this.entries.has(r)) return;
|
|
1369
1396
|
let i = this.perTrack.get(t) ?? 0;
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1397
|
+
i >= Pt || (this.perTrack.set(t, i + 1), this.start(r, this.withCmcd(e, t, n), !1, Mt), this.stats.started += 1);
|
|
1398
|
+
}
|
|
1399
|
+
prefetchHint(e, t) {
|
|
1400
|
+
let n = K(e);
|
|
1401
|
+
if (this.entries.has(n)) return;
|
|
1402
|
+
let r = this.hints.get(t) ?? [];
|
|
1403
|
+
for (; r.length >= It;) {
|
|
1404
|
+
let e = r.shift();
|
|
1405
|
+
e !== void 0 && this.drop(e) && (this.stats.hintDropped += 1);
|
|
1406
|
+
}
|
|
1407
|
+
r.push(n), this.hints.set(t, r), this.start(n, this.withCmcd(e, t, "media"), !0, Ft), this.stats.hintStarted += 1;
|
|
1408
|
+
}
|
|
1409
|
+
dropHints(e) {
|
|
1410
|
+
for (let t of this.hints.get(e) ?? []) this.drop(t) && (this.stats.hintDropped += 1);
|
|
1411
|
+
this.hints.delete(e);
|
|
1412
|
+
}
|
|
1413
|
+
drop(e) {
|
|
1414
|
+
let t = this.entries.get(e);
|
|
1415
|
+
return t ? (this.entries.delete(e), t.abort.abort(), !0) : !1;
|
|
1416
|
+
}
|
|
1417
|
+
start(e, t, n, r) {
|
|
1418
|
+
let i = new AbortController(), a = {
|
|
1373
1419
|
started: performance.now(),
|
|
1374
1420
|
first: 0,
|
|
1421
|
+
end: 0,
|
|
1422
|
+
hint: n,
|
|
1423
|
+
headers: Promise.resolve(),
|
|
1375
1424
|
bytes: Promise.resolve(null),
|
|
1376
|
-
abort:
|
|
1377
|
-
};
|
|
1378
|
-
|
|
1425
|
+
abort: i
|
|
1426
|
+
}, o = () => {};
|
|
1427
|
+
a.headers = new Promise((e) => o = e), a.bytes = fetch(t, {
|
|
1379
1428
|
credentials: "omit",
|
|
1380
1429
|
mode: "cors",
|
|
1381
|
-
signal:
|
|
1382
|
-
}).then(async (e) =>
|
|
1383
|
-
|
|
1384
|
-
|
|
1430
|
+
signal: i.signal
|
|
1431
|
+
}).then(async (e) => {
|
|
1432
|
+
if (a.first = performance.now(), o(), !e.ok) return null;
|
|
1433
|
+
let t = await e.arrayBuffer();
|
|
1434
|
+
return a.end = performance.now(), t;
|
|
1435
|
+
}).catch(() => null).finally(o), this.entries.set(e, a), setTimeout(() => {
|
|
1436
|
+
this.entries.get(e) === a && (this.entries.delete(e), i.abort(), n ? this.stats.hintExpired += 1 : this.stats.expired += 1);
|
|
1437
|
+
}, r);
|
|
1385
1438
|
}
|
|
1386
1439
|
take(e) {
|
|
1387
|
-
let t =
|
|
1440
|
+
let t = K(e), n = this.entries.get(t);
|
|
1388
1441
|
return n && this.entries.delete(t), n;
|
|
1389
1442
|
}
|
|
1390
1443
|
destroy() {
|
|
1391
1444
|
for (let e of this.entries.values()) e.abort.abort();
|
|
1392
|
-
this.entries.clear();
|
|
1445
|
+
this.entries.clear(), this.hints.clear();
|
|
1393
1446
|
}
|
|
1394
1447
|
withCmcd(e, t, n) {
|
|
1395
1448
|
let { sessionId: r, contentId: i } = this.cmcd;
|
|
@@ -1404,40 +1457,51 @@ var Nt = class {
|
|
|
1404
1457
|
}
|
|
1405
1458
|
}
|
|
1406
1459
|
};
|
|
1407
|
-
function
|
|
1460
|
+
function Rt(t) {
|
|
1408
1461
|
let n = e.DefaultConfig?.loader;
|
|
1409
1462
|
if (typeof n != "function") return;
|
|
1410
1463
|
class r extends n {
|
|
1411
1464
|
served = !1;
|
|
1412
1465
|
cancelled = !1;
|
|
1413
|
-
|
|
1466
|
+
entry;
|
|
1467
|
+
stats = zt();
|
|
1414
1468
|
load(e, n, r) {
|
|
1415
1469
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1416
1470
|
if (!i) {
|
|
1417
1471
|
super.load(e, n, r);
|
|
1418
1472
|
return;
|
|
1419
1473
|
}
|
|
1420
|
-
this.served = !0;
|
|
1421
|
-
let a = performance.now(), o =
|
|
1422
|
-
|
|
1423
|
-
},
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1474
|
+
this.served = !0, this.entry = i;
|
|
1475
|
+
let a = performance.now(), o = () => {
|
|
1476
|
+
i.hint ? t.stats.hintFailed += 1 : t.stats.failed += 1;
|
|
1477
|
+
}, s = () => {
|
|
1478
|
+
!this.cancelled && this.served && (i.abort.abort(), o(), this.served = !1, this.entry = void 0, super.load(e, n, r));
|
|
1479
|
+
}, c = n?.loadPolicy, l = c?.maxTimeToFirstByteMs || Nt, u = setTimeout(s, l);
|
|
1480
|
+
i.headers.then(() => {
|
|
1481
|
+
clearTimeout(u);
|
|
1482
|
+
let e = c?.maxLoadTimeMs;
|
|
1483
|
+
e && (u = setTimeout(s, Math.max(0, e - (performance.now() - a))));
|
|
1484
|
+
}), i.bytes.then((s) => {
|
|
1485
|
+
if (clearTimeout(u), this.cancelled || !this.served) return;
|
|
1486
|
+
if (!s) {
|
|
1487
|
+
o(), this.served = !1, super.load(e, n, r);
|
|
1428
1488
|
return;
|
|
1429
1489
|
}
|
|
1430
|
-
t.stats.served += 1;
|
|
1431
1490
|
let c = this.stats;
|
|
1432
|
-
|
|
1491
|
+
if (i.hint) {
|
|
1492
|
+
t.stats.hintServed += 1;
|
|
1493
|
+
let e = performance.now(), n = Math.max(0, (i.end || e) - (i.first || e)), r = Math.max(0, (i.first || e) - a);
|
|
1494
|
+
c.loading.end = e, c.loading.first = e - n, c.loading.start = c.loading.first - r;
|
|
1495
|
+
} else t.stats.served += 1, c.loading.start = a, c.loading.first = Math.max(a, i.first || a), c.loading.end = performance.now();
|
|
1496
|
+
c.loaded = c.total = s.byteLength, this.entry = void 0, r.onSuccess({
|
|
1433
1497
|
url: e.url,
|
|
1434
|
-
data:
|
|
1498
|
+
data: s
|
|
1435
1499
|
}, c, e, null);
|
|
1436
1500
|
});
|
|
1437
1501
|
}
|
|
1438
1502
|
abort() {
|
|
1439
1503
|
if (this.served) {
|
|
1440
|
-
this.cancelled = !0, this.stats.aborted = !0;
|
|
1504
|
+
this.cancelled = !0, this.stats.aborted = !0, this.entry?.abort.abort(), this.entry = void 0;
|
|
1441
1505
|
return;
|
|
1442
1506
|
}
|
|
1443
1507
|
super.abort();
|
|
@@ -1445,7 +1509,7 @@ function Pt(t) {
|
|
|
1445
1509
|
}
|
|
1446
1510
|
return r;
|
|
1447
1511
|
}
|
|
1448
|
-
function
|
|
1512
|
+
function zt() {
|
|
1449
1513
|
return {
|
|
1450
1514
|
aborted: !1,
|
|
1451
1515
|
loaded: 0,
|
|
@@ -1469,10 +1533,10 @@ function Ft() {
|
|
|
1469
1533
|
}
|
|
1470
1534
|
};
|
|
1471
1535
|
}
|
|
1472
|
-
function
|
|
1536
|
+
function Bt(e) {
|
|
1473
1537
|
return e === "audio" ? "audio" : "main";
|
|
1474
1538
|
}
|
|
1475
|
-
function
|
|
1539
|
+
function Vt(e, t) {
|
|
1476
1540
|
let n = [];
|
|
1477
1541
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1478
1542
|
url: t.initSegment.url,
|
|
@@ -1489,6 +1553,17 @@ function Lt(e, t) {
|
|
|
1489
1553
|
});
|
|
1490
1554
|
return n;
|
|
1491
1555
|
}
|
|
1556
|
+
function Ht(e) {
|
|
1557
|
+
let t = e, n = t?.preloadHint;
|
|
1558
|
+
if (!n || !t?.url || n.TYPE !== "PART" || n["BYTERANGE-START"] !== void 0 || n["BYTERANGE-LENGTH"] !== void 0) return null;
|
|
1559
|
+
let r = n.URI;
|
|
1560
|
+
if (typeof r != "string" || !r) return null;
|
|
1561
|
+
try {
|
|
1562
|
+
return new URL(r, t.url).toString();
|
|
1563
|
+
} catch {
|
|
1564
|
+
return null;
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1492
1567
|
//#endregion
|
|
1493
1568
|
//#region src/core/percentile.ts
|
|
1494
1569
|
function q(e, t) {
|
|
@@ -1496,11 +1571,11 @@ function q(e, t) {
|
|
|
1496
1571
|
}
|
|
1497
1572
|
//#endregion
|
|
1498
1573
|
//#region src/core/engine/hls.ts
|
|
1499
|
-
function
|
|
1574
|
+
function Ut() {
|
|
1500
1575
|
return e.isSupported();
|
|
1501
1576
|
}
|
|
1502
|
-
var
|
|
1503
|
-
function
|
|
1577
|
+
var Wt = 3, Gt = 1e6, Kt = 20, qt = 1e4, Jt = 3, Yt = 5, Xt = 3, Zt = 1e4, Qt = 3e4, $t = 12e3, en = 3e3, tn = .02, nn = 6e3, rn = .5, an = 3, on = .5, sn = 1.1, cn = .25, ln = 5e3, un = 4e3, dn = 2, fn = 5, pn = 2, mn = 2, hn = 4, gn = 4, _n = 2e3, vn = 3e4, yn = 1, bn = 2;
|
|
1578
|
+
function xn(e, t, n) {
|
|
1504
1579
|
if (n <= 0 || t < 0 || t >= e.length) return t;
|
|
1505
1580
|
let r = (t, n) => e[t].width === e[n].width && e[t].height === e[n].height, i = (t) => {
|
|
1506
1581
|
for (; t + 1 < e.length && r(t + 1, t);) t++;
|
|
@@ -1509,11 +1584,11 @@ function hn(e, t, n) {
|
|
|
1509
1584
|
for (let t = 0; t < n && a + 1 < e.length; t++) a = i(a + 1);
|
|
1510
1585
|
return a;
|
|
1511
1586
|
}
|
|
1512
|
-
var
|
|
1513
|
-
function
|
|
1587
|
+
var Sn = .2, Cn = 30, wn = 2, Tn = 2, En = 2, Dn = 9, On = .5, kn = 64, An = 1e4, jn = 8, Mn = .6, Nn = .4, Pn = .4, Fn = 2, In = 6e4, J = .5, Ln = 3.5, Rn = 300;
|
|
1588
|
+
function zn(e) {
|
|
1514
1589
|
return (e?.part ?? e?.frag)?.stats;
|
|
1515
1590
|
}
|
|
1516
|
-
function
|
|
1591
|
+
function Bn() {
|
|
1517
1592
|
if (typeof navigator > "u") return 0;
|
|
1518
1593
|
try {
|
|
1519
1594
|
let e = navigator.connection?.rtt;
|
|
@@ -1522,20 +1597,20 @@ function Pn() {
|
|
|
1522
1597
|
return 0;
|
|
1523
1598
|
}
|
|
1524
1599
|
}
|
|
1525
|
-
function
|
|
1600
|
+
function Vn(e) {
|
|
1526
1601
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1527
1602
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1528
1603
|
return;
|
|
1529
1604
|
}
|
|
1530
|
-
e.liveSyncDuration ??=
|
|
1531
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1532
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1605
|
+
e.liveSyncDuration ??= En;
|
|
1606
|
+
let t = Math.max(12, e.liveSyncDuration + Dn);
|
|
1607
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Hn(e, e.liveSyncDuration);
|
|
1533
1608
|
}
|
|
1534
|
-
function
|
|
1609
|
+
function Hn(e, t) {
|
|
1535
1610
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1536
1611
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1537
1612
|
}
|
|
1538
|
-
var
|
|
1613
|
+
var Un = class {
|
|
1539
1614
|
name = "hls";
|
|
1540
1615
|
hls = null;
|
|
1541
1616
|
deps;
|
|
@@ -1565,6 +1640,8 @@ var Ln = class {
|
|
|
1565
1640
|
recoveryResetTimer = null;
|
|
1566
1641
|
networkRetryTimer = null;
|
|
1567
1642
|
licenseRetryTimer = null;
|
|
1643
|
+
offlineHold = !1;
|
|
1644
|
+
onOnline = null;
|
|
1568
1645
|
onVisibility = null;
|
|
1569
1646
|
onSeeking = null;
|
|
1570
1647
|
onPause = null;
|
|
@@ -1629,11 +1706,11 @@ var Ln = class {
|
|
|
1629
1706
|
frameCounter;
|
|
1630
1707
|
detachFrames = null;
|
|
1631
1708
|
constructor(e) {
|
|
1632
|
-
this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.frameCounter = new
|
|
1709
|
+
this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.frameCounter = new mt(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1633
1710
|
}
|
|
1634
1711
|
async load() {
|
|
1635
1712
|
this.detachFrames ??= this.frameCounter.attach();
|
|
1636
|
-
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a =
|
|
1713
|
+
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = V(r) && H(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
1637
1714
|
if (e.drmEnabled && !o) {
|
|
1638
1715
|
i({
|
|
1639
1716
|
type: "error",
|
|
@@ -1642,14 +1719,21 @@ var Ln = class {
|
|
|
1642
1719
|
});
|
|
1643
1720
|
return;
|
|
1644
1721
|
}
|
|
1645
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1722
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ke(r), Xe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1646
1723
|
let e = this.hls;
|
|
1647
1724
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1648
1725
|
let t = e.liveSyncPosition;
|
|
1649
1726
|
if (typeof t != "number") return;
|
|
1650
1727
|
let n = typeof e.targetLatency == "number" && e.targetLatency > 0 ? e.targetLatency : 3;
|
|
1651
1728
|
t - r.currentTime > Math.max(n * 3, 8) && (r.currentTime = t);
|
|
1652
|
-
}, document.addEventListener("visibilitychange", this.onVisibility)), this.
|
|
1729
|
+
}, document.addEventListener("visibilitychange", this.onVisibility)), typeof window < "u" && (this.onOnline = () => {
|
|
1730
|
+
if (this.offlineHold && (this.offlineHold = !1, this.networkRecoveries = 0, this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), !this.stopped && this.hls)) {
|
|
1731
|
+
this.lastAdvanceMs = Date.now(), this.lastFragLoadingMs = 0, this.resetStarvationWindow(), this.resetChaseWindow(), this.clearKick();
|
|
1732
|
+
try {
|
|
1733
|
+
this.hls.startLoad();
|
|
1734
|
+
} catch {}
|
|
1735
|
+
}
|
|
1736
|
+
}, window.addEventListener("online", this.onOnline)), this.onSeeking = () => {
|
|
1653
1737
|
this.clampOverSeek(), this.loadSuspended && (this.resumeLoading(), this.schedulePauseSuspend());
|
|
1654
1738
|
}, r.addEventListener("seeking", this.onSeeking), this.onTimeUpdate = () => this.updateCatchUpBand(), r.addEventListener("timeupdate", this.onTimeUpdate), this.onPause = () => this.schedulePauseSuspend(), this.onPlay = () => this.resumeLoading(), r.addEventListener("pause", this.onPause), r.addEventListener("play", this.onPlay), this.sizeCapManaged && typeof ResizeObserver < "u" && (this.capObserver = new ResizeObserver(() => this.onMediaResize()), this.capObserver.observe(r), this.watchDprChanges());
|
|
1655
1739
|
}
|
|
@@ -1665,7 +1749,7 @@ var Ln = class {
|
|
|
1665
1749
|
}
|
|
1666
1750
|
this.loadSuspended = !0;
|
|
1667
1751
|
}
|
|
1668
|
-
},
|
|
1752
|
+
}, ln));
|
|
1669
1753
|
}
|
|
1670
1754
|
resumeLoading() {
|
|
1671
1755
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1697,7 +1781,7 @@ var Ln = class {
|
|
|
1697
1781
|
let t = e.liveSyncPosition;
|
|
1698
1782
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1699
1783
|
let { video: n } = this.deps;
|
|
1700
|
-
n.currentTime <= t +
|
|
1784
|
+
n.currentTime <= t + On || (n.currentTime = t);
|
|
1701
1785
|
}
|
|
1702
1786
|
reanchorPartTimeline(e, t) {
|
|
1703
1787
|
let { frag: n, part: r } = t;
|
|
@@ -1709,7 +1793,7 @@ var Ln = class {
|
|
|
1709
1793
|
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1710
1794
|
if (!s) return;
|
|
1711
1795
|
let c = a.startPTS - s.start;
|
|
1712
|
-
if (!(!Number.isFinite(c) || Math.abs(c) <
|
|
1796
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < tn)) {
|
|
1713
1797
|
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1714
1798
|
i.fragmentHint?.setStart(i.fragmentHint.start + c), this.deps.debug === !0 && console.info(`havik-player: LL-HLS timeline re-anchored by ${c >= 0 ? "+" : ""}${c.toFixed(3)}s at sn ${n.sn} (level ${n.level})`);
|
|
1715
1799
|
}
|
|
@@ -1717,7 +1801,7 @@ var Ln = class {
|
|
|
1717
1801
|
startHls() {
|
|
1718
1802
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
1719
1803
|
this.clearKick(), this.resetStarvationWindow(), this.resetChaseWindow(), this.resetFrameDropWindow(), this.lastFragLoadingMs = 0, this.lastEndSN = -1, this.lastAdvanceMs = 0;
|
|
1720
|
-
let u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d =
|
|
1804
|
+
let u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d = V(this.deps.video) && H(), f = {
|
|
1721
1805
|
debug: s === !0,
|
|
1722
1806
|
enableWorker: !o,
|
|
1723
1807
|
lowLatencyMode: o,
|
|
@@ -1732,24 +1816,24 @@ var Ln = class {
|
|
|
1732
1816
|
emeEnabled: !0,
|
|
1733
1817
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1734
1818
|
drmSystemOptions: {
|
|
1735
|
-
videoRobustness:
|
|
1736
|
-
audioRobustness:
|
|
1737
|
-
videoEncryptionScheme:
|
|
1738
|
-
audioEncryptionScheme:
|
|
1819
|
+
videoRobustness: P.video,
|
|
1820
|
+
audioRobustness: P.audio,
|
|
1821
|
+
videoEncryptionScheme: P.scheme,
|
|
1822
|
+
audioEncryptionScheme: P.scheme
|
|
1739
1823
|
},
|
|
1740
|
-
...
|
|
1824
|
+
...j() ? { requestMediaKeySystemAccessFunc: Ge(t) } : {},
|
|
1741
1825
|
licenseXhrSetup: (e, t) => {
|
|
1742
1826
|
let o = performance.now(), s = () => {
|
|
1743
1827
|
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), this.licenseRequested = !0, e.addEventListener("loadend", () => {
|
|
1744
1828
|
this.licenseTimeMs === 0 && (this.licenseTimeMs = Math.max(1, Math.round(performance.now() - o)));
|
|
1745
1829
|
});
|
|
1746
1830
|
}, { freshLicenseUrl: c } = this.deps;
|
|
1747
|
-
if (!c || !
|
|
1831
|
+
if (!c || !G(this.licenseUrl)) {
|
|
1748
1832
|
s();
|
|
1749
1833
|
return;
|
|
1750
1834
|
}
|
|
1751
1835
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1752
|
-
u = setTimeout(() => e(void 0),
|
|
1836
|
+
u = setTimeout(() => e(void 0), Zt);
|
|
1753
1837
|
});
|
|
1754
1838
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1755
1839
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1764,35 +1848,37 @@ var Ln = class {
|
|
|
1764
1848
|
} } : {},
|
|
1765
1849
|
...c
|
|
1766
1850
|
};
|
|
1767
|
-
|
|
1768
|
-
|
|
1851
|
+
this.prefetch?.destroy(), this.prefetch = null;
|
|
1852
|
+
let p = !1, m = !1, h = u && this.deps.mediaDuringKey !== !1, g = this.deps.preloadHints === !0;
|
|
1853
|
+
if ((h || g) && !f.fLoader) {
|
|
1854
|
+
let e = new Lt({
|
|
1769
1855
|
sessionId: n.analytics?.sid,
|
|
1770
1856
|
contentId: n.matchUrn
|
|
1771
|
-
}), t =
|
|
1772
|
-
t && (this.prefetch = e, f.fLoader = t);
|
|
1857
|
+
}), t = Rt(e);
|
|
1858
|
+
t && (this.prefetch = e, p = h, m = g, f.fLoader = t);
|
|
1773
1859
|
}
|
|
1774
|
-
|
|
1775
|
-
let
|
|
1776
|
-
if (this.hls =
|
|
1777
|
-
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(
|
|
1778
|
-
}),
|
|
1860
|
+
Vn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
|
|
1861
|
+
let _ = new e(f);
|
|
1862
|
+
if (this.hls = _, this.armHoldBack(_, f), _.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(_, t)), _.on(e.Events.MANIFEST_PARSED, () => {
|
|
1863
|
+
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(_), this.measureLadder(_), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1864
|
+
}), _.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1779
1865
|
t?.frag?.type === "main" && (this.kickKind !== "dead" && this.clearKick(), (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
1780
1866
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1781
|
-
},
|
|
1782
|
-
}),
|
|
1867
|
+
}, Qt)));
|
|
1868
|
+
}), _.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1783
1869
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1784
|
-
}),
|
|
1870
|
+
}), _.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
1785
1871
|
t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
|
|
1786
|
-
let n = t?.frag, r =
|
|
1872
|
+
let n = t?.frag, r = zn(t), i = r?.loaded;
|
|
1787
1873
|
typeof i == "number" && (this.bytesLoaded += i), !this.reportedFirstBytes && typeof i == "number" && i > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1788
1874
|
let a = r?.loading;
|
|
1789
|
-
a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length >
|
|
1875
|
+
a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length > kn && this.requestTimesMs.shift()), this.sampleHoldBack(t);
|
|
1790
1876
|
let o = n?.url;
|
|
1791
1877
|
if (o) {
|
|
1792
|
-
let e =
|
|
1878
|
+
let e = dt(o);
|
|
1793
1879
|
e && (this.cdnHost = e);
|
|
1794
1880
|
}
|
|
1795
|
-
}),
|
|
1881
|
+
}), _.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
1796
1882
|
let n = t?.stats?.loaded;
|
|
1797
1883
|
if (typeof n == "number" && (this.playlistBytesLoaded += n), this.reportedFirstPlaylist || (this.reportedFirstPlaylist = !0, l({ type: "firstPlaylist" })), this.detectedLowLatency) return;
|
|
1798
1884
|
let r = t.details;
|
|
@@ -1800,31 +1886,47 @@ var Ln = class {
|
|
|
1800
1886
|
type: "lowLatencyDetected",
|
|
1801
1887
|
value: !0
|
|
1802
1888
|
}));
|
|
1803
|
-
}),
|
|
1889
|
+
}), _.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch && m) {
|
|
1890
|
+
let t = this.prefetch, n = this.deps.video, r = (e, r) => {
|
|
1891
|
+
if (n.paused) return;
|
|
1892
|
+
let i = e;
|
|
1893
|
+
if (!i?.live || !i.partList?.length || typeof i.edge != "number") return;
|
|
1894
|
+
let a = n.buffered, o = a.length ? a.end(a.length - 1) : 0;
|
|
1895
|
+
if (i.edge - o > Wt * (i.partTarget || .5)) return;
|
|
1896
|
+
let s = Ht(e);
|
|
1897
|
+
s && t.prefetchHint(s, r);
|
|
1898
|
+
};
|
|
1899
|
+
_.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
1900
|
+
t.level === _.loadLevel && r(t.details, "main");
|
|
1901
|
+
}), _.on(e.Events.AUDIO_TRACK_LOADED, (e, t) => {
|
|
1902
|
+
t?.id === _.audioTrack && r(t?.details, "audio");
|
|
1903
|
+
}), _.on(e.Events.LEVEL_SWITCHING, () => t.dropHints("main")), _.on(e.Events.AUDIO_TRACK_SWITCHING, () => t.dropHints("audio"));
|
|
1904
|
+
}
|
|
1905
|
+
if (this.prefetch && p) {
|
|
1804
1906
|
let t = this.prefetch;
|
|
1805
|
-
|
|
1806
|
-
let r = n?.frag, i =
|
|
1807
|
-
if (r && t.isActive(i)) for (let e of
|
|
1808
|
-
}),
|
|
1907
|
+
_.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1908
|
+
let r = n?.frag, i = Bt(r?.type);
|
|
1909
|
+
if (r && t.isActive(i)) for (let e of Vt(_, r)) t.prefetch(e.url, i, e.kind);
|
|
1910
|
+
}), _.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Bt(n?.frag?.type)));
|
|
1809
1911
|
}
|
|
1810
|
-
|
|
1912
|
+
_.on(e.Events.KEY_LOADED, () => {
|
|
1811
1913
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1812
1914
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1813
1915
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.adaptHoldBack(), this.checkFrameDrops();
|
|
1814
|
-
},
|
|
1916
|
+
}, en), _.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1815
1917
|
this.renditionSwitches += 1;
|
|
1816
|
-
let n = this.lastLevelIndex >= 0 ?
|
|
1918
|
+
let n = this.lastLevelIndex >= 0 ? _.levels[this.lastLevelIndex] : void 0, r = _.levels[t.level];
|
|
1817
1919
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, this.armFrameDropGrace(), l({
|
|
1818
1920
|
type: "qualitychange",
|
|
1819
1921
|
index: t.level
|
|
1820
1922
|
});
|
|
1821
|
-
}),
|
|
1923
|
+
}), _.on(e.Events.AUDIO_TRACK_SWITCHED, (e, t) => l({
|
|
1822
1924
|
type: "audiotrackchange",
|
|
1823
1925
|
id: t.id
|
|
1824
|
-
})),
|
|
1926
|
+
})), _.on(e.Events.SUBTITLE_TRACK_SWITCH, (e, t) => l({
|
|
1825
1927
|
type: "texttrackchange",
|
|
1826
1928
|
id: t.id
|
|
1827
|
-
})),
|
|
1929
|
+
})), _.on(e.Events.ERROR, (e, t) => this.onError(t)), _.loadSource(n.manifestUrl), _.attachMedia(t);
|
|
1828
1930
|
}
|
|
1829
1931
|
getQualityLevels() {
|
|
1830
1932
|
return this.hls ? this.hls.levels.map((e, t) => ({
|
|
@@ -1862,9 +1964,9 @@ var Ln = class {
|
|
|
1862
1964
|
let o = e.config ?? {}, s = typeof self < "u" && self.devicePixelRatio > 0 ? self.devicePixelRatio : 1, c = o.ignoreDevicePixelRatio ? 1 : s;
|
|
1863
1965
|
c = Math.min(c, o.maxDevicePixelRatio ?? Infinity);
|
|
1864
1966
|
let l = t.getMaxLevelByMediaSize(e.levels, i * c, a * c), u = this.deps.sizeCapHeadroom;
|
|
1865
|
-
if (u == null && s >=
|
|
1866
|
-
let d = u ??
|
|
1867
|
-
return
|
|
1967
|
+
if (u == null && s >= bn) return l;
|
|
1968
|
+
let d = u ?? yn, f = Number.isNaN(d) ? yn : d === Infinity ? e.levels.length : Math.max(0, Math.floor(d));
|
|
1969
|
+
return xn(e.levels, l, f);
|
|
1868
1970
|
}
|
|
1869
1971
|
onMediaResize() {
|
|
1870
1972
|
if (!this.sizeCapManaged) return;
|
|
@@ -1879,7 +1981,7 @@ var Ln = class {
|
|
|
1879
1981
|
return;
|
|
1880
1982
|
}
|
|
1881
1983
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1882
|
-
let t = e > this.sizeCapLevel ?
|
|
1984
|
+
let t = e > this.sizeCapLevel ? _n : vn;
|
|
1883
1985
|
this.capTimer = setTimeout(() => {
|
|
1884
1986
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1885
1987
|
}, t);
|
|
@@ -1889,9 +1991,9 @@ var Ln = class {
|
|
|
1889
1991
|
this.ladderHeights = t.length ? [...new Set(t)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = e.levels.length ? Math.round(Math.max(...e.levels.map((e) => e.bitrate)) / 1e3) : 0;
|
|
1890
1992
|
}
|
|
1891
1993
|
dropLevelsWidevineCannotPlay(e) {
|
|
1892
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1893
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1894
|
-
for (let n of t)
|
|
1994
|
+
this.removeLevelsWhere(e, (e) => Ze(e) !== !0);
|
|
1995
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && F(e) !== "avc" && !!F(e)));
|
|
1996
|
+
for (let n of t) Ye(n).then((t) => {
|
|
1895
1997
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1896
1998
|
});
|
|
1897
1999
|
}
|
|
@@ -1899,10 +2001,10 @@ var Ln = class {
|
|
|
1899
2001
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1900
2002
|
if (n.forEach((e, n) => {
|
|
1901
2003
|
let a = e.videoCodec;
|
|
1902
|
-
a &&
|
|
2004
|
+
a && F(a) && t(a) && (r.push(n), i.add(a));
|
|
1903
2005
|
}), !r.length) return !1;
|
|
1904
2006
|
let a = [...i].join(", ");
|
|
1905
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !
|
|
2007
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !F(e.videoCodec) || Ze(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1906
2008
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1907
2009
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1908
2010
|
}
|
|
@@ -2005,12 +2107,12 @@ var Ln = class {
|
|
|
2005
2107
|
this.lastAdvanceMs = Date.now();
|
|
2006
2108
|
return;
|
|
2007
2109
|
}
|
|
2008
|
-
if (this.loadSuspended) {
|
|
2110
|
+
if (this.loadSuspended || this.offlineHold) {
|
|
2009
2111
|
this.lastAdvanceMs = Date.now();
|
|
2010
2112
|
return;
|
|
2011
2113
|
}
|
|
2012
2114
|
let e = Date.now() - this.lastAdvanceMs;
|
|
2013
|
-
!this.chaseSuspended && e >
|
|
2115
|
+
!this.chaseSuspended && e > nn && this.suspendChasing(), e > $t && this.emitEnded("stalled");
|
|
2014
2116
|
}
|
|
2015
2117
|
resetStarvationWindow() {
|
|
2016
2118
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -2021,11 +2123,11 @@ var Ln = class {
|
|
|
2021
2123
|
checkStarvation() {
|
|
2022
2124
|
let e = this.hls, { video: t } = this.deps;
|
|
2023
2125
|
if (!e || this.endedEmitted || !this.sawLive || this.chaseSuspended) return;
|
|
2024
|
-
if (typeof document < "u" && document.hidden || this.loadSuspended) {
|
|
2126
|
+
if (typeof document < "u" && document.hidden || this.loadSuspended || this.offlineHold) {
|
|
2025
2127
|
this.resetStarvationWindow();
|
|
2026
2128
|
return;
|
|
2027
2129
|
}
|
|
2028
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
2130
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < nn, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > un, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = z(t), c = o - s, l = c !== this.starvedFrames;
|
|
2029
2131
|
if (this.starvedFrames = c, !a || l) {
|
|
2030
2132
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
2031
2133
|
return;
|
|
@@ -2034,12 +2136,12 @@ var Ln = class {
|
|
|
2034
2136
|
this.resetStarvationWindow();
|
|
2035
2137
|
return;
|
|
2036
2138
|
}
|
|
2037
|
-
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length >
|
|
2139
|
+
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > hn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= pn && (this.clearKick(), this.starvationRebuilds < mn)) {
|
|
2038
2140
|
this.starvationRebuilds += 1, this.resetStarvationWindow(), this.clearRecoveryReset(), console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
|
|
2039
2141
|
return;
|
|
2040
2142
|
}
|
|
2041
|
-
let u = i && this.starvedTicks >=
|
|
2042
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
2143
|
+
let u = i && this.starvedTicks >= dn, d = !i && this.deadTicks >= hn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= gn;
|
|
2144
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= fn))) {
|
|
2043
2145
|
this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, this.kickKind = d ? "dead" : "quiet", this.clearRecoveryReset(), console.warn(d ? "havik-player: video starved while hls.js keeps loading media it never plays (dead pipeline at the live edge) — restarting the load" : "havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
|
|
2044
2146
|
try {
|
|
2045
2147
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -2050,11 +2152,11 @@ var Ln = class {
|
|
|
2050
2152
|
}
|
|
2051
2153
|
updateCatchUpBand() {
|
|
2052
2154
|
let e = this.hls;
|
|
2053
|
-
if (!e || this.catchUpRate <= 1 || this.chaseSuspended || this.loadSuspended) return;
|
|
2155
|
+
if (!e || this.catchUpRate <= 1 || this.chaseSuspended || this.loadSuspended || this.offlineHold) return;
|
|
2054
2156
|
let t = e.latency, n = e.targetLatency;
|
|
2055
2157
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
2056
2158
|
let r = t - n;
|
|
2057
|
-
!this.catchUpEngaged && r >
|
|
2159
|
+
!this.catchUpEngaged && r > rn ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= rn && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
2058
2160
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
2059
2161
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
2060
2162
|
}
|
|
@@ -2067,19 +2169,19 @@ var Ln = class {
|
|
|
2067
2169
|
}), n < 0 ? 0 : n;
|
|
2068
2170
|
}
|
|
2069
2171
|
armFrameDropGrace() {
|
|
2070
|
-
this.fpsGraceTicks > 0 || (this.fpsGraceTicks =
|
|
2172
|
+
this.fpsGraceTicks > 0 || (this.fpsGraceTicks = Tn, this.fpsBadTicks = 0);
|
|
2071
2173
|
}
|
|
2072
2174
|
resetFrameDropWindow() {
|
|
2073
2175
|
this.fpsLastFrames = -1, this.fpsLastDropped = -1, this.fpsBadTicks = 0;
|
|
2074
2176
|
}
|
|
2075
2177
|
checkFrameDrops() {
|
|
2076
2178
|
let e = this.hls, { video: t } = this.deps;
|
|
2077
|
-
if (!e || !this.fpsCapManaged || this.loadSuspended || t.paused || !e.autoLevelEnabled || typeof document < "u" && document.hidden) {
|
|
2179
|
+
if (!e || !this.fpsCapManaged || this.loadSuspended || this.offlineHold || t.paused || !e.autoLevelEnabled || typeof document < "u" && document.hidden) {
|
|
2078
2180
|
this.resetFrameDropWindow();
|
|
2079
2181
|
return;
|
|
2080
2182
|
}
|
|
2081
|
-
let { totalFrames: n, dropped: r } =
|
|
2082
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
2183
|
+
let { totalFrames: n, dropped: r } = z(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
2184
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Cn || o < 0) {
|
|
2083
2185
|
this.fpsBadTicks = 0;
|
|
2084
2186
|
return;
|
|
2085
2187
|
}
|
|
@@ -2087,11 +2189,11 @@ var Ln = class {
|
|
|
2087
2189
|
--this.fpsGraceTicks, this.fpsBadTicks = 0;
|
|
2088
2190
|
return;
|
|
2089
2191
|
}
|
|
2090
|
-
if (o <=
|
|
2192
|
+
if (o <= Sn * a) {
|
|
2091
2193
|
this.fpsBadTicks = 0;
|
|
2092
2194
|
return;
|
|
2093
2195
|
}
|
|
2094
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
2196
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < wn) return;
|
|
2095
2197
|
this.fpsBadTicks = 0;
|
|
2096
2198
|
let s = e.levels, c = s[e.currentLevel];
|
|
2097
2199
|
if (!c) return;
|
|
@@ -2103,27 +2205,27 @@ var Ln = class {
|
|
|
2103
2205
|
}
|
|
2104
2206
|
checkFutileChase() {
|
|
2105
2207
|
let e = this.hls, { video: t } = this.deps;
|
|
2106
|
-
if (!e || this.endedEmitted || !this.sawLive || this.chaseSuspended || this.loadSuspended || typeof document < "u" && document.hidden) {
|
|
2208
|
+
if (!e || this.endedEmitted || !this.sawLive || this.chaseSuspended || this.loadSuspended || this.offlineHold || typeof document < "u" && document.hidden) {
|
|
2107
2209
|
this.resetChaseWindow();
|
|
2108
2210
|
return;
|
|
2109
2211
|
}
|
|
2110
2212
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
2111
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
2213
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(sn, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
2112
2214
|
this.resetChaseWindow();
|
|
2113
2215
|
return;
|
|
2114
2216
|
}
|
|
2115
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
2217
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= on) {
|
|
2116
2218
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
2117
2219
|
return;
|
|
2118
2220
|
}
|
|
2119
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
2221
|
+
if (this.chaseTicks += 1, this.chaseTicks < an) return;
|
|
2120
2222
|
this.resetChaseWindow();
|
|
2121
2223
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2122
2224
|
if (!(a > 1)) return;
|
|
2123
2225
|
let o = e.targetLatency;
|
|
2124
2226
|
if (typeof o != "number" || !(o > 0)) return;
|
|
2125
2227
|
let s = Math.min(n, a - 1);
|
|
2126
|
-
s < o +
|
|
2228
|
+
s < o + cn || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s, this.deps.emit({
|
|
2127
2229
|
type: "livetargetchange",
|
|
2128
2230
|
change: {
|
|
2129
2231
|
targetSeconds: s,
|
|
@@ -2140,13 +2242,13 @@ var Ln = class {
|
|
|
2140
2242
|
if (!this.holdBackEnabled || this.holdBackPriorChecked || !e || (this.holdBackPriorChecked = !0, this.holdBackApplied > 0 || this.holdBackStepCount > 0)) return;
|
|
2141
2243
|
let t = e.targetLatency;
|
|
2142
2244
|
if (this.holdBackBase < 0 && typeof t == "number" && t > 0 && (this.holdBackBase = t), this.holdBackBase < 0) return;
|
|
2143
|
-
let n =
|
|
2144
|
-
if (!(n >=
|
|
2245
|
+
let n = Bn();
|
|
2246
|
+
if (!(n >= Rn)) return;
|
|
2145
2247
|
let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase + J);
|
|
2146
2248
|
i > r && (this.holdBackStepCount = 1, this.moveHoldBack(e, r, i, "connection-rtt", `connection rtt ${n} ms`));
|
|
2147
2249
|
}
|
|
2148
2250
|
holdBackCeiling(e) {
|
|
2149
|
-
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t :
|
|
2251
|
+
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t : Ln, r = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2150
2252
|
return r > 1 ? Math.min(n, r - 1) : n;
|
|
2151
2253
|
}
|
|
2152
2254
|
sampleHoldBack(e) {
|
|
@@ -2155,7 +2257,7 @@ var Ln = class {
|
|
|
2155
2257
|
if (t !== "main" && t !== "audio") return;
|
|
2156
2258
|
let n = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag?.duration;
|
|
2157
2259
|
if (typeof n != "number" || !(n > 0)) return;
|
|
2158
|
-
let r =
|
|
2260
|
+
let r = zn(e)?.loading;
|
|
2159
2261
|
if (!r || !(r.start > 0) || !(r.end > 0)) return;
|
|
2160
2262
|
let i = r.first > r.start ? r.first : r.end, a = Math.max(0, i - r.start) / (n * 1e3);
|
|
2161
2263
|
this.holdBackSamples.push({
|
|
@@ -2166,24 +2268,24 @@ var Ln = class {
|
|
|
2166
2268
|
adaptHoldBack() {
|
|
2167
2269
|
if (!this.holdBackEnabled) return;
|
|
2168
2270
|
let e = this.hls;
|
|
2169
|
-
if (!e || this.endedEmitted || !this.sawLive || this.chaseSuspended || this.loadSuspended || typeof document < "u" && document.hidden) {
|
|
2271
|
+
if (!e || this.endedEmitted || !this.sawLive || this.chaseSuspended || this.loadSuspended || this.offlineHold || typeof document < "u" && document.hidden) {
|
|
2170
2272
|
this.holdBackSlowTicks = 0, this.holdBackFastSince = 0, this.holdBackSamples = [];
|
|
2171
2273
|
return;
|
|
2172
2274
|
}
|
|
2173
|
-
let t = Date.now(), n = t -
|
|
2275
|
+
let t = Date.now(), n = t - An, r = this.holdBackSamples, i = 0;
|
|
2174
2276
|
for (; i < r.length && r[i].t < n;) i += 1;
|
|
2175
2277
|
i > 0 && r.splice(0, i);
|
|
2176
2278
|
let a = e.targetLatency;
|
|
2177
2279
|
if (typeof a != "number" || !(a > 0)) return;
|
|
2178
2280
|
this.holdBackBase < 0 && (this.holdBackBase = a);
|
|
2179
2281
|
let o = this.holdBackBase, s = this.holdBackCeiling(e);
|
|
2180
|
-
if (r.length <
|
|
2282
|
+
if (r.length < jn) {
|
|
2181
2283
|
this.holdBackSlowTicks = 0;
|
|
2182
2284
|
return;
|
|
2183
2285
|
}
|
|
2184
2286
|
let c = r.map((e) => e.ratio).sort((e, t) => e - t), l = q(c, 95), u = q(c, 50), d = Math.round(l * 1e3);
|
|
2185
|
-
if (l >=
|
|
2186
|
-
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks <
|
|
2287
|
+
if (l >= Mn && u >= Nn) {
|
|
2288
|
+
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks < Fn) return;
|
|
2187
2289
|
this.holdBackSlowTicks = 0;
|
|
2188
2290
|
let t = Math.ceil((s - o) / J), n = Math.ceil((a - o) / J - 1e-9);
|
|
2189
2291
|
if (n > this.holdBackStepCount && (this.holdBackStepCount = n), this.holdBackStepCount >= t) return;
|
|
@@ -2193,7 +2295,7 @@ var Ln = class {
|
|
|
2193
2295
|
this.moveHoldBack(e, a, r, "slow-fetches", `part fetches slow (first byte p50 ${Math.round(u * 1e3)} / p95 ${d} ms per 1 s of media)`);
|
|
2194
2296
|
return;
|
|
2195
2297
|
}
|
|
2196
|
-
if (this.holdBackSlowTicks = 0, l >=
|
|
2298
|
+
if (this.holdBackSlowTicks = 0, l >= Pn) {
|
|
2197
2299
|
this.holdBackFastSince = 0;
|
|
2198
2300
|
return;
|
|
2199
2301
|
}
|
|
@@ -2201,7 +2303,7 @@ var Ln = class {
|
|
|
2201
2303
|
this.holdBackFastSince = t;
|
|
2202
2304
|
return;
|
|
2203
2305
|
}
|
|
2204
|
-
if (t - this.holdBackFastSince <
|
|
2306
|
+
if (t - this.holdBackFastSince < In || (this.holdBackFastSince = t, this.holdBackStepCount === 0 || a !== this.holdBackApplied)) return;
|
|
2205
2307
|
--this.holdBackStepCount;
|
|
2206
2308
|
let f = Math.max(o, o + this.holdBackStepCount * J);
|
|
2207
2309
|
f >= a || this.moveHoldBack(e, a, f, "fast-fetches", `part fetches fast again (p95 first byte ${d} ms per 1 s of media)`);
|
|
@@ -2244,17 +2346,17 @@ var Ln = class {
|
|
|
2244
2346
|
} catch {}
|
|
2245
2347
|
}
|
|
2246
2348
|
startEstimate() {
|
|
2247
|
-
return this.deps.rememberBandwidth === !1 ?
|
|
2349
|
+
return this.deps.rememberBandwidth === !1 ? Gt : ze() ?? Gt;
|
|
2248
2350
|
}
|
|
2249
2351
|
maybeRememberBandwidth(e) {
|
|
2250
|
-
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded <
|
|
2352
|
+
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Kt) return;
|
|
2251
2353
|
let t = Date.now();
|
|
2252
|
-
if (!e && t - this.bwSavedAt <
|
|
2354
|
+
if (!e && t - this.bwSavedAt < qt) return;
|
|
2253
2355
|
let n = this.hls?.bandwidthEstimate;
|
|
2254
|
-
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t,
|
|
2356
|
+
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Be(n));
|
|
2255
2357
|
}
|
|
2256
2358
|
destroy() {
|
|
2257
|
-
if (this.maybeRememberBandwidth(!0), this.detachFrames?.(), this.detachFrames = null, this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
|
|
2359
|
+
if (this.maybeRememberBandwidth(!0), this.detachFrames?.(), this.detachFrames = null, this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onOnline && typeof window < "u" && (window.removeEventListener("online", this.onOnline), this.onOnline = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
|
|
2258
2360
|
try {
|
|
2259
2361
|
this.hls.destroy();
|
|
2260
2362
|
} catch (e) {
|
|
@@ -2269,7 +2371,7 @@ var Ln = class {
|
|
|
2269
2371
|
scheduleLicenseRetry(t) {
|
|
2270
2372
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
2271
2373
|
let n = t.response?.code ?? 0;
|
|
2272
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
2374
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Xt) return !1;
|
|
2273
2375
|
this.licenseRecoveries += 1;
|
|
2274
2376
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
2275
2377
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -2301,7 +2403,11 @@ var Ln = class {
|
|
|
2301
2403
|
return;
|
|
2302
2404
|
}
|
|
2303
2405
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
2304
|
-
if (
|
|
2406
|
+
if (!R() && (t.response?.code ?? 0) === 0) {
|
|
2407
|
+
this.offlineHold = !0, this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null);
|
|
2408
|
+
return;
|
|
2409
|
+
}
|
|
2410
|
+
if (this.networkRecoveries < Yt) {
|
|
2305
2411
|
this.networkRecoveries += 1;
|
|
2306
2412
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
2307
2413
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -2318,7 +2424,7 @@ var Ln = class {
|
|
|
2318
2424
|
return;
|
|
2319
2425
|
}
|
|
2320
2426
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
2321
|
-
if (this.mediaRecoveries <
|
|
2427
|
+
if (this.mediaRecoveries < Jt) {
|
|
2322
2428
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
2323
2429
|
return;
|
|
2324
2430
|
}
|
|
@@ -2339,18 +2445,18 @@ var Ln = class {
|
|
|
2339
2445
|
}
|
|
2340
2446
|
}
|
|
2341
2447
|
toError(t, r = "PLAYBACK") {
|
|
2342
|
-
let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(
|
|
2343
|
-
return new n(r === "DRM" ? a(o, l) : o === 401 ? "UNAUTHORIZED" : o === 403 ? "FORBIDDEN" : "INTERNAL", o, `${r} error: ${s}${c ? ` (${c})` : ""}`, l ? { serverCode: l } : void 0);
|
|
2448
|
+
let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(jt(t.networkDetails)) : void 0;
|
|
2449
|
+
return new n(r === "DRM" ? a(o, l) : r === "NETWORK" && o === 0 ? "NETWORK" : o === 401 ? "UNAUTHORIZED" : o === 403 ? "FORBIDDEN" : "INTERNAL", o, `${r} error: ${s}${c ? ` (${c})` : ""}`, l ? { serverCode: l } : void 0);
|
|
2344
2450
|
}
|
|
2345
|
-
},
|
|
2451
|
+
}, Wn = 15e3, Gn = 6e5, Kn = 3e5, qn = 100, Y = 1, Jn = 1e3, Yn = 3e4, Xn = 1e3, Zn = {
|
|
2346
2452
|
inline: "PRESENTATION_INLINE",
|
|
2347
2453
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2348
2454
|
pip: "PRESENTATION_PIP"
|
|
2349
|
-
},
|
|
2455
|
+
}, Qn = {
|
|
2350
2456
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2351
2457
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2352
2458
|
none: "KEY_SYSTEM_NONE"
|
|
2353
|
-
},
|
|
2459
|
+
}, $n = /* @__PURE__ */ new Set([
|
|
2354
2460
|
"INVALID_URN",
|
|
2355
2461
|
"NOT_FOUND",
|
|
2356
2462
|
"GEO_DENIED",
|
|
@@ -2371,7 +2477,7 @@ var Ln = class {
|
|
|
2371
2477
|
ended: "PLAYER_STATE_ENDED",
|
|
2372
2478
|
error: "PLAYER_STATE_ERROR"
|
|
2373
2479
|
};
|
|
2374
|
-
function
|
|
2480
|
+
function er(e) {
|
|
2375
2481
|
try {
|
|
2376
2482
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2377
2483
|
return !n || r.length === 0 || n !== "feed" && !n.startsWith("feed-") ? void 0 : (t.hostname = [n.replace(/^feed/, "beacons"), ...r].join("."), t.pathname = "", t.search = "", t.origin);
|
|
@@ -2379,8 +2485,8 @@ function Jn(e) {
|
|
|
2379
2485
|
return;
|
|
2380
2486
|
}
|
|
2381
2487
|
}
|
|
2382
|
-
var
|
|
2383
|
-
function
|
|
2488
|
+
var tr = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), nr = /* @__PURE__ */ new Set(), Z = /* @__PURE__ */ new Set(), Q = /* @__PURE__ */ new Set(), rr = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2489
|
+
function ir(e) {
|
|
2384
2490
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2385
2491
|
let t;
|
|
2386
2492
|
try {
|
|
@@ -2389,19 +2495,19 @@ function Qn(e) {
|
|
|
2389
2495
|
} catch {
|
|
2390
2496
|
return;
|
|
2391
2497
|
}
|
|
2392
|
-
if (
|
|
2393
|
-
Z.add(t), _(
|
|
2498
|
+
if (nr.has(t) && !Z.has(t)) {
|
|
2499
|
+
Z.add(t), _(rr(new URL(t).origin));
|
|
2394
2500
|
for (let e of Q) e.noteCspBlocked();
|
|
2395
2501
|
}
|
|
2396
2502
|
}
|
|
2397
|
-
function
|
|
2503
|
+
function ar(e, t) {
|
|
2398
2504
|
return _(t, e), { disabledReason: t };
|
|
2399
2505
|
}
|
|
2400
|
-
function
|
|
2401
|
-
if (n) return t && !
|
|
2506
|
+
function or(e, t, n) {
|
|
2507
|
+
if (n) return t && !tr(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2402
2508
|
if (t) return { endpoint: t };
|
|
2403
|
-
if (t !== void 0) return
|
|
2404
|
-
let r =
|
|
2509
|
+
if (t !== void 0) return ar("empty-endpoint", "analytics is disabled: no QoE beacons will be sent. analytics.endpoint was supplied but empty. Pass a real beacons origin, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, or omit the option to derive it from baseUrl (or analytics: false to opt out).");
|
|
2510
|
+
let r = er(e);
|
|
2405
2511
|
if (r) return { endpoint: r };
|
|
2406
2512
|
let i;
|
|
2407
2513
|
try {
|
|
@@ -2409,9 +2515,9 @@ function er(e, t, n) {
|
|
|
2409
2515
|
} catch {
|
|
2410
2516
|
i = e;
|
|
2411
2517
|
}
|
|
2412
|
-
return
|
|
2518
|
+
return ar(i, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${i}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
|
|
2413
2519
|
}
|
|
2414
|
-
var
|
|
2520
|
+
var sr = class {
|
|
2415
2521
|
opts;
|
|
2416
2522
|
url;
|
|
2417
2523
|
cspKey;
|
|
@@ -2493,8 +2599,8 @@ var tr = class {
|
|
|
2493
2599
|
constructor(e) {
|
|
2494
2600
|
this.opts = {
|
|
2495
2601
|
...e,
|
|
2496
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2497
|
-
idleMs: e.idleMs ??
|
|
2602
|
+
heartbeatMs: e.heartbeatMs ?? Wn,
|
|
2603
|
+
idleMs: e.idleMs ?? Gn
|
|
2498
2604
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2499
2605
|
try {
|
|
2500
2606
|
let e = new URL(this.url);
|
|
@@ -2511,11 +2617,11 @@ var tr = class {
|
|
|
2511
2617
|
sdkVersion: this.opts.sdkVersion,
|
|
2512
2618
|
...this.opts.environment
|
|
2513
2619
|
};
|
|
2514
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2620
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Jn), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.cspKey && nr.add(this.cspKey), document.addEventListener("securitypolicyviolation", ir), Q.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2515
2621
|
}
|
|
2516
2622
|
checkSuspension(e) {
|
|
2517
2623
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2518
|
-
let t = Math.max(this.opts.idleMs,
|
|
2624
|
+
let t = Math.max(this.opts.idleMs, Kn);
|
|
2519
2625
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2520
2626
|
}
|
|
2521
2627
|
syncIdle(e) {
|
|
@@ -2538,12 +2644,12 @@ var tr = class {
|
|
|
2538
2644
|
let a = {
|
|
2539
2645
|
fromState: X[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2540
2646
|
toState: X[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2541
|
-
presentation:
|
|
2647
|
+
presentation: Zn[this.presentation]
|
|
2542
2648
|
}, o = this.causeOf(e, t, i);
|
|
2543
2649
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2544
2650
|
}
|
|
2545
2651
|
seekInduced(e) {
|
|
2546
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2652
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < Xn;
|
|
2547
2653
|
}
|
|
2548
2654
|
causeOf(e, t, n) {
|
|
2549
2655
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2617,7 +2723,7 @@ var tr = class {
|
|
|
2617
2723
|
let r = n ?? "";
|
|
2618
2724
|
if (r !== "") return /^fragLoad/i.test(r) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /^(manifest|level|audioTrack|subtitleTrack)/i.test(r) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(r) ? "ERROR_STAGE_DRM" : /parsing|append|buffer|remux|decrypt|media/i.test(r) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
|
|
2619
2725
|
if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
|
|
2620
|
-
if (
|
|
2726
|
+
if ($n.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2621
2727
|
let i = t ?? "";
|
|
2622
2728
|
return /frag|segment/i.test(i) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /manifest|level|playlist/i.test(i) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(i) ? "ERROR_STAGE_DRM" : /buffer|decode|media|append/i.test(i) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
|
|
2623
2729
|
}
|
|
@@ -2671,7 +2777,7 @@ var tr = class {
|
|
|
2671
2777
|
maybeEmitMediaInfo(e) {
|
|
2672
2778
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2673
2779
|
let t = {};
|
|
2674
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2780
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Qn[e.keySystem]), e.drmSecurityLevel && (t.drmSecurityLevel = e.drmSecurityLevel), e.ladderHeights?.length && (t.ladderHeights = e.ladderHeights), e.ladderTopBitrateKbps && (t.ladderTopBitrateKbps = e.ladderTopBitrateKbps), e.lowLatency && (t.lowLatency = !0);
|
|
2675
2781
|
let n = JSON.stringify(t);
|
|
2676
2782
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2677
2783
|
}
|
|
@@ -2691,7 +2797,7 @@ var tr = class {
|
|
|
2691
2797
|
let c = r?.positionMs ?? 0;
|
|
2692
2798
|
c > 0 && (i.exitPositionMs = Math.round(c)), this.activeTotalMs > 0 && (i.activeWatchTimeMs = Math.round(this.activeTotalMs)), this.mutedTotalMs > 0 && (i.mutedTimeMs = Math.round(this.mutedTotalMs));
|
|
2693
2799
|
let l = e !== "END_REASON_ENDED";
|
|
2694
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2800
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= Yn && (i.abandonAfterStallMs = Math.max(Y, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Yn && (i.abandonAfterErrorMs = Math.max(Y, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
|
|
2695
2801
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2696
2802
|
u > 0 && (i.decodedFramesTotal = u), e === "END_REASON_STOPPED" && this.startupTimeMs === 0 && this.lastErrorStage === null && (e = "END_REASON_ABORTED", i.reason = e), this.startupTimeMs === 0 && e !== "END_REASON_ABORTED" && (i.failedStage = this.lastErrorStage ?? (this.manifestLoadMs === 0 ? "ERROR_STAGE_MANIFEST" : this.firstFragLoadMs === 0 ? "ERROR_STAGE_FIRST_SEGMENT" : "ERROR_STAGE_OTHER")), this.pending.push(this.wrap({ sessionEnd: i })), this.flush(e === "END_REASON_PAGEHIDE");
|
|
2697
2803
|
}
|
|
@@ -2711,13 +2817,13 @@ var tr = class {
|
|
|
2711
2817
|
};
|
|
2712
2818
|
}
|
|
2713
2819
|
noteCspBlocked() {
|
|
2714
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2820
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(rr(new URL(this.url).origin)));
|
|
2715
2821
|
}
|
|
2716
2822
|
cspBlocked() {
|
|
2717
2823
|
return !!this.cspKey && Z.has(this.cspKey);
|
|
2718
2824
|
}
|
|
2719
2825
|
enqueue(e) {
|
|
2720
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2826
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > qn;) {
|
|
2721
2827
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2722
2828
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2723
2829
|
}
|
|
@@ -2744,7 +2850,7 @@ var tr = class {
|
|
|
2744
2850
|
};
|
|
2745
2851
|
//#endregion
|
|
2746
2852
|
//#region src/core/environment.ts
|
|
2747
|
-
function
|
|
2853
|
+
function cr() {
|
|
2748
2854
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2749
2855
|
let e;
|
|
2750
2856
|
try {
|
|
@@ -2769,14 +2875,14 @@ function nr() {
|
|
|
2769
2875
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2770
2876
|
};
|
|
2771
2877
|
}
|
|
2772
|
-
function
|
|
2878
|
+
function lr() {
|
|
2773
2879
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2774
2880
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2775
2881
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2776
2882
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2777
2883
|
return e?.mobile ?? (typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1 && n > 0 && n < 900) ? n >= 600 ? "DEVICE_CLASS_TABLET" : "DEVICE_CLASS_PHONE" : e || n >= 900 || /mac|win|linux|chrome os/i.test(t) ? "DEVICE_CLASS_DESKTOP" : "DEVICE_CLASS_OTHER";
|
|
2778
2884
|
}
|
|
2779
|
-
function
|
|
2885
|
+
function ur() {
|
|
2780
2886
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2781
2887
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2782
2888
|
let t = {
|
|
@@ -2795,17 +2901,17 @@ function ir() {
|
|
|
2795
2901
|
}
|
|
2796
2902
|
return typeof e.downlink == "number" && e.downlink > 0 && (i.downlinkKbps = Math.round(e.downlink * 1e3)), typeof e.rtt == "number" && e.rtt > 0 && (i.rttMs = Math.round(e.rtt)), e.saveData && (i.saveData = !0), i;
|
|
2797
2903
|
}
|
|
2798
|
-
function
|
|
2799
|
-
let t =
|
|
2800
|
-
deviceClass:
|
|
2904
|
+
function dr(e) {
|
|
2905
|
+
let t = cr(), n = {
|
|
2906
|
+
deviceClass: lr(),
|
|
2801
2907
|
integration: t.integration,
|
|
2802
|
-
...
|
|
2908
|
+
...ur()
|
|
2803
2909
|
};
|
|
2804
2910
|
t.host && (n.host = t.host), typeof screen < "u" && screen.width > 0 && (n.screenWidth = screen.width, n.screenHeight = screen.height), typeof window < "u" && window.devicePixelRatio > 0 && (n.devicePixelRatio = Math.round(window.devicePixelRatio * 100) / 100);
|
|
2805
2911
|
let r = e.getBoundingClientRect?.();
|
|
2806
2912
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2807
2913
|
}
|
|
2808
|
-
async function
|
|
2914
|
+
async function fr() {
|
|
2809
2915
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2810
2916
|
if (!e?.getHighEntropyValues) return {};
|
|
2811
2917
|
try {
|
|
@@ -2817,7 +2923,7 @@ async function or() {
|
|
|
2817
2923
|
}
|
|
2818
2924
|
//#endregion
|
|
2819
2925
|
//#region src/core/version.ts
|
|
2820
|
-
var
|
|
2926
|
+
var pr = "2.25.0", mr = {
|
|
2821
2927
|
accent: "#E1B600",
|
|
2822
2928
|
accentText: "#1B1C23",
|
|
2823
2929
|
background: "#0e0f13",
|
|
@@ -2828,7 +2934,7 @@ var sr = "2.23.4", cr = {
|
|
|
2828
2934
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2829
2935
|
radius: "8px",
|
|
2830
2936
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2831
|
-
},
|
|
2937
|
+
}, hr = {
|
|
2832
2938
|
accent: "--havik-accent",
|
|
2833
2939
|
accentText: "--havik-accent-text",
|
|
2834
2940
|
background: "--havik-bg",
|
|
@@ -2840,26 +2946,26 @@ var sr = "2.23.4", cr = {
|
|
|
2840
2946
|
radius: "--havik-radius",
|
|
2841
2947
|
fontFamily: "--havik-font"
|
|
2842
2948
|
};
|
|
2843
|
-
function
|
|
2949
|
+
function gr(e, t) {
|
|
2844
2950
|
let n = {
|
|
2845
|
-
...
|
|
2951
|
+
...mr,
|
|
2846
2952
|
...t
|
|
2847
2953
|
};
|
|
2848
|
-
for (let t of Object.keys(
|
|
2954
|
+
for (let t of Object.keys(hr)) e.style.setProperty(hr[t], n[t]);
|
|
2849
2955
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2850
2956
|
}
|
|
2851
2957
|
//#endregion
|
|
2852
2958
|
//#region src/ui/styles.ts
|
|
2853
|
-
var
|
|
2854
|
-
function
|
|
2855
|
-
let n = e.querySelector(`style#${
|
|
2856
|
-
if (n && (!t ||
|
|
2959
|
+
var _r = "havik-player-styles", vr = "\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 touch-action:manipulation}\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/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;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/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\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/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n 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", yr = /* @__PURE__ */ new WeakMap();
|
|
2960
|
+
function br(e = document, t) {
|
|
2961
|
+
let n = e.querySelector(`style#${_r}`);
|
|
2962
|
+
if (n && (!t || yr.get(n) === t)) return;
|
|
2857
2963
|
let r = e.createElement("style");
|
|
2858
|
-
r.id =
|
|
2964
|
+
r.id = _r, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = vr, yr.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2859
2965
|
}
|
|
2860
2966
|
//#endregion
|
|
2861
2967
|
//#region src/ui/icons.ts
|
|
2862
|
-
var
|
|
2968
|
+
var xr = {
|
|
2863
2969
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2864
2970
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2865
2971
|
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\"/>",
|
|
@@ -2873,11 +2979,11 @@ var hr = {
|
|
|
2873
2979
|
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\"/>"
|
|
2874
2980
|
};
|
|
2875
2981
|
function $(e) {
|
|
2876
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2982
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${xr[e]}</svg>`;
|
|
2877
2983
|
}
|
|
2878
2984
|
//#endregion
|
|
2879
2985
|
//#region src/ui/controls.ts
|
|
2880
|
-
var
|
|
2986
|
+
var Sr = 3e3, Cr = 250, wr = /* @__PURE__ */ new Set([
|
|
2881
2987
|
"GONE",
|
|
2882
2988
|
"NOT_FOUND",
|
|
2883
2989
|
"GEO_DENIED",
|
|
@@ -2885,15 +2991,15 @@ var gr = 3e3, _r = 250, vr = /* @__PURE__ */ new Set([
|
|
|
2885
2991
|
"UNAUTHORIZED",
|
|
2886
2992
|
"DRM_DEVICE_REVOKED"
|
|
2887
2993
|
]);
|
|
2888
|
-
function
|
|
2994
|
+
function Tr(e) {
|
|
2889
2995
|
let t = "This match isn't available in your country";
|
|
2890
2996
|
return e ? `${t} (${e})` : t;
|
|
2891
2997
|
}
|
|
2892
|
-
var
|
|
2893
|
-
function
|
|
2894
|
-
return new
|
|
2998
|
+
var Er = "This device can't play protected video";
|
|
2999
|
+
function Dr(e) {
|
|
3000
|
+
return new Or(e);
|
|
2895
3001
|
}
|
|
2896
|
-
var
|
|
3002
|
+
var Or = class {
|
|
2897
3003
|
root;
|
|
2898
3004
|
video;
|
|
2899
3005
|
player;
|
|
@@ -2932,6 +3038,7 @@ var Sr = class {
|
|
|
2932
3038
|
endedMessage;
|
|
2933
3039
|
interruptedMessage;
|
|
2934
3040
|
errorMessage;
|
|
3041
|
+
offlineMessage;
|
|
2935
3042
|
hideTimer;
|
|
2936
3043
|
tapTimer;
|
|
2937
3044
|
surfacePointerType = "";
|
|
@@ -2941,7 +3048,7 @@ var Sr = class {
|
|
|
2941
3048
|
scrubbing = !1;
|
|
2942
3049
|
offFns = [];
|
|
2943
3050
|
constructor(e) {
|
|
2944
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
3051
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Sr, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, this.offlineMessage = e.offlineMessage ?? "No internet connection — waiting to reconnect", br(this.doc, e.cspNonce), 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");
|
|
2945
3052
|
let t = (e, t, n) => {
|
|
2946
3053
|
let r = this.doc.createElement(e);
|
|
2947
3054
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2997,7 +3104,7 @@ var Sr = class {
|
|
|
2997
3104
|
}), this.on(this.muteBtn, "click", () => this.player.setMuted(!e.muted)), this.on(this.volSlider, "input", () => {
|
|
2998
3105
|
let t = Number(this.volSlider.value);
|
|
2999
3106
|
this.setVolumeFill(t), this.player.setVolume(t), t > 0 && e.muted && this.player.setMuted(!1);
|
|
3000
|
-
}), this.on(this.liveGo, "click", () => this.player.seekToLive()), this.on(this.pipBtn, "click", () => void this.togglePip()), this.on(this.fsBtn, "click", () => void this.toggleFullscreen()), this.on(this.ccBtn, "click", () => this.toggleMenu("cc")), this.on(this.audioBtn, "click", () => this.toggleMenu("audio")), this.on(this.qualityBtn, "click", () => this.toggleMenu("quality")), this.on(this.seek, "pointerdown", (e) => this.onSeekDown(e)), this.on(this.seek, "keydown", (e) => this.onSeekKey(e)), this.on(e, "play", () => this.syncPlayPause()), this.on(e, "pause", () => this.syncPlayPause()), this.on(e, "volumechange", () => this.syncVolume()), this.on(e, "timeupdate", () => this.syncProgress()), this.on(e, "progress", () => this.syncProgress()), this.on(e, "durationchange", () => this.syncProgress()), this.on(e, "loadedmetadata", () => this.syncFullscreenSupport()), this.offFns.push(this.player.on("statechange", () => this.syncState())), this.offFns.push(this.player.on("ended", () => this.syncState())), this.offFns.push(this.player.on("ready", () => this.refreshTracks())), this.offFns.push(this.player.on("qualitychange", () => this.onTracksChanged())), this.offFns.push(this.player.on("audiotrackchange", () => this.onTracksChanged())), this.offFns.push(this.player.on("texttrackchange", () => this.onTracksChanged())), this.offFns.push(this.player.on("pipchange", (e) => this.syncPip(e))), this.offFns.push(this.player.on("stats", () => this.syncLive())), this.offFns.push(this.player.on("error", (e) => {
|
|
3107
|
+
}), this.on(this.liveGo, "click", () => this.player.seekToLive()), this.on(this.pipBtn, "click", () => void this.togglePip()), this.on(this.fsBtn, "click", () => void this.toggleFullscreen()), this.on(this.ccBtn, "click", () => this.toggleMenu("cc")), this.on(this.audioBtn, "click", () => this.toggleMenu("audio")), this.on(this.qualityBtn, "click", () => this.toggleMenu("quality")), this.on(this.seek, "pointerdown", (e) => this.onSeekDown(e)), this.on(this.seek, "keydown", (e) => this.onSeekKey(e)), this.on(e, "play", () => this.syncPlayPause()), this.on(e, "pause", () => this.syncPlayPause()), this.on(e, "volumechange", () => this.syncVolume()), this.on(e, "timeupdate", () => this.syncProgress()), this.on(e, "progress", () => this.syncProgress()), this.on(e, "durationchange", () => this.syncProgress()), this.on(e, "loadedmetadata", () => this.syncFullscreenSupport()), this.offFns.push(this.player.on("statechange", () => this.syncState())), this.offFns.push(this.player.on("ended", () => this.syncState())), this.offFns.push(this.player.on("offline", () => this.syncState())), this.offFns.push(this.player.on("online", () => this.syncState())), this.offFns.push(this.player.on("ready", () => this.refreshTracks())), this.offFns.push(this.player.on("qualitychange", () => this.onTracksChanged())), this.offFns.push(this.player.on("audiotrackchange", () => this.onTracksChanged())), this.offFns.push(this.player.on("texttrackchange", () => this.onTracksChanged())), this.offFns.push(this.player.on("pipchange", (e) => this.syncPip(e))), this.offFns.push(this.player.on("stats", () => this.syncLive())), this.offFns.push(this.player.on("error", (e) => {
|
|
3001
3108
|
this.lastError = e, this.statusKind = null, this.syncState();
|
|
3002
3109
|
}));
|
|
3003
3110
|
let t = (e) => e.pointerType !== "touch";
|
|
@@ -3027,7 +3134,7 @@ var Sr = class {
|
|
|
3027
3134
|
let t = this.surfaceWasHidden;
|
|
3028
3135
|
this.tapTimer = setTimeout(() => {
|
|
3029
3136
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
3030
|
-
},
|
|
3137
|
+
}, Cr);
|
|
3031
3138
|
}
|
|
3032
3139
|
toggleBar(e) {
|
|
3033
3140
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -3044,10 +3151,14 @@ var Sr = class {
|
|
|
3044
3151
|
}
|
|
3045
3152
|
syncStatus(e) {
|
|
3046
3153
|
let t = null;
|
|
3047
|
-
|
|
3154
|
+
if (this.statusOverlays) {
|
|
3155
|
+
let n = this.player.offline && e !== "ended" && e !== "idle", r = !this.hasPlayed && (e === "paused" || e === "waiting");
|
|
3156
|
+
e === "ended" ? t = "ended" : n && !r ? t = "offline" : e === "error" ? t = "error" : e === "waiting" ? t = "waiting" : !this.hasPlayed && (e === "idle" || e === "paused") && (t = "preplay");
|
|
3157
|
+
}
|
|
3158
|
+
this.renderStatus(t);
|
|
3048
3159
|
}
|
|
3049
3160
|
statusMessageFor(e) {
|
|
3050
|
-
return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ?
|
|
3161
|
+
return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "offline" ? this.offlineMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? Tr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? Er : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
|
|
3051
3162
|
}
|
|
3052
3163
|
renderStatus(e) {
|
|
3053
3164
|
let t = this.statusMessageFor(e);
|
|
@@ -3062,7 +3173,7 @@ var Sr = class {
|
|
|
3062
3173
|
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = $("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
|
|
3063
3174
|
} else {
|
|
3064
3175
|
let r = this.doc.createElement("div");
|
|
3065
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
3176
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !wr.has(this.lastError.code)) {
|
|
3066
3177
|
let e = this.doc.createElement("button");
|
|
3067
3178
|
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${$("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
3068
3179
|
}
|
|
@@ -3103,7 +3214,7 @@ var Sr = class {
|
|
|
3103
3214
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
3104
3215
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
3105
3216
|
}
|
|
3106
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
3217
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${kr(this.video.currentTime)} / ${kr(this.video.duration)}`);
|
|
3107
3218
|
}
|
|
3108
3219
|
syncLive() {
|
|
3109
3220
|
let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
|
|
@@ -3153,17 +3264,17 @@ var Sr = class {
|
|
|
3153
3264
|
renderQualityMenu() {
|
|
3154
3265
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
3155
3266
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
3156
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
3267
|
+
for (let n of e) this.menu.append(this.menuItem(Ar(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
3157
3268
|
}
|
|
3158
3269
|
renderAudioMenu() {
|
|
3159
3270
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
3160
3271
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
3161
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3272
|
+
for (let t of e) this.menu.append(this.menuItem(jr(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
3162
3273
|
}
|
|
3163
3274
|
renderCcMenu() {
|
|
3164
3275
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
3165
3276
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
3166
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3277
|
+
for (let t of e) this.menu.append(this.menuItem(Mr(t), !1, () => this.player.setTextTrack(t.id)));
|
|
3167
3278
|
}
|
|
3168
3279
|
onTracksChanged() {
|
|
3169
3280
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -3183,14 +3294,14 @@ var Sr = class {
|
|
|
3183
3294
|
}
|
|
3184
3295
|
async toggleFullscreen() {
|
|
3185
3296
|
try {
|
|
3186
|
-
|
|
3297
|
+
ye(this.video, this.root) ? await C(this.video, this.root) : await S(this.video, this.root);
|
|
3187
3298
|
} catch {}
|
|
3188
3299
|
}
|
|
3189
3300
|
syncFullscreenSupport() {
|
|
3190
|
-
this.fsSupported =
|
|
3301
|
+
this.fsSupported = x(this.video, this.root), this.fsBtn.style.display = this.fsSupported ? "" : "none";
|
|
3191
3302
|
}
|
|
3192
3303
|
syncFullscreen() {
|
|
3193
|
-
let e =
|
|
3304
|
+
let e = ye(this.video, this.root);
|
|
3194
3305
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
3195
3306
|
}
|
|
3196
3307
|
poke() {
|
|
@@ -3268,41 +3379,51 @@ var Sr = class {
|
|
|
3268
3379
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
3269
3380
|
}
|
|
3270
3381
|
};
|
|
3271
|
-
function
|
|
3382
|
+
function kr(e) {
|
|
3272
3383
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
3273
3384
|
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");
|
|
3274
3385
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
3275
3386
|
}
|
|
3276
|
-
function
|
|
3387
|
+
function Ar(e) {
|
|
3277
3388
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
3278
3389
|
}
|
|
3279
|
-
function
|
|
3390
|
+
function jr(e) {
|
|
3280
3391
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3281
3392
|
}
|
|
3282
|
-
function
|
|
3393
|
+
function Mr(e) {
|
|
3283
3394
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3284
3395
|
}
|
|
3285
3396
|
//#endregion
|
|
3286
3397
|
//#region src/managed/index.ts
|
|
3287
|
-
var
|
|
3288
|
-
|
|
3398
|
+
var Nr = 6e3, Pr = 45e3, Fr = 2e3, Ir = 3, Lr = 5e3, Rr = 2e3, zr = 48e4, Br = "keySystemLicenseRequestFailed", Vr = /* @__PURE__ */ new Set([
|
|
3399
|
+
"GONE",
|
|
3400
|
+
"NOT_FOUND",
|
|
3401
|
+
"INVALID_URN",
|
|
3402
|
+
"UNAUTHORIZED",
|
|
3403
|
+
"GEO_DENIED",
|
|
3404
|
+
"DRM_DEVICE_REVOKED"
|
|
3405
|
+
]);
|
|
3406
|
+
function Hr(e) {
|
|
3407
|
+
return !Vr.has(e);
|
|
3408
|
+
}
|
|
3409
|
+
function Ur(e) {
|
|
3289
3410
|
if (e.env !== void 0 && e.baseUrl !== void 0) throw new n("INTERNAL", 0, `createPlayer: pass env OR baseUrl, not both (got env=${JSON.stringify(e.env)} and baseUrl=${JSON.stringify(e.baseUrl)})`);
|
|
3290
|
-
if (e.env !== void 0) return
|
|
3411
|
+
if (e.env !== void 0) return ct(e.env);
|
|
3291
3412
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
3292
3413
|
return e.baseUrl;
|
|
3293
3414
|
}
|
|
3294
|
-
async function
|
|
3415
|
+
async function Wr(e) {
|
|
3295
3416
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
3296
|
-
let t =
|
|
3417
|
+
let t = Ur(e);
|
|
3297
3418
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
3298
3419
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
3299
|
-
let r = new
|
|
3420
|
+
let r = new Gr({
|
|
3300
3421
|
...e,
|
|
3301
3422
|
baseUrl: t
|
|
3302
3423
|
});
|
|
3303
3424
|
return await r.start(), r;
|
|
3304
3425
|
}
|
|
3305
|
-
var
|
|
3426
|
+
var Gr = class {
|
|
3306
3427
|
opts;
|
|
3307
3428
|
abort = new AbortController();
|
|
3308
3429
|
listeners = {};
|
|
@@ -3337,12 +3458,17 @@ var Lr = class {
|
|
|
3337
3458
|
playRequested = !1;
|
|
3338
3459
|
idleClosed = !1;
|
|
3339
3460
|
pendingStartLoad = !1;
|
|
3461
|
+
connectivity = null;
|
|
3462
|
+
failedWhileOffline = !1;
|
|
3340
3463
|
constructor(e) {
|
|
3341
3464
|
this.opts = e;
|
|
3342
3465
|
}
|
|
3343
3466
|
get state() {
|
|
3344
3467
|
return this._state;
|
|
3345
3468
|
}
|
|
3469
|
+
get offline() {
|
|
3470
|
+
return !R();
|
|
3471
|
+
}
|
|
3346
3472
|
get descriptor() {
|
|
3347
3473
|
return this._descriptor;
|
|
3348
3474
|
}
|
|
@@ -3350,7 +3476,7 @@ var Lr = class {
|
|
|
3350
3476
|
return this._endedReason;
|
|
3351
3477
|
}
|
|
3352
3478
|
async start() {
|
|
3353
|
-
this.opts.muted && (this.opts.video.muted = !0), this.opts.poster && (this.opts.video.poster = this.opts.poster), this.mountControls(), this.attachPipListeners(), this.attachEndedPlayGuard(), this.setState("loading");
|
|
3479
|
+
this.opts.muted && (this.opts.video.muted = !0), this.opts.poster && (this.opts.video.poster = this.opts.poster), this.mountControls(), this.attachPipListeners(), this.attachEndedPlayGuard(), this.watchConnectivity(), this.setState("loading");
|
|
3354
3480
|
let e = ++this.loadGen, t = this.resolveOptions();
|
|
3355
3481
|
try {
|
|
3356
3482
|
let n = await v(t);
|
|
@@ -3363,7 +3489,7 @@ var Lr = class {
|
|
|
3363
3489
|
this.setState("waiting"), this.beginArming(e, t.liveStartsAtMs);
|
|
3364
3490
|
return;
|
|
3365
3491
|
}
|
|
3366
|
-
throw t;
|
|
3492
|
+
throw this.destroy(), t;
|
|
3367
3493
|
}
|
|
3368
3494
|
}
|
|
3369
3495
|
resolveOptions() {
|
|
@@ -3376,7 +3502,7 @@ var Lr = class {
|
|
|
3376
3502
|
};
|
|
3377
3503
|
}
|
|
3378
3504
|
beginArming(e, t, n = !1) {
|
|
3379
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
3505
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
|
|
3380
3506
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
3381
3507
|
}
|
|
3382
3508
|
beginArmingByPolling(e) {
|
|
@@ -3397,7 +3523,7 @@ var Lr = class {
|
|
|
3397
3523
|
setTimeout(() => {
|
|
3398
3524
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3399
3525
|
phase: i ? "unavailable" : "tooEarly",
|
|
3400
|
-
retryInMs:
|
|
3526
|
+
retryInMs: Pr,
|
|
3401
3527
|
attempt: 1,
|
|
3402
3528
|
elapsedMs: 0,
|
|
3403
3529
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3436,13 +3562,13 @@ var Lr = class {
|
|
|
3436
3562
|
!a && !p() && h();
|
|
3437
3563
|
}, e);
|
|
3438
3564
|
};
|
|
3439
|
-
_(
|
|
3565
|
+
_(Nr), this.armingSub = T({
|
|
3440
3566
|
eventsBaseUrl: t,
|
|
3441
3567
|
matchUrn: this.opts.matchUrn,
|
|
3442
3568
|
credential: this.opts.credential,
|
|
3443
|
-
onAlive: () => _(
|
|
3569
|
+
onAlive: () => _(Pr),
|
|
3444
3570
|
onState: (e) => {
|
|
3445
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3571
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Fr);
|
|
3446
3572
|
},
|
|
3447
3573
|
onError: () => h()
|
|
3448
3574
|
});
|
|
@@ -3465,7 +3591,7 @@ var Lr = class {
|
|
|
3465
3591
|
let n = await c(this.opts.credential);
|
|
3466
3592
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3467
3593
|
this.setState("loading");
|
|
3468
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3594
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = ht(this.opts.video, (e) => {
|
|
3469
3595
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3470
3596
|
});
|
|
3471
3597
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3487,26 +3613,26 @@ var Lr = class {
|
|
|
3487
3613
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3488
3614
|
let i = e.analytics?.sid;
|
|
3489
3615
|
if (!i) return;
|
|
3490
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3616
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = or(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3491
3617
|
if (!o) {
|
|
3492
3618
|
s && setTimeout(() => {
|
|
3493
3619
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3494
3620
|
}, 0);
|
|
3495
3621
|
return;
|
|
3496
3622
|
}
|
|
3497
|
-
let c = this.opts.video, l = new
|
|
3623
|
+
let c = this.opts.video, l = new sr({
|
|
3498
3624
|
endpoint: o,
|
|
3499
3625
|
sid: i,
|
|
3500
3626
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3501
|
-
sdkVersion:
|
|
3502
|
-
environment:
|
|
3627
|
+
sdkVersion: pr,
|
|
3628
|
+
environment: dr(c),
|
|
3503
3629
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3504
3630
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3505
3631
|
onBlocked: (e) => setTimeout(() => {
|
|
3506
3632
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3507
3633
|
}, 0),
|
|
3508
3634
|
sample: () => {
|
|
3509
|
-
let e = this.engine?.getStats() ??
|
|
3635
|
+
let e = this.engine?.getStats() ?? ut, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3510
3636
|
return {
|
|
3511
3637
|
...e,
|
|
3512
3638
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3520,7 +3646,7 @@ var Lr = class {
|
|
|
3520
3646
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3521
3647
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3522
3648
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3523
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3649
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), fr().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3524
3650
|
}
|
|
3525
3651
|
currentPresentation() {
|
|
3526
3652
|
let e = this.opts.video;
|
|
@@ -3535,7 +3661,7 @@ var Lr = class {
|
|
|
3535
3661
|
video: this.opts.video,
|
|
3536
3662
|
descriptor: e,
|
|
3537
3663
|
credential: t,
|
|
3538
|
-
deviceId:
|
|
3664
|
+
deviceId: k(),
|
|
3539
3665
|
userId: this.opts.userId,
|
|
3540
3666
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
3541
3667
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -3544,17 +3670,18 @@ var Lr = class {
|
|
|
3544
3670
|
adaptiveHoldBack: this.opts.adaptiveHoldBack,
|
|
3545
3671
|
adaptiveHoldBackCeiling: this.opts.adaptiveHoldBackCeiling,
|
|
3546
3672
|
mediaDuringKey: this.opts.mediaDuringKey,
|
|
3673
|
+
preloadHints: this.opts.preloadHints,
|
|
3547
3674
|
debug: this.opts.debug,
|
|
3548
3675
|
deferLoad: r,
|
|
3549
3676
|
hlsConfig: i,
|
|
3550
3677
|
emit: (e) => this.onEngineEvent(e),
|
|
3551
3678
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3552
3679
|
}, o = this.opts.engine ?? "auto";
|
|
3553
|
-
if (o === "native") return new
|
|
3554
|
-
if (o === "hls") return new
|
|
3555
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
3556
|
-
if (
|
|
3557
|
-
if (
|
|
3680
|
+
if (o === "native") return new U(a);
|
|
3681
|
+
if (o === "hls") return new Un(a);
|
|
3682
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && V(this.opts.video) && H() || !e.drmEnabled && Dt() && V(this.opts.video)) return new U(a);
|
|
3683
|
+
if (Ut()) return new Un(a);
|
|
3684
|
+
if (V(this.opts.video)) return new U(a);
|
|
3558
3685
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3559
3686
|
}
|
|
3560
3687
|
onEngineEvent(e) {
|
|
@@ -3604,11 +3731,11 @@ var Lr = class {
|
|
|
3604
3731
|
}
|
|
3605
3732
|
startLiveState(e) {
|
|
3606
3733
|
if (this.opts.liveStateEvents === !1) return;
|
|
3607
|
-
let t = this.opts.eventsBaseUrl ??
|
|
3734
|
+
let t = this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
|
|
3608
3735
|
if (!t) return;
|
|
3609
3736
|
this.closeLiveState();
|
|
3610
3737
|
let i = 0, a = !1;
|
|
3611
|
-
this.liveStateSub =
|
|
3738
|
+
this.liveStateSub = T({
|
|
3612
3739
|
eventsBaseUrl: t,
|
|
3613
3740
|
matchUrn: this.opts.matchUrn,
|
|
3614
3741
|
credential: this.opts.credential,
|
|
@@ -3620,11 +3747,11 @@ var Lr = class {
|
|
|
3620
3747
|
},
|
|
3621
3748
|
onError: (o) => {
|
|
3622
3749
|
if (!(this.destroyed || e !== this.loadGen || a) && !this.endedHandled) {
|
|
3623
|
-
if (o instanceof
|
|
3750
|
+
if (o instanceof w && (o.terminal || o.status === 404)) {
|
|
3624
3751
|
a = !0, this.emit("warning", new n(r(o.status), o.status, `live-state events answered HTTP ${o.status} for ${this.opts.matchUrn}: the match is ` + (o.terminal ? "gone, so the subscription stopped" : "not in the catalog (ended and dropped, or not listed yet), so it retries every 5 min") + " — end-of-stream detection falls back to the HLS staleness watchdog."));
|
|
3625
3752
|
return;
|
|
3626
3753
|
}
|
|
3627
|
-
i += 1, i >=
|
|
3754
|
+
i += 1, i >= Ir && (a = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${i} 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.`)));
|
|
3628
3755
|
}
|
|
3629
3756
|
}
|
|
3630
3757
|
});
|
|
@@ -3632,6 +3759,18 @@ var Lr = class {
|
|
|
3632
3759
|
closeLiveState() {
|
|
3633
3760
|
this.liveStateSub?.close(), this.liveStateSub = null;
|
|
3634
3761
|
}
|
|
3762
|
+
watchConnectivity() {
|
|
3763
|
+
this.connectivity || (this.connectivity = lt(), this.connectivity.onChange((e) => {
|
|
3764
|
+
if (this.destroyed) return;
|
|
3765
|
+
if (!e) {
|
|
3766
|
+
this.emit("offline");
|
|
3767
|
+
return;
|
|
3768
|
+
}
|
|
3769
|
+
if (this.emit("online"), this._state !== "error" || !this._lastError) return;
|
|
3770
|
+
let t = this._lastError.code;
|
|
3771
|
+
Hr(t) && (t === "NETWORK" || this.failedWhileOffline) && this.retry().catch(() => void 0);
|
|
3772
|
+
}));
|
|
3773
|
+
}
|
|
3635
3774
|
watchReturn() {
|
|
3636
3775
|
this.onReturnVisible || typeof document > "u" || this.opts.liveStateEvents !== !1 && (document.visibilityState === "hidden" && (this.hiddenAtMs = Date.now()), this.onReturnVisible = () => {
|
|
3637
3776
|
if (document.visibilityState === "hidden") {
|
|
@@ -3639,7 +3778,7 @@ var Lr = class {
|
|
|
3639
3778
|
return;
|
|
3640
3779
|
}
|
|
3641
3780
|
let e = this.hiddenAtMs;
|
|
3642
|
-
this.hiddenAtMs = null, e != null && Date.now() - e >=
|
|
3781
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= Lr && this.resyncLiveState();
|
|
3643
3782
|
}, this.onReturnPageShow = (e) => {
|
|
3644
3783
|
e.persisted && this.resyncLiveState();
|
|
3645
3784
|
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
@@ -3671,7 +3810,7 @@ var Lr = class {
|
|
|
3671
3810
|
scheduleRejoin(e) {
|
|
3672
3811
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3673
3812
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3674
|
-
}, Math.random() *
|
|
3813
|
+
}, Math.random() * Fr));
|
|
3675
3814
|
}
|
|
3676
3815
|
cancelRejoin() {
|
|
3677
3816
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3695,7 +3834,7 @@ var Lr = class {
|
|
|
3695
3834
|
}
|
|
3696
3835
|
t.controls = !1;
|
|
3697
3836
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3698
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3837
|
+
r && r.insertBefore(n, t), n.appendChild(t), gr(n, this.opts.theme), this.container = n, this.controlBar = Dr({
|
|
3699
3838
|
root: n,
|
|
3700
3839
|
video: t,
|
|
3701
3840
|
player: this,
|
|
@@ -3705,6 +3844,7 @@ var Lr = class {
|
|
|
3705
3844
|
streamEnded: () => this.streamEnded,
|
|
3706
3845
|
interruptedMessage: this.opts.interruptedMessage,
|
|
3707
3846
|
errorMessage: this.opts.errorMessage,
|
|
3847
|
+
offlineMessage: this.opts.offlineMessage,
|
|
3708
3848
|
cspNonce: this.opts.cspNonce
|
|
3709
3849
|
});
|
|
3710
3850
|
}
|
|
@@ -3733,7 +3873,7 @@ var Lr = class {
|
|
|
3733
3873
|
}
|
|
3734
3874
|
startStats() {
|
|
3735
3875
|
this.stopStats();
|
|
3736
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3876
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Rr);
|
|
3737
3877
|
this.statsTimer = setInterval(() => {
|
|
3738
3878
|
if (!this.engine) return;
|
|
3739
3879
|
let e = this.engine.getStats();
|
|
@@ -3744,14 +3884,14 @@ var Lr = class {
|
|
|
3744
3884
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3745
3885
|
}
|
|
3746
3886
|
isStaleLicenseDenial(e) {
|
|
3747
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3887
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Br || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : G(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3748
3888
|
}
|
|
3749
3889
|
scheduleLicenseRefresh() {
|
|
3750
3890
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3751
3891
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3752
|
-
document.visibilityState !== "visible" || this.destroyed ||
|
|
3892
|
+
document.visibilityState !== "visible" || this.destroyed || G(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3753
3893
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3754
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3894
|
+
let e = this.opts.licenseRefreshMs ?? zr;
|
|
3755
3895
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3756
3896
|
}
|
|
3757
3897
|
stopRefresh() {
|
|
@@ -3808,7 +3948,7 @@ var Lr = class {
|
|
|
3808
3948
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3809
3949
|
}
|
|
3810
3950
|
getStats() {
|
|
3811
|
-
return this.engine?.getStats() ??
|
|
3951
|
+
return this.engine?.getStats() ?? ut;
|
|
3812
3952
|
}
|
|
3813
3953
|
getQualityLevels() {
|
|
3814
3954
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3847,13 +3987,13 @@ var Lr = class {
|
|
|
3847
3987
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
3848
3988
|
}
|
|
3849
3989
|
async enterFullscreen() {
|
|
3850
|
-
return !this.destroyed &&
|
|
3990
|
+
return !this.destroyed && S(this.opts.video, this.container ?? void 0);
|
|
3851
3991
|
}
|
|
3852
3992
|
async exitFullscreen() {
|
|
3853
|
-
await
|
|
3993
|
+
await C(this.opts.video, this.container ?? void 0);
|
|
3854
3994
|
}
|
|
3855
3995
|
fullscreenSupported() {
|
|
3856
|
-
return !this.destroyed &&
|
|
3996
|
+
return !this.destroyed && x(this.opts.video, this.container ?? void 0);
|
|
3857
3997
|
}
|
|
3858
3998
|
retry() {
|
|
3859
3999
|
return this.reload();
|
|
@@ -3878,13 +4018,13 @@ var Lr = class {
|
|
|
3878
4018
|
return n.add(t), () => n.delete(t);
|
|
3879
4019
|
}
|
|
3880
4020
|
destroy() {
|
|
3881
|
-
this.destroyed || (this.destroyed = !0, this.loadGen += 1, this.abort.abort(), this.stopStats(), this.stopRefresh(), this.unmountControls(), this.cancelRejoin(), this.closeArming(), this.closeLiveState(), this.unwatchReturn(), this.detachMedia?.(), this.detachPip?.(), this.detachEndedPlayGuard?.(), this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.engine?.destroy(), this.engine = null, this.setState("idle"), this.clearListeners());
|
|
4021
|
+
this.destroyed || (this.destroyed = !0, this.loadGen += 1, this.abort.abort(), this.stopStats(), this.stopRefresh(), this.unmountControls(), this.cancelRejoin(), this.closeArming(), this.closeLiveState(), this.unwatchReturn(), this.connectivity?.destroy(), this.connectivity = null, this.detachMedia?.(), this.detachPip?.(), this.detachEndedPlayGuard?.(), this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.engine?.destroy(), this.engine = null, this.setState("idle"), this.clearListeners());
|
|
3882
4022
|
}
|
|
3883
4023
|
clearListeners() {
|
|
3884
4024
|
for (let e of Object.keys(this.listeners)) this.listeners[e]?.clear();
|
|
3885
4025
|
}
|
|
3886
4026
|
fail(e) {
|
|
3887
|
-
this._lastError = e, this.setState("error"), this.analyticsSession?.noteFatal(), this.emit("error", e);
|
|
4027
|
+
this._lastError = e, this.failedWhileOffline = !R(), this.setState("error"), this.analyticsSession?.noteFatal(), this.emit("error", e);
|
|
3888
4028
|
}
|
|
3889
4029
|
setState(e) {
|
|
3890
4030
|
if (e === this._state) return;
|
|
@@ -3916,12 +4056,12 @@ var Lr = class {
|
|
|
3916
4056
|
};
|
|
3917
4057
|
//#endregion
|
|
3918
4058
|
//#region src/embed/protocol.ts
|
|
3919
|
-
function
|
|
4059
|
+
function Kr(e) {
|
|
3920
4060
|
return !!e && typeof e == "object" && typeof e.type == "string" && e.type.startsWith("oddin:");
|
|
3921
4061
|
}
|
|
3922
4062
|
//#endregion
|
|
3923
4063
|
//#region src/embed/host.ts
|
|
3924
|
-
function
|
|
4064
|
+
function qr(e) {
|
|
3925
4065
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3926
4066
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3927
4067
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3930,7 +4070,7 @@ function zr(e) {
|
|
|
3930
4070
|
let r = document.createElement("iframe");
|
|
3931
4071
|
r.src = t.toString(), r.allow = "autoplay; encrypted-media; fullscreen", r.setAttribute("allowfullscreen", ""), r.referrerPolicy = "no-referrer", r.setAttribute("sandbox", e.sandbox ?? "allow-scripts allow-same-origin allow-presentation"), r.style.cssText = "border:0;width:100%;height:100%;display:block", e.container.appendChild(r);
|
|
3932
4072
|
let i = /* @__PURE__ */ new Set(), a = (t) => {
|
|
3933
|
-
if (t.source !== r.contentWindow || t.origin !== n || !
|
|
4073
|
+
if (t.source !== r.contentWindow || t.origin !== n || !Kr(t.data)) return;
|
|
3934
4074
|
let a = t.data;
|
|
3935
4075
|
a.type === "oddin:ready" && a.protocol !== 1 && console.warn(`havik-player: embed protocol v${a.protocol} != host v1. Pin the embed page version to the SDK version to avoid skew.`), e.onEvent?.(a), i.forEach((e) => e(a));
|
|
3936
4076
|
};
|
|
@@ -3980,15 +4120,15 @@ function zr(e) {
|
|
|
3980
4120
|
}
|
|
3981
4121
|
//#endregion
|
|
3982
4122
|
//#region src/embed/page.ts
|
|
3983
|
-
var
|
|
3984
|
-
function
|
|
4123
|
+
var Jr = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
4124
|
+
function Yr(e) {
|
|
3985
4125
|
if (typeof e == "boolean") return e;
|
|
3986
4126
|
if (typeof e == "object" && e) {
|
|
3987
4127
|
let t = e.endpoint;
|
|
3988
4128
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3989
4129
|
}
|
|
3990
4130
|
}
|
|
3991
|
-
function
|
|
4131
|
+
function Xr() {
|
|
3992
4132
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3993
4133
|
if (e) return {
|
|
3994
4134
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3998,7 +4138,7 @@ function Hr() {
|
|
|
3998
4138
|
autoplay: e.autoplay ?? !0,
|
|
3999
4139
|
muted: e.muted ?? !0,
|
|
4000
4140
|
waitForLive: e.waitForLive ?? !0,
|
|
4001
|
-
analytics:
|
|
4141
|
+
analytics: Yr(e.analytics)
|
|
4002
4142
|
};
|
|
4003
4143
|
let t = new URLSearchParams(location.search);
|
|
4004
4144
|
return {
|
|
@@ -4011,9 +4151,9 @@ function Hr() {
|
|
|
4011
4151
|
waitForLive: !0
|
|
4012
4152
|
};
|
|
4013
4153
|
}
|
|
4014
|
-
async function
|
|
4015
|
-
let e =
|
|
4016
|
-
|
|
4154
|
+
async function Zr() {
|
|
4155
|
+
let e = Xr();
|
|
4156
|
+
$r();
|
|
4017
4157
|
let t = document.createElement("video");
|
|
4018
4158
|
t.setAttribute("playsinline", ""), t.muted = e.muted ?? !0, t.style.cssText = "width:100%;height:100%;object-fit:contain;background:#000;aspect-ratio:auto", document.body.appendChild(t);
|
|
4019
4159
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -4069,12 +4209,12 @@ async function Ur() {
|
|
|
4069
4209
|
message: e.message,
|
|
4070
4210
|
...e.country === void 0 ? {} : { country: e.country }
|
|
4071
4211
|
})), e.on("autoplayblocked", () => {
|
|
4072
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
4212
|
+
i({ type: "oddin:autoplayblocked" }), Qr(t, e);
|
|
4073
4213
|
});
|
|
4074
4214
|
}, s = async (r) => {
|
|
4075
4215
|
a?.destroy(), a = null;
|
|
4076
4216
|
try {
|
|
4077
|
-
let n = await
|
|
4217
|
+
let n = await Wr({
|
|
4078
4218
|
video: t,
|
|
4079
4219
|
baseUrl: e.baseUrl,
|
|
4080
4220
|
matchUrn: r,
|
|
@@ -4137,30 +4277,30 @@ async function Ur() {
|
|
|
4137
4277
|
a?.retry();
|
|
4138
4278
|
break;
|
|
4139
4279
|
case "oddin:load":
|
|
4140
|
-
typeof e.matchUrn == "string" &&
|
|
4280
|
+
typeof e.matchUrn == "string" && Jr.test(e.matchUrn) && s(e.matchUrn);
|
|
4141
4281
|
break;
|
|
4142
4282
|
case "oddin:destroy": c();
|
|
4143
4283
|
}
|
|
4144
4284
|
}, u = (e) => {
|
|
4145
|
-
r && e.origin === r &&
|
|
4285
|
+
r && e.origin === r && Kr(e.data) && l(e.data);
|
|
4146
4286
|
};
|
|
4147
4287
|
r && window.addEventListener("message", u), window.addEventListener("pagehide", c, { once: !0 }), await s(e.matchUrn), i({
|
|
4148
4288
|
type: "oddin:ready",
|
|
4149
4289
|
protocol: 1
|
|
4150
4290
|
});
|
|
4151
4291
|
}
|
|
4152
|
-
function
|
|
4292
|
+
function Qr(e, t) {
|
|
4153
4293
|
if (document.getElementById("havik-tap")) return;
|
|
4154
4294
|
let n = document.createElement("button");
|
|
4155
4295
|
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", () => {
|
|
4156
4296
|
n.remove(), t.play();
|
|
4157
4297
|
}), document.body.appendChild(n);
|
|
4158
4298
|
}
|
|
4159
|
-
function
|
|
4299
|
+
function $r() {
|
|
4160
4300
|
let e = document.createElement("style");
|
|
4161
4301
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
4162
4302
|
}
|
|
4163
4303
|
//#endregion
|
|
4164
|
-
export {
|
|
4304
|
+
export { w as LiveStateHttpError, mr as ODDIN_THEME, n as PlaybackError, gr as applyTheme, ct as baseUrlForEnv, Zr as bootEmbed, ke as clearDeviceId, Ve as clearRememberedBandwidth, Wr as createPlayer, E as deriveEventsBaseUrl, it as detectDrmSupport, S as enterVideoFullscreen, C as exitVideoFullscreen, be as fetchCatalog, Se as fetchTournament, we as flattenMatches, x as fullscreenSupported, k as getDeviceId, ot as isLowLatencyManifest, Kr as isOddinMessage, je as licenseRequestHeaders, qr as mountEmbed, fe as pollToLive, y as resolveStream, T as subscribeLiveState, ye as videoFullscreenActive, Ee as watchStatus };
|
|
4165
4305
|
|
|
4166
4306
|
//# sourceMappingURL=index.js.map
|