@oddin-gg/havik-player 2.23.3 → 2.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +50 -5
- package/dist/index.d.ts +50 -5
- package/dist/index.js +500 -411
- package/dist/index.js.map +1 -1
- package/docs/API.md +21 -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 He = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
704
|
+
function Ue(e) {
|
|
695
705
|
return e.startsWith("com.widevine");
|
|
696
706
|
}
|
|
697
707
|
function P(e, t) {
|
|
698
|
-
if (!
|
|
708
|
+
if (!Ue(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 = He.indexOf(e.robustness);
|
|
713
|
+
return n === -1 || He.indexOf(t) > n;
|
|
704
714
|
});
|
|
705
|
-
}, r =
|
|
715
|
+
}, r = He.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
706
716
|
...t,
|
|
707
717
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
708
718
|
...t,
|
|
@@ -711,11 +721,11 @@ function P(e, t) {
|
|
|
711
721
|
})));
|
|
712
722
|
return [...t, ...r];
|
|
713
723
|
}
|
|
714
|
-
function
|
|
715
|
-
return (t, n) =>
|
|
724
|
+
function We(e) {
|
|
725
|
+
return (t, n) => N() ? navigator.requestMediaKeySystemAccess(t, P(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
731
|
var F = {
|
|
@@ -723,14 +733,14 @@ var F = {
|
|
|
723
733
|
audio: "SW_SECURE_CRYPTO",
|
|
724
734
|
scheme: "cbcs"
|
|
725
735
|
};
|
|
726
|
-
function
|
|
727
|
-
if (!
|
|
736
|
+
function Ge(e) {
|
|
737
|
+
if (!N()) return;
|
|
728
738
|
let t = (e, t) => ({
|
|
729
739
|
contentType: e,
|
|
730
740
|
robustness: t,
|
|
731
741
|
encryptionScheme: F.scheme
|
|
732
742
|
});
|
|
733
|
-
|
|
743
|
+
We(e)("com.widevine.alpha", [{
|
|
734
744
|
initDataTypes: ["cenc"],
|
|
735
745
|
distinctiveIdentifier: "optional",
|
|
736
746
|
persistentState: "optional",
|
|
@@ -750,14 +760,14 @@ function I(e) {
|
|
|
750
760
|
function L(e) {
|
|
751
761
|
return (e ?? "").trim().toLowerCase();
|
|
752
762
|
}
|
|
753
|
-
var
|
|
763
|
+
var Ke = {
|
|
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 = L(e), n =
|
|
768
|
+
}, qe = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
|
|
769
|
+
function Je(e) {
|
|
770
|
+
let t = L(e), n = qe.get(t);
|
|
761
771
|
if (n) return n;
|
|
762
772
|
let r = {
|
|
763
773
|
initDataTypes: ["cenc"],
|
|
@@ -776,22 +786,22 @@ function Ke(e) {
|
|
|
776
786
|
return !1;
|
|
777
787
|
}
|
|
778
788
|
})().then((e) => (R.set(t, e), e));
|
|
779
|
-
return
|
|
789
|
+
return qe.set(t, i), i;
|
|
780
790
|
}
|
|
781
|
-
function
|
|
782
|
-
if (
|
|
791
|
+
function Ye() {
|
|
792
|
+
if (N()) for (let e of Object.values(Ke)) Je(e);
|
|
783
793
|
}
|
|
784
|
-
function
|
|
794
|
+
function Xe(e) {
|
|
785
795
|
let t = I(e);
|
|
786
|
-
if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(
|
|
796
|
+
if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(Ke[t]));
|
|
787
797
|
}
|
|
788
798
|
//#endregion
|
|
789
799
|
//#region src/core/drm/support.ts
|
|
790
|
-
var
|
|
800
|
+
var Ze = 5e3, Qe = "video/mp4; codecs=\"avc1.42E01E\"", $e = "audio/mp4; codecs=\"mp4a.40.2\"", et = {
|
|
791
801
|
widevine: ["com.widevine.alpha"],
|
|
792
802
|
fairplay: ["com.apple.fps"]
|
|
793
803
|
};
|
|
794
|
-
function
|
|
804
|
+
function tt(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: Qe,
|
|
803
813
|
robustness: "",
|
|
804
814
|
encryptionScheme: "cbcs"
|
|
805
815
|
}],
|
|
806
816
|
audioCapabilities: [{
|
|
807
|
-
contentType:
|
|
817
|
+
contentType: $e,
|
|
808
818
|
robustness: "",
|
|
809
819
|
encryptionScheme: "cbcs"
|
|
810
820
|
}]
|
|
811
821
|
}] : P("com.widevine.alpha", [{
|
|
812
822
|
initDataTypes: ["cenc"],
|
|
813
823
|
videoCapabilities: [{
|
|
814
|
-
contentType:
|
|
824
|
+
contentType: Qe,
|
|
815
825
|
robustness: F.video,
|
|
816
826
|
encryptionScheme: F.scheme
|
|
817
827
|
}],
|
|
818
828
|
audioCapabilities: [{
|
|
819
|
-
contentType:
|
|
829
|
+
contentType: $e,
|
|
820
830
|
robustness: F.audio,
|
|
821
831
|
encryptionScheme: F.scheme
|
|
822
832
|
}]
|
|
823
833
|
}]);
|
|
824
834
|
}
|
|
825
|
-
function
|
|
835
|
+
function nt(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 rt(e = {}) {
|
|
846
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ze, 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 = et[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 nt((await nt(i(n, tt(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
860
870
|
verdict: "supported",
|
|
861
871
|
system: e,
|
|
862
872
|
detail: r
|
|
@@ -880,37 +890,37 @@ async function tt(e = {}) {
|
|
|
880
890
|
}
|
|
881
891
|
//#endregion
|
|
882
892
|
//#region src/core/manifest.ts
|
|
883
|
-
var
|
|
884
|
-
function
|
|
885
|
-
return
|
|
893
|
+
var it = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
894
|
+
function at(e) {
|
|
895
|
+
return it.test(e);
|
|
886
896
|
}
|
|
887
897
|
//#endregion
|
|
888
898
|
//#region src/core/env.ts
|
|
889
|
-
var
|
|
899
|
+
var ot = {
|
|
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 st(e) {
|
|
904
|
+
let t = Object.prototype.hasOwnProperty.call(ot, e) ? ot[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 ct = { droppedFrames: 0 };
|
|
911
|
+
function lt(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 ut = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
919
|
+
function dt(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" || ut.test(i.name)) && i.startTime >= n) {
|
|
923
|
+
let e = lt(i.name);
|
|
914
924
|
e && (t = e, n = i.startTime);
|
|
915
925
|
}
|
|
916
926
|
return t;
|
|
@@ -922,7 +932,7 @@ function z(e) {
|
|
|
922
932
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
923
933
|
};
|
|
924
934
|
}
|
|
925
|
-
var
|
|
935
|
+
var ft = class {
|
|
926
936
|
video;
|
|
927
937
|
baseFrames = 0;
|
|
928
938
|
baseDropped = 0;
|
|
@@ -945,7 +955,7 @@ var ut = class {
|
|
|
945
955
|
};
|
|
946
956
|
}
|
|
947
957
|
};
|
|
948
|
-
function
|
|
958
|
+
function pt(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 mt = 2e3, ht = 3, B = 500, gt = 6e3, _t = .25, vt = 250, yt = .05, bt = 4, xt = 12e3, St = .25, Ct = 1e3;
|
|
976
|
+
function wt(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];
|
|
@@ -979,7 +989,7 @@ function H() {
|
|
|
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
|
|
992
|
+
function Tt() {
|
|
983
993
|
if (typeof navigator > "u" || !H()) 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;
|
|
@@ -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 ft(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 = Dt(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 = wt(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 ||= dt(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 <= bt, !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
|
}
|
|
@@ -1184,7 +1194,7 @@ var U = class {
|
|
|
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 >= mt && 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));
|
|
@@ -1194,7 +1204,7 @@ var U = class {
|
|
|
1194
1204
|
let e = this.liveEnd(), t = W, n = t(), r = 0, i = () => {
|
|
1195
1205
|
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1196
1206
|
r += B;
|
|
1197
|
-
let a = this.liveEnd(), o = a != null && (e == null || a >= e +
|
|
1207
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + _t), s = Math.max(r, t() - n) >= gt;
|
|
1198
1208
|
if (o || s && a != null) {
|
|
1199
1209
|
this.snapToLive();
|
|
1200
1210
|
return;
|
|
@@ -1214,9 +1224,9 @@ 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 = Et(e, e.currentTime);
|
|
1228
|
+
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= yt) && (this.bufferedAdvancedAt = W()), this.lastBufferedEnd = t);
|
|
1229
|
+
}, vt);
|
|
1220
1230
|
}
|
|
1221
1231
|
checkEndStale() {
|
|
1222
1232
|
if (this.endedEmitted) return;
|
|
@@ -1224,14 +1234,14 @@ var U = class {
|
|
|
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) >= St;
|
|
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 > Ct || a || i.paused) {
|
|
1231
1241
|
this.edgeStampedAt = e;
|
|
1232
1242
|
return;
|
|
1233
1243
|
}
|
|
1234
|
-
e - (this.edgeStampedAt ?? e) >
|
|
1244
|
+
e - (this.edgeStampedAt ?? e) > xt && (this.endedEmitted = !0, this.deps.emit({
|
|
1235
1245
|
type: "ended",
|
|
1236
1246
|
reason: "stalled"
|
|
1237
1247
|
}));
|
|
@@ -1245,7 +1255,7 @@ 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 = Et(e, e.currentTime) ?? this.lastBufferedEnd;
|
|
1249
1259
|
if (n != null) {
|
|
1250
1260
|
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (W() - e) / 1e3));
|
|
1251
1261
|
(t == null || r > t) && (t = r);
|
|
@@ -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 - ht, r);
|
|
1265
1275
|
try {
|
|
1266
1276
|
e.currentTime = i;
|
|
1267
1277
|
} catch {}
|
|
@@ -1282,7 +1292,7 @@ var U = class {
|
|
|
1282
1292
|
function W() {
|
|
1283
1293
|
return typeof performance < "u" ? performance.now() : Date.now();
|
|
1284
1294
|
}
|
|
1285
|
-
function
|
|
1295
|
+
function Et(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,7 +1301,7 @@ function wt(e, t) {
|
|
|
1291
1301
|
}
|
|
1292
1302
|
return null;
|
|
1293
1303
|
}
|
|
1294
|
-
function
|
|
1304
|
+
function Dt(e, t) {
|
|
1295
1305
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1296
1306
|
}
|
|
1297
1307
|
//#endregion
|
|
@@ -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 Ot = 4096;
|
|
1322
|
+
function kt(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 > Ot)) 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 At = 15e3, jt = 5e3, Mt = 6, Nt = 4e3, Pt = 2;
|
|
1336
|
+
function K(e) {
|
|
1327
1337
|
try {
|
|
1328
1338
|
let t = new URL(e);
|
|
1329
1339
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1331,17 +1341,23 @@ function jt(e) {
|
|
|
1331
1341
|
return e;
|
|
1332
1342
|
}
|
|
1333
1343
|
}
|
|
1334
|
-
var
|
|
1344
|
+
var Ft = class {
|
|
1335
1345
|
cmcd;
|
|
1336
1346
|
entries = /* @__PURE__ */ new Map();
|
|
1337
1347
|
keyed = /* @__PURE__ */ new Set();
|
|
1338
1348
|
perTrack = /* @__PURE__ */ new Map();
|
|
1349
|
+
hints = /* @__PURE__ */ new Map();
|
|
1339
1350
|
stats = {
|
|
1340
1351
|
started: 0,
|
|
1341
1352
|
served: 0,
|
|
1342
1353
|
missed: 0,
|
|
1343
1354
|
failed: 0,
|
|
1344
|
-
expired: 0
|
|
1355
|
+
expired: 0,
|
|
1356
|
+
hintStarted: 0,
|
|
1357
|
+
hintServed: 0,
|
|
1358
|
+
hintFailed: 0,
|
|
1359
|
+
hintExpired: 0,
|
|
1360
|
+
hintDropped: 0
|
|
1345
1361
|
};
|
|
1346
1362
|
constructor(e = {}) {
|
|
1347
1363
|
this.cmcd = e;
|
|
@@ -1354,32 +1370,58 @@ var Mt = class {
|
|
|
1354
1370
|
}
|
|
1355
1371
|
prefetch(e, t, n) {
|
|
1356
1372
|
if (!this.isActive(t)) return;
|
|
1357
|
-
let r =
|
|
1373
|
+
let r = K(e);
|
|
1358
1374
|
if (this.entries.has(r)) return;
|
|
1359
1375
|
let i = this.perTrack.get(t) ?? 0;
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1376
|
+
i >= Mt || (this.perTrack.set(t, i + 1), this.start(r, this.withCmcd(e, t, n), !1, At), this.stats.started += 1);
|
|
1377
|
+
}
|
|
1378
|
+
prefetchHint(e, t) {
|
|
1379
|
+
let n = K(e);
|
|
1380
|
+
if (this.entries.has(n)) return;
|
|
1381
|
+
let r = this.hints.get(t) ?? [];
|
|
1382
|
+
for (; r.length >= Pt;) {
|
|
1383
|
+
let e = r.shift();
|
|
1384
|
+
e !== void 0 && this.drop(e) && (this.stats.hintDropped += 1);
|
|
1385
|
+
}
|
|
1386
|
+
r.push(n), this.hints.set(t, r), this.start(n, this.withCmcd(e, t, "media"), !0, Nt), this.stats.hintStarted += 1;
|
|
1387
|
+
}
|
|
1388
|
+
dropHints(e) {
|
|
1389
|
+
for (let t of this.hints.get(e) ?? []) this.drop(t) && (this.stats.hintDropped += 1);
|
|
1390
|
+
this.hints.delete(e);
|
|
1391
|
+
}
|
|
1392
|
+
drop(e) {
|
|
1393
|
+
let t = this.entries.get(e);
|
|
1394
|
+
return t ? (this.entries.delete(e), t.abort.abort(), !0) : !1;
|
|
1395
|
+
}
|
|
1396
|
+
start(e, t, n, r) {
|
|
1397
|
+
let i = new AbortController(), a = {
|
|
1363
1398
|
started: performance.now(),
|
|
1364
1399
|
first: 0,
|
|
1400
|
+
end: 0,
|
|
1401
|
+
hint: n,
|
|
1402
|
+
headers: Promise.resolve(),
|
|
1365
1403
|
bytes: Promise.resolve(null),
|
|
1366
|
-
abort:
|
|
1367
|
-
};
|
|
1368
|
-
|
|
1404
|
+
abort: i
|
|
1405
|
+
}, o = () => {};
|
|
1406
|
+
a.headers = new Promise((e) => o = e), a.bytes = fetch(t, {
|
|
1369
1407
|
credentials: "omit",
|
|
1370
1408
|
mode: "cors",
|
|
1371
|
-
signal:
|
|
1372
|
-
}).then(async (e) =>
|
|
1373
|
-
|
|
1374
|
-
|
|
1409
|
+
signal: i.signal
|
|
1410
|
+
}).then(async (e) => {
|
|
1411
|
+
if (a.first = performance.now(), o(), !e.ok) return null;
|
|
1412
|
+
let t = await e.arrayBuffer();
|
|
1413
|
+
return a.end = performance.now(), t;
|
|
1414
|
+
}).catch(() => null).finally(o), this.entries.set(e, a), setTimeout(() => {
|
|
1415
|
+
this.entries.get(e) === a && (this.entries.delete(e), i.abort(), n ? this.stats.hintExpired += 1 : this.stats.expired += 1);
|
|
1416
|
+
}, r);
|
|
1375
1417
|
}
|
|
1376
1418
|
take(e) {
|
|
1377
|
-
let t =
|
|
1419
|
+
let t = K(e), n = this.entries.get(t);
|
|
1378
1420
|
return n && this.entries.delete(t), n;
|
|
1379
1421
|
}
|
|
1380
1422
|
destroy() {
|
|
1381
1423
|
for (let e of this.entries.values()) e.abort.abort();
|
|
1382
|
-
this.entries.clear();
|
|
1424
|
+
this.entries.clear(), this.hints.clear();
|
|
1383
1425
|
}
|
|
1384
1426
|
withCmcd(e, t, n) {
|
|
1385
1427
|
let { sessionId: r, contentId: i } = this.cmcd;
|
|
@@ -1394,40 +1436,51 @@ var Mt = class {
|
|
|
1394
1436
|
}
|
|
1395
1437
|
}
|
|
1396
1438
|
};
|
|
1397
|
-
function
|
|
1439
|
+
function It(t) {
|
|
1398
1440
|
let n = e.DefaultConfig?.loader;
|
|
1399
1441
|
if (typeof n != "function") return;
|
|
1400
1442
|
class r extends n {
|
|
1401
1443
|
served = !1;
|
|
1402
1444
|
cancelled = !1;
|
|
1403
|
-
|
|
1445
|
+
entry;
|
|
1446
|
+
stats = Lt();
|
|
1404
1447
|
load(e, n, r) {
|
|
1405
1448
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1406
1449
|
if (!i) {
|
|
1407
1450
|
super.load(e, n, r);
|
|
1408
1451
|
return;
|
|
1409
1452
|
}
|
|
1410
|
-
this.served = !0;
|
|
1411
|
-
let a = performance.now(), o =
|
|
1412
|
-
|
|
1413
|
-
},
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1453
|
+
this.served = !0, this.entry = i;
|
|
1454
|
+
let a = performance.now(), o = () => {
|
|
1455
|
+
i.hint ? t.stats.hintFailed += 1 : t.stats.failed += 1;
|
|
1456
|
+
}, s = () => {
|
|
1457
|
+
!this.cancelled && this.served && (i.abort.abort(), o(), this.served = !1, this.entry = void 0, super.load(e, n, r));
|
|
1458
|
+
}, c = n?.loadPolicy, l = c?.maxTimeToFirstByteMs || jt, u = setTimeout(s, l);
|
|
1459
|
+
i.headers.then(() => {
|
|
1460
|
+
clearTimeout(u);
|
|
1461
|
+
let e = c?.maxLoadTimeMs;
|
|
1462
|
+
e && (u = setTimeout(s, Math.max(0, e - (performance.now() - a))));
|
|
1463
|
+
}), i.bytes.then((s) => {
|
|
1464
|
+
if (clearTimeout(u), this.cancelled || !this.served) return;
|
|
1465
|
+
if (!s) {
|
|
1466
|
+
o(), this.served = !1, super.load(e, n, r);
|
|
1418
1467
|
return;
|
|
1419
1468
|
}
|
|
1420
|
-
t.stats.served += 1;
|
|
1421
1469
|
let c = this.stats;
|
|
1422
|
-
|
|
1470
|
+
if (i.hint) {
|
|
1471
|
+
t.stats.hintServed += 1;
|
|
1472
|
+
let e = performance.now(), n = Math.max(0, (i.end || e) - (i.first || e)), r = Math.max(0, (i.first || e) - a);
|
|
1473
|
+
c.loading.end = e, c.loading.first = e - n, c.loading.start = c.loading.first - r;
|
|
1474
|
+
} else t.stats.served += 1, c.loading.start = a, c.loading.first = Math.max(a, i.first || a), c.loading.end = performance.now();
|
|
1475
|
+
c.loaded = c.total = s.byteLength, this.entry = void 0, r.onSuccess({
|
|
1423
1476
|
url: e.url,
|
|
1424
|
-
data:
|
|
1477
|
+
data: s
|
|
1425
1478
|
}, c, e, null);
|
|
1426
1479
|
});
|
|
1427
1480
|
}
|
|
1428
1481
|
abort() {
|
|
1429
1482
|
if (this.served) {
|
|
1430
|
-
this.cancelled = !0, this.stats.aborted = !0;
|
|
1483
|
+
this.cancelled = !0, this.stats.aborted = !0, this.entry?.abort.abort(), this.entry = void 0;
|
|
1431
1484
|
return;
|
|
1432
1485
|
}
|
|
1433
1486
|
super.abort();
|
|
@@ -1435,7 +1488,7 @@ function Nt(t) {
|
|
|
1435
1488
|
}
|
|
1436
1489
|
return r;
|
|
1437
1490
|
}
|
|
1438
|
-
function
|
|
1491
|
+
function Lt() {
|
|
1439
1492
|
return {
|
|
1440
1493
|
aborted: !1,
|
|
1441
1494
|
loaded: 0,
|
|
@@ -1459,10 +1512,10 @@ function Pt() {
|
|
|
1459
1512
|
}
|
|
1460
1513
|
};
|
|
1461
1514
|
}
|
|
1462
|
-
function
|
|
1515
|
+
function Rt(e) {
|
|
1463
1516
|
return e === "audio" ? "audio" : "main";
|
|
1464
1517
|
}
|
|
1465
|
-
function
|
|
1518
|
+
function zt(e, t) {
|
|
1466
1519
|
let n = [];
|
|
1467
1520
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1468
1521
|
url: t.initSegment.url,
|
|
@@ -1479,18 +1532,29 @@ function It(e, t) {
|
|
|
1479
1532
|
});
|
|
1480
1533
|
return n;
|
|
1481
1534
|
}
|
|
1535
|
+
function Bt(e) {
|
|
1536
|
+
let t = e, n = t?.preloadHint;
|
|
1537
|
+
if (!n || !t?.url || n.TYPE !== "PART" || n["BYTERANGE-START"] !== void 0 || n["BYTERANGE-LENGTH"] !== void 0) return null;
|
|
1538
|
+
let r = n.URI;
|
|
1539
|
+
if (typeof r != "string" || !r) return null;
|
|
1540
|
+
try {
|
|
1541
|
+
return new URL(r, t.url).toString();
|
|
1542
|
+
} catch {
|
|
1543
|
+
return null;
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1482
1546
|
//#endregion
|
|
1483
1547
|
//#region src/core/percentile.ts
|
|
1484
|
-
function
|
|
1548
|
+
function q(e, t) {
|
|
1485
1549
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1486
1550
|
}
|
|
1487
1551
|
//#endregion
|
|
1488
1552
|
//#region src/core/engine/hls.ts
|
|
1489
|
-
function
|
|
1553
|
+
function Vt() {
|
|
1490
1554
|
return e.isSupported();
|
|
1491
1555
|
}
|
|
1492
|
-
var
|
|
1493
|
-
function
|
|
1556
|
+
var Ht = 3, Ut = 1e6, Wt = 20, Gt = 1e4, Kt = 3, qt = 5, Jt = 3, Yt = 1e4, Xt = 3e4, Zt = 12e3, Qt = 3e3, $t = .02, en = 6e3, tn = .5, nn = 3, rn = .5, an = 1.1, on = .25, sn = 5e3, cn = 4e3, ln = 2, un = 5, dn = 2, fn = 2, pn = 4, mn = 4, hn = 2e3, gn = 3e4, _n = 1, vn = 2;
|
|
1557
|
+
function yn(e, t, n) {
|
|
1494
1558
|
if (n <= 0 || t < 0 || t >= e.length) return t;
|
|
1495
1559
|
let r = (t, n) => e[t].width === e[n].width && e[t].height === e[n].height, i = (t) => {
|
|
1496
1560
|
for (; t + 1 < e.length && r(t + 1, t);) t++;
|
|
@@ -1499,11 +1563,11 @@ function mn(e, t, n) {
|
|
|
1499
1563
|
for (let t = 0; t < n && a + 1 < e.length; t++) a = i(a + 1);
|
|
1500
1564
|
return a;
|
|
1501
1565
|
}
|
|
1502
|
-
var
|
|
1503
|
-
function
|
|
1566
|
+
var bn = .2, xn = 30, Sn = 2, Cn = 2, wn = 2, Tn = 9, En = .5, Dn = 64, On = 1e4, kn = 8, An = .6, jn = .4, Mn = .4, Nn = 2, Pn = 6e4, J = .5, Fn = 3.5, In = 300;
|
|
1567
|
+
function Ln(e) {
|
|
1504
1568
|
return (e?.part ?? e?.frag)?.stats;
|
|
1505
1569
|
}
|
|
1506
|
-
function
|
|
1570
|
+
function Rn() {
|
|
1507
1571
|
if (typeof navigator > "u") return 0;
|
|
1508
1572
|
try {
|
|
1509
1573
|
let e = navigator.connection?.rtt;
|
|
@@ -1512,20 +1576,20 @@ function Nn() {
|
|
|
1512
1576
|
return 0;
|
|
1513
1577
|
}
|
|
1514
1578
|
}
|
|
1515
|
-
function
|
|
1579
|
+
function zn(e) {
|
|
1516
1580
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1517
1581
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1518
1582
|
return;
|
|
1519
1583
|
}
|
|
1520
|
-
e.liveSyncDuration ??=
|
|
1521
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1522
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1584
|
+
e.liveSyncDuration ??= wn;
|
|
1585
|
+
let t = Math.max(12, e.liveSyncDuration + Tn);
|
|
1586
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Bn(e, e.liveSyncDuration);
|
|
1523
1587
|
}
|
|
1524
|
-
function
|
|
1588
|
+
function Bn(e, t) {
|
|
1525
1589
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1526
1590
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1527
1591
|
}
|
|
1528
|
-
var
|
|
1592
|
+
var Vn = class {
|
|
1529
1593
|
name = "hls";
|
|
1530
1594
|
hls = null;
|
|
1531
1595
|
deps;
|
|
@@ -1619,7 +1683,7 @@ var In = class {
|
|
|
1619
1683
|
frameCounter;
|
|
1620
1684
|
detachFrames = null;
|
|
1621
1685
|
constructor(e) {
|
|
1622
|
-
this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.frameCounter = new
|
|
1686
|
+
this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.frameCounter = new ft(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1623
1687
|
}
|
|
1624
1688
|
async load() {
|
|
1625
1689
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1632,7 +1696,7 @@ var In = class {
|
|
|
1632
1696
|
});
|
|
1633
1697
|
return;
|
|
1634
1698
|
}
|
|
1635
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1699
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ge(r), Ye()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1636
1700
|
let e = this.hls;
|
|
1637
1701
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1638
1702
|
let t = e.liveSyncPosition;
|
|
@@ -1655,7 +1719,7 @@ var In = class {
|
|
|
1655
1719
|
}
|
|
1656
1720
|
this.loadSuspended = !0;
|
|
1657
1721
|
}
|
|
1658
|
-
},
|
|
1722
|
+
}, sn));
|
|
1659
1723
|
}
|
|
1660
1724
|
resumeLoading() {
|
|
1661
1725
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1687,7 +1751,7 @@ var In = class {
|
|
|
1687
1751
|
let t = e.liveSyncPosition;
|
|
1688
1752
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1689
1753
|
let { video: n } = this.deps;
|
|
1690
|
-
n.currentTime <= t +
|
|
1754
|
+
n.currentTime <= t + En || (n.currentTime = t);
|
|
1691
1755
|
}
|
|
1692
1756
|
reanchorPartTimeline(e, t) {
|
|
1693
1757
|
let { frag: n, part: r } = t;
|
|
@@ -1699,7 +1763,7 @@ var In = class {
|
|
|
1699
1763
|
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1700
1764
|
if (!s) return;
|
|
1701
1765
|
let c = a.startPTS - s.start;
|
|
1702
|
-
if (!(!Number.isFinite(c) || Math.abs(c) <
|
|
1766
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < $t)) {
|
|
1703
1767
|
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1704
1768
|
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
1769
|
}
|
|
@@ -1727,7 +1791,7 @@ var In = class {
|
|
|
1727
1791
|
videoEncryptionScheme: F.scheme,
|
|
1728
1792
|
audioEncryptionScheme: F.scheme
|
|
1729
1793
|
},
|
|
1730
|
-
...
|
|
1794
|
+
...N() ? { requestMediaKeySystemAccessFunc: We(t) } : {},
|
|
1731
1795
|
licenseXhrSetup: (e, t) => {
|
|
1732
1796
|
let o = performance.now(), s = () => {
|
|
1733
1797
|
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", () => {
|
|
@@ -1739,7 +1803,7 @@ var In = class {
|
|
|
1739
1803
|
return;
|
|
1740
1804
|
}
|
|
1741
1805
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1742
|
-
u = setTimeout(() => e(void 0),
|
|
1806
|
+
u = setTimeout(() => e(void 0), Yt);
|
|
1743
1807
|
});
|
|
1744
1808
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1745
1809
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1754,35 +1818,37 @@ var In = class {
|
|
|
1754
1818
|
} } : {},
|
|
1755
1819
|
...c
|
|
1756
1820
|
};
|
|
1757
|
-
|
|
1758
|
-
|
|
1821
|
+
this.prefetch?.destroy(), this.prefetch = null;
|
|
1822
|
+
let p = !1, m = !1, h = u && this.deps.mediaDuringKey !== !1, g = this.deps.preloadHints === !0;
|
|
1823
|
+
if ((h || g) && !f.fLoader) {
|
|
1824
|
+
let e = new Ft({
|
|
1759
1825
|
sessionId: n.analytics?.sid,
|
|
1760
1826
|
contentId: n.matchUrn
|
|
1761
|
-
}), t =
|
|
1762
|
-
t && (this.prefetch = e, f.fLoader = t);
|
|
1827
|
+
}), t = It(e);
|
|
1828
|
+
t && (this.prefetch = e, p = h, m = g, f.fLoader = t);
|
|
1763
1829
|
}
|
|
1764
|
-
|
|
1765
|
-
let
|
|
1766
|
-
if (this.hls =
|
|
1767
|
-
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(
|
|
1768
|
-
}),
|
|
1830
|
+
zn(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;
|
|
1831
|
+
let _ = new e(f);
|
|
1832
|
+
if (this.hls = _, this.armHoldBack(_, f), _.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(_, t)), _.on(e.Events.MANIFEST_PARSED, () => {
|
|
1833
|
+
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(_), this.measureLadder(_), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1834
|
+
}), _.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1769
1835
|
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
1836
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1771
|
-
},
|
|
1772
|
-
}),
|
|
1837
|
+
}, Xt)));
|
|
1838
|
+
}), _.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1773
1839
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1774
|
-
}),
|
|
1840
|
+
}), _.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
1775
1841
|
t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
|
|
1776
|
-
let n = t?.frag, r =
|
|
1842
|
+
let n = t?.frag, r = Ln(t), i = r?.loaded;
|
|
1777
1843
|
typeof i == "number" && (this.bytesLoaded += i), !this.reportedFirstBytes && typeof i == "number" && i > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1778
1844
|
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 >
|
|
1845
|
+
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 > Dn && this.requestTimesMs.shift()), this.sampleHoldBack(t);
|
|
1780
1846
|
let o = n?.url;
|
|
1781
1847
|
if (o) {
|
|
1782
|
-
let e =
|
|
1848
|
+
let e = lt(o);
|
|
1783
1849
|
e && (this.cdnHost = e);
|
|
1784
1850
|
}
|
|
1785
|
-
}),
|
|
1851
|
+
}), _.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
1786
1852
|
let n = t?.stats?.loaded;
|
|
1787
1853
|
if (typeof n == "number" && (this.playlistBytesLoaded += n), this.reportedFirstPlaylist || (this.reportedFirstPlaylist = !0, l({ type: "firstPlaylist" })), this.detectedLowLatency) return;
|
|
1788
1854
|
let r = t.details;
|
|
@@ -1790,31 +1856,47 @@ var In = class {
|
|
|
1790
1856
|
type: "lowLatencyDetected",
|
|
1791
1857
|
value: !0
|
|
1792
1858
|
}));
|
|
1793
|
-
}),
|
|
1859
|
+
}), _.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch && m) {
|
|
1860
|
+
let t = this.prefetch, n = this.deps.video, r = (e, r) => {
|
|
1861
|
+
if (n.paused) return;
|
|
1862
|
+
let i = e;
|
|
1863
|
+
if (!i?.live || !i.partList?.length || typeof i.edge != "number") return;
|
|
1864
|
+
let a = n.buffered, o = a.length ? a.end(a.length - 1) : 0;
|
|
1865
|
+
if (i.edge - o > Ht * (i.partTarget || .5)) return;
|
|
1866
|
+
let s = Bt(e);
|
|
1867
|
+
s && t.prefetchHint(s, r);
|
|
1868
|
+
};
|
|
1869
|
+
_.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
1870
|
+
t.level === _.loadLevel && r(t.details, "main");
|
|
1871
|
+
}), _.on(e.Events.AUDIO_TRACK_LOADED, (e, t) => {
|
|
1872
|
+
t?.id === _.audioTrack && r(t?.details, "audio");
|
|
1873
|
+
}), _.on(e.Events.LEVEL_SWITCHING, () => t.dropHints("main")), _.on(e.Events.AUDIO_TRACK_SWITCHING, () => t.dropHints("audio"));
|
|
1874
|
+
}
|
|
1875
|
+
if (this.prefetch && p) {
|
|
1794
1876
|
let t = this.prefetch;
|
|
1795
|
-
|
|
1796
|
-
let r = n?.frag, i =
|
|
1797
|
-
if (r && t.isActive(i)) for (let e of
|
|
1798
|
-
}),
|
|
1877
|
+
_.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1878
|
+
let r = n?.frag, i = Rt(r?.type);
|
|
1879
|
+
if (r && t.isActive(i)) for (let e of zt(_, r)) t.prefetch(e.url, i, e.kind);
|
|
1880
|
+
}), _.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Rt(n?.frag?.type)));
|
|
1799
1881
|
}
|
|
1800
|
-
|
|
1882
|
+
_.on(e.Events.KEY_LOADED, () => {
|
|
1801
1883
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1802
1884
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1803
1885
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.adaptHoldBack(), this.checkFrameDrops();
|
|
1804
|
-
},
|
|
1886
|
+
}, Qt), _.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1805
1887
|
this.renditionSwitches += 1;
|
|
1806
|
-
let n = this.lastLevelIndex >= 0 ?
|
|
1888
|
+
let n = this.lastLevelIndex >= 0 ? _.levels[this.lastLevelIndex] : void 0, r = _.levels[t.level];
|
|
1807
1889
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, this.armFrameDropGrace(), l({
|
|
1808
1890
|
type: "qualitychange",
|
|
1809
1891
|
index: t.level
|
|
1810
1892
|
});
|
|
1811
|
-
}),
|
|
1893
|
+
}), _.on(e.Events.AUDIO_TRACK_SWITCHED, (e, t) => l({
|
|
1812
1894
|
type: "audiotrackchange",
|
|
1813
1895
|
id: t.id
|
|
1814
|
-
})),
|
|
1896
|
+
})), _.on(e.Events.SUBTITLE_TRACK_SWITCH, (e, t) => l({
|
|
1815
1897
|
type: "texttrackchange",
|
|
1816
1898
|
id: t.id
|
|
1817
|
-
})),
|
|
1899
|
+
})), _.on(e.Events.ERROR, (e, t) => this.onError(t)), _.loadSource(n.manifestUrl), _.attachMedia(t);
|
|
1818
1900
|
}
|
|
1819
1901
|
getQualityLevels() {
|
|
1820
1902
|
return this.hls ? this.hls.levels.map((e, t) => ({
|
|
@@ -1852,9 +1934,9 @@ var In = class {
|
|
|
1852
1934
|
let o = e.config ?? {}, s = typeof self < "u" && self.devicePixelRatio > 0 ? self.devicePixelRatio : 1, c = o.ignoreDevicePixelRatio ? 1 : s;
|
|
1853
1935
|
c = Math.min(c, o.maxDevicePixelRatio ?? Infinity);
|
|
1854
1936
|
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
|
|
1937
|
+
if (u == null && s >= vn) return l;
|
|
1938
|
+
let d = u ?? _n, f = Number.isNaN(d) ? _n : d === Infinity ? e.levels.length : Math.max(0, Math.floor(d));
|
|
1939
|
+
return yn(e.levels, l, f);
|
|
1858
1940
|
}
|
|
1859
1941
|
onMediaResize() {
|
|
1860
1942
|
if (!this.sizeCapManaged) return;
|
|
@@ -1869,7 +1951,7 @@ var In = class {
|
|
|
1869
1951
|
return;
|
|
1870
1952
|
}
|
|
1871
1953
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1872
|
-
let t = e > this.sizeCapLevel ?
|
|
1954
|
+
let t = e > this.sizeCapLevel ? hn : gn;
|
|
1873
1955
|
this.capTimer = setTimeout(() => {
|
|
1874
1956
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1875
1957
|
}, t);
|
|
@@ -1879,9 +1961,9 @@ var In = class {
|
|
|
1879
1961
|
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
1962
|
}
|
|
1881
1963
|
dropLevelsWidevineCannotPlay(e) {
|
|
1882
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1964
|
+
this.removeLevelsWhere(e, (e) => Xe(e) !== !0);
|
|
1883
1965
|
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
|
|
1884
|
-
for (let n of t)
|
|
1966
|
+
for (let n of t) Je(n).then((t) => {
|
|
1885
1967
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1886
1968
|
});
|
|
1887
1969
|
}
|
|
@@ -1892,7 +1974,7 @@ var In = class {
|
|
|
1892
1974
|
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1893
1975
|
}), !r.length) return !1;
|
|
1894
1976
|
let a = [...i].join(", ");
|
|
1895
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) ||
|
|
1977
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Xe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1896
1978
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1897
1979
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1898
1980
|
}
|
|
@@ -2000,7 +2082,7 @@ var In = class {
|
|
|
2000
2082
|
return;
|
|
2001
2083
|
}
|
|
2002
2084
|
let e = Date.now() - this.lastAdvanceMs;
|
|
2003
|
-
!this.chaseSuspended && e >
|
|
2085
|
+
!this.chaseSuspended && e > en && this.suspendChasing(), e > Zt && this.emitEnded("stalled");
|
|
2004
2086
|
}
|
|
2005
2087
|
resetStarvationWindow() {
|
|
2006
2088
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -2015,7 +2097,7 @@ var In = class {
|
|
|
2015
2097
|
this.resetStarvationWindow();
|
|
2016
2098
|
return;
|
|
2017
2099
|
}
|
|
2018
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
2100
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < en, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > cn, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = z(t), c = o - s, l = c !== this.starvedFrames;
|
|
2019
2101
|
if (this.starvedFrames = c, !a || l) {
|
|
2020
2102
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
2021
2103
|
return;
|
|
@@ -2024,12 +2106,12 @@ var In = class {
|
|
|
2024
2106
|
this.resetStarvationWindow();
|
|
2025
2107
|
return;
|
|
2026
2108
|
}
|
|
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 >
|
|
2109
|
+
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 > pn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= dn && (this.clearKick(), this.starvationRebuilds < fn)) {
|
|
2028
2110
|
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
2111
|
return;
|
|
2030
2112
|
}
|
|
2031
|
-
let u = i && this.starvedTicks >=
|
|
2032
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
2113
|
+
let u = i && this.starvedTicks >= ln, d = !i && this.deadTicks >= pn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= mn;
|
|
2114
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= un))) {
|
|
2033
2115
|
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
2116
|
try {
|
|
2035
2117
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -2044,7 +2126,7 @@ var In = class {
|
|
|
2044
2126
|
let t = e.latency, n = e.targetLatency;
|
|
2045
2127
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
2046
2128
|
let r = t - n;
|
|
2047
|
-
!this.catchUpEngaged && r >
|
|
2129
|
+
!this.catchUpEngaged && r > tn ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= tn && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
2048
2130
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
2049
2131
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
2050
2132
|
}
|
|
@@ -2057,7 +2139,7 @@ var In = class {
|
|
|
2057
2139
|
}), n < 0 ? 0 : n;
|
|
2058
2140
|
}
|
|
2059
2141
|
armFrameDropGrace() {
|
|
2060
|
-
this.fpsGraceTicks > 0 || (this.fpsGraceTicks =
|
|
2142
|
+
this.fpsGraceTicks > 0 || (this.fpsGraceTicks = Cn, this.fpsBadTicks = 0);
|
|
2061
2143
|
}
|
|
2062
2144
|
resetFrameDropWindow() {
|
|
2063
2145
|
this.fpsLastFrames = -1, this.fpsLastDropped = -1, this.fpsBadTicks = 0;
|
|
@@ -2069,7 +2151,7 @@ var In = class {
|
|
|
2069
2151
|
return;
|
|
2070
2152
|
}
|
|
2071
2153
|
let { totalFrames: n, dropped: r } = z(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
2072
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
2154
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < xn || o < 0) {
|
|
2073
2155
|
this.fpsBadTicks = 0;
|
|
2074
2156
|
return;
|
|
2075
2157
|
}
|
|
@@ -2077,11 +2159,11 @@ var In = class {
|
|
|
2077
2159
|
--this.fpsGraceTicks, this.fpsBadTicks = 0;
|
|
2078
2160
|
return;
|
|
2079
2161
|
}
|
|
2080
|
-
if (o <=
|
|
2162
|
+
if (o <= bn * a) {
|
|
2081
2163
|
this.fpsBadTicks = 0;
|
|
2082
2164
|
return;
|
|
2083
2165
|
}
|
|
2084
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
2166
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < Sn) return;
|
|
2085
2167
|
this.fpsBadTicks = 0;
|
|
2086
2168
|
let s = e.levels, c = s[e.currentLevel];
|
|
2087
2169
|
if (!c) return;
|
|
@@ -2098,22 +2180,22 @@ var In = class {
|
|
|
2098
2180
|
return;
|
|
2099
2181
|
}
|
|
2100
2182
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
2101
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
2183
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(an, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
2102
2184
|
this.resetChaseWindow();
|
|
2103
2185
|
return;
|
|
2104
2186
|
}
|
|
2105
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
2187
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= rn) {
|
|
2106
2188
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
2107
2189
|
return;
|
|
2108
2190
|
}
|
|
2109
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
2191
|
+
if (this.chaseTicks += 1, this.chaseTicks < nn) return;
|
|
2110
2192
|
this.resetChaseWindow();
|
|
2111
2193
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2112
2194
|
if (!(a > 1)) return;
|
|
2113
2195
|
let o = e.targetLatency;
|
|
2114
2196
|
if (typeof o != "number" || !(o > 0)) return;
|
|
2115
2197
|
let s = Math.min(n, a - 1);
|
|
2116
|
-
s < o +
|
|
2198
|
+
s < o + on || (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
2199
|
type: "livetargetchange",
|
|
2118
2200
|
change: {
|
|
2119
2201
|
targetSeconds: s,
|
|
@@ -2130,13 +2212,13 @@ var In = class {
|
|
|
2130
2212
|
if (!this.holdBackEnabled || this.holdBackPriorChecked || !e || (this.holdBackPriorChecked = !0, this.holdBackApplied > 0 || this.holdBackStepCount > 0)) return;
|
|
2131
2213
|
let t = e.targetLatency;
|
|
2132
2214
|
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 +
|
|
2215
|
+
let n = Rn();
|
|
2216
|
+
if (!(n >= In)) return;
|
|
2217
|
+
let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase + J);
|
|
2136
2218
|
i > r && (this.holdBackStepCount = 1, this.moveHoldBack(e, r, i, "connection-rtt", `connection rtt ${n} ms`));
|
|
2137
2219
|
}
|
|
2138
2220
|
holdBackCeiling(e) {
|
|
2139
|
-
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t :
|
|
2221
|
+
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t : Fn, r = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2140
2222
|
return r > 1 ? Math.min(n, r - 1) : n;
|
|
2141
2223
|
}
|
|
2142
2224
|
sampleHoldBack(e) {
|
|
@@ -2145,7 +2227,7 @@ var In = class {
|
|
|
2145
2227
|
if (t !== "main" && t !== "audio") return;
|
|
2146
2228
|
let n = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag?.duration;
|
|
2147
2229
|
if (typeof n != "number" || !(n > 0)) return;
|
|
2148
|
-
let r =
|
|
2230
|
+
let r = Ln(e)?.loading;
|
|
2149
2231
|
if (!r || !(r.start > 0) || !(r.end > 0)) return;
|
|
2150
2232
|
let i = r.first > r.start ? r.first : r.end, a = Math.max(0, i - r.start) / (n * 1e3);
|
|
2151
2233
|
this.holdBackSamples.push({
|
|
@@ -2160,30 +2242,30 @@ var In = class {
|
|
|
2160
2242
|
this.holdBackSlowTicks = 0, this.holdBackFastSince = 0, this.holdBackSamples = [];
|
|
2161
2243
|
return;
|
|
2162
2244
|
}
|
|
2163
|
-
let t = Date.now(), n = t -
|
|
2245
|
+
let t = Date.now(), n = t - On, r = this.holdBackSamples, i = 0;
|
|
2164
2246
|
for (; i < r.length && r[i].t < n;) i += 1;
|
|
2165
2247
|
i > 0 && r.splice(0, i);
|
|
2166
2248
|
let a = e.targetLatency;
|
|
2167
2249
|
if (typeof a != "number" || !(a > 0)) return;
|
|
2168
2250
|
this.holdBackBase < 0 && (this.holdBackBase = a);
|
|
2169
2251
|
let o = this.holdBackBase, s = this.holdBackCeiling(e);
|
|
2170
|
-
if (r.length <
|
|
2252
|
+
if (r.length < kn) {
|
|
2171
2253
|
this.holdBackSlowTicks = 0;
|
|
2172
2254
|
return;
|
|
2173
2255
|
}
|
|
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 <
|
|
2256
|
+
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);
|
|
2257
|
+
if (l >= An && u >= jn) {
|
|
2258
|
+
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks < Nn) return;
|
|
2177
2259
|
this.holdBackSlowTicks = 0;
|
|
2178
|
-
let t = Math.ceil((s - o) /
|
|
2260
|
+
let t = Math.ceil((s - o) / J), n = Math.ceil((a - o) / J - 1e-9);
|
|
2179
2261
|
if (n > this.holdBackStepCount && (this.holdBackStepCount = n), this.holdBackStepCount >= t) return;
|
|
2180
2262
|
this.holdBackStepCount += 1;
|
|
2181
|
-
let r = Math.min(s, o + this.holdBackStepCount *
|
|
2263
|
+
let r = Math.min(s, o + this.holdBackStepCount * J);
|
|
2182
2264
|
if (r <= a) return;
|
|
2183
2265
|
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
2266
|
return;
|
|
2185
2267
|
}
|
|
2186
|
-
if (this.holdBackSlowTicks = 0, l >=
|
|
2268
|
+
if (this.holdBackSlowTicks = 0, l >= Mn) {
|
|
2187
2269
|
this.holdBackFastSince = 0;
|
|
2188
2270
|
return;
|
|
2189
2271
|
}
|
|
@@ -2191,9 +2273,9 @@ var In = class {
|
|
|
2191
2273
|
this.holdBackFastSince = t;
|
|
2192
2274
|
return;
|
|
2193
2275
|
}
|
|
2194
|
-
if (t - this.holdBackFastSince <
|
|
2276
|
+
if (t - this.holdBackFastSince < Pn || (this.holdBackFastSince = t, this.holdBackStepCount === 0 || a !== this.holdBackApplied)) return;
|
|
2195
2277
|
--this.holdBackStepCount;
|
|
2196
|
-
let f = Math.max(o, o + this.holdBackStepCount *
|
|
2278
|
+
let f = Math.max(o, o + this.holdBackStepCount * J);
|
|
2197
2279
|
f >= a || this.moveHoldBack(e, a, f, "fast-fetches", `part fetches fast again (p95 first byte ${d} ms per 1 s of media)`);
|
|
2198
2280
|
}
|
|
2199
2281
|
moveHoldBack(e, t, n, r, i) {
|
|
@@ -2234,14 +2316,14 @@ var In = class {
|
|
|
2234
2316
|
} catch {}
|
|
2235
2317
|
}
|
|
2236
2318
|
startEstimate() {
|
|
2237
|
-
return this.deps.rememberBandwidth === !1 ?
|
|
2319
|
+
return this.deps.rememberBandwidth === !1 ? Ut : Le() ?? Ut;
|
|
2238
2320
|
}
|
|
2239
2321
|
maybeRememberBandwidth(e) {
|
|
2240
|
-
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded <
|
|
2322
|
+
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Wt) return;
|
|
2241
2323
|
let t = Date.now();
|
|
2242
|
-
if (!e && t - this.bwSavedAt <
|
|
2324
|
+
if (!e && t - this.bwSavedAt < Gt) return;
|
|
2243
2325
|
let n = this.hls?.bandwidthEstimate;
|
|
2244
|
-
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t,
|
|
2326
|
+
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Re(n));
|
|
2245
2327
|
}
|
|
2246
2328
|
destroy() {
|
|
2247
2329
|
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 +2341,7 @@ var In = class {
|
|
|
2259
2341
|
scheduleLicenseRetry(t) {
|
|
2260
2342
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
2261
2343
|
let n = t.response?.code ?? 0;
|
|
2262
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
2344
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Jt) return !1;
|
|
2263
2345
|
this.licenseRecoveries += 1;
|
|
2264
2346
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
2265
2347
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -2291,7 +2373,7 @@ var In = class {
|
|
|
2291
2373
|
return;
|
|
2292
2374
|
}
|
|
2293
2375
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
2294
|
-
if (this.networkRecoveries <
|
|
2376
|
+
if (this.networkRecoveries < qt) {
|
|
2295
2377
|
this.networkRecoveries += 1;
|
|
2296
2378
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
2297
2379
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -2308,7 +2390,7 @@ var In = class {
|
|
|
2308
2390
|
return;
|
|
2309
2391
|
}
|
|
2310
2392
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
2311
|
-
if (this.mediaRecoveries <
|
|
2393
|
+
if (this.mediaRecoveries < Kt) {
|
|
2312
2394
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
2313
2395
|
return;
|
|
2314
2396
|
}
|
|
@@ -2329,18 +2411,18 @@ var In = class {
|
|
|
2329
2411
|
}
|
|
2330
2412
|
}
|
|
2331
2413
|
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(
|
|
2414
|
+
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(kt(t.networkDetails)) : void 0;
|
|
2333
2415
|
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
2416
|
}
|
|
2335
|
-
},
|
|
2417
|
+
}, Hn = 15e3, Un = 6e5, Wn = 3e5, Gn = 100, Y = 1, Kn = 1e3, qn = 3e4, Jn = 1e3, Yn = {
|
|
2336
2418
|
inline: "PRESENTATION_INLINE",
|
|
2337
2419
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2338
2420
|
pip: "PRESENTATION_PIP"
|
|
2339
|
-
},
|
|
2421
|
+
}, Xn = {
|
|
2340
2422
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2341
2423
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2342
2424
|
none: "KEY_SYSTEM_NONE"
|
|
2343
|
-
},
|
|
2425
|
+
}, Zn = /* @__PURE__ */ new Set([
|
|
2344
2426
|
"INVALID_URN",
|
|
2345
2427
|
"NOT_FOUND",
|
|
2346
2428
|
"GEO_DENIED",
|
|
@@ -2351,7 +2433,7 @@ var In = class {
|
|
|
2351
2433
|
"FORBIDDEN",
|
|
2352
2434
|
"RATE_LIMITED",
|
|
2353
2435
|
"TIMEOUT"
|
|
2354
|
-
]),
|
|
2436
|
+
]), X = {
|
|
2355
2437
|
idle: "PLAYER_STATE_IDLE",
|
|
2356
2438
|
waiting: "PLAYER_STATE_WAITING",
|
|
2357
2439
|
loading: "PLAYER_STATE_LOADING",
|
|
@@ -2361,7 +2443,7 @@ var In = class {
|
|
|
2361
2443
|
ended: "PLAYER_STATE_ENDED",
|
|
2362
2444
|
error: "PLAYER_STATE_ERROR"
|
|
2363
2445
|
};
|
|
2364
|
-
function
|
|
2446
|
+
function Qn(e) {
|
|
2365
2447
|
try {
|
|
2366
2448
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2367
2449
|
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 +2451,8 @@ function qn(e) {
|
|
|
2369
2451
|
return;
|
|
2370
2452
|
}
|
|
2371
2453
|
}
|
|
2372
|
-
var
|
|
2373
|
-
function
|
|
2454
|
+
var $n = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), er = /* @__PURE__ */ new Set(), Z = /* @__PURE__ */ new Set(), Q = /* @__PURE__ */ new Set(), tr = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2455
|
+
function nr(e) {
|
|
2374
2456
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2375
2457
|
let t;
|
|
2376
2458
|
try {
|
|
@@ -2379,19 +2461,19 @@ function Zn(e) {
|
|
|
2379
2461
|
} catch {
|
|
2380
2462
|
return;
|
|
2381
2463
|
}
|
|
2382
|
-
if (
|
|
2383
|
-
|
|
2384
|
-
for (let e of
|
|
2464
|
+
if (er.has(t) && !Z.has(t)) {
|
|
2465
|
+
Z.add(t), _(tr(new URL(t).origin));
|
|
2466
|
+
for (let e of Q) e.noteCspBlocked();
|
|
2385
2467
|
}
|
|
2386
2468
|
}
|
|
2387
|
-
function
|
|
2469
|
+
function rr(e, t) {
|
|
2388
2470
|
return _(t, e), { disabledReason: t };
|
|
2389
2471
|
}
|
|
2390
|
-
function
|
|
2391
|
-
if (n) return t &&
|
|
2472
|
+
function ir(e, t, n) {
|
|
2473
|
+
if (n) return t && !$n(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2392
2474
|
if (t) return { endpoint: t };
|
|
2393
|
-
if (t !== void 0) return
|
|
2394
|
-
let r =
|
|
2475
|
+
if (t !== void 0) return rr("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).");
|
|
2476
|
+
let r = Qn(e);
|
|
2395
2477
|
if (r) return { endpoint: r };
|
|
2396
2478
|
let i;
|
|
2397
2479
|
try {
|
|
@@ -2399,9 +2481,9 @@ function $n(e, t, n) {
|
|
|
2399
2481
|
} catch {
|
|
2400
2482
|
i = e;
|
|
2401
2483
|
}
|
|
2402
|
-
return
|
|
2484
|
+
return rr(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
2485
|
}
|
|
2404
|
-
var
|
|
2486
|
+
var ar = class {
|
|
2405
2487
|
opts;
|
|
2406
2488
|
url;
|
|
2407
2489
|
cspKey;
|
|
@@ -2483,8 +2565,8 @@ var er = class {
|
|
|
2483
2565
|
constructor(e) {
|
|
2484
2566
|
this.opts = {
|
|
2485
2567
|
...e,
|
|
2486
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2487
|
-
idleMs: e.idleMs ??
|
|
2568
|
+
heartbeatMs: e.heartbeatMs ?? Hn,
|
|
2569
|
+
idleMs: e.idleMs ?? Un
|
|
2488
2570
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2489
2571
|
try {
|
|
2490
2572
|
let e = new URL(this.url);
|
|
@@ -2501,11 +2583,11 @@ var er = class {
|
|
|
2501
2583
|
sdkVersion: this.opts.sdkVersion,
|
|
2502
2584
|
...this.opts.environment
|
|
2503
2585
|
};
|
|
2504
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2586
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Kn), 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 && er.add(this.cspKey), document.addEventListener("securitypolicyviolation", nr), Q.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2505
2587
|
}
|
|
2506
2588
|
checkSuspension(e) {
|
|
2507
2589
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2508
|
-
let t = Math.max(this.opts.idleMs,
|
|
2590
|
+
let t = Math.max(this.opts.idleMs, Wn);
|
|
2509
2591
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2510
2592
|
}
|
|
2511
2593
|
syncIdle(e) {
|
|
@@ -2519,21 +2601,21 @@ var er = class {
|
|
|
2519
2601
|
noteStateChange(e, t, n, r) {
|
|
2520
2602
|
if (this.endedFlag || e === t) return;
|
|
2521
2603
|
let i = this.now();
|
|
2522
|
-
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(
|
|
2604
|
+
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
2605
|
this.stallIsSeekInduced = this.seekInduced(i);
|
|
2524
2606
|
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(
|
|
2607
|
+
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(Y, Math.round(this.playingTotalMs)));
|
|
2526
2608
|
} else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
|
|
2527
2609
|
this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
|
|
2528
2610
|
let a = {
|
|
2529
|
-
fromState:
|
|
2530
|
-
toState:
|
|
2531
|
-
presentation:
|
|
2611
|
+
fromState: X[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2612
|
+
toState: X[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2613
|
+
presentation: Yn[this.presentation]
|
|
2532
2614
|
}, o = this.causeOf(e, t, i);
|
|
2533
2615
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2534
2616
|
}
|
|
2535
2617
|
seekInduced(e) {
|
|
2536
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2618
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < Jn;
|
|
2537
2619
|
}
|
|
2538
2620
|
causeOf(e, t, n) {
|
|
2539
2621
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2570,25 +2652,25 @@ var er = class {
|
|
|
2570
2652
|
}
|
|
2571
2653
|
this.muteChanges += 1;
|
|
2572
2654
|
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(
|
|
2655
|
+
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
2656
|
}
|
|
2575
2657
|
notePresentation(e) {
|
|
2576
2658
|
this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
|
|
2577
2659
|
}
|
|
2578
2660
|
notePlayIntent() {
|
|
2579
|
-
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs =
|
|
2661
|
+
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
2662
|
}
|
|
2581
2663
|
noteReady() {
|
|
2582
|
-
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(
|
|
2664
|
+
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(Y, this.now() - this.startupAnchorMs));
|
|
2583
2665
|
}
|
|
2584
2666
|
noteFirstPlaylist() {
|
|
2585
|
-
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(
|
|
2667
|
+
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(Y, this.now() - this.startupAnchorMs));
|
|
2586
2668
|
}
|
|
2587
2669
|
noteDrmReady() {
|
|
2588
|
-
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(
|
|
2670
|
+
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(Y, this.now() - this.startupAnchorMs));
|
|
2589
2671
|
}
|
|
2590
2672
|
noteFirstBytes() {
|
|
2591
|
-
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(
|
|
2673
|
+
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(Y, this.now() - this.startupAnchorMs));
|
|
2592
2674
|
}
|
|
2593
2675
|
noteSeek() {
|
|
2594
2676
|
this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
|
|
@@ -2607,7 +2689,7 @@ var er = class {
|
|
|
2607
2689
|
let r = n ?? "";
|
|
2608
2690
|
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
2691
|
if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
|
|
2610
|
-
if (
|
|
2692
|
+
if (Zn.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2611
2693
|
let i = t ?? "";
|
|
2612
2694
|
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
2695
|
}
|
|
@@ -2639,7 +2721,7 @@ var er = class {
|
|
|
2639
2721
|
let l = t.droppedFrames ?? 0;
|
|
2640
2722
|
l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
|
|
2641
2723
|
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 =
|
|
2724
|
+
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
2725
|
let d = this.mutedTotalMs;
|
|
2644
2726
|
this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
|
|
2645
2727
|
let f = t.upshifts ?? 0;
|
|
@@ -2654,20 +2736,20 @@ var er = class {
|
|
|
2654
2736
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2655
2737
|
o.requestCountDelta = _;
|
|
2656
2738
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2657
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2739
|
+
n.length > 0 && (o.requestTimeP50Ms = q(n, 50), o.requestTimeP95Ms = q(n, 95));
|
|
2658
2740
|
}
|
|
2659
2741
|
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
2742
|
}
|
|
2661
2743
|
maybeEmitMediaInfo(e) {
|
|
2662
2744
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2663
2745
|
let t = {};
|
|
2664
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2746
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Xn[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
2747
|
let n = JSON.stringify(t);
|
|
2666
2748
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2667
2749
|
}
|
|
2668
2750
|
end(e, t) {
|
|
2669
2751
|
if (this.endedFlag) return;
|
|
2670
|
-
this.endedFlag = !0,
|
|
2752
|
+
this.endedFlag = !0, Q.delete(this);
|
|
2671
2753
|
let n = t ?? this.now();
|
|
2672
2754
|
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
2755
|
let r = this.safeSample();
|
|
@@ -2681,7 +2763,7 @@ var er = class {
|
|
|
2681
2763
|
let c = r?.positionMs ?? 0;
|
|
2682
2764
|
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
2765
|
let l = e !== "END_REASON_ENDED";
|
|
2684
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2766
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= qn && (i.abandonAfterStallMs = Math.max(Y, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= qn && (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
2767
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2686
2768
|
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
2769
|
}
|
|
@@ -2701,13 +2783,13 @@ var er = class {
|
|
|
2701
2783
|
};
|
|
2702
2784
|
}
|
|
2703
2785
|
noteCspBlocked() {
|
|
2704
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2786
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(tr(new URL(this.url).origin)));
|
|
2705
2787
|
}
|
|
2706
2788
|
cspBlocked() {
|
|
2707
|
-
return !!this.cspKey &&
|
|
2789
|
+
return !!this.cspKey && Z.has(this.cspKey);
|
|
2708
2790
|
}
|
|
2709
2791
|
enqueue(e) {
|
|
2710
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2792
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Gn;) {
|
|
2711
2793
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2712
2794
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2713
2795
|
}
|
|
@@ -2734,7 +2816,7 @@ var er = class {
|
|
|
2734
2816
|
};
|
|
2735
2817
|
//#endregion
|
|
2736
2818
|
//#region src/core/environment.ts
|
|
2737
|
-
function
|
|
2819
|
+
function or() {
|
|
2738
2820
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2739
2821
|
let e;
|
|
2740
2822
|
try {
|
|
@@ -2759,14 +2841,14 @@ function tr() {
|
|
|
2759
2841
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2760
2842
|
};
|
|
2761
2843
|
}
|
|
2762
|
-
function
|
|
2844
|
+
function sr() {
|
|
2763
2845
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2764
2846
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2765
2847
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2766
2848
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2767
2849
|
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
2850
|
}
|
|
2769
|
-
function
|
|
2851
|
+
function cr() {
|
|
2770
2852
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2771
2853
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2772
2854
|
let t = {
|
|
@@ -2785,17 +2867,17 @@ function rr() {
|
|
|
2785
2867
|
}
|
|
2786
2868
|
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
2869
|
}
|
|
2788
|
-
function
|
|
2789
|
-
let t =
|
|
2790
|
-
deviceClass:
|
|
2870
|
+
function lr(e) {
|
|
2871
|
+
let t = or(), n = {
|
|
2872
|
+
deviceClass: sr(),
|
|
2791
2873
|
integration: t.integration,
|
|
2792
|
-
...
|
|
2874
|
+
...cr()
|
|
2793
2875
|
};
|
|
2794
2876
|
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
2877
|
let r = e.getBoundingClientRect?.();
|
|
2796
2878
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2797
2879
|
}
|
|
2798
|
-
async function
|
|
2880
|
+
async function ur() {
|
|
2799
2881
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2800
2882
|
if (!e?.getHighEntropyValues) return {};
|
|
2801
2883
|
try {
|
|
@@ -2807,7 +2889,7 @@ async function ar() {
|
|
|
2807
2889
|
}
|
|
2808
2890
|
//#endregion
|
|
2809
2891
|
//#region src/core/version.ts
|
|
2810
|
-
var
|
|
2892
|
+
var dr = "2.24.0", fr = {
|
|
2811
2893
|
accent: "#E1B600",
|
|
2812
2894
|
accentText: "#1B1C23",
|
|
2813
2895
|
background: "#0e0f13",
|
|
@@ -2818,7 +2900,7 @@ var or = "2.23.3", sr = {
|
|
|
2818
2900
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2819
2901
|
radius: "8px",
|
|
2820
2902
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2821
|
-
},
|
|
2903
|
+
}, pr = {
|
|
2822
2904
|
accent: "--havik-accent",
|
|
2823
2905
|
accentText: "--havik-accent-text",
|
|
2824
2906
|
background: "--havik-bg",
|
|
@@ -2830,26 +2912,26 @@ var or = "2.23.3", sr = {
|
|
|
2830
2912
|
radius: "--havik-radius",
|
|
2831
2913
|
fontFamily: "--havik-font"
|
|
2832
2914
|
};
|
|
2833
|
-
function
|
|
2915
|
+
function mr(e, t) {
|
|
2834
2916
|
let n = {
|
|
2835
|
-
...
|
|
2917
|
+
...fr,
|
|
2836
2918
|
...t
|
|
2837
2919
|
};
|
|
2838
|
-
for (let t of Object.keys(
|
|
2920
|
+
for (let t of Object.keys(pr)) e.style.setProperty(pr[t], n[t]);
|
|
2839
2921
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2840
2922
|
}
|
|
2841
2923
|
//#endregion
|
|
2842
2924
|
//#region src/ui/styles.ts
|
|
2843
|
-
var
|
|
2844
|
-
function
|
|
2845
|
-
let n = e.querySelector(`style#${
|
|
2846
|
-
if (n && (!t ||
|
|
2925
|
+
var hr = "havik-player-styles", gr = "\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", _r = /* @__PURE__ */ new WeakMap();
|
|
2926
|
+
function vr(e = document, t) {
|
|
2927
|
+
let n = e.querySelector(`style#${hr}`);
|
|
2928
|
+
if (n && (!t || _r.get(n) === t)) return;
|
|
2847
2929
|
let r = e.createElement("style");
|
|
2848
|
-
r.id =
|
|
2930
|
+
r.id = hr, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = gr, _r.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2849
2931
|
}
|
|
2850
2932
|
//#endregion
|
|
2851
2933
|
//#region src/ui/icons.ts
|
|
2852
|
-
var
|
|
2934
|
+
var yr = {
|
|
2853
2935
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2854
2936
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2855
2937
|
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 +2944,12 @@ var mr = {
|
|
|
2862
2944
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
2863
2945
|
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
2946
|
};
|
|
2865
|
-
function
|
|
2866
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2947
|
+
function $(e) {
|
|
2948
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${yr[e]}</svg>`;
|
|
2867
2949
|
}
|
|
2868
2950
|
//#endregion
|
|
2869
2951
|
//#region src/ui/controls.ts
|
|
2870
|
-
var
|
|
2952
|
+
var br = 3e3, xr = 250, Sr = /* @__PURE__ */ new Set([
|
|
2871
2953
|
"GONE",
|
|
2872
2954
|
"NOT_FOUND",
|
|
2873
2955
|
"GEO_DENIED",
|
|
@@ -2875,15 +2957,15 @@ var hr = 3e3, gr = 250, _r = /* @__PURE__ */ new Set([
|
|
|
2875
2957
|
"UNAUTHORIZED",
|
|
2876
2958
|
"DRM_DEVICE_REVOKED"
|
|
2877
2959
|
]);
|
|
2878
|
-
function
|
|
2960
|
+
function Cr(e) {
|
|
2879
2961
|
let t = "This match isn't available in your country";
|
|
2880
2962
|
return e ? `${t} (${e})` : t;
|
|
2881
2963
|
}
|
|
2882
|
-
var
|
|
2883
|
-
function
|
|
2884
|
-
return new
|
|
2964
|
+
var wr = "This device can't play protected video";
|
|
2965
|
+
function Tr(e) {
|
|
2966
|
+
return new Er(e);
|
|
2885
2967
|
}
|
|
2886
|
-
var
|
|
2968
|
+
var Er = class {
|
|
2887
2969
|
root;
|
|
2888
2970
|
video;
|
|
2889
2971
|
player;
|
|
@@ -2931,7 +3013,7 @@ var xr = class {
|
|
|
2931
3013
|
scrubbing = !1;
|
|
2932
3014
|
offFns = [];
|
|
2933
3015
|
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 ??
|
|
3016
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? br, 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, vr(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
3017
|
let t = (e, t, n) => {
|
|
2936
3018
|
let r = this.doc.createElement(e);
|
|
2937
3019
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2942,12 +3024,12 @@ var xr = class {
|
|
|
2942
3024
|
"aria-label": r,
|
|
2943
3025
|
title: r
|
|
2944
3026
|
});
|
|
2945
|
-
return i.innerHTML =
|
|
3027
|
+
return i.innerHTML = $(n), i;
|
|
2946
3028
|
};
|
|
2947
3029
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
2948
3030
|
type: "button",
|
|
2949
3031
|
"aria-label": "Play"
|
|
2950
|
-
}), this.center.innerHTML =
|
|
3032
|
+
}), 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
3033
|
role: "slider",
|
|
2952
3034
|
"aria-label": "Seek",
|
|
2953
3035
|
"aria-valuemin": "0",
|
|
@@ -2965,7 +3047,7 @@ var xr = class {
|
|
|
2965
3047
|
"aria-label": "Volume"
|
|
2966
3048
|
});
|
|
2967
3049
|
let a = t("div", "havik-vol");
|
|
2968
|
-
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML =
|
|
3050
|
+
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = $("liveDot");
|
|
2969
3051
|
let o = this.doc.createElement("span");
|
|
2970
3052
|
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
3053
|
let s = t("div", "havik-spacer");
|
|
@@ -3017,7 +3099,7 @@ var xr = class {
|
|
|
3017
3099
|
let t = this.surfaceWasHidden;
|
|
3018
3100
|
this.tapTimer = setTimeout(() => {
|
|
3019
3101
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
3020
|
-
},
|
|
3102
|
+
}, xr);
|
|
3021
3103
|
}
|
|
3022
3104
|
toggleBar(e) {
|
|
3023
3105
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -3037,7 +3119,7 @@ var xr = class {
|
|
|
3037
3119
|
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
3120
|
}
|
|
3039
3121
|
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" ?
|
|
3122
|
+
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" ? Cr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? wr : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
|
|
3041
3123
|
}
|
|
3042
3124
|
renderStatus(e) {
|
|
3043
3125
|
let t = this.statusMessageFor(e);
|
|
@@ -3049,12 +3131,12 @@ var xr = class {
|
|
|
3049
3131
|
}
|
|
3050
3132
|
if (e === "preplay") {
|
|
3051
3133
|
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 =
|
|
3134
|
+
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
3135
|
} else {
|
|
3054
3136
|
let r = this.doc.createElement("div");
|
|
3055
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
3137
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Sr.has(this.lastError.code)) {
|
|
3056
3138
|
let e = this.doc.createElement("button");
|
|
3057
|
-
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${
|
|
3139
|
+
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
3140
|
}
|
|
3059
3141
|
}
|
|
3060
3142
|
this.root.append(n), this.statusBox = n, this.show();
|
|
@@ -3093,7 +3175,7 @@ var xr = class {
|
|
|
3093
3175
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
3094
3176
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
3095
3177
|
}
|
|
3096
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
3178
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Dr(this.video.currentTime)} / ${Dr(this.video.duration)}`);
|
|
3097
3179
|
}
|
|
3098
3180
|
syncLive() {
|
|
3099
3181
|
let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
|
|
@@ -3143,17 +3225,17 @@ var xr = class {
|
|
|
3143
3225
|
renderQualityMenu() {
|
|
3144
3226
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
3145
3227
|
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(
|
|
3228
|
+
for (let n of e) this.menu.append(this.menuItem(Or(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
3147
3229
|
}
|
|
3148
3230
|
renderAudioMenu() {
|
|
3149
3231
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
3150
3232
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
3151
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3233
|
+
for (let t of e) this.menu.append(this.menuItem(kr(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
3152
3234
|
}
|
|
3153
3235
|
renderCcMenu() {
|
|
3154
3236
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
3155
3237
|
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(
|
|
3238
|
+
for (let t of e) this.menu.append(this.menuItem(Ar(t), !1, () => this.player.setTextTrack(t.id)));
|
|
3157
3239
|
}
|
|
3158
3240
|
onTracksChanged() {
|
|
3159
3241
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -3241,7 +3323,7 @@ var xr = class {
|
|
|
3241
3323
|
}
|
|
3242
3324
|
}
|
|
3243
3325
|
setIcon(e, t) {
|
|
3244
|
-
e.innerHTML =
|
|
3326
|
+
e.innerHTML = $(t);
|
|
3245
3327
|
}
|
|
3246
3328
|
destroy() {
|
|
3247
3329
|
this.hideTimer && clearTimeout(this.hideTimer), this.tapTimer && clearTimeout(this.tapTimer);
|
|
@@ -3258,41 +3340,41 @@ var xr = class {
|
|
|
3258
3340
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
3259
3341
|
}
|
|
3260
3342
|
};
|
|
3261
|
-
function
|
|
3343
|
+
function Dr(e) {
|
|
3262
3344
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
3263
3345
|
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
3346
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
3265
3347
|
}
|
|
3266
|
-
function
|
|
3348
|
+
function Or(e) {
|
|
3267
3349
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
3268
3350
|
}
|
|
3269
|
-
function
|
|
3351
|
+
function kr(e) {
|
|
3270
3352
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3271
3353
|
}
|
|
3272
|
-
function
|
|
3354
|
+
function Ar(e) {
|
|
3273
3355
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3274
3356
|
}
|
|
3275
3357
|
//#endregion
|
|
3276
3358
|
//#region src/managed/index.ts
|
|
3277
|
-
var
|
|
3278
|
-
function
|
|
3359
|
+
var jr = 6e3, Mr = 45e3, Nr = 2e3, Pr = 3, Fr = 5e3, Ir = 2e3, Lr = 48e4, Rr = "keySystemLicenseRequestFailed";
|
|
3360
|
+
function zr(e) {
|
|
3279
3361
|
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
|
|
3362
|
+
if (e.env !== void 0) return st(e.env);
|
|
3281
3363
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
3282
3364
|
return e.baseUrl;
|
|
3283
3365
|
}
|
|
3284
|
-
async function
|
|
3366
|
+
async function Br(e) {
|
|
3285
3367
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
3286
|
-
let t =
|
|
3368
|
+
let t = zr(e);
|
|
3287
3369
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
3288
3370
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
3289
|
-
let r = new
|
|
3371
|
+
let r = new Vr({
|
|
3290
3372
|
...e,
|
|
3291
3373
|
baseUrl: t
|
|
3292
3374
|
});
|
|
3293
3375
|
return await r.start(), r;
|
|
3294
3376
|
}
|
|
3295
|
-
var
|
|
3377
|
+
var Vr = class {
|
|
3296
3378
|
opts;
|
|
3297
3379
|
abort = new AbortController();
|
|
3298
3380
|
listeners = {};
|
|
@@ -3366,7 +3448,7 @@ var Ir = class {
|
|
|
3366
3448
|
};
|
|
3367
3449
|
}
|
|
3368
3450
|
beginArming(e, t, n = !1) {
|
|
3369
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
3451
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
|
|
3370
3452
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
3371
3453
|
}
|
|
3372
3454
|
beginArmingByPolling(e) {
|
|
@@ -3387,7 +3469,7 @@ var Ir = class {
|
|
|
3387
3469
|
setTimeout(() => {
|
|
3388
3470
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3389
3471
|
phase: i ? "unavailable" : "tooEarly",
|
|
3390
|
-
retryInMs:
|
|
3472
|
+
retryInMs: Mr,
|
|
3391
3473
|
attempt: 1,
|
|
3392
3474
|
elapsedMs: 0,
|
|
3393
3475
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3426,13 +3508,13 @@ var Ir = class {
|
|
|
3426
3508
|
!a && !p() && h();
|
|
3427
3509
|
}, e);
|
|
3428
3510
|
};
|
|
3429
|
-
_(
|
|
3511
|
+
_(jr), this.armingSub = D({
|
|
3430
3512
|
eventsBaseUrl: t,
|
|
3431
3513
|
matchUrn: this.opts.matchUrn,
|
|
3432
3514
|
credential: this.opts.credential,
|
|
3433
|
-
onAlive: () => _(
|
|
3515
|
+
onAlive: () => _(Mr),
|
|
3434
3516
|
onState: (e) => {
|
|
3435
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3517
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Nr);
|
|
3436
3518
|
},
|
|
3437
3519
|
onError: () => h()
|
|
3438
3520
|
});
|
|
@@ -3455,7 +3537,7 @@ var Ir = class {
|
|
|
3455
3537
|
let n = await c(this.opts.credential);
|
|
3456
3538
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3457
3539
|
this.setState("loading");
|
|
3458
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3540
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = pt(this.opts.video, (e) => {
|
|
3459
3541
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3460
3542
|
});
|
|
3461
3543
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3477,26 +3559,26 @@ var Ir = class {
|
|
|
3477
3559
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3478
3560
|
let i = e.analytics?.sid;
|
|
3479
3561
|
if (!i) return;
|
|
3480
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3562
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = ir(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3481
3563
|
if (!o) {
|
|
3482
3564
|
s && setTimeout(() => {
|
|
3483
3565
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3484
3566
|
}, 0);
|
|
3485
3567
|
return;
|
|
3486
3568
|
}
|
|
3487
|
-
let c = this.opts.video, l = new
|
|
3569
|
+
let c = this.opts.video, l = new ar({
|
|
3488
3570
|
endpoint: o,
|
|
3489
3571
|
sid: i,
|
|
3490
3572
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3491
|
-
sdkVersion:
|
|
3492
|
-
environment:
|
|
3573
|
+
sdkVersion: dr,
|
|
3574
|
+
environment: lr(c),
|
|
3493
3575
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3494
3576
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3495
3577
|
onBlocked: (e) => setTimeout(() => {
|
|
3496
3578
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3497
3579
|
}, 0),
|
|
3498
3580
|
sample: () => {
|
|
3499
|
-
let e = this.engine?.getStats() ??
|
|
3581
|
+
let e = this.engine?.getStats() ?? ct, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3500
3582
|
return {
|
|
3501
3583
|
...e,
|
|
3502
3584
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3510,7 +3592,7 @@ var Ir = class {
|
|
|
3510
3592
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3511
3593
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3512
3594
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3513
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3595
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), ur().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3514
3596
|
}
|
|
3515
3597
|
currentPresentation() {
|
|
3516
3598
|
let e = this.opts.video;
|
|
@@ -3525,7 +3607,7 @@ var Ir = class {
|
|
|
3525
3607
|
video: this.opts.video,
|
|
3526
3608
|
descriptor: e,
|
|
3527
3609
|
credential: t,
|
|
3528
|
-
deviceId:
|
|
3610
|
+
deviceId: j(),
|
|
3529
3611
|
userId: this.opts.userId,
|
|
3530
3612
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
3531
3613
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -3534,6 +3616,7 @@ var Ir = class {
|
|
|
3534
3616
|
adaptiveHoldBack: this.opts.adaptiveHoldBack,
|
|
3535
3617
|
adaptiveHoldBackCeiling: this.opts.adaptiveHoldBackCeiling,
|
|
3536
3618
|
mediaDuringKey: this.opts.mediaDuringKey,
|
|
3619
|
+
preloadHints: this.opts.preloadHints,
|
|
3537
3620
|
debug: this.opts.debug,
|
|
3538
3621
|
deferLoad: r,
|
|
3539
3622
|
hlsConfig: i,
|
|
@@ -3541,9 +3624,9 @@ var Ir = class {
|
|
|
3541
3624
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3542
3625
|
}, o = this.opts.engine ?? "auto";
|
|
3543
3626
|
if (o === "native") return new U(a);
|
|
3544
|
-
if (o === "hls") return new
|
|
3545
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && V(this.opts.video) && H() || !e.drmEnabled &&
|
|
3546
|
-
if (
|
|
3627
|
+
if (o === "hls") return new Vn(a);
|
|
3628
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && V(this.opts.video) && H() || !e.drmEnabled && Tt() && V(this.opts.video)) return new U(a);
|
|
3629
|
+
if (Vt()) return new Vn(a);
|
|
3547
3630
|
if (V(this.opts.video)) return new U(a);
|
|
3548
3631
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3549
3632
|
}
|
|
@@ -3594,11 +3677,11 @@ var Ir = class {
|
|
|
3594
3677
|
}
|
|
3595
3678
|
startLiveState(e) {
|
|
3596
3679
|
if (this.opts.liveStateEvents === !1) return;
|
|
3597
|
-
let t = this.opts.eventsBaseUrl ??
|
|
3680
|
+
let t = this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
|
|
3598
3681
|
if (!t) return;
|
|
3599
3682
|
this.closeLiveState();
|
|
3600
|
-
let
|
|
3601
|
-
this.liveStateSub =
|
|
3683
|
+
let i = 0, a = !1;
|
|
3684
|
+
this.liveStateSub = D({
|
|
3602
3685
|
eventsBaseUrl: t,
|
|
3603
3686
|
matchUrn: this.opts.matchUrn,
|
|
3604
3687
|
credential: this.opts.credential,
|
|
@@ -3606,10 +3689,16 @@ var Ir = class {
|
|
|
3606
3689
|
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
3690
|
},
|
|
3608
3691
|
onAlive: () => {
|
|
3609
|
-
|
|
3692
|
+
i = 0, a = !1;
|
|
3610
3693
|
},
|
|
3611
|
-
onError: () => {
|
|
3612
|
-
this.destroyed || e !== this.loadGen ||
|
|
3694
|
+
onError: (o) => {
|
|
3695
|
+
if (!(this.destroyed || e !== this.loadGen || a) && !this.endedHandled) {
|
|
3696
|
+
if (o instanceof E && (o.terminal || o.status === 404)) {
|
|
3697
|
+
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."));
|
|
3698
|
+
return;
|
|
3699
|
+
}
|
|
3700
|
+
i += 1, i >= Pr && (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.`)));
|
|
3701
|
+
}
|
|
3613
3702
|
}
|
|
3614
3703
|
});
|
|
3615
3704
|
}
|
|
@@ -3623,7 +3712,7 @@ var Ir = class {
|
|
|
3623
3712
|
return;
|
|
3624
3713
|
}
|
|
3625
3714
|
let e = this.hiddenAtMs;
|
|
3626
|
-
this.hiddenAtMs = null, e != null && Date.now() - e >=
|
|
3715
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= Fr && this.resyncLiveState();
|
|
3627
3716
|
}, this.onReturnPageShow = (e) => {
|
|
3628
3717
|
e.persisted && this.resyncLiveState();
|
|
3629
3718
|
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
@@ -3655,7 +3744,7 @@ var Ir = class {
|
|
|
3655
3744
|
scheduleRejoin(e) {
|
|
3656
3745
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3657
3746
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3658
|
-
}, Math.random() *
|
|
3747
|
+
}, Math.random() * Nr));
|
|
3659
3748
|
}
|
|
3660
3749
|
cancelRejoin() {
|
|
3661
3750
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3679,7 +3768,7 @@ var Ir = class {
|
|
|
3679
3768
|
}
|
|
3680
3769
|
t.controls = !1;
|
|
3681
3770
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3682
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3771
|
+
r && r.insertBefore(n, t), n.appendChild(t), mr(n, this.opts.theme), this.container = n, this.controlBar = Tr({
|
|
3683
3772
|
root: n,
|
|
3684
3773
|
video: t,
|
|
3685
3774
|
player: this,
|
|
@@ -3717,7 +3806,7 @@ var Ir = class {
|
|
|
3717
3806
|
}
|
|
3718
3807
|
startStats() {
|
|
3719
3808
|
this.stopStats();
|
|
3720
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3809
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Ir);
|
|
3721
3810
|
this.statsTimer = setInterval(() => {
|
|
3722
3811
|
if (!this.engine) return;
|
|
3723
3812
|
let e = this.engine.getStats();
|
|
@@ -3728,14 +3817,14 @@ var Ir = class {
|
|
|
3728
3817
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3729
3818
|
}
|
|
3730
3819
|
isStaleLicenseDenial(e) {
|
|
3731
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3820
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Rr || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : G(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3732
3821
|
}
|
|
3733
3822
|
scheduleLicenseRefresh() {
|
|
3734
3823
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3735
3824
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3736
3825
|
document.visibilityState !== "visible" || this.destroyed || G(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3737
3826
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3738
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3827
|
+
let e = this.opts.licenseRefreshMs ?? Lr;
|
|
3739
3828
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3740
3829
|
}
|
|
3741
3830
|
stopRefresh() {
|
|
@@ -3792,7 +3881,7 @@ var Ir = class {
|
|
|
3792
3881
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3793
3882
|
}
|
|
3794
3883
|
getStats() {
|
|
3795
|
-
return this.engine?.getStats() ??
|
|
3884
|
+
return this.engine?.getStats() ?? ct;
|
|
3796
3885
|
}
|
|
3797
3886
|
getQualityLevels() {
|
|
3798
3887
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3900,12 +3989,12 @@ var Ir = class {
|
|
|
3900
3989
|
};
|
|
3901
3990
|
//#endregion
|
|
3902
3991
|
//#region src/embed/protocol.ts
|
|
3903
|
-
function
|
|
3992
|
+
function Hr(e) {
|
|
3904
3993
|
return !!e && typeof e == "object" && typeof e.type == "string" && e.type.startsWith("oddin:");
|
|
3905
3994
|
}
|
|
3906
3995
|
//#endregion
|
|
3907
3996
|
//#region src/embed/host.ts
|
|
3908
|
-
function
|
|
3997
|
+
function Ur(e) {
|
|
3909
3998
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3910
3999
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3911
4000
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3914,7 +4003,7 @@ function Lr(e) {
|
|
|
3914
4003
|
let r = document.createElement("iframe");
|
|
3915
4004
|
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
4005
|
let i = /* @__PURE__ */ new Set(), a = (t) => {
|
|
3917
|
-
if (t.source !== r.contentWindow || t.origin !== n ||
|
|
4006
|
+
if (t.source !== r.contentWindow || t.origin !== n || !Hr(t.data)) return;
|
|
3918
4007
|
let a = t.data;
|
|
3919
4008
|
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
4009
|
};
|
|
@@ -3964,15 +4053,15 @@ function Lr(e) {
|
|
|
3964
4053
|
}
|
|
3965
4054
|
//#endregion
|
|
3966
4055
|
//#region src/embed/page.ts
|
|
3967
|
-
var
|
|
3968
|
-
function
|
|
4056
|
+
var Wr = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
4057
|
+
function Gr(e) {
|
|
3969
4058
|
if (typeof e == "boolean") return e;
|
|
3970
4059
|
if (typeof e == "object" && e) {
|
|
3971
4060
|
let t = e.endpoint;
|
|
3972
4061
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3973
4062
|
}
|
|
3974
4063
|
}
|
|
3975
|
-
function
|
|
4064
|
+
function Kr() {
|
|
3976
4065
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3977
4066
|
if (e) return {
|
|
3978
4067
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3982,7 +4071,7 @@ function Br() {
|
|
|
3982
4071
|
autoplay: e.autoplay ?? !0,
|
|
3983
4072
|
muted: e.muted ?? !0,
|
|
3984
4073
|
waitForLive: e.waitForLive ?? !0,
|
|
3985
|
-
analytics:
|
|
4074
|
+
analytics: Gr(e.analytics)
|
|
3986
4075
|
};
|
|
3987
4076
|
let t = new URLSearchParams(location.search);
|
|
3988
4077
|
return {
|
|
@@ -3995,9 +4084,9 @@ function Br() {
|
|
|
3995
4084
|
waitForLive: !0
|
|
3996
4085
|
};
|
|
3997
4086
|
}
|
|
3998
|
-
async function
|
|
3999
|
-
let e =
|
|
4000
|
-
|
|
4087
|
+
async function qr() {
|
|
4088
|
+
let e = Kr();
|
|
4089
|
+
Yr();
|
|
4001
4090
|
let t = document.createElement("video");
|
|
4002
4091
|
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
4092
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -4053,12 +4142,12 @@ async function Vr() {
|
|
|
4053
4142
|
message: e.message,
|
|
4054
4143
|
...e.country === void 0 ? {} : { country: e.country }
|
|
4055
4144
|
})), e.on("autoplayblocked", () => {
|
|
4056
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
4145
|
+
i({ type: "oddin:autoplayblocked" }), Jr(t, e);
|
|
4057
4146
|
});
|
|
4058
4147
|
}, s = async (r) => {
|
|
4059
4148
|
a?.destroy(), a = null;
|
|
4060
4149
|
try {
|
|
4061
|
-
let n = await
|
|
4150
|
+
let n = await Br({
|
|
4062
4151
|
video: t,
|
|
4063
4152
|
baseUrl: e.baseUrl,
|
|
4064
4153
|
matchUrn: r,
|
|
@@ -4121,30 +4210,30 @@ async function Vr() {
|
|
|
4121
4210
|
a?.retry();
|
|
4122
4211
|
break;
|
|
4123
4212
|
case "oddin:load":
|
|
4124
|
-
typeof e.matchUrn == "string" &&
|
|
4213
|
+
typeof e.matchUrn == "string" && Wr.test(e.matchUrn) && s(e.matchUrn);
|
|
4125
4214
|
break;
|
|
4126
4215
|
case "oddin:destroy": c();
|
|
4127
4216
|
}
|
|
4128
4217
|
}, u = (e) => {
|
|
4129
|
-
r && e.origin === r &&
|
|
4218
|
+
r && e.origin === r && Hr(e.data) && l(e.data);
|
|
4130
4219
|
};
|
|
4131
4220
|
r && window.addEventListener("message", u), window.addEventListener("pagehide", c, { once: !0 }), await s(e.matchUrn), i({
|
|
4132
4221
|
type: "oddin:ready",
|
|
4133
4222
|
protocol: 1
|
|
4134
4223
|
});
|
|
4135
4224
|
}
|
|
4136
|
-
function
|
|
4225
|
+
function Jr(e, t) {
|
|
4137
4226
|
if (document.getElementById("havik-tap")) return;
|
|
4138
4227
|
let n = document.createElement("button");
|
|
4139
4228
|
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
4229
|
n.remove(), t.play();
|
|
4141
4230
|
}), document.body.appendChild(n);
|
|
4142
4231
|
}
|
|
4143
|
-
function
|
|
4232
|
+
function Yr() {
|
|
4144
4233
|
let e = document.createElement("style");
|
|
4145
4234
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
4146
4235
|
}
|
|
4147
4236
|
//#endregion
|
|
4148
|
-
export {
|
|
4237
|
+
export { E as LiveStateHttpError, fr as ODDIN_THEME, n as PlaybackError, mr as applyTheme, st as baseUrlForEnv, qr as bootEmbed, De as clearDeviceId, ze as clearRememberedBandwidth, Br as createPlayer, O as deriveEventsBaseUrl, rt as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, j as getDeviceId, at as isLowLatencyManifest, Hr as isOddinMessage, ke as licenseRequestHeaders, Ur as mountEmbed, fe as pollToLive, y as resolveStream, D as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
|
|
4149
4238
|
|
|
4150
4239
|
//# sourceMappingURL=index.js.map
|