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