@oddin-gg/havik-player 2.23.3 → 2.23.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/havik-player.global.js +19 -19
- 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 +40 -5
- package/dist/index.d.ts +40 -5
- package/dist/index.js +436 -420
- package/dist/index.js.map +1 -1
- package/docs/API.md +20 -12
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -491,16 +491,23 @@ function we(e) {
|
|
|
491
491
|
}
|
|
492
492
|
//#endregion
|
|
493
493
|
//#region src/core/events.ts
|
|
494
|
-
var Te = 45e3
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
494
|
+
var Te = 45e3, E = class extends Error {
|
|
495
|
+
status;
|
|
496
|
+
terminal;
|
|
497
|
+
constructor(e) {
|
|
498
|
+
let t = e === 410;
|
|
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
|
+
}
|
|
501
|
+
}, Ee = 3e5;
|
|
502
|
+
function D(e) {
|
|
503
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = Math.max(t, e.notFoundRetryMs ?? Ee), i = e.idleTimeoutMs ?? Te, a = Number.isFinite(i) && i > 0 ? i : 0, o = new AbortController(), s = !1, l = (e) => new Promise((t) => {
|
|
504
|
+
if (o.signal.aborted) return t();
|
|
498
505
|
let n = setTimeout(t, e);
|
|
499
|
-
|
|
506
|
+
o.signal.addEventListener("abort", () => {
|
|
500
507
|
clearTimeout(n), t();
|
|
501
508
|
}, { once: !0 });
|
|
502
|
-
}),
|
|
503
|
-
if (
|
|
509
|
+
}), u = (t) => {
|
|
510
|
+
if (s) return;
|
|
504
511
|
e.onAlive?.();
|
|
505
512
|
let n = "message", r = [];
|
|
506
513
|
for (let e of t.split("\n")) {
|
|
@@ -513,69 +520,72 @@ function E(e) {
|
|
|
513
520
|
let t = JSON.parse(r.join("\n"));
|
|
514
521
|
t && typeof t.state == "string" && e.onState(t);
|
|
515
522
|
} catch {}
|
|
516
|
-
},
|
|
517
|
-
let r = e.getReader(),
|
|
518
|
-
|
|
523
|
+
}, d = /\r\n\r\n|\n\n|\r\r/, p = async (e, t, n) => {
|
|
524
|
+
let r = e.getReader(), i = new TextDecoder(), o = "", c = !1, l, f = () => {
|
|
525
|
+
a && (clearTimeout(l), l = setTimeout(() => {
|
|
519
526
|
n(), r.cancel().catch(() => {});
|
|
520
|
-
},
|
|
527
|
+
}, a));
|
|
521
528
|
};
|
|
522
529
|
try {
|
|
523
530
|
for (f();;) {
|
|
524
531
|
let { value: e, done: n } = await r.read();
|
|
525
532
|
if (n) return;
|
|
526
|
-
e && e.length > 0 && (f(), c || (c = !0, t())),
|
|
527
|
-
let
|
|
528
|
-
for (; (
|
|
529
|
-
if (
|
|
533
|
+
e && e.length > 0 && (f(), c || (c = !0, t())), o += i.decode(e, { stream: !0 });
|
|
534
|
+
let a;
|
|
535
|
+
for (; (a = d.exec(o)) !== null;) u(o.slice(0, a.index)), o = o.slice(a.index + a[0].length);
|
|
536
|
+
if (s) return;
|
|
530
537
|
}
|
|
531
538
|
} finally {
|
|
532
|
-
clearTimeout(
|
|
539
|
+
clearTimeout(l), await r.cancel().catch(() => {});
|
|
533
540
|
}
|
|
534
541
|
};
|
|
535
542
|
return (async () => {
|
|
536
|
-
let
|
|
537
|
-
for (; !
|
|
538
|
-
let
|
|
539
|
-
|
|
540
|
-
let
|
|
541
|
-
|
|
543
|
+
let i = t;
|
|
544
|
+
for (; !s;) {
|
|
545
|
+
let u = new AbortController(), d = () => u.abort();
|
|
546
|
+
o.signal.addEventListener("abort", d, { once: !0 });
|
|
547
|
+
let m = null, h = !1, g = !1, _, ee = () => {
|
|
548
|
+
m = `no data for ${a}ms`, u.abort();
|
|
542
549
|
};
|
|
543
550
|
try {
|
|
544
551
|
let n = await c(e.credential);
|
|
545
|
-
if (
|
|
546
|
-
let
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
},
|
|
550
|
-
let
|
|
552
|
+
if (s) return;
|
|
553
|
+
let r = f(e.eventsBaseUrl, `/v1/events/${encodeURIComponent(e.matchUrn)}`);
|
|
554
|
+
a && (_ = setTimeout(() => {
|
|
555
|
+
m = `no response headers within ${a}ms`, u.abort();
|
|
556
|
+
}, a));
|
|
557
|
+
let o = await fetch(r, {
|
|
551
558
|
method: "GET",
|
|
552
559
|
headers: {
|
|
553
560
|
"x-api-key": n.apiKey,
|
|
554
561
|
accept: "text/event-stream"
|
|
555
562
|
},
|
|
556
|
-
signal:
|
|
563
|
+
signal: u.signal,
|
|
557
564
|
cache: "no-store",
|
|
558
565
|
credentials: "omit",
|
|
559
566
|
mode: "cors"
|
|
560
567
|
});
|
|
561
|
-
if (clearTimeout(
|
|
562
|
-
!
|
|
563
|
-
|
|
564
|
-
|
|
568
|
+
if (clearTimeout(_), s) return;
|
|
569
|
+
if (!o.ok || !o.body) {
|
|
570
|
+
let t = new E(o.status);
|
|
571
|
+
h = t.terminal, g = o.status === 404, e.onError?.(t);
|
|
572
|
+
} else await p(o.body, () => {
|
|
573
|
+
i = t;
|
|
574
|
+
}, ee);
|
|
565
575
|
} catch (t) {
|
|
566
|
-
if (
|
|
567
|
-
|
|
576
|
+
if (s || o.signal.aborted) return;
|
|
577
|
+
m || e.onError?.(t);
|
|
568
578
|
} finally {
|
|
569
|
-
clearTimeout(
|
|
579
|
+
clearTimeout(_), o.signal.removeEventListener("abort", d), u.abort();
|
|
570
580
|
}
|
|
571
|
-
if (
|
|
572
|
-
|
|
581
|
+
if (s || h) return;
|
|
582
|
+
m && e.onError?.(/* @__PURE__ */ Error(`live-state subscribe idle: ${m} — reconnecting`)), await l(g ? Math.max(i, r) : i), i = Math.min(n, i * 2);
|
|
573
583
|
}
|
|
574
584
|
})(), { close() {
|
|
575
|
-
|
|
585
|
+
s || (s = !0, o.abort());
|
|
576
586
|
} };
|
|
577
587
|
}
|
|
578
|
-
function
|
|
588
|
+
function O(e) {
|
|
579
589
|
try {
|
|
580
590
|
let t = new URL(e);
|
|
581
591
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -585,27 +595,27 @@ function D(e) {
|
|
|
585
595
|
}
|
|
586
596
|
//#endregion
|
|
587
597
|
//#region src/core/drm/deviceId.ts
|
|
588
|
-
var
|
|
589
|
-
function
|
|
590
|
-
if (
|
|
598
|
+
var k = "havik.player.deviceId", A;
|
|
599
|
+
function j() {
|
|
600
|
+
if (A) return A;
|
|
591
601
|
try {
|
|
592
|
-
let e = globalThis.localStorage?.getItem(
|
|
593
|
-
if (e) return
|
|
602
|
+
let e = globalThis.localStorage?.getItem(k);
|
|
603
|
+
if (e) return A = e, e;
|
|
594
604
|
} catch {}
|
|
595
|
-
let e =
|
|
596
|
-
|
|
605
|
+
let e = Oe();
|
|
606
|
+
A = e;
|
|
597
607
|
try {
|
|
598
|
-
globalThis.localStorage?.setItem(
|
|
608
|
+
globalThis.localStorage?.setItem(k, e);
|
|
599
609
|
} catch {}
|
|
600
610
|
return e;
|
|
601
611
|
}
|
|
602
|
-
function
|
|
603
|
-
|
|
612
|
+
function De() {
|
|
613
|
+
A = void 0;
|
|
604
614
|
try {
|
|
605
|
-
globalThis.localStorage?.removeItem(
|
|
615
|
+
globalThis.localStorage?.removeItem(k);
|
|
606
616
|
} catch {}
|
|
607
617
|
}
|
|
608
|
-
function
|
|
618
|
+
function Oe() {
|
|
609
619
|
let e = globalThis.crypto;
|
|
610
620
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
611
621
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -617,32 +627,32 @@ function De() {
|
|
|
617
627
|
}
|
|
618
628
|
//#endregion
|
|
619
629
|
//#region src/core/drm/headers.ts
|
|
620
|
-
function
|
|
630
|
+
function ke(e, t, n = {}) {
|
|
621
631
|
let r = {
|
|
622
632
|
"x-api-key": t.apiKey,
|
|
623
633
|
"X-Match-Urn": e.matchUrn,
|
|
624
|
-
"X-Device-Id": n.deviceId ??
|
|
634
|
+
"X-Device-Id": n.deviceId ?? j(),
|
|
625
635
|
"Content-Type": "application/octet-stream"
|
|
626
636
|
};
|
|
627
637
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
628
638
|
}
|
|
629
639
|
//#endregion
|
|
630
640
|
//#region src/core/bandwidthMemory.ts
|
|
631
|
-
var
|
|
632
|
-
function
|
|
641
|
+
var M = "havik.player.bandwidth", Ae = .8, je = 2e7, Me = 3e5;
|
|
642
|
+
function Ne() {
|
|
633
643
|
return globalThis.navigator?.connection;
|
|
634
644
|
}
|
|
635
|
-
function
|
|
636
|
-
let e =
|
|
645
|
+
function Pe() {
|
|
646
|
+
let e = Ne()?.type;
|
|
637
647
|
return typeof e == "string" && e !== "" && e !== "unknown" ? e : "any";
|
|
638
648
|
}
|
|
639
|
-
function
|
|
640
|
-
let e =
|
|
649
|
+
function Fe() {
|
|
650
|
+
let e = Ne()?.downlink;
|
|
641
651
|
return typeof e == "number" && Number.isFinite(e) && e > 0 ? e * 1e6 : void 0;
|
|
642
652
|
}
|
|
643
|
-
function
|
|
653
|
+
function Ie() {
|
|
644
654
|
try {
|
|
645
|
-
let e = globalThis.localStorage?.getItem(
|
|
655
|
+
let e = globalThis.localStorage?.getItem(M);
|
|
646
656
|
if (!e) return {};
|
|
647
657
|
let t = JSON.parse(e);
|
|
648
658
|
return t && typeof t == "object" && !Array.isArray(t) ? t : {};
|
|
@@ -650,36 +660,36 @@ function Fe() {
|
|
|
650
660
|
return {};
|
|
651
661
|
}
|
|
652
662
|
}
|
|
653
|
-
function
|
|
654
|
-
let t =
|
|
663
|
+
function Le(e = Date.now()) {
|
|
664
|
+
let t = Ie()[Pe()];
|
|
655
665
|
if (!t || typeof t.bps != "number" || typeof t.at != "number" || !Number.isFinite(t.bps) || t.bps <= 0) return;
|
|
656
666
|
let n = e - t.at;
|
|
657
667
|
if (n < 0 || n > 2592e5) return;
|
|
658
|
-
let r =
|
|
659
|
-
return Math.round(Math.min(
|
|
668
|
+
let r = Fe(), i = r === void 0 ? t.bps : Math.min(t.bps, r);
|
|
669
|
+
return Math.round(Math.min(je, Math.max(Me, i * Ae)));
|
|
660
670
|
}
|
|
661
|
-
function
|
|
671
|
+
function Re(e, t = Date.now()) {
|
|
662
672
|
if (!Number.isFinite(e) || e <= 0) return;
|
|
663
|
-
let n =
|
|
664
|
-
n[
|
|
673
|
+
let n = Ie();
|
|
674
|
+
n[Pe()] = {
|
|
665
675
|
bps: Math.round(e),
|
|
666
676
|
at: t
|
|
667
677
|
};
|
|
668
678
|
try {
|
|
669
|
-
globalThis.localStorage?.setItem(
|
|
679
|
+
globalThis.localStorage?.setItem(M, JSON.stringify(n));
|
|
670
680
|
} catch {}
|
|
671
681
|
}
|
|
672
|
-
function
|
|
682
|
+
function ze() {
|
|
673
683
|
try {
|
|
674
|
-
globalThis.localStorage?.removeItem(
|
|
684
|
+
globalThis.localStorage?.removeItem(M);
|
|
675
685
|
} catch {}
|
|
676
686
|
}
|
|
677
687
|
//#endregion
|
|
678
688
|
//#region src/core/drm/cdm.ts
|
|
679
|
-
var
|
|
680
|
-
function
|
|
681
|
-
let n =
|
|
682
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
689
|
+
var Be = /* @__PURE__ */ new WeakMap();
|
|
690
|
+
function Ve(e, t) {
|
|
691
|
+
let n = Be.get(e);
|
|
692
|
+
n || (n = /* @__PURE__ */ new Map(), Be.set(e, n));
|
|
683
693
|
let r = n.get(t.keySystem);
|
|
684
694
|
if (r) return r;
|
|
685
695
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -687,22 +697,22 @@ function Be(e, t) {
|
|
|
687
697
|
});
|
|
688
698
|
return n.set(t.keySystem, i), i;
|
|
689
699
|
}
|
|
690
|
-
function
|
|
700
|
+
function N() {
|
|
691
701
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
692
702
|
}
|
|
693
|
-
var
|
|
694
|
-
function
|
|
703
|
+
var P = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
704
|
+
function He(e) {
|
|
695
705
|
return e.startsWith("com.widevine");
|
|
696
706
|
}
|
|
697
|
-
function
|
|
698
|
-
if (!
|
|
707
|
+
function F(e, t) {
|
|
708
|
+
if (!He(e)) return t;
|
|
699
709
|
let n = (e, t) => {
|
|
700
710
|
let n = e.videoCapabilities;
|
|
701
711
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
702
|
-
let n =
|
|
703
|
-
return n === -1 ||
|
|
712
|
+
let n = P.indexOf(e.robustness);
|
|
713
|
+
return n === -1 || P.indexOf(t) > n;
|
|
704
714
|
});
|
|
705
|
-
}, r =
|
|
715
|
+
}, r = P.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
706
716
|
...t,
|
|
707
717
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
708
718
|
...t,
|
|
@@ -711,53 +721,53 @@ function P(e, t) {
|
|
|
711
721
|
})));
|
|
712
722
|
return [...t, ...r];
|
|
713
723
|
}
|
|
714
|
-
function
|
|
715
|
-
return (t, n) =>
|
|
724
|
+
function Ue(e) {
|
|
725
|
+
return (t, n) => N() ? navigator.requestMediaKeySystemAccess(t, F(t, n)).then((t) => ({
|
|
716
726
|
keySystem: t.keySystem,
|
|
717
727
|
getConfiguration: () => t.getConfiguration(),
|
|
718
|
-
createMediaKeys: () =>
|
|
728
|
+
createMediaKeys: () => Ve(e, t)
|
|
719
729
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
720
730
|
}
|
|
721
|
-
var
|
|
731
|
+
var I = {
|
|
722
732
|
video: "SW_SECURE_DECODE",
|
|
723
733
|
audio: "SW_SECURE_CRYPTO",
|
|
724
734
|
scheme: "cbcs"
|
|
725
735
|
};
|
|
726
|
-
function
|
|
727
|
-
if (!
|
|
736
|
+
function We(e) {
|
|
737
|
+
if (!N()) return;
|
|
728
738
|
let t = (e, t) => ({
|
|
729
739
|
contentType: e,
|
|
730
740
|
robustness: t,
|
|
731
|
-
encryptionScheme:
|
|
741
|
+
encryptionScheme: I.scheme
|
|
732
742
|
});
|
|
733
|
-
|
|
743
|
+
Ue(e)("com.widevine.alpha", [{
|
|
734
744
|
initDataTypes: ["cenc"],
|
|
735
745
|
distinctiveIdentifier: "optional",
|
|
736
746
|
persistentState: "optional",
|
|
737
747
|
sessionTypes: ["temporary"],
|
|
738
|
-
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"",
|
|
739
|
-
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"",
|
|
748
|
+
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", I.audio)],
|
|
749
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", I.video)]
|
|
740
750
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
741
751
|
}
|
|
742
|
-
function
|
|
743
|
-
let t =
|
|
752
|
+
function L(e) {
|
|
753
|
+
let t = R(e);
|
|
744
754
|
if (/^avc[13]/.test(t)) return "avc";
|
|
745
755
|
if (/^(hvc1|hev1)/.test(t)) return "hevc";
|
|
746
756
|
if (/^(dvh1|dvhe)/.test(t)) return "dv";
|
|
747
757
|
if (t.startsWith("av01")) return "av1";
|
|
748
758
|
if (/^vp0?9/.test(t)) return "vp9";
|
|
749
759
|
}
|
|
750
|
-
function
|
|
760
|
+
function R(e) {
|
|
751
761
|
return (e ?? "").trim().toLowerCase();
|
|
752
762
|
}
|
|
753
|
-
var
|
|
763
|
+
var Ge = {
|
|
754
764
|
hevc: "hvc1.1.6.L93.90",
|
|
755
765
|
dv: "dvh1.05.06",
|
|
756
766
|
av1: "av01.0.05M.08",
|
|
757
767
|
vp9: "vp09.00.10.08"
|
|
758
|
-
},
|
|
759
|
-
function
|
|
760
|
-
let t =
|
|
768
|
+
}, Ke = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Map();
|
|
769
|
+
function qe(e) {
|
|
770
|
+
let t = R(e), n = Ke.get(t);
|
|
761
771
|
if (n) return n;
|
|
762
772
|
let r = {
|
|
763
773
|
initDataTypes: ["cenc"],
|
|
@@ -766,32 +776,32 @@ function Ke(e) {
|
|
|
766
776
|
sessionTypes: ["temporary"],
|
|
767
777
|
videoCapabilities: [{
|
|
768
778
|
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
769
|
-
robustness:
|
|
770
|
-
encryptionScheme:
|
|
779
|
+
robustness: I.video,
|
|
780
|
+
encryptionScheme: I.scheme
|
|
771
781
|
}]
|
|
772
782
|
}, i = (async () => {
|
|
773
783
|
try {
|
|
774
|
-
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha",
|
|
784
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", F("com.widevine.alpha", [r])), !0;
|
|
775
785
|
} catch {
|
|
776
786
|
return !1;
|
|
777
787
|
}
|
|
778
|
-
})().then((e) => (
|
|
779
|
-
return
|
|
788
|
+
})().then((e) => (z.set(t, e), e));
|
|
789
|
+
return Ke.set(t, i), i;
|
|
780
790
|
}
|
|
781
|
-
function
|
|
782
|
-
if (
|
|
791
|
+
function Je() {
|
|
792
|
+
if (N()) for (let e of Object.values(Ge)) qe(e);
|
|
783
793
|
}
|
|
784
|
-
function
|
|
785
|
-
let t =
|
|
786
|
-
if (t) return t === "avc" ? !0 :
|
|
794
|
+
function Ye(e) {
|
|
795
|
+
let t = L(e);
|
|
796
|
+
if (t) return t === "avc" ? !0 : z.get(R(e)) ?? z.get(R(Ge[t]));
|
|
787
797
|
}
|
|
788
798
|
//#endregion
|
|
789
799
|
//#region src/core/drm/support.ts
|
|
790
|
-
var
|
|
800
|
+
var Xe = 5e3, Ze = "video/mp4; codecs=\"avc1.42E01E\"", Qe = "audio/mp4; codecs=\"mp4a.40.2\"", $e = {
|
|
791
801
|
widevine: ["com.widevine.alpha"],
|
|
792
802
|
fairplay: ["com.apple.fps"]
|
|
793
803
|
};
|
|
794
|
-
function
|
|
804
|
+
function et(e) {
|
|
795
805
|
return e === "fairplay" ? [{
|
|
796
806
|
initDataTypes: [
|
|
797
807
|
"sinf",
|
|
@@ -799,30 +809,30 @@ function $e(e) {
|
|
|
799
809
|
"cenc"
|
|
800
810
|
],
|
|
801
811
|
videoCapabilities: [{
|
|
802
|
-
contentType:
|
|
812
|
+
contentType: Ze,
|
|
803
813
|
robustness: "",
|
|
804
814
|
encryptionScheme: "cbcs"
|
|
805
815
|
}],
|
|
806
816
|
audioCapabilities: [{
|
|
807
|
-
contentType:
|
|
817
|
+
contentType: Qe,
|
|
808
818
|
robustness: "",
|
|
809
819
|
encryptionScheme: "cbcs"
|
|
810
820
|
}]
|
|
811
|
-
}] :
|
|
821
|
+
}] : F("com.widevine.alpha", [{
|
|
812
822
|
initDataTypes: ["cenc"],
|
|
813
823
|
videoCapabilities: [{
|
|
814
|
-
contentType:
|
|
815
|
-
robustness:
|
|
816
|
-
encryptionScheme:
|
|
824
|
+
contentType: Ze,
|
|
825
|
+
robustness: I.video,
|
|
826
|
+
encryptionScheme: I.scheme
|
|
817
827
|
}],
|
|
818
828
|
audioCapabilities: [{
|
|
819
|
-
contentType:
|
|
820
|
-
robustness:
|
|
821
|
-
encryptionScheme:
|
|
829
|
+
contentType: Qe,
|
|
830
|
+
robustness: I.audio,
|
|
831
|
+
encryptionScheme: I.scheme
|
|
822
832
|
}]
|
|
823
833
|
}]);
|
|
824
834
|
}
|
|
825
|
-
function
|
|
835
|
+
function tt(e, t) {
|
|
826
836
|
return new Promise((n, r) => {
|
|
827
837
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
828
838
|
e.then((e) => {
|
|
@@ -832,8 +842,8 @@ function et(e, t) {
|
|
|
832
842
|
});
|
|
833
843
|
});
|
|
834
844
|
}
|
|
835
|
-
async function
|
|
836
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
845
|
+
async function nt(e = {}) {
|
|
846
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Xe, r = {};
|
|
837
847
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
838
848
|
verdict: "insecure-context",
|
|
839
849
|
detail: r
|
|
@@ -845,7 +855,7 @@ async function tt(e = {}) {
|
|
|
845
855
|
};
|
|
846
856
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
847
857
|
for (let e of t) {
|
|
848
|
-
let t =
|
|
858
|
+
let t = $e[e];
|
|
849
859
|
if (!t) {
|
|
850
860
|
r[e] = "unknown system";
|
|
851
861
|
continue;
|
|
@@ -856,7 +866,7 @@ async function tt(e = {}) {
|
|
|
856
866
|
break;
|
|
857
867
|
}
|
|
858
868
|
try {
|
|
859
|
-
return await
|
|
869
|
+
return await tt((await tt(i(n, et(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
860
870
|
verdict: "supported",
|
|
861
871
|
system: e,
|
|
862
872
|
detail: r
|
|
@@ -880,49 +890,49 @@ async function tt(e = {}) {
|
|
|
880
890
|
}
|
|
881
891
|
//#endregion
|
|
882
892
|
//#region src/core/manifest.ts
|
|
883
|
-
var
|
|
884
|
-
function
|
|
885
|
-
return
|
|
893
|
+
var rt = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
894
|
+
function it(e) {
|
|
895
|
+
return rt.test(e);
|
|
886
896
|
}
|
|
887
897
|
//#endregion
|
|
888
898
|
//#region src/core/env.ts
|
|
889
|
-
var
|
|
899
|
+
var at = {
|
|
890
900
|
integration: "https://feed-dev.oddin-video.gg",
|
|
891
901
|
production: "https://feed.oddin-video.gg"
|
|
892
902
|
};
|
|
893
|
-
function
|
|
894
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
903
|
+
function ot(e) {
|
|
904
|
+
let t = Object.prototype.hasOwnProperty.call(at, e) ? at[e] : void 0;
|
|
895
905
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
896
906
|
return t;
|
|
897
907
|
}
|
|
898
908
|
//#endregion
|
|
899
909
|
//#region src/core/stats.ts
|
|
900
|
-
var
|
|
901
|
-
function
|
|
910
|
+
var st = { droppedFrames: 0 };
|
|
911
|
+
function ct(e) {
|
|
902
912
|
try {
|
|
903
913
|
return new URL(e).host;
|
|
904
914
|
} catch {
|
|
905
915
|
return "";
|
|
906
916
|
}
|
|
907
917
|
}
|
|
908
|
-
var
|
|
909
|
-
function
|
|
918
|
+
var lt = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
919
|
+
function ut(e) {
|
|
910
920
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
911
921
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
912
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
913
|
-
let e =
|
|
922
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || lt.test(i.name)) && i.startTime >= n) {
|
|
923
|
+
let e = ct(i.name);
|
|
914
924
|
e && (t = e, n = i.startTime);
|
|
915
925
|
}
|
|
916
926
|
return t;
|
|
917
927
|
}
|
|
918
|
-
function
|
|
928
|
+
function B(e) {
|
|
919
929
|
let t = e.getVideoPlaybackQuality?.();
|
|
920
930
|
return {
|
|
921
931
|
dropped: t?.droppedVideoFrames ?? 0,
|
|
922
932
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
923
933
|
};
|
|
924
934
|
}
|
|
925
|
-
var
|
|
935
|
+
var dt = class {
|
|
926
936
|
video;
|
|
927
937
|
baseFrames = 0;
|
|
928
938
|
baseDropped = 0;
|
|
@@ -932,7 +942,7 @@ var ut = class {
|
|
|
932
942
|
this.video = e;
|
|
933
943
|
}
|
|
934
944
|
read() {
|
|
935
|
-
let e =
|
|
945
|
+
let e = B(this.video);
|
|
936
946
|
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, {
|
|
937
947
|
dropped: this.baseDropped + e.dropped,
|
|
938
948
|
totalFrames: this.baseFrames + e.totalFrames
|
|
@@ -945,7 +955,7 @@ var ut = class {
|
|
|
945
955
|
};
|
|
946
956
|
}
|
|
947
957
|
};
|
|
948
|
-
function
|
|
958
|
+
function ft(e, t) {
|
|
949
959
|
let n = [
|
|
950
960
|
["playing", () => t("playing")],
|
|
951
961
|
["waiting", () => t("buffering")],
|
|
@@ -962,8 +972,8 @@ function dt(e, t) {
|
|
|
962
972
|
}
|
|
963
973
|
//#endregion
|
|
964
974
|
//#region src/core/engine/native.ts
|
|
965
|
-
var
|
|
966
|
-
function
|
|
975
|
+
var pt = 2e3, mt = 3, V = 500, ht = 6e3, gt = .25, _t = 250, vt = .05, yt = 4, bt = 12e3, xt = .25, St = 1e3;
|
|
976
|
+
function Ct(e) {
|
|
967
977
|
try {
|
|
968
978
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
969
979
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -971,20 +981,20 @@ function St(e) {
|
|
|
971
981
|
return;
|
|
972
982
|
}
|
|
973
983
|
}
|
|
974
|
-
function
|
|
984
|
+
function H(e) {
|
|
975
985
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
976
986
|
}
|
|
977
|
-
function
|
|
987
|
+
function U() {
|
|
978
988
|
if (typeof window > "u") return !1;
|
|
979
989
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
980
990
|
return e || t;
|
|
981
991
|
}
|
|
982
|
-
function
|
|
983
|
-
if (typeof navigator > "u" || !
|
|
992
|
+
function wt() {
|
|
993
|
+
if (typeof navigator > "u" || !U()) return !1;
|
|
984
994
|
let e = navigator.userAgent ?? "";
|
|
985
995
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
986
996
|
}
|
|
987
|
-
var
|
|
997
|
+
var W = class {
|
|
988
998
|
name = "native";
|
|
989
999
|
deps;
|
|
990
1000
|
onLoaded;
|
|
@@ -1014,7 +1024,7 @@ var U = class {
|
|
|
1014
1024
|
frameCounter;
|
|
1015
1025
|
detachFrames = null;
|
|
1016
1026
|
constructor(e) {
|
|
1017
|
-
this.deps = e, this.frameCounter = new
|
|
1027
|
+
this.deps = e, this.frameCounter = new dt(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
|
|
1018
1028
|
}
|
|
1019
1029
|
async load() {
|
|
1020
1030
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1035,7 +1045,7 @@ var U = class {
|
|
|
1035
1045
|
type: "error",
|
|
1036
1046
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
1037
1047
|
fatal: !0
|
|
1038
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
1048
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Et(t.manifestUrl, t.analytics?.sid), e.load();
|
|
1039
1049
|
}
|
|
1040
1050
|
startLoad() {
|
|
1041
1051
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -1063,7 +1073,7 @@ var U = class {
|
|
|
1063
1073
|
};
|
|
1064
1074
|
this.onEncrypted = (n) => {
|
|
1065
1075
|
let a = n;
|
|
1066
|
-
a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
1076
|
+
a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Ct(a.initData), (async () => {
|
|
1067
1077
|
try {
|
|
1068
1078
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
1069
1079
|
initDataTypes: [a.initDataType],
|
|
@@ -1163,10 +1173,10 @@ var U = class {
|
|
|
1163
1173
|
droppedFrames: t.dropped,
|
|
1164
1174
|
decodedFrames: t.totalFrames
|
|
1165
1175
|
};
|
|
1166
|
-
if (this.cdnHost ||=
|
|
1176
|
+
if (this.cdnHost ||= ut(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1167
1177
|
n.isLive = !0;
|
|
1168
1178
|
let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
|
|
1169
|
-
Number.isFinite(r) && (n.atLiveEdge = r <=
|
|
1179
|
+
Number.isFinite(r) && (n.atLiveEdge = r <= yt, !e.paused && r >= 0 && (n.latencySeconds = r));
|
|
1170
1180
|
} else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
|
|
1171
1181
|
return n;
|
|
1172
1182
|
}
|
|
@@ -1178,30 +1188,30 @@ var U = class {
|
|
|
1178
1188
|
}
|
|
1179
1189
|
watchRefocus() {
|
|
1180
1190
|
this.deps.snapToLiveOnRefocus === !1 || typeof document > "u" || this.onVisibility || (this.onVisibility = () => {
|
|
1181
|
-
let e =
|
|
1191
|
+
let e = G();
|
|
1182
1192
|
if (document.visibilityState === "hidden") {
|
|
1183
1193
|
this.hiddenSince = e, this.cancelRefocus();
|
|
1184
1194
|
return;
|
|
1185
1195
|
}
|
|
1186
1196
|
let t = this.hiddenSince;
|
|
1187
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1197
|
+
this.hiddenSince = null, t != null && e - t >= pt && this.armRefocus();
|
|
1188
1198
|
}, this.onPageShow = (e) => {
|
|
1189
1199
|
e.persisted && this.armRefocus();
|
|
1190
1200
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
1191
1201
|
}
|
|
1192
1202
|
armRefocus() {
|
|
1193
1203
|
if (this.cancelRefocus(), Number.isFinite(this.deps.video.duration)) return;
|
|
1194
|
-
let e = this.liveEnd(), t =
|
|
1204
|
+
let e = this.liveEnd(), t = G, n = t(), r = 0, i = () => {
|
|
1195
1205
|
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1196
|
-
r +=
|
|
1197
|
-
let a = this.liveEnd(), o = a != null && (e == null || a >= e +
|
|
1206
|
+
r += V;
|
|
1207
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + gt), s = Math.max(r, t() - n) >= ht;
|
|
1198
1208
|
if (o || s && a != null) {
|
|
1199
1209
|
this.snapToLive();
|
|
1200
1210
|
return;
|
|
1201
1211
|
}
|
|
1202
|
-
this.refocusTimer = setTimeout(i,
|
|
1212
|
+
this.refocusTimer = setTimeout(i, V);
|
|
1203
1213
|
};
|
|
1204
|
-
this.refocusTimer = setTimeout(i,
|
|
1214
|
+
this.refocusTimer = setTimeout(i, V);
|
|
1205
1215
|
}
|
|
1206
1216
|
cancelRefocus() {
|
|
1207
1217
|
this.refocusTimer != null && clearTimeout(this.refocusTimer), this.refocusTimer = null;
|
|
@@ -1214,24 +1224,24 @@ var U = class {
|
|
|
1214
1224
|
}, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
|
|
1215
1225
|
if (e.duration !== Infinity) return;
|
|
1216
1226
|
this.checkEndStale();
|
|
1217
|
-
let t =
|
|
1218
|
-
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >=
|
|
1219
|
-
},
|
|
1227
|
+
let t = Tt(e, e.currentTime);
|
|
1228
|
+
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= vt) && (this.bufferedAdvancedAt = G()), this.lastBufferedEnd = t);
|
|
1229
|
+
}, _t);
|
|
1220
1230
|
}
|
|
1221
1231
|
checkEndStale() {
|
|
1222
1232
|
if (this.endedEmitted) return;
|
|
1223
|
-
let e =
|
|
1233
|
+
let e = G(), t = this.lastTickAt == null ? 0 : e - this.lastTickAt;
|
|
1224
1234
|
this.lastTickAt = e;
|
|
1225
1235
|
let n = this.liveEnd();
|
|
1226
1236
|
if (n == null) return;
|
|
1227
|
-
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >=
|
|
1237
|
+
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= xt;
|
|
1228
1238
|
this.lastSeekableEnd = n;
|
|
1229
1239
|
let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
|
|
1230
|
-
if (r || t >
|
|
1240
|
+
if (r || t > St || a || i.paused) {
|
|
1231
1241
|
this.edgeStampedAt = e;
|
|
1232
1242
|
return;
|
|
1233
1243
|
}
|
|
1234
|
-
e - (this.edgeStampedAt ?? e) >
|
|
1244
|
+
e - (this.edgeStampedAt ?? e) > bt && (this.endedEmitted = !0, this.deps.emit({
|
|
1235
1245
|
type: "ended",
|
|
1236
1246
|
reason: "stalled"
|
|
1237
1247
|
}));
|
|
@@ -1245,9 +1255,9 @@ var U = class {
|
|
|
1245
1255
|
liveEdgeEstimate() {
|
|
1246
1256
|
let e = this.deps.video;
|
|
1247
1257
|
if (e.duration !== Infinity) return null;
|
|
1248
|
-
let t = this.liveEnd(), n =
|
|
1258
|
+
let t = this.liveEnd(), n = Tt(e, e.currentTime) ?? this.lastBufferedEnd;
|
|
1249
1259
|
if (n != null) {
|
|
1250
|
-
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (
|
|
1260
|
+
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (G() - e) / 1e3));
|
|
1251
1261
|
(t == null || r > t) && (t = r);
|
|
1252
1262
|
}
|
|
1253
1263
|
return t != null && Number.isFinite(t) ? t : null;
|
|
@@ -1261,7 +1271,7 @@ var U = class {
|
|
|
1261
1271
|
snapToLive() {
|
|
1262
1272
|
let e = this.deps.video, t = this.liveEnd();
|
|
1263
1273
|
if (t == null) return;
|
|
1264
|
-
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t -
|
|
1274
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - mt, r);
|
|
1265
1275
|
try {
|
|
1266
1276
|
e.currentTime = i;
|
|
1267
1277
|
} catch {}
|
|
@@ -1279,10 +1289,10 @@ var U = class {
|
|
|
1279
1289
|
} catch {}
|
|
1280
1290
|
}
|
|
1281
1291
|
};
|
|
1282
|
-
function
|
|
1292
|
+
function G() {
|
|
1283
1293
|
return typeof performance < "u" ? performance.now() : Date.now();
|
|
1284
1294
|
}
|
|
1285
|
-
function
|
|
1295
|
+
function Tt(e, t) {
|
|
1286
1296
|
let n = e.buffered;
|
|
1287
1297
|
if (!n || !Number.isFinite(t)) return null;
|
|
1288
1298
|
for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
|
|
@@ -1291,12 +1301,12 @@ function wt(e, t) {
|
|
|
1291
1301
|
}
|
|
1292
1302
|
return null;
|
|
1293
1303
|
}
|
|
1294
|
-
function
|
|
1304
|
+
function Et(e, t) {
|
|
1295
1305
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1296
1306
|
}
|
|
1297
1307
|
//#endregion
|
|
1298
1308
|
//#region src/core/drm/signedUrl.ts
|
|
1299
|
-
function
|
|
1309
|
+
function K(e, t = Date.now()) {
|
|
1300
1310
|
if (!e) return !1;
|
|
1301
1311
|
let n;
|
|
1302
1312
|
try {
|
|
@@ -1308,13 +1318,13 @@ function G(e, t = Date.now()) {
|
|
|
1308
1318
|
}
|
|
1309
1319
|
//#endregion
|
|
1310
1320
|
//#region src/core/drm/xhrBody.ts
|
|
1311
|
-
var
|
|
1312
|
-
function
|
|
1321
|
+
var Dt = 4096;
|
|
1322
|
+
function Ot(e) {
|
|
1313
1323
|
if (!e || typeof e != "object") return;
|
|
1314
1324
|
let { response: t } = e;
|
|
1315
1325
|
if (typeof t == "string") return t;
|
|
1316
1326
|
let n;
|
|
1317
|
-
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 >
|
|
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 > Dt)) try {
|
|
1318
1328
|
return new TextDecoder().decode(n);
|
|
1319
1329
|
} catch {
|
|
1320
1330
|
return;
|
|
@@ -1322,8 +1332,8 @@ function Dt(e) {
|
|
|
1322
1332
|
}
|
|
1323
1333
|
//#endregion
|
|
1324
1334
|
//#region src/core/engine/prefetch.ts
|
|
1325
|
-
var
|
|
1326
|
-
function
|
|
1335
|
+
var kt = 15e3, At = 5e3, jt = 6;
|
|
1336
|
+
function Mt(e) {
|
|
1327
1337
|
try {
|
|
1328
1338
|
let t = new URL(e);
|
|
1329
1339
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1331,7 +1341,7 @@ function jt(e) {
|
|
|
1331
1341
|
return e;
|
|
1332
1342
|
}
|
|
1333
1343
|
}
|
|
1334
|
-
var
|
|
1344
|
+
var Nt = class {
|
|
1335
1345
|
cmcd;
|
|
1336
1346
|
entries = /* @__PURE__ */ new Map();
|
|
1337
1347
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1354,10 +1364,10 @@ var Mt = class {
|
|
|
1354
1364
|
}
|
|
1355
1365
|
prefetch(e, t, n) {
|
|
1356
1366
|
if (!this.isActive(t)) return;
|
|
1357
|
-
let r =
|
|
1367
|
+
let r = Mt(e);
|
|
1358
1368
|
if (this.entries.has(r)) return;
|
|
1359
1369
|
let i = this.perTrack.get(t) ?? 0;
|
|
1360
|
-
if (i >=
|
|
1370
|
+
if (i >= jt) return;
|
|
1361
1371
|
this.perTrack.set(t, i + 1);
|
|
1362
1372
|
let a = new AbortController(), o = {
|
|
1363
1373
|
started: performance.now(),
|
|
@@ -1371,10 +1381,10 @@ var Mt = class {
|
|
|
1371
1381
|
signal: a.signal
|
|
1372
1382
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1373
1383
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1374
|
-
},
|
|
1384
|
+
}, kt);
|
|
1375
1385
|
}
|
|
1376
1386
|
take(e) {
|
|
1377
|
-
let t =
|
|
1387
|
+
let t = Mt(e), n = this.entries.get(t);
|
|
1378
1388
|
return n && this.entries.delete(t), n;
|
|
1379
1389
|
}
|
|
1380
1390
|
destroy() {
|
|
@@ -1394,13 +1404,13 @@ var Mt = class {
|
|
|
1394
1404
|
}
|
|
1395
1405
|
}
|
|
1396
1406
|
};
|
|
1397
|
-
function
|
|
1407
|
+
function Pt(t) {
|
|
1398
1408
|
let n = e.DefaultConfig?.loader;
|
|
1399
1409
|
if (typeof n != "function") return;
|
|
1400
1410
|
class r extends n {
|
|
1401
1411
|
served = !1;
|
|
1402
1412
|
cancelled = !1;
|
|
1403
|
-
stats =
|
|
1413
|
+
stats = Ft();
|
|
1404
1414
|
load(e, n, r) {
|
|
1405
1415
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1406
1416
|
if (!i) {
|
|
@@ -1408,7 +1418,7 @@ function Nt(t) {
|
|
|
1408
1418
|
return;
|
|
1409
1419
|
}
|
|
1410
1420
|
this.served = !0;
|
|
1411
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1421
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || At, s = setTimeout(() => {
|
|
1412
1422
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1413
1423
|
}, o);
|
|
1414
1424
|
i.bytes.then((o) => {
|
|
@@ -1435,7 +1445,7 @@ function Nt(t) {
|
|
|
1435
1445
|
}
|
|
1436
1446
|
return r;
|
|
1437
1447
|
}
|
|
1438
|
-
function
|
|
1448
|
+
function Ft() {
|
|
1439
1449
|
return {
|
|
1440
1450
|
aborted: !1,
|
|
1441
1451
|
loaded: 0,
|
|
@@ -1459,10 +1469,10 @@ function Pt() {
|
|
|
1459
1469
|
}
|
|
1460
1470
|
};
|
|
1461
1471
|
}
|
|
1462
|
-
function
|
|
1472
|
+
function It(e) {
|
|
1463
1473
|
return e === "audio" ? "audio" : "main";
|
|
1464
1474
|
}
|
|
1465
|
-
function
|
|
1475
|
+
function Lt(e, t) {
|
|
1466
1476
|
let n = [];
|
|
1467
1477
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1468
1478
|
url: t.initSegment.url,
|
|
@@ -1481,16 +1491,16 @@ function It(e, t) {
|
|
|
1481
1491
|
}
|
|
1482
1492
|
//#endregion
|
|
1483
1493
|
//#region src/core/percentile.ts
|
|
1484
|
-
function
|
|
1494
|
+
function q(e, t) {
|
|
1485
1495
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1486
1496
|
}
|
|
1487
1497
|
//#endregion
|
|
1488
1498
|
//#region src/core/engine/hls.ts
|
|
1489
|
-
function
|
|
1499
|
+
function Rt() {
|
|
1490
1500
|
return e.isSupported();
|
|
1491
1501
|
}
|
|
1492
|
-
var
|
|
1493
|
-
function
|
|
1502
|
+
var zt = 1e6, Bt = 20, Vt = 1e4, Ht = 3, Ut = 5, Wt = 3, Gt = 1e4, Kt = 3e4, qt = 12e3, Jt = 3e3, Yt = .02, Xt = 6e3, Zt = .5, Qt = 3, $t = .5, en = 1.1, tn = .25, nn = 5e3, rn = 4e3, an = 2, on = 5, sn = 2, cn = 2, ln = 4, un = 4, dn = 2e3, fn = 3e4, pn = 1, mn = 2;
|
|
1503
|
+
function hn(e, t, n) {
|
|
1494
1504
|
if (n <= 0 || t < 0 || t >= e.length) return t;
|
|
1495
1505
|
let r = (t, n) => e[t].width === e[n].width && e[t].height === e[n].height, i = (t) => {
|
|
1496
1506
|
for (; t + 1 < e.length && r(t + 1, t);) t++;
|
|
@@ -1499,11 +1509,11 @@ function mn(e, t, n) {
|
|
|
1499
1509
|
for (let t = 0; t < n && a + 1 < e.length; t++) a = i(a + 1);
|
|
1500
1510
|
return a;
|
|
1501
1511
|
}
|
|
1502
|
-
var
|
|
1503
|
-
function
|
|
1512
|
+
var gn = .2, _n = 30, vn = 2, yn = 2, bn = 2, xn = 9, Sn = .5, Cn = 64, wn = 1e4, Tn = 8, En = .6, Dn = .4, On = .4, kn = 2, An = 6e4, J = .5, jn = 3.5, Mn = 300;
|
|
1513
|
+
function Nn(e) {
|
|
1504
1514
|
return (e?.part ?? e?.frag)?.stats;
|
|
1505
1515
|
}
|
|
1506
|
-
function
|
|
1516
|
+
function Pn() {
|
|
1507
1517
|
if (typeof navigator > "u") return 0;
|
|
1508
1518
|
try {
|
|
1509
1519
|
let e = navigator.connection?.rtt;
|
|
@@ -1512,20 +1522,20 @@ function Nn() {
|
|
|
1512
1522
|
return 0;
|
|
1513
1523
|
}
|
|
1514
1524
|
}
|
|
1515
|
-
function
|
|
1525
|
+
function Fn(e) {
|
|
1516
1526
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1517
1527
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1518
1528
|
return;
|
|
1519
1529
|
}
|
|
1520
|
-
e.liveSyncDuration ??=
|
|
1521
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1522
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1530
|
+
e.liveSyncDuration ??= bn;
|
|
1531
|
+
let t = Math.max(12, e.liveSyncDuration + xn);
|
|
1532
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), In(e, e.liveSyncDuration);
|
|
1523
1533
|
}
|
|
1524
|
-
function
|
|
1534
|
+
function In(e, t) {
|
|
1525
1535
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1526
1536
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1527
1537
|
}
|
|
1528
|
-
var
|
|
1538
|
+
var Ln = class {
|
|
1529
1539
|
name = "hls";
|
|
1530
1540
|
hls = null;
|
|
1531
1541
|
deps;
|
|
@@ -1619,11 +1629,11 @@ var In = class {
|
|
|
1619
1629
|
frameCounter;
|
|
1620
1630
|
detachFrames = null;
|
|
1621
1631
|
constructor(e) {
|
|
1622
|
-
this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.frameCounter = new
|
|
1632
|
+
this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.frameCounter = new dt(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1623
1633
|
}
|
|
1624
1634
|
async load() {
|
|
1625
1635
|
this.detachFrames ??= this.frameCounter.attach();
|
|
1626
|
-
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a =
|
|
1636
|
+
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = H(r) && U(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
1627
1637
|
if (e.drmEnabled && !o) {
|
|
1628
1638
|
i({
|
|
1629
1639
|
type: "error",
|
|
@@ -1632,7 +1642,7 @@ var In = class {
|
|
|
1632
1642
|
});
|
|
1633
1643
|
return;
|
|
1634
1644
|
}
|
|
1635
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1645
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (We(r), Je()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1636
1646
|
let e = this.hls;
|
|
1637
1647
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1638
1648
|
let t = e.liveSyncPosition;
|
|
@@ -1655,7 +1665,7 @@ var In = class {
|
|
|
1655
1665
|
}
|
|
1656
1666
|
this.loadSuspended = !0;
|
|
1657
1667
|
}
|
|
1658
|
-
},
|
|
1668
|
+
}, nn));
|
|
1659
1669
|
}
|
|
1660
1670
|
resumeLoading() {
|
|
1661
1671
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1687,7 +1697,7 @@ var In = class {
|
|
|
1687
1697
|
let t = e.liveSyncPosition;
|
|
1688
1698
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1689
1699
|
let { video: n } = this.deps;
|
|
1690
|
-
n.currentTime <= t +
|
|
1700
|
+
n.currentTime <= t + Sn || (n.currentTime = t);
|
|
1691
1701
|
}
|
|
1692
1702
|
reanchorPartTimeline(e, t) {
|
|
1693
1703
|
let { frag: n, part: r } = t;
|
|
@@ -1699,7 +1709,7 @@ var In = class {
|
|
|
1699
1709
|
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1700
1710
|
if (!s) return;
|
|
1701
1711
|
let c = a.startPTS - s.start;
|
|
1702
|
-
if (!(!Number.isFinite(c) || Math.abs(c) <
|
|
1712
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < Yt)) {
|
|
1703
1713
|
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1704
1714
|
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})`);
|
|
1705
1715
|
}
|
|
@@ -1707,7 +1717,7 @@ var In = class {
|
|
|
1707
1717
|
startHls() {
|
|
1708
1718
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
1709
1719
|
this.clearKick(), this.resetStarvationWindow(), this.resetChaseWindow(), this.resetFrameDropWindow(), this.lastFragLoadingMs = 0, this.lastEndSN = -1, this.lastAdvanceMs = 0;
|
|
1710
|
-
let u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d =
|
|
1720
|
+
let u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d = H(this.deps.video) && U(), f = {
|
|
1711
1721
|
debug: s === !0,
|
|
1712
1722
|
enableWorker: !o,
|
|
1713
1723
|
lowLatencyMode: o,
|
|
@@ -1722,24 +1732,24 @@ var In = class {
|
|
|
1722
1732
|
emeEnabled: !0,
|
|
1723
1733
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1724
1734
|
drmSystemOptions: {
|
|
1725
|
-
videoRobustness:
|
|
1726
|
-
audioRobustness:
|
|
1727
|
-
videoEncryptionScheme:
|
|
1728
|
-
audioEncryptionScheme:
|
|
1735
|
+
videoRobustness: I.video,
|
|
1736
|
+
audioRobustness: I.audio,
|
|
1737
|
+
videoEncryptionScheme: I.scheme,
|
|
1738
|
+
audioEncryptionScheme: I.scheme
|
|
1729
1739
|
},
|
|
1730
|
-
...
|
|
1740
|
+
...N() ? { requestMediaKeySystemAccessFunc: Ue(t) } : {},
|
|
1731
1741
|
licenseXhrSetup: (e, t) => {
|
|
1732
1742
|
let o = performance.now(), s = () => {
|
|
1733
1743
|
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", () => {
|
|
1734
1744
|
this.licenseTimeMs === 0 && (this.licenseTimeMs = Math.max(1, Math.round(performance.now() - o)));
|
|
1735
1745
|
});
|
|
1736
1746
|
}, { freshLicenseUrl: c } = this.deps;
|
|
1737
|
-
if (!c || !
|
|
1747
|
+
if (!c || !K(this.licenseUrl)) {
|
|
1738
1748
|
s();
|
|
1739
1749
|
return;
|
|
1740
1750
|
}
|
|
1741
1751
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1742
|
-
u = setTimeout(() => e(void 0),
|
|
1752
|
+
u = setTimeout(() => e(void 0), Gt);
|
|
1743
1753
|
});
|
|
1744
1754
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1745
1755
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1755,31 +1765,31 @@ var In = class {
|
|
|
1755
1765
|
...c
|
|
1756
1766
|
};
|
|
1757
1767
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !f.fLoader) {
|
|
1758
|
-
let e = new
|
|
1768
|
+
let e = new Nt({
|
|
1759
1769
|
sessionId: n.analytics?.sid,
|
|
1760
1770
|
contentId: n.matchUrn
|
|
1761
|
-
}), t =
|
|
1771
|
+
}), t = Pt(e);
|
|
1762
1772
|
t && (this.prefetch = e, f.fLoader = t);
|
|
1763
1773
|
}
|
|
1764
|
-
|
|
1774
|
+
Fn(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;
|
|
1765
1775
|
let p = new e(f);
|
|
1766
1776
|
if (this.hls = p, this.armHoldBack(p, f), p.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(p, t)), p.on(e.Events.MANIFEST_PARSED, () => {
|
|
1767
1777
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(p), this.measureLadder(p), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1768
1778
|
}), p.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1769
1779
|
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(() => {
|
|
1770
1780
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1771
|
-
},
|
|
1781
|
+
}, Kt)));
|
|
1772
1782
|
}), p.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1773
1783
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1774
1784
|
}), p.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
1775
1785
|
t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
|
|
1776
|
-
let n = t?.frag, r =
|
|
1786
|
+
let n = t?.frag, r = Nn(t), i = r?.loaded;
|
|
1777
1787
|
typeof i == "number" && (this.bytesLoaded += i), !this.reportedFirstBytes && typeof i == "number" && i > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1778
1788
|
let a = r?.loading;
|
|
1779
|
-
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 >
|
|
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 > Cn && this.requestTimesMs.shift()), this.sampleHoldBack(t);
|
|
1780
1790
|
let o = n?.url;
|
|
1781
1791
|
if (o) {
|
|
1782
|
-
let e =
|
|
1792
|
+
let e = ct(o);
|
|
1783
1793
|
e && (this.cdnHost = e);
|
|
1784
1794
|
}
|
|
1785
1795
|
}), p.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1793,15 +1803,15 @@ var In = class {
|
|
|
1793
1803
|
}), p.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1794
1804
|
let t = this.prefetch;
|
|
1795
1805
|
p.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1796
|
-
let r = n?.frag, i =
|
|
1797
|
-
if (r && t.isActive(i)) for (let e of
|
|
1798
|
-
}), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1806
|
+
let r = n?.frag, i = It(r?.type);
|
|
1807
|
+
if (r && t.isActive(i)) for (let e of Lt(p, r)) t.prefetch(e.url, i, e.kind);
|
|
1808
|
+
}), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(It(n?.frag?.type)));
|
|
1799
1809
|
}
|
|
1800
1810
|
p.on(e.Events.KEY_LOADED, () => {
|
|
1801
1811
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1802
1812
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1803
1813
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.adaptHoldBack(), this.checkFrameDrops();
|
|
1804
|
-
},
|
|
1814
|
+
}, Jt), p.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1805
1815
|
this.renditionSwitches += 1;
|
|
1806
1816
|
let n = this.lastLevelIndex >= 0 ? p.levels[this.lastLevelIndex] : void 0, r = p.levels[t.level];
|
|
1807
1817
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, this.armFrameDropGrace(), l({
|
|
@@ -1852,9 +1862,9 @@ var In = class {
|
|
|
1852
1862
|
let o = e.config ?? {}, s = typeof self < "u" && self.devicePixelRatio > 0 ? self.devicePixelRatio : 1, c = o.ignoreDevicePixelRatio ? 1 : s;
|
|
1853
1863
|
c = Math.min(c, o.maxDevicePixelRatio ?? Infinity);
|
|
1854
1864
|
let l = t.getMaxLevelByMediaSize(e.levels, i * c, a * c), u = this.deps.sizeCapHeadroom;
|
|
1855
|
-
if (u == null && s >=
|
|
1856
|
-
let d = u ??
|
|
1857
|
-
return
|
|
1865
|
+
if (u == null && s >= mn) return l;
|
|
1866
|
+
let d = u ?? pn, f = Number.isNaN(d) ? pn : d === Infinity ? e.levels.length : Math.max(0, Math.floor(d));
|
|
1867
|
+
return hn(e.levels, l, f);
|
|
1858
1868
|
}
|
|
1859
1869
|
onMediaResize() {
|
|
1860
1870
|
if (!this.sizeCapManaged) return;
|
|
@@ -1869,7 +1879,7 @@ var In = class {
|
|
|
1869
1879
|
return;
|
|
1870
1880
|
}
|
|
1871
1881
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1872
|
-
let t = e > this.sizeCapLevel ?
|
|
1882
|
+
let t = e > this.sizeCapLevel ? dn : fn;
|
|
1873
1883
|
this.capTimer = setTimeout(() => {
|
|
1874
1884
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1875
1885
|
}, t);
|
|
@@ -1879,9 +1889,9 @@ var In = class {
|
|
|
1879
1889
|
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;
|
|
1880
1890
|
}
|
|
1881
1891
|
dropLevelsWidevineCannotPlay(e) {
|
|
1882
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1883
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1884
|
-
for (let n of t)
|
|
1892
|
+
this.removeLevelsWhere(e, (e) => Ye(e) !== !0);
|
|
1893
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && L(e) !== "avc" && !!L(e)));
|
|
1894
|
+
for (let n of t) qe(n).then((t) => {
|
|
1885
1895
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1886
1896
|
});
|
|
1887
1897
|
}
|
|
@@ -1889,10 +1899,10 @@ var In = class {
|
|
|
1889
1899
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1890
1900
|
if (n.forEach((e, n) => {
|
|
1891
1901
|
let a = e.videoCodec;
|
|
1892
|
-
a &&
|
|
1902
|
+
a && L(a) && t(a) && (r.push(n), i.add(a));
|
|
1893
1903
|
}), !r.length) return !1;
|
|
1894
1904
|
let a = [...i].join(", ");
|
|
1895
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !
|
|
1905
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !L(e.videoCodec) || Ye(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1896
1906
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1897
1907
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1898
1908
|
}
|
|
@@ -2000,7 +2010,7 @@ var In = class {
|
|
|
2000
2010
|
return;
|
|
2001
2011
|
}
|
|
2002
2012
|
let e = Date.now() - this.lastAdvanceMs;
|
|
2003
|
-
!this.chaseSuspended && e >
|
|
2013
|
+
!this.chaseSuspended && e > Xt && this.suspendChasing(), e > qt && this.emitEnded("stalled");
|
|
2004
2014
|
}
|
|
2005
2015
|
resetStarvationWindow() {
|
|
2006
2016
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -2015,7 +2025,7 @@ var In = class {
|
|
|
2015
2025
|
this.resetStarvationWindow();
|
|
2016
2026
|
return;
|
|
2017
2027
|
}
|
|
2018
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
2028
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < Xt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > rn, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
|
|
2019
2029
|
if (this.starvedFrames = c, !a || l) {
|
|
2020
2030
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
2021
2031
|
return;
|
|
@@ -2024,12 +2034,12 @@ var In = class {
|
|
|
2024
2034
|
this.resetStarvationWindow();
|
|
2025
2035
|
return;
|
|
2026
2036
|
}
|
|
2027
|
-
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 >
|
|
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 > ln && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= sn && (this.clearKick(), this.starvationRebuilds < cn)) {
|
|
2028
2038
|
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");
|
|
2029
2039
|
return;
|
|
2030
2040
|
}
|
|
2031
|
-
let u = i && this.starvedTicks >=
|
|
2032
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
2041
|
+
let u = i && this.starvedTicks >= an, d = !i && this.deadTicks >= ln && this.recentMainFrags.reduce((e, t) => e + t, 0) >= un;
|
|
2042
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= on))) {
|
|
2033
2043
|
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");
|
|
2034
2044
|
try {
|
|
2035
2045
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -2044,7 +2054,7 @@ var In = class {
|
|
|
2044
2054
|
let t = e.latency, n = e.targetLatency;
|
|
2045
2055
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
2046
2056
|
let r = t - n;
|
|
2047
|
-
!this.catchUpEngaged && r >
|
|
2057
|
+
!this.catchUpEngaged && r > Zt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Zt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
2048
2058
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
2049
2059
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
2050
2060
|
}
|
|
@@ -2057,7 +2067,7 @@ var In = class {
|
|
|
2057
2067
|
}), n < 0 ? 0 : n;
|
|
2058
2068
|
}
|
|
2059
2069
|
armFrameDropGrace() {
|
|
2060
|
-
this.fpsGraceTicks > 0 || (this.fpsGraceTicks =
|
|
2070
|
+
this.fpsGraceTicks > 0 || (this.fpsGraceTicks = yn, this.fpsBadTicks = 0);
|
|
2061
2071
|
}
|
|
2062
2072
|
resetFrameDropWindow() {
|
|
2063
2073
|
this.fpsLastFrames = -1, this.fpsLastDropped = -1, this.fpsBadTicks = 0;
|
|
@@ -2068,8 +2078,8 @@ var In = class {
|
|
|
2068
2078
|
this.resetFrameDropWindow();
|
|
2069
2079
|
return;
|
|
2070
2080
|
}
|
|
2071
|
-
let { totalFrames: n, dropped: r } =
|
|
2072
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
2081
|
+
let { totalFrames: n, dropped: r } = B(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
2082
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < _n || o < 0) {
|
|
2073
2083
|
this.fpsBadTicks = 0;
|
|
2074
2084
|
return;
|
|
2075
2085
|
}
|
|
@@ -2077,11 +2087,11 @@ var In = class {
|
|
|
2077
2087
|
--this.fpsGraceTicks, this.fpsBadTicks = 0;
|
|
2078
2088
|
return;
|
|
2079
2089
|
}
|
|
2080
|
-
if (o <=
|
|
2090
|
+
if (o <= gn * a) {
|
|
2081
2091
|
this.fpsBadTicks = 0;
|
|
2082
2092
|
return;
|
|
2083
2093
|
}
|
|
2084
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
2094
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < vn) return;
|
|
2085
2095
|
this.fpsBadTicks = 0;
|
|
2086
2096
|
let s = e.levels, c = s[e.currentLevel];
|
|
2087
2097
|
if (!c) return;
|
|
@@ -2098,22 +2108,22 @@ var In = class {
|
|
|
2098
2108
|
return;
|
|
2099
2109
|
}
|
|
2100
2110
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
2101
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
2111
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(en, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
2102
2112
|
this.resetChaseWindow();
|
|
2103
2113
|
return;
|
|
2104
2114
|
}
|
|
2105
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
2115
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= $t) {
|
|
2106
2116
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
2107
2117
|
return;
|
|
2108
2118
|
}
|
|
2109
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
2119
|
+
if (this.chaseTicks += 1, this.chaseTicks < Qt) return;
|
|
2110
2120
|
this.resetChaseWindow();
|
|
2111
2121
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2112
2122
|
if (!(a > 1)) return;
|
|
2113
2123
|
let o = e.targetLatency;
|
|
2114
2124
|
if (typeof o != "number" || !(o > 0)) return;
|
|
2115
2125
|
let s = Math.min(n, a - 1);
|
|
2116
|
-
s < o +
|
|
2126
|
+
s < o + tn || (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({
|
|
2117
2127
|
type: "livetargetchange",
|
|
2118
2128
|
change: {
|
|
2119
2129
|
targetSeconds: s,
|
|
@@ -2130,13 +2140,13 @@ var In = class {
|
|
|
2130
2140
|
if (!this.holdBackEnabled || this.holdBackPriorChecked || !e || (this.holdBackPriorChecked = !0, this.holdBackApplied > 0 || this.holdBackStepCount > 0)) return;
|
|
2131
2141
|
let t = e.targetLatency;
|
|
2132
2142
|
if (this.holdBackBase < 0 && typeof t == "number" && t > 0 && (this.holdBackBase = t), this.holdBackBase < 0) return;
|
|
2133
|
-
let n =
|
|
2134
|
-
if (!(n >=
|
|
2135
|
-
let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase +
|
|
2143
|
+
let n = Pn();
|
|
2144
|
+
if (!(n >= Mn)) return;
|
|
2145
|
+
let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase + J);
|
|
2136
2146
|
i > r && (this.holdBackStepCount = 1, this.moveHoldBack(e, r, i, "connection-rtt", `connection rtt ${n} ms`));
|
|
2137
2147
|
}
|
|
2138
2148
|
holdBackCeiling(e) {
|
|
2139
|
-
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t :
|
|
2149
|
+
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t : jn, r = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2140
2150
|
return r > 1 ? Math.min(n, r - 1) : n;
|
|
2141
2151
|
}
|
|
2142
2152
|
sampleHoldBack(e) {
|
|
@@ -2145,7 +2155,7 @@ var In = class {
|
|
|
2145
2155
|
if (t !== "main" && t !== "audio") return;
|
|
2146
2156
|
let n = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag?.duration;
|
|
2147
2157
|
if (typeof n != "number" || !(n > 0)) return;
|
|
2148
|
-
let r =
|
|
2158
|
+
let r = Nn(e)?.loading;
|
|
2149
2159
|
if (!r || !(r.start > 0) || !(r.end > 0)) return;
|
|
2150
2160
|
let i = r.first > r.start ? r.first : r.end, a = Math.max(0, i - r.start) / (n * 1e3);
|
|
2151
2161
|
this.holdBackSamples.push({
|
|
@@ -2160,30 +2170,30 @@ var In = class {
|
|
|
2160
2170
|
this.holdBackSlowTicks = 0, this.holdBackFastSince = 0, this.holdBackSamples = [];
|
|
2161
2171
|
return;
|
|
2162
2172
|
}
|
|
2163
|
-
let t = Date.now(), n = t -
|
|
2173
|
+
let t = Date.now(), n = t - wn, r = this.holdBackSamples, i = 0;
|
|
2164
2174
|
for (; i < r.length && r[i].t < n;) i += 1;
|
|
2165
2175
|
i > 0 && r.splice(0, i);
|
|
2166
2176
|
let a = e.targetLatency;
|
|
2167
2177
|
if (typeof a != "number" || !(a > 0)) return;
|
|
2168
2178
|
this.holdBackBase < 0 && (this.holdBackBase = a);
|
|
2169
2179
|
let o = this.holdBackBase, s = this.holdBackCeiling(e);
|
|
2170
|
-
if (r.length <
|
|
2180
|
+
if (r.length < Tn) {
|
|
2171
2181
|
this.holdBackSlowTicks = 0;
|
|
2172
2182
|
return;
|
|
2173
2183
|
}
|
|
2174
|
-
let c = r.map((e) => e.ratio).sort((e, t) => e - t), l =
|
|
2175
|
-
if (l >=
|
|
2176
|
-
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks <
|
|
2184
|
+
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 >= En && u >= Dn) {
|
|
2186
|
+
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks < kn) return;
|
|
2177
2187
|
this.holdBackSlowTicks = 0;
|
|
2178
|
-
let t = Math.ceil((s - o) /
|
|
2188
|
+
let t = Math.ceil((s - o) / J), n = Math.ceil((a - o) / J - 1e-9);
|
|
2179
2189
|
if (n > this.holdBackStepCount && (this.holdBackStepCount = n), this.holdBackStepCount >= t) return;
|
|
2180
2190
|
this.holdBackStepCount += 1;
|
|
2181
|
-
let r = Math.min(s, o + this.holdBackStepCount *
|
|
2191
|
+
let r = Math.min(s, o + this.holdBackStepCount * J);
|
|
2182
2192
|
if (r <= a) return;
|
|
2183
2193
|
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)`);
|
|
2184
2194
|
return;
|
|
2185
2195
|
}
|
|
2186
|
-
if (this.holdBackSlowTicks = 0, l >=
|
|
2196
|
+
if (this.holdBackSlowTicks = 0, l >= On) {
|
|
2187
2197
|
this.holdBackFastSince = 0;
|
|
2188
2198
|
return;
|
|
2189
2199
|
}
|
|
@@ -2191,9 +2201,9 @@ var In = class {
|
|
|
2191
2201
|
this.holdBackFastSince = t;
|
|
2192
2202
|
return;
|
|
2193
2203
|
}
|
|
2194
|
-
if (t - this.holdBackFastSince <
|
|
2204
|
+
if (t - this.holdBackFastSince < An || (this.holdBackFastSince = t, this.holdBackStepCount === 0 || a !== this.holdBackApplied)) return;
|
|
2195
2205
|
--this.holdBackStepCount;
|
|
2196
|
-
let f = Math.max(o, o + this.holdBackStepCount *
|
|
2206
|
+
let f = Math.max(o, o + this.holdBackStepCount * J);
|
|
2197
2207
|
f >= a || this.moveHoldBack(e, a, f, "fast-fetches", `part fetches fast again (p95 first byte ${d} ms per 1 s of media)`);
|
|
2198
2208
|
}
|
|
2199
2209
|
moveHoldBack(e, t, n, r, i) {
|
|
@@ -2234,14 +2244,14 @@ var In = class {
|
|
|
2234
2244
|
} catch {}
|
|
2235
2245
|
}
|
|
2236
2246
|
startEstimate() {
|
|
2237
|
-
return this.deps.rememberBandwidth === !1 ?
|
|
2247
|
+
return this.deps.rememberBandwidth === !1 ? zt : Le() ?? zt;
|
|
2238
2248
|
}
|
|
2239
2249
|
maybeRememberBandwidth(e) {
|
|
2240
|
-
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded <
|
|
2250
|
+
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Bt) return;
|
|
2241
2251
|
let t = Date.now();
|
|
2242
|
-
if (!e && t - this.bwSavedAt <
|
|
2252
|
+
if (!e && t - this.bwSavedAt < Vt) return;
|
|
2243
2253
|
let n = this.hls?.bandwidthEstimate;
|
|
2244
|
-
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t,
|
|
2254
|
+
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Re(n));
|
|
2245
2255
|
}
|
|
2246
2256
|
destroy() {
|
|
2247
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) {
|
|
@@ -2259,7 +2269,7 @@ var In = class {
|
|
|
2259
2269
|
scheduleLicenseRetry(t) {
|
|
2260
2270
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
2261
2271
|
let n = t.response?.code ?? 0;
|
|
2262
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
2272
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Wt) return !1;
|
|
2263
2273
|
this.licenseRecoveries += 1;
|
|
2264
2274
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
2265
2275
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -2291,7 +2301,7 @@ var In = class {
|
|
|
2291
2301
|
return;
|
|
2292
2302
|
}
|
|
2293
2303
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
2294
|
-
if (this.networkRecoveries <
|
|
2304
|
+
if (this.networkRecoveries < Ut) {
|
|
2295
2305
|
this.networkRecoveries += 1;
|
|
2296
2306
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
2297
2307
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -2308,7 +2318,7 @@ var In = class {
|
|
|
2308
2318
|
return;
|
|
2309
2319
|
}
|
|
2310
2320
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
2311
|
-
if (this.mediaRecoveries <
|
|
2321
|
+
if (this.mediaRecoveries < Ht) {
|
|
2312
2322
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
2313
2323
|
return;
|
|
2314
2324
|
}
|
|
@@ -2329,18 +2339,18 @@ var In = class {
|
|
|
2329
2339
|
}
|
|
2330
2340
|
}
|
|
2331
2341
|
toError(t, r = "PLAYBACK") {
|
|
2332
|
-
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(
|
|
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(Ot(t.networkDetails)) : void 0;
|
|
2333
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);
|
|
2334
2344
|
}
|
|
2335
|
-
},
|
|
2345
|
+
}, Rn = 15e3, zn = 6e5, Bn = 3e5, Vn = 100, Y = 1, Hn = 1e3, Un = 3e4, Wn = 1e3, Gn = {
|
|
2336
2346
|
inline: "PRESENTATION_INLINE",
|
|
2337
2347
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2338
2348
|
pip: "PRESENTATION_PIP"
|
|
2339
|
-
},
|
|
2349
|
+
}, Kn = {
|
|
2340
2350
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2341
2351
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2342
2352
|
none: "KEY_SYSTEM_NONE"
|
|
2343
|
-
},
|
|
2353
|
+
}, qn = /* @__PURE__ */ new Set([
|
|
2344
2354
|
"INVALID_URN",
|
|
2345
2355
|
"NOT_FOUND",
|
|
2346
2356
|
"GEO_DENIED",
|
|
@@ -2351,7 +2361,7 @@ var In = class {
|
|
|
2351
2361
|
"FORBIDDEN",
|
|
2352
2362
|
"RATE_LIMITED",
|
|
2353
2363
|
"TIMEOUT"
|
|
2354
|
-
]),
|
|
2364
|
+
]), X = {
|
|
2355
2365
|
idle: "PLAYER_STATE_IDLE",
|
|
2356
2366
|
waiting: "PLAYER_STATE_WAITING",
|
|
2357
2367
|
loading: "PLAYER_STATE_LOADING",
|
|
@@ -2361,7 +2371,7 @@ var In = class {
|
|
|
2361
2371
|
ended: "PLAYER_STATE_ENDED",
|
|
2362
2372
|
error: "PLAYER_STATE_ERROR"
|
|
2363
2373
|
};
|
|
2364
|
-
function
|
|
2374
|
+
function Jn(e) {
|
|
2365
2375
|
try {
|
|
2366
2376
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2367
2377
|
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);
|
|
@@ -2369,8 +2379,8 @@ function qn(e) {
|
|
|
2369
2379
|
return;
|
|
2370
2380
|
}
|
|
2371
2381
|
}
|
|
2372
|
-
var
|
|
2373
|
-
function
|
|
2382
|
+
var Yn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Xn = /* @__PURE__ */ new Set(), Z = /* @__PURE__ */ new Set(), Q = /* @__PURE__ */ new Set(), Zn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2383
|
+
function Qn(e) {
|
|
2374
2384
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2375
2385
|
let t;
|
|
2376
2386
|
try {
|
|
@@ -2379,19 +2389,19 @@ function Zn(e) {
|
|
|
2379
2389
|
} catch {
|
|
2380
2390
|
return;
|
|
2381
2391
|
}
|
|
2382
|
-
if (
|
|
2383
|
-
|
|
2384
|
-
for (let e of
|
|
2392
|
+
if (Xn.has(t) && !Z.has(t)) {
|
|
2393
|
+
Z.add(t), _(Zn(new URL(t).origin));
|
|
2394
|
+
for (let e of Q) e.noteCspBlocked();
|
|
2385
2395
|
}
|
|
2386
2396
|
}
|
|
2387
|
-
function
|
|
2397
|
+
function $n(e, t) {
|
|
2388
2398
|
return _(t, e), { disabledReason: t };
|
|
2389
2399
|
}
|
|
2390
|
-
function
|
|
2391
|
-
if (n) return t && !
|
|
2400
|
+
function er(e, t, n) {
|
|
2401
|
+
if (n) return t && !Yn(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2392
2402
|
if (t) return { endpoint: t };
|
|
2393
|
-
if (t !== void 0) return
|
|
2394
|
-
let r =
|
|
2403
|
+
if (t !== void 0) return $n("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).");
|
|
2404
|
+
let r = Jn(e);
|
|
2395
2405
|
if (r) return { endpoint: r };
|
|
2396
2406
|
let i;
|
|
2397
2407
|
try {
|
|
@@ -2399,9 +2409,9 @@ function $n(e, t, n) {
|
|
|
2399
2409
|
} catch {
|
|
2400
2410
|
i = e;
|
|
2401
2411
|
}
|
|
2402
|
-
return
|
|
2412
|
+
return $n(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).`);
|
|
2403
2413
|
}
|
|
2404
|
-
var
|
|
2414
|
+
var tr = class {
|
|
2405
2415
|
opts;
|
|
2406
2416
|
url;
|
|
2407
2417
|
cspKey;
|
|
@@ -2483,8 +2493,8 @@ var er = class {
|
|
|
2483
2493
|
constructor(e) {
|
|
2484
2494
|
this.opts = {
|
|
2485
2495
|
...e,
|
|
2486
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2487
|
-
idleMs: e.idleMs ??
|
|
2496
|
+
heartbeatMs: e.heartbeatMs ?? Rn,
|
|
2497
|
+
idleMs: e.idleMs ?? zn
|
|
2488
2498
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2489
2499
|
try {
|
|
2490
2500
|
let e = new URL(this.url);
|
|
@@ -2501,11 +2511,11 @@ var er = class {
|
|
|
2501
2511
|
sdkVersion: this.opts.sdkVersion,
|
|
2502
2512
|
...this.opts.environment
|
|
2503
2513
|
};
|
|
2504
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2514
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Hn), 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 && Xn.add(this.cspKey), document.addEventListener("securitypolicyviolation", Qn), Q.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2505
2515
|
}
|
|
2506
2516
|
checkSuspension(e) {
|
|
2507
2517
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2508
|
-
let t = Math.max(this.opts.idleMs,
|
|
2518
|
+
let t = Math.max(this.opts.idleMs, Bn);
|
|
2509
2519
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2510
2520
|
}
|
|
2511
2521
|
syncIdle(e) {
|
|
@@ -2519,21 +2529,21 @@ var er = class {
|
|
|
2519
2529
|
noteStateChange(e, t, n, r) {
|
|
2520
2530
|
if (this.endedFlag || e === t) return;
|
|
2521
2531
|
let i = this.now();
|
|
2522
|
-
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(
|
|
2532
|
+
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(Y, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(Y, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
|
|
2523
2533
|
this.stallIsSeekInduced = this.seekInduced(i);
|
|
2524
2534
|
let e = !this.isHidden && !this.stallIsSeekInduced;
|
|
2525
|
-
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(
|
|
2535
|
+
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(Y, Math.round(this.playingTotalMs)));
|
|
2526
2536
|
} else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
|
|
2527
2537
|
this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
|
|
2528
2538
|
let a = {
|
|
2529
|
-
fromState:
|
|
2530
|
-
toState:
|
|
2531
|
-
presentation:
|
|
2539
|
+
fromState: X[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2540
|
+
toState: X[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2541
|
+
presentation: Gn[this.presentation]
|
|
2532
2542
|
}, o = this.causeOf(e, t, i);
|
|
2533
2543
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2534
2544
|
}
|
|
2535
2545
|
seekInduced(e) {
|
|
2536
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2546
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < Wn;
|
|
2537
2547
|
}
|
|
2538
2548
|
causeOf(e, t, n) {
|
|
2539
2549
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2570,25 +2580,25 @@ var er = class {
|
|
|
2570
2580
|
}
|
|
2571
2581
|
this.muteChanges += 1;
|
|
2572
2582
|
let r = this.now();
|
|
2573
|
-
n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(
|
|
2583
|
+
n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(Y, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
|
|
2574
2584
|
}
|
|
2575
2585
|
notePresentation(e) {
|
|
2576
2586
|
this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
|
|
2577
2587
|
}
|
|
2578
2588
|
notePlayIntent() {
|
|
2579
|
-
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs =
|
|
2589
|
+
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = Y), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = Y), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = Y), this.drmSetupMs > 0 && (this.drmSetupMs = Y));
|
|
2580
2590
|
}
|
|
2581
2591
|
noteReady() {
|
|
2582
|
-
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(
|
|
2592
|
+
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(Y, this.now() - this.startupAnchorMs));
|
|
2583
2593
|
}
|
|
2584
2594
|
noteFirstPlaylist() {
|
|
2585
|
-
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(
|
|
2595
|
+
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(Y, this.now() - this.startupAnchorMs));
|
|
2586
2596
|
}
|
|
2587
2597
|
noteDrmReady() {
|
|
2588
|
-
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(
|
|
2598
|
+
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(Y, this.now() - this.startupAnchorMs));
|
|
2589
2599
|
}
|
|
2590
2600
|
noteFirstBytes() {
|
|
2591
|
-
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(
|
|
2601
|
+
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(Y, this.now() - this.startupAnchorMs));
|
|
2592
2602
|
}
|
|
2593
2603
|
noteSeek() {
|
|
2594
2604
|
this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
|
|
@@ -2607,7 +2617,7 @@ var er = class {
|
|
|
2607
2617
|
let r = n ?? "";
|
|
2608
2618
|
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";
|
|
2609
2619
|
if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
|
|
2610
|
-
if (
|
|
2620
|
+
if (qn.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2611
2621
|
let i = t ?? "";
|
|
2612
2622
|
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";
|
|
2613
2623
|
}
|
|
@@ -2639,7 +2649,7 @@ var er = class {
|
|
|
2639
2649
|
let l = t.droppedFrames ?? 0;
|
|
2640
2650
|
l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
|
|
2641
2651
|
let u = t.renditionSwitches ?? 0;
|
|
2642
|
-
u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState =
|
|
2652
|
+
u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = X[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
|
|
2643
2653
|
let d = this.mutedTotalMs;
|
|
2644
2654
|
this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
|
|
2645
2655
|
let f = t.upshifts ?? 0;
|
|
@@ -2654,20 +2664,20 @@ var er = class {
|
|
|
2654
2664
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2655
2665
|
o.requestCountDelta = _;
|
|
2656
2666
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2657
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2667
|
+
n.length > 0 && (o.requestTimeP50Ms = q(n, 50), o.requestTimeP95Ms = q(n, 95));
|
|
2658
2668
|
}
|
|
2659
2669
|
typeof t.latencySeconds == "number" && typeof t.targetLatencySeconds == "number" && (o.driftMs = Math.round((t.latencySeconds - t.targetLatencySeconds) * 1e3)), typeof t.playbackRate == "number" && t.playbackRate > 0 && (o.playbackRate = t.playbackRate), t.qualityPinned === !0 && (o.qualityPinned = !0), t.cdnHost && (o.cdnHost = t.cdnHost), this.maybeEmitMediaInfo(t), this.enqueue({ heartbeat: o }), this.flush(), s > 0 && this.noteFirstBytes();
|
|
2660
2670
|
}
|
|
2661
2671
|
maybeEmitMediaInfo(e) {
|
|
2662
2672
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2663
2673
|
let t = {};
|
|
2664
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2674
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Kn[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);
|
|
2665
2675
|
let n = JSON.stringify(t);
|
|
2666
2676
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2667
2677
|
}
|
|
2668
2678
|
end(e, t) {
|
|
2669
2679
|
if (this.endedFlag) return;
|
|
2670
|
-
this.endedFlag = !0,
|
|
2680
|
+
this.endedFlag = !0, Q.delete(this);
|
|
2671
2681
|
let n = t ?? this.now();
|
|
2672
2682
|
this.playingSinceMs !== null && (this.playingTotalMs += n - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += n - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += n - this.bufferingSinceMs, this.bufferingSinceMs = null), this.mutedSinceMs !== null && (this.mutedTotalMs += n - this.mutedSinceMs, this.mutedSinceMs = null), this.waitingSinceMs !== null && (this.waitingTotalMs += n - this.waitingSinceMs, this.waitingSinceMs = null), this.isPlaying = !1, this.syncActive(n), this.closePresentation(n), this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.timer &&= (clearInterval(this.timer), null), this.idleTimer &&= (clearTimeout(this.idleTimer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), document.removeEventListener("freeze", this.onFreeze), document.removeEventListener("resume", this.onResume));
|
|
2673
2683
|
let r = this.safeSample();
|
|
@@ -2681,7 +2691,7 @@ var er = class {
|
|
|
2681
2691
|
let c = r?.positionMs ?? 0;
|
|
2682
2692
|
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));
|
|
2683
2693
|
let l = e !== "END_REASON_ENDED";
|
|
2684
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2694
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= Un && (i.abandonAfterStallMs = Math.max(Y, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Un && (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);
|
|
2685
2695
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2686
2696
|
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");
|
|
2687
2697
|
}
|
|
@@ -2701,13 +2711,13 @@ var er = class {
|
|
|
2701
2711
|
};
|
|
2702
2712
|
}
|
|
2703
2713
|
noteCspBlocked() {
|
|
2704
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2714
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(Zn(new URL(this.url).origin)));
|
|
2705
2715
|
}
|
|
2706
2716
|
cspBlocked() {
|
|
2707
|
-
return !!this.cspKey &&
|
|
2717
|
+
return !!this.cspKey && Z.has(this.cspKey);
|
|
2708
2718
|
}
|
|
2709
2719
|
enqueue(e) {
|
|
2710
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2720
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Vn;) {
|
|
2711
2721
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2712
2722
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2713
2723
|
}
|
|
@@ -2734,7 +2744,7 @@ var er = class {
|
|
|
2734
2744
|
};
|
|
2735
2745
|
//#endregion
|
|
2736
2746
|
//#region src/core/environment.ts
|
|
2737
|
-
function
|
|
2747
|
+
function nr() {
|
|
2738
2748
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2739
2749
|
let e;
|
|
2740
2750
|
try {
|
|
@@ -2759,14 +2769,14 @@ function tr() {
|
|
|
2759
2769
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2760
2770
|
};
|
|
2761
2771
|
}
|
|
2762
|
-
function
|
|
2772
|
+
function rr() {
|
|
2763
2773
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2764
2774
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2765
2775
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2766
2776
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2767
2777
|
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";
|
|
2768
2778
|
}
|
|
2769
|
-
function
|
|
2779
|
+
function ir() {
|
|
2770
2780
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2771
2781
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2772
2782
|
let t = {
|
|
@@ -2785,17 +2795,17 @@ function rr() {
|
|
|
2785
2795
|
}
|
|
2786
2796
|
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;
|
|
2787
2797
|
}
|
|
2788
|
-
function
|
|
2789
|
-
let t =
|
|
2790
|
-
deviceClass:
|
|
2798
|
+
function ar(e) {
|
|
2799
|
+
let t = nr(), n = {
|
|
2800
|
+
deviceClass: rr(),
|
|
2791
2801
|
integration: t.integration,
|
|
2792
|
-
...
|
|
2802
|
+
...ir()
|
|
2793
2803
|
};
|
|
2794
2804
|
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);
|
|
2795
2805
|
let r = e.getBoundingClientRect?.();
|
|
2796
2806
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2797
2807
|
}
|
|
2798
|
-
async function
|
|
2808
|
+
async function or() {
|
|
2799
2809
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2800
2810
|
if (!e?.getHighEntropyValues) return {};
|
|
2801
2811
|
try {
|
|
@@ -2807,7 +2817,7 @@ async function ar() {
|
|
|
2807
2817
|
}
|
|
2808
2818
|
//#endregion
|
|
2809
2819
|
//#region src/core/version.ts
|
|
2810
|
-
var
|
|
2820
|
+
var sr = "2.23.4", cr = {
|
|
2811
2821
|
accent: "#E1B600",
|
|
2812
2822
|
accentText: "#1B1C23",
|
|
2813
2823
|
background: "#0e0f13",
|
|
@@ -2818,7 +2828,7 @@ var or = "2.23.3", sr = {
|
|
|
2818
2828
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2819
2829
|
radius: "8px",
|
|
2820
2830
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2821
|
-
},
|
|
2831
|
+
}, lr = {
|
|
2822
2832
|
accent: "--havik-accent",
|
|
2823
2833
|
accentText: "--havik-accent-text",
|
|
2824
2834
|
background: "--havik-bg",
|
|
@@ -2830,26 +2840,26 @@ var or = "2.23.3", sr = {
|
|
|
2830
2840
|
radius: "--havik-radius",
|
|
2831
2841
|
fontFamily: "--havik-font"
|
|
2832
2842
|
};
|
|
2833
|
-
function
|
|
2843
|
+
function ur(e, t) {
|
|
2834
2844
|
let n = {
|
|
2835
|
-
...
|
|
2845
|
+
...cr,
|
|
2836
2846
|
...t
|
|
2837
2847
|
};
|
|
2838
|
-
for (let t of Object.keys(
|
|
2848
|
+
for (let t of Object.keys(lr)) e.style.setProperty(lr[t], n[t]);
|
|
2839
2849
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2840
2850
|
}
|
|
2841
2851
|
//#endregion
|
|
2842
2852
|
//#region src/ui/styles.ts
|
|
2843
|
-
var
|
|
2844
|
-
function
|
|
2845
|
-
let n = e.querySelector(`style#${
|
|
2846
|
-
if (n && (!t ||
|
|
2853
|
+
var dr = "havik-player-styles", fr = "\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", pr = /* @__PURE__ */ new WeakMap();
|
|
2854
|
+
function mr(e = document, t) {
|
|
2855
|
+
let n = e.querySelector(`style#${dr}`);
|
|
2856
|
+
if (n && (!t || pr.get(n) === t)) return;
|
|
2847
2857
|
let r = e.createElement("style");
|
|
2848
|
-
r.id =
|
|
2858
|
+
r.id = dr, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = fr, pr.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2849
2859
|
}
|
|
2850
2860
|
//#endregion
|
|
2851
2861
|
//#region src/ui/icons.ts
|
|
2852
|
-
var
|
|
2862
|
+
var hr = {
|
|
2853
2863
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2854
2864
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2855
2865
|
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\"/>",
|
|
@@ -2862,12 +2872,12 @@ var mr = {
|
|
|
2862
2872
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
2863
2873
|
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\"/>"
|
|
2864
2874
|
};
|
|
2865
|
-
function
|
|
2866
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2875
|
+
function $(e) {
|
|
2876
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${hr[e]}</svg>`;
|
|
2867
2877
|
}
|
|
2868
2878
|
//#endregion
|
|
2869
2879
|
//#region src/ui/controls.ts
|
|
2870
|
-
var
|
|
2880
|
+
var gr = 3e3, _r = 250, vr = /* @__PURE__ */ new Set([
|
|
2871
2881
|
"GONE",
|
|
2872
2882
|
"NOT_FOUND",
|
|
2873
2883
|
"GEO_DENIED",
|
|
@@ -2875,15 +2885,15 @@ var hr = 3e3, gr = 250, _r = /* @__PURE__ */ new Set([
|
|
|
2875
2885
|
"UNAUTHORIZED",
|
|
2876
2886
|
"DRM_DEVICE_REVOKED"
|
|
2877
2887
|
]);
|
|
2878
|
-
function
|
|
2888
|
+
function yr(e) {
|
|
2879
2889
|
let t = "This match isn't available in your country";
|
|
2880
2890
|
return e ? `${t} (${e})` : t;
|
|
2881
2891
|
}
|
|
2882
|
-
var
|
|
2883
|
-
function
|
|
2884
|
-
return new
|
|
2892
|
+
var br = "This device can't play protected video";
|
|
2893
|
+
function xr(e) {
|
|
2894
|
+
return new Sr(e);
|
|
2885
2895
|
}
|
|
2886
|
-
var
|
|
2896
|
+
var Sr = class {
|
|
2887
2897
|
root;
|
|
2888
2898
|
video;
|
|
2889
2899
|
player;
|
|
@@ -2931,7 +2941,7 @@ var xr = class {
|
|
|
2931
2941
|
scrubbing = !1;
|
|
2932
2942
|
offFns = [];
|
|
2933
2943
|
constructor(e) {
|
|
2934
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2944
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? gr, 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, mr(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");
|
|
2935
2945
|
let t = (e, t, n) => {
|
|
2936
2946
|
let r = this.doc.createElement(e);
|
|
2937
2947
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2942,12 +2952,12 @@ var xr = class {
|
|
|
2942
2952
|
"aria-label": r,
|
|
2943
2953
|
title: r
|
|
2944
2954
|
});
|
|
2945
|
-
return i.innerHTML =
|
|
2955
|
+
return i.innerHTML = $(n), i;
|
|
2946
2956
|
};
|
|
2947
2957
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
2948
2958
|
type: "button",
|
|
2949
2959
|
"aria-label": "Play"
|
|
2950
|
-
}), this.center.innerHTML =
|
|
2960
|
+
}), this.center.innerHTML = $("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
|
|
2951
2961
|
role: "slider",
|
|
2952
2962
|
"aria-label": "Seek",
|
|
2953
2963
|
"aria-valuemin": "0",
|
|
@@ -2965,7 +2975,7 @@ var xr = class {
|
|
|
2965
2975
|
"aria-label": "Volume"
|
|
2966
2976
|
});
|
|
2967
2977
|
let a = t("div", "havik-vol");
|
|
2968
|
-
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML =
|
|
2978
|
+
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = $("liveDot");
|
|
2969
2979
|
let o = this.doc.createElement("span");
|
|
2970
2980
|
o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
|
|
2971
2981
|
let s = t("div", "havik-spacer");
|
|
@@ -3017,7 +3027,7 @@ var xr = class {
|
|
|
3017
3027
|
let t = this.surfaceWasHidden;
|
|
3018
3028
|
this.tapTimer = setTimeout(() => {
|
|
3019
3029
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
3020
|
-
},
|
|
3030
|
+
}, _r);
|
|
3021
3031
|
}
|
|
3022
3032
|
toggleBar(e) {
|
|
3023
3033
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -3037,7 +3047,7 @@ var xr = class {
|
|
|
3037
3047
|
this.statusOverlays && (e === "ended" ? t = "ended" : e === "error" ? t = "error" : e === "waiting" ? t = "waiting" : !this.hasPlayed && (e === "idle" || e === "paused") && (t = "preplay")), this.renderStatus(t);
|
|
3038
3048
|
}
|
|
3039
3049
|
statusMessageFor(e) {
|
|
3040
|
-
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" ?
|
|
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" ? yr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? br : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
|
|
3041
3051
|
}
|
|
3042
3052
|
renderStatus(e) {
|
|
3043
3053
|
let t = this.statusMessageFor(e);
|
|
@@ -3049,12 +3059,12 @@ var xr = class {
|
|
|
3049
3059
|
}
|
|
3050
3060
|
if (e === "preplay") {
|
|
3051
3061
|
let e = this.doc.createElement("button");
|
|
3052
|
-
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML =
|
|
3062
|
+
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);
|
|
3053
3063
|
} else {
|
|
3054
3064
|
let r = this.doc.createElement("div");
|
|
3055
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
3065
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !vr.has(this.lastError.code)) {
|
|
3056
3066
|
let e = this.doc.createElement("button");
|
|
3057
|
-
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${
|
|
3067
|
+
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${$("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
3058
3068
|
}
|
|
3059
3069
|
}
|
|
3060
3070
|
this.root.append(n), this.statusBox = n, this.show();
|
|
@@ -3093,7 +3103,7 @@ var xr = class {
|
|
|
3093
3103
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
3094
3104
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
3095
3105
|
}
|
|
3096
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
3106
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Cr(this.video.currentTime)} / ${Cr(this.video.duration)}`);
|
|
3097
3107
|
}
|
|
3098
3108
|
syncLive() {
|
|
3099
3109
|
let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
|
|
@@ -3143,17 +3153,17 @@ var xr = class {
|
|
|
3143
3153
|
renderQualityMenu() {
|
|
3144
3154
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
3145
3155
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
3146
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
3156
|
+
for (let n of e) this.menu.append(this.menuItem(wr(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
3147
3157
|
}
|
|
3148
3158
|
renderAudioMenu() {
|
|
3149
3159
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
3150
3160
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
3151
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3161
|
+
for (let t of e) this.menu.append(this.menuItem(Tr(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
3152
3162
|
}
|
|
3153
3163
|
renderCcMenu() {
|
|
3154
3164
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
3155
3165
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
3156
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3166
|
+
for (let t of e) this.menu.append(this.menuItem(Er(t), !1, () => this.player.setTextTrack(t.id)));
|
|
3157
3167
|
}
|
|
3158
3168
|
onTracksChanged() {
|
|
3159
3169
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -3241,7 +3251,7 @@ var xr = class {
|
|
|
3241
3251
|
}
|
|
3242
3252
|
}
|
|
3243
3253
|
setIcon(e, t) {
|
|
3244
|
-
e.innerHTML =
|
|
3254
|
+
e.innerHTML = $(t);
|
|
3245
3255
|
}
|
|
3246
3256
|
destroy() {
|
|
3247
3257
|
this.hideTimer && clearTimeout(this.hideTimer), this.tapTimer && clearTimeout(this.tapTimer);
|
|
@@ -3258,41 +3268,41 @@ var xr = class {
|
|
|
3258
3268
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
3259
3269
|
}
|
|
3260
3270
|
};
|
|
3261
|
-
function
|
|
3271
|
+
function Cr(e) {
|
|
3262
3272
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
3263
3273
|
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");
|
|
3264
3274
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
3265
3275
|
}
|
|
3266
|
-
function
|
|
3276
|
+
function wr(e) {
|
|
3267
3277
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
3268
3278
|
}
|
|
3269
|
-
function
|
|
3279
|
+
function Tr(e) {
|
|
3270
3280
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3271
3281
|
}
|
|
3272
|
-
function
|
|
3282
|
+
function Er(e) {
|
|
3273
3283
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3274
3284
|
}
|
|
3275
3285
|
//#endregion
|
|
3276
3286
|
//#region src/managed/index.ts
|
|
3277
|
-
var
|
|
3278
|
-
function
|
|
3287
|
+
var Dr = 6e3, Or = 45e3, kr = 2e3, Ar = 3, jr = 5e3, Mr = 2e3, Nr = 48e4, Pr = "keySystemLicenseRequestFailed";
|
|
3288
|
+
function Fr(e) {
|
|
3279
3289
|
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)})`);
|
|
3280
|
-
if (e.env !== void 0) return
|
|
3290
|
+
if (e.env !== void 0) return ot(e.env);
|
|
3281
3291
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
3282
3292
|
return e.baseUrl;
|
|
3283
3293
|
}
|
|
3284
|
-
async function
|
|
3294
|
+
async function Ir(e) {
|
|
3285
3295
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
3286
|
-
let t =
|
|
3296
|
+
let t = Fr(e);
|
|
3287
3297
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
3288
3298
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
3289
|
-
let r = new
|
|
3299
|
+
let r = new Lr({
|
|
3290
3300
|
...e,
|
|
3291
3301
|
baseUrl: t
|
|
3292
3302
|
});
|
|
3293
3303
|
return await r.start(), r;
|
|
3294
3304
|
}
|
|
3295
|
-
var
|
|
3305
|
+
var Lr = class {
|
|
3296
3306
|
opts;
|
|
3297
3307
|
abort = new AbortController();
|
|
3298
3308
|
listeners = {};
|
|
@@ -3366,7 +3376,7 @@ var Ir = class {
|
|
|
3366
3376
|
};
|
|
3367
3377
|
}
|
|
3368
3378
|
beginArming(e, t, n = !1) {
|
|
3369
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
3379
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
|
|
3370
3380
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
3371
3381
|
}
|
|
3372
3382
|
beginArmingByPolling(e) {
|
|
@@ -3387,7 +3397,7 @@ var Ir = class {
|
|
|
3387
3397
|
setTimeout(() => {
|
|
3388
3398
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3389
3399
|
phase: i ? "unavailable" : "tooEarly",
|
|
3390
|
-
retryInMs:
|
|
3400
|
+
retryInMs: Or,
|
|
3391
3401
|
attempt: 1,
|
|
3392
3402
|
elapsedMs: 0,
|
|
3393
3403
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3426,13 +3436,13 @@ var Ir = class {
|
|
|
3426
3436
|
!a && !p() && h();
|
|
3427
3437
|
}, e);
|
|
3428
3438
|
};
|
|
3429
|
-
_(
|
|
3439
|
+
_(Dr), this.armingSub = D({
|
|
3430
3440
|
eventsBaseUrl: t,
|
|
3431
3441
|
matchUrn: this.opts.matchUrn,
|
|
3432
3442
|
credential: this.opts.credential,
|
|
3433
|
-
onAlive: () => _(
|
|
3443
|
+
onAlive: () => _(Or),
|
|
3434
3444
|
onState: (e) => {
|
|
3435
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3445
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * kr);
|
|
3436
3446
|
},
|
|
3437
3447
|
onError: () => h()
|
|
3438
3448
|
});
|
|
@@ -3455,7 +3465,7 @@ var Ir = class {
|
|
|
3455
3465
|
let n = await c(this.opts.credential);
|
|
3456
3466
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3457
3467
|
this.setState("loading");
|
|
3458
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3468
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = ft(this.opts.video, (e) => {
|
|
3459
3469
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3460
3470
|
});
|
|
3461
3471
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3477,26 +3487,26 @@ var Ir = class {
|
|
|
3477
3487
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3478
3488
|
let i = e.analytics?.sid;
|
|
3479
3489
|
if (!i) return;
|
|
3480
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3490
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = er(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3481
3491
|
if (!o) {
|
|
3482
3492
|
s && setTimeout(() => {
|
|
3483
3493
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3484
3494
|
}, 0);
|
|
3485
3495
|
return;
|
|
3486
3496
|
}
|
|
3487
|
-
let c = this.opts.video, l = new
|
|
3497
|
+
let c = this.opts.video, l = new tr({
|
|
3488
3498
|
endpoint: o,
|
|
3489
3499
|
sid: i,
|
|
3490
3500
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3491
|
-
sdkVersion:
|
|
3492
|
-
environment:
|
|
3501
|
+
sdkVersion: sr,
|
|
3502
|
+
environment: ar(c),
|
|
3493
3503
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3494
3504
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3495
3505
|
onBlocked: (e) => setTimeout(() => {
|
|
3496
3506
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3497
3507
|
}, 0),
|
|
3498
3508
|
sample: () => {
|
|
3499
|
-
let e = this.engine?.getStats() ??
|
|
3509
|
+
let e = this.engine?.getStats() ?? st, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3500
3510
|
return {
|
|
3501
3511
|
...e,
|
|
3502
3512
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3510,7 +3520,7 @@ var Ir = class {
|
|
|
3510
3520
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3511
3521
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3512
3522
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3513
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3523
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), or().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3514
3524
|
}
|
|
3515
3525
|
currentPresentation() {
|
|
3516
3526
|
let e = this.opts.video;
|
|
@@ -3525,7 +3535,7 @@ var Ir = class {
|
|
|
3525
3535
|
video: this.opts.video,
|
|
3526
3536
|
descriptor: e,
|
|
3527
3537
|
credential: t,
|
|
3528
|
-
deviceId:
|
|
3538
|
+
deviceId: j(),
|
|
3529
3539
|
userId: this.opts.userId,
|
|
3530
3540
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
3531
3541
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -3540,11 +3550,11 @@ var Ir = class {
|
|
|
3540
3550
|
emit: (e) => this.onEngineEvent(e),
|
|
3541
3551
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3542
3552
|
}, o = this.opts.engine ?? "auto";
|
|
3543
|
-
if (o === "native") return new
|
|
3544
|
-
if (o === "hls") return new
|
|
3545
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
3546
|
-
if (
|
|
3547
|
-
if (
|
|
3553
|
+
if (o === "native") return new W(a);
|
|
3554
|
+
if (o === "hls") return new Ln(a);
|
|
3555
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled && wt() && H(this.opts.video)) return new W(a);
|
|
3556
|
+
if (Rt()) return new Ln(a);
|
|
3557
|
+
if (H(this.opts.video)) return new W(a);
|
|
3548
3558
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3549
3559
|
}
|
|
3550
3560
|
onEngineEvent(e) {
|
|
@@ -3594,11 +3604,11 @@ var Ir = class {
|
|
|
3594
3604
|
}
|
|
3595
3605
|
startLiveState(e) {
|
|
3596
3606
|
if (this.opts.liveStateEvents === !1) return;
|
|
3597
|
-
let t = this.opts.eventsBaseUrl ??
|
|
3607
|
+
let t = this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
|
|
3598
3608
|
if (!t) return;
|
|
3599
3609
|
this.closeLiveState();
|
|
3600
|
-
let
|
|
3601
|
-
this.liveStateSub =
|
|
3610
|
+
let i = 0, a = !1;
|
|
3611
|
+
this.liveStateSub = D({
|
|
3602
3612
|
eventsBaseUrl: t,
|
|
3603
3613
|
matchUrn: this.opts.matchUrn,
|
|
3604
3614
|
credential: this.opts.credential,
|
|
@@ -3606,10 +3616,16 @@ var Ir = class {
|
|
|
3606
3616
|
this.destroyed || e !== this.loadGen || (t.state === "gone" ? this.onStreamEnded(!0, t.reason ?? "match_ended") : t.state === "ended" ? this.onStreamEnded(!1, t.reason) : t.state === "live" && this.endedHandled && this.scheduleRejoin(e));
|
|
3607
3617
|
},
|
|
3608
3618
|
onAlive: () => {
|
|
3609
|
-
|
|
3619
|
+
i = 0, a = !1;
|
|
3610
3620
|
},
|
|
3611
|
-
onError: () => {
|
|
3612
|
-
this.destroyed || e !== this.loadGen ||
|
|
3621
|
+
onError: (o) => {
|
|
3622
|
+
if (!(this.destroyed || e !== this.loadGen || a) && !this.endedHandled) {
|
|
3623
|
+
if (o instanceof E && (o.terminal || o.status === 404)) {
|
|
3624
|
+
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
|
+
return;
|
|
3626
|
+
}
|
|
3627
|
+
i += 1, i >= Ar && (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
|
+
}
|
|
3613
3629
|
}
|
|
3614
3630
|
});
|
|
3615
3631
|
}
|
|
@@ -3623,7 +3639,7 @@ var Ir = class {
|
|
|
3623
3639
|
return;
|
|
3624
3640
|
}
|
|
3625
3641
|
let e = this.hiddenAtMs;
|
|
3626
|
-
this.hiddenAtMs = null, e != null && Date.now() - e >=
|
|
3642
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= jr && this.resyncLiveState();
|
|
3627
3643
|
}, this.onReturnPageShow = (e) => {
|
|
3628
3644
|
e.persisted && this.resyncLiveState();
|
|
3629
3645
|
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
@@ -3655,7 +3671,7 @@ var Ir = class {
|
|
|
3655
3671
|
scheduleRejoin(e) {
|
|
3656
3672
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3657
3673
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3658
|
-
}, Math.random() *
|
|
3674
|
+
}, Math.random() * kr));
|
|
3659
3675
|
}
|
|
3660
3676
|
cancelRejoin() {
|
|
3661
3677
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3679,7 +3695,7 @@ var Ir = class {
|
|
|
3679
3695
|
}
|
|
3680
3696
|
t.controls = !1;
|
|
3681
3697
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3682
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3698
|
+
r && r.insertBefore(n, t), n.appendChild(t), ur(n, this.opts.theme), this.container = n, this.controlBar = xr({
|
|
3683
3699
|
root: n,
|
|
3684
3700
|
video: t,
|
|
3685
3701
|
player: this,
|
|
@@ -3717,7 +3733,7 @@ var Ir = class {
|
|
|
3717
3733
|
}
|
|
3718
3734
|
startStats() {
|
|
3719
3735
|
this.stopStats();
|
|
3720
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3736
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Mr);
|
|
3721
3737
|
this.statsTimer = setInterval(() => {
|
|
3722
3738
|
if (!this.engine) return;
|
|
3723
3739
|
let e = this.engine.getStats();
|
|
@@ -3728,14 +3744,14 @@ var Ir = class {
|
|
|
3728
3744
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3729
3745
|
}
|
|
3730
3746
|
isStaleLicenseDenial(e) {
|
|
3731
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3747
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Pr || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3732
3748
|
}
|
|
3733
3749
|
scheduleLicenseRefresh() {
|
|
3734
3750
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3735
3751
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3736
|
-
document.visibilityState !== "visible" || this.destroyed ||
|
|
3752
|
+
document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3737
3753
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3738
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3754
|
+
let e = this.opts.licenseRefreshMs ?? Nr;
|
|
3739
3755
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3740
3756
|
}
|
|
3741
3757
|
stopRefresh() {
|
|
@@ -3792,7 +3808,7 @@ var Ir = class {
|
|
|
3792
3808
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3793
3809
|
}
|
|
3794
3810
|
getStats() {
|
|
3795
|
-
return this.engine?.getStats() ??
|
|
3811
|
+
return this.engine?.getStats() ?? st;
|
|
3796
3812
|
}
|
|
3797
3813
|
getQualityLevels() {
|
|
3798
3814
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3900,12 +3916,12 @@ var Ir = class {
|
|
|
3900
3916
|
};
|
|
3901
3917
|
//#endregion
|
|
3902
3918
|
//#region src/embed/protocol.ts
|
|
3903
|
-
function
|
|
3919
|
+
function Rr(e) {
|
|
3904
3920
|
return !!e && typeof e == "object" && typeof e.type == "string" && e.type.startsWith("oddin:");
|
|
3905
3921
|
}
|
|
3906
3922
|
//#endregion
|
|
3907
3923
|
//#region src/embed/host.ts
|
|
3908
|
-
function
|
|
3924
|
+
function zr(e) {
|
|
3909
3925
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3910
3926
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3911
3927
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3914,7 +3930,7 @@ function Lr(e) {
|
|
|
3914
3930
|
let r = document.createElement("iframe");
|
|
3915
3931
|
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);
|
|
3916
3932
|
let i = /* @__PURE__ */ new Set(), a = (t) => {
|
|
3917
|
-
if (t.source !== r.contentWindow || t.origin !== n ||
|
|
3933
|
+
if (t.source !== r.contentWindow || t.origin !== n || !Rr(t.data)) return;
|
|
3918
3934
|
let a = t.data;
|
|
3919
3935
|
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));
|
|
3920
3936
|
};
|
|
@@ -3964,15 +3980,15 @@ function Lr(e) {
|
|
|
3964
3980
|
}
|
|
3965
3981
|
//#endregion
|
|
3966
3982
|
//#region src/embed/page.ts
|
|
3967
|
-
var
|
|
3968
|
-
function
|
|
3983
|
+
var Br = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3984
|
+
function Vr(e) {
|
|
3969
3985
|
if (typeof e == "boolean") return e;
|
|
3970
3986
|
if (typeof e == "object" && e) {
|
|
3971
3987
|
let t = e.endpoint;
|
|
3972
3988
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3973
3989
|
}
|
|
3974
3990
|
}
|
|
3975
|
-
function
|
|
3991
|
+
function Hr() {
|
|
3976
3992
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3977
3993
|
if (e) return {
|
|
3978
3994
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3982,7 +3998,7 @@ function Br() {
|
|
|
3982
3998
|
autoplay: e.autoplay ?? !0,
|
|
3983
3999
|
muted: e.muted ?? !0,
|
|
3984
4000
|
waitForLive: e.waitForLive ?? !0,
|
|
3985
|
-
analytics:
|
|
4001
|
+
analytics: Vr(e.analytics)
|
|
3986
4002
|
};
|
|
3987
4003
|
let t = new URLSearchParams(location.search);
|
|
3988
4004
|
return {
|
|
@@ -3995,9 +4011,9 @@ function Br() {
|
|
|
3995
4011
|
waitForLive: !0
|
|
3996
4012
|
};
|
|
3997
4013
|
}
|
|
3998
|
-
async function
|
|
3999
|
-
let e =
|
|
4000
|
-
|
|
4014
|
+
async function Ur() {
|
|
4015
|
+
let e = Hr();
|
|
4016
|
+
Gr();
|
|
4001
4017
|
let t = document.createElement("video");
|
|
4002
4018
|
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);
|
|
4003
4019
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -4053,12 +4069,12 @@ async function Vr() {
|
|
|
4053
4069
|
message: e.message,
|
|
4054
4070
|
...e.country === void 0 ? {} : { country: e.country }
|
|
4055
4071
|
})), e.on("autoplayblocked", () => {
|
|
4056
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
4072
|
+
i({ type: "oddin:autoplayblocked" }), Wr(t, e);
|
|
4057
4073
|
});
|
|
4058
4074
|
}, s = async (r) => {
|
|
4059
4075
|
a?.destroy(), a = null;
|
|
4060
4076
|
try {
|
|
4061
|
-
let n = await
|
|
4077
|
+
let n = await Ir({
|
|
4062
4078
|
video: t,
|
|
4063
4079
|
baseUrl: e.baseUrl,
|
|
4064
4080
|
matchUrn: r,
|
|
@@ -4121,30 +4137,30 @@ async function Vr() {
|
|
|
4121
4137
|
a?.retry();
|
|
4122
4138
|
break;
|
|
4123
4139
|
case "oddin:load":
|
|
4124
|
-
typeof e.matchUrn == "string" &&
|
|
4140
|
+
typeof e.matchUrn == "string" && Br.test(e.matchUrn) && s(e.matchUrn);
|
|
4125
4141
|
break;
|
|
4126
4142
|
case "oddin:destroy": c();
|
|
4127
4143
|
}
|
|
4128
4144
|
}, u = (e) => {
|
|
4129
|
-
r && e.origin === r &&
|
|
4145
|
+
r && e.origin === r && Rr(e.data) && l(e.data);
|
|
4130
4146
|
};
|
|
4131
4147
|
r && window.addEventListener("message", u), window.addEventListener("pagehide", c, { once: !0 }), await s(e.matchUrn), i({
|
|
4132
4148
|
type: "oddin:ready",
|
|
4133
4149
|
protocol: 1
|
|
4134
4150
|
});
|
|
4135
4151
|
}
|
|
4136
|
-
function
|
|
4152
|
+
function Wr(e, t) {
|
|
4137
4153
|
if (document.getElementById("havik-tap")) return;
|
|
4138
4154
|
let n = document.createElement("button");
|
|
4139
4155
|
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", () => {
|
|
4140
4156
|
n.remove(), t.play();
|
|
4141
4157
|
}), document.body.appendChild(n);
|
|
4142
4158
|
}
|
|
4143
|
-
function
|
|
4159
|
+
function Gr() {
|
|
4144
4160
|
let e = document.createElement("style");
|
|
4145
4161
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
4146
4162
|
}
|
|
4147
4163
|
//#endregion
|
|
4148
|
-
export {
|
|
4164
|
+
export { E as LiveStateHttpError, cr as ODDIN_THEME, n as PlaybackError, ur as applyTheme, ot as baseUrlForEnv, Ur as bootEmbed, De as clearDeviceId, ze as clearRememberedBandwidth, Ir as createPlayer, O as deriveEventsBaseUrl, nt as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, j as getDeviceId, it as isLowLatencyManifest, Rr as isOddinMessage, ke as licenseRequestHeaders, zr as mountEmbed, fe as pollToLive, y as resolveStream, D as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
|
|
4149
4165
|
|
|
4150
4166
|
//# sourceMappingURL=index.js.map
|