@oddin-gg/havik-player 2.23.3 → 2.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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
- function E(e) {
496
- let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? Te, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, s = (e) => new Promise((t) => {
497
- if (a.signal.aborted) return t();
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
- a.signal.addEventListener("abort", () => {
506
+ o.signal.addEventListener("abort", () => {
500
507
  clearTimeout(n), t();
501
508
  }, { once: !0 });
502
- }), l = (t) => {
503
- if (o) return;
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
- }, u = /\r\n\r\n|\n\n|\r\r/, d = async (e, t, n) => {
517
- let r = e.getReader(), a = new TextDecoder(), s = "", c = !1, d, f = () => {
518
- i && (clearTimeout(d), d = setTimeout(() => {
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
- }, i));
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())), s += a.decode(e, { stream: !0 });
527
- let i;
528
- for (; (i = u.exec(s)) !== null;) l(s.slice(0, i.index)), s = s.slice(i.index + i[0].length);
529
- if (o) return;
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(d), await r.cancel().catch(() => {});
539
+ clearTimeout(l), await r.cancel().catch(() => {});
533
540
  }
534
541
  };
535
542
  return (async () => {
536
- let r = t;
537
- for (; !o;) {
538
- let l = new AbortController(), u = () => l.abort();
539
- a.signal.addEventListener("abort", u, { once: !0 });
540
- let p = null, m, h = () => {
541
- p = `no data for ${i}ms`, l.abort();
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 (o) return;
546
- let a = f(e.eventsBaseUrl, `/v1/events/${encodeURIComponent(e.matchUrn)}`);
547
- i && (m = setTimeout(() => {
548
- p = `no response headers within ${i}ms`, l.abort();
549
- }, i));
550
- let s = await fetch(a, {
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: l.signal,
563
+ signal: u.signal,
557
564
  cache: "no-store",
558
565
  credentials: "omit",
559
566
  mode: "cors"
560
567
  });
561
- if (clearTimeout(m), o) return;
562
- !s.ok || !s.body ? e.onError?.(/* @__PURE__ */ Error(`live-state subscribe failed: HTTP ${s.status}`)) : await d(s.body, () => {
563
- r = t;
564
- }, h);
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 (o || a.signal.aborted) return;
567
- p || e.onError?.(t);
576
+ if (s || o.signal.aborted) return;
577
+ m || e.onError?.(t);
568
578
  } finally {
569
- clearTimeout(m), a.signal.removeEventListener("abort", u), l.abort();
579
+ clearTimeout(_), o.signal.removeEventListener("abort", d), u.abort();
570
580
  }
571
- if (o) return;
572
- p && e.onError?.(/* @__PURE__ */ Error(`live-state subscribe idle: ${p} — reconnecting`)), await s(r), r = Math.min(n, r * 2);
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
- o || (o = !0, a.abort());
585
+ s || (s = !0, o.abort());
576
586
  } };
577
587
  }
578
- function D(e) {
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 O = "havik.player.deviceId", k;
589
- function A() {
590
- if (k) return k;
598
+ var k = "havik.player.deviceId", A;
599
+ function j() {
600
+ if (A) return A;
591
601
  try {
592
- let e = globalThis.localStorage?.getItem(O);
593
- if (e) return k = e, e;
602
+ let e = globalThis.localStorage?.getItem(k);
603
+ if (e) return A = e, e;
594
604
  } catch {}
595
- let e = De();
596
- k = e;
605
+ let e = Oe();
606
+ A = e;
597
607
  try {
598
- globalThis.localStorage?.setItem(O, e);
608
+ globalThis.localStorage?.setItem(k, e);
599
609
  } catch {}
600
610
  return e;
601
611
  }
602
- function Ee() {
603
- k = void 0;
612
+ function De() {
613
+ A = void 0;
604
614
  try {
605
- globalThis.localStorage?.removeItem(O);
615
+ globalThis.localStorage?.removeItem(k);
606
616
  } catch {}
607
617
  }
608
- function De() {
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 Oe(e, t, n = {}) {
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 ?? A(),
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 j = "havik.player.bandwidth", ke = .8, Ae = 2e7, je = 3e5;
632
- function Me() {
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 Ne() {
636
- let e = Me()?.type;
645
+ function Pe() {
646
+ let e = Ne()?.type;
637
647
  return typeof e == "string" && e !== "" && e !== "unknown" ? e : "any";
638
648
  }
639
- function Pe() {
640
- let e = Me()?.downlink;
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 Fe() {
653
+ function Ie() {
644
654
  try {
645
- let e = globalThis.localStorage?.getItem(j);
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 Ie(e = Date.now()) {
654
- let t = Fe()[Ne()];
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 = Pe(), i = r === void 0 ? t.bps : Math.min(t.bps, r);
659
- return Math.round(Math.min(Ae, Math.max(je, i * ke)));
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 Le(e, t = Date.now()) {
671
+ function Re(e, t = Date.now()) {
662
672
  if (!Number.isFinite(e) || e <= 0) return;
663
- let n = Fe();
664
- n[Ne()] = {
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(j, JSON.stringify(n));
679
+ globalThis.localStorage?.setItem(M, JSON.stringify(n));
670
680
  } catch {}
671
681
  }
672
- function Re() {
682
+ function ze() {
673
683
  try {
674
- globalThis.localStorage?.removeItem(j);
684
+ globalThis.localStorage?.removeItem(M);
675
685
  } catch {}
676
686
  }
677
687
  //#endregion
678
688
  //#region src/core/drm/cdm.ts
679
- var ze = /* @__PURE__ */ new WeakMap();
680
- function Be(e, t) {
681
- let n = ze.get(e);
682
- n || (n = /* @__PURE__ */ new Map(), ze.set(e, n));
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 M() {
700
+ function N() {
691
701
  return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
692
702
  }
693
- var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
694
- function Ve(e) {
703
+ var He = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
704
+ function Ue(e) {
695
705
  return e.startsWith("com.widevine");
696
706
  }
697
707
  function P(e, t) {
698
- if (!Ve(e)) return t;
708
+ if (!Ue(e)) return t;
699
709
  let n = (e, t) => {
700
710
  let n = e.videoCapabilities;
701
711
  return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
702
- let n = N.indexOf(e.robustness);
703
- return n === -1 || N.indexOf(t) > n;
712
+ let n = He.indexOf(e.robustness);
713
+ return n === -1 || He.indexOf(t) > n;
704
714
  });
705
- }, r = N.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
715
+ }, r = He.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
706
716
  ...t,
707
717
  videoCapabilities: t.videoCapabilities?.map((t) => ({
708
718
  ...t,
@@ -711,11 +721,11 @@ function P(e, t) {
711
721
  })));
712
722
  return [...t, ...r];
713
723
  }
714
- function He(e) {
715
- return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, P(t, n)).then((t) => ({
724
+ function We(e) {
725
+ return (t, n) => N() ? navigator.requestMediaKeySystemAccess(t, P(t, n)).then((t) => ({
716
726
  keySystem: t.keySystem,
717
727
  getConfiguration: () => t.getConfiguration(),
718
- createMediaKeys: () => Be(e, t)
728
+ createMediaKeys: () => Ve(e, t)
719
729
  })) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
720
730
  }
721
731
  var F = {
@@ -723,14 +733,14 @@ var F = {
723
733
  audio: "SW_SECURE_CRYPTO",
724
734
  scheme: "cbcs"
725
735
  };
726
- function Ue(e) {
727
- if (!M()) return;
736
+ function Ge(e) {
737
+ if (!N()) return;
728
738
  let t = (e, t) => ({
729
739
  contentType: e,
730
740
  robustness: t,
731
741
  encryptionScheme: F.scheme
732
742
  });
733
- He(e)("com.widevine.alpha", [{
743
+ We(e)("com.widevine.alpha", [{
734
744
  initDataTypes: ["cenc"],
735
745
  distinctiveIdentifier: "optional",
736
746
  persistentState: "optional",
@@ -750,14 +760,14 @@ function I(e) {
750
760
  function L(e) {
751
761
  return (e ?? "").trim().toLowerCase();
752
762
  }
753
- var We = {
763
+ var Ke = {
754
764
  hevc: "hvc1.1.6.L93.90",
755
765
  dv: "dvh1.05.06",
756
766
  av1: "av01.0.05M.08",
757
767
  vp9: "vp09.00.10.08"
758
- }, Ge = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
759
- function Ke(e) {
760
- let t = L(e), n = Ge.get(t);
768
+ }, qe = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
769
+ function Je(e) {
770
+ let t = L(e), n = qe.get(t);
761
771
  if (n) return n;
762
772
  let r = {
763
773
  initDataTypes: ["cenc"],
@@ -776,22 +786,22 @@ function Ke(e) {
776
786
  return !1;
777
787
  }
778
788
  })().then((e) => (R.set(t, e), e));
779
- return Ge.set(t, i), i;
789
+ return qe.set(t, i), i;
780
790
  }
781
- function qe() {
782
- if (M()) for (let e of Object.values(We)) Ke(e);
791
+ function Ye() {
792
+ if (N()) for (let e of Object.values(Ke)) Je(e);
783
793
  }
784
- function Je(e) {
794
+ function Xe(e) {
785
795
  let t = I(e);
786
- if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(We[t]));
796
+ if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(Ke[t]));
787
797
  }
788
798
  //#endregion
789
799
  //#region src/core/drm/support.ts
790
- var Ye = 5e3, Xe = "video/mp4; codecs=\"avc1.42E01E\"", Ze = "audio/mp4; codecs=\"mp4a.40.2\"", Qe = {
800
+ var Ze = 5e3, Qe = "video/mp4; codecs=\"avc1.42E01E\"", $e = "audio/mp4; codecs=\"mp4a.40.2\"", et = {
791
801
  widevine: ["com.widevine.alpha"],
792
802
  fairplay: ["com.apple.fps"]
793
803
  };
794
- function $e(e) {
804
+ function tt(e) {
795
805
  return e === "fairplay" ? [{
796
806
  initDataTypes: [
797
807
  "sinf",
@@ -799,30 +809,30 @@ function $e(e) {
799
809
  "cenc"
800
810
  ],
801
811
  videoCapabilities: [{
802
- contentType: Xe,
812
+ contentType: Qe,
803
813
  robustness: "",
804
814
  encryptionScheme: "cbcs"
805
815
  }],
806
816
  audioCapabilities: [{
807
- contentType: Ze,
817
+ contentType: $e,
808
818
  robustness: "",
809
819
  encryptionScheme: "cbcs"
810
820
  }]
811
821
  }] : P("com.widevine.alpha", [{
812
822
  initDataTypes: ["cenc"],
813
823
  videoCapabilities: [{
814
- contentType: Xe,
824
+ contentType: Qe,
815
825
  robustness: F.video,
816
826
  encryptionScheme: F.scheme
817
827
  }],
818
828
  audioCapabilities: [{
819
- contentType: Ze,
829
+ contentType: $e,
820
830
  robustness: F.audio,
821
831
  encryptionScheme: F.scheme
822
832
  }]
823
833
  }]);
824
834
  }
825
- function et(e, t) {
835
+ function nt(e, t) {
826
836
  return new Promise((n, r) => {
827
837
  let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
828
838
  e.then((e) => {
@@ -832,8 +842,8 @@ function et(e, t) {
832
842
  });
833
843
  });
834
844
  }
835
- async function tt(e = {}) {
836
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ye, r = {};
845
+ async function rt(e = {}) {
846
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ze, r = {};
837
847
  if (typeof window < "u" && window.isSecureContext === !1) return {
838
848
  verdict: "insecure-context",
839
849
  detail: r
@@ -845,7 +855,7 @@ async function tt(e = {}) {
845
855
  };
846
856
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
847
857
  for (let e of t) {
848
- let t = Qe[e];
858
+ let t = et[e];
849
859
  if (!t) {
850
860
  r[e] = "unknown system";
851
861
  continue;
@@ -856,7 +866,7 @@ async function tt(e = {}) {
856
866
  break;
857
867
  }
858
868
  try {
859
- return await et((await et(i(n, $e(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
869
+ return await nt((await nt(i(n, tt(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
860
870
  verdict: "supported",
861
871
  system: e,
862
872
  detail: r
@@ -880,37 +890,37 @@ async function tt(e = {}) {
880
890
  }
881
891
  //#endregion
882
892
  //#region src/core/manifest.ts
883
- var nt = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
884
- function rt(e) {
885
- return nt.test(e);
893
+ var it = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
894
+ function at(e) {
895
+ return it.test(e);
886
896
  }
887
897
  //#endregion
888
898
  //#region src/core/env.ts
889
- var it = {
899
+ var ot = {
890
900
  integration: "https://feed-dev.oddin-video.gg",
891
901
  production: "https://feed.oddin-video.gg"
892
902
  };
893
- function at(e) {
894
- let t = Object.prototype.hasOwnProperty.call(it, e) ? it[e] : void 0;
903
+ function st(e) {
904
+ let t = Object.prototype.hasOwnProperty.call(ot, e) ? ot[e] : void 0;
895
905
  if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
896
906
  return t;
897
907
  }
898
908
  //#endregion
899
909
  //#region src/core/stats.ts
900
- var ot = { droppedFrames: 0 };
901
- function st(e) {
910
+ var ct = { droppedFrames: 0 };
911
+ function lt(e) {
902
912
  try {
903
913
  return new URL(e).host;
904
914
  } catch {
905
915
  return "";
906
916
  }
907
917
  }
908
- var ct = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
909
- function lt(e) {
918
+ var ut = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
919
+ function dt(e) {
910
920
  if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
911
921
  let t = "", n = -1, r = performance.getEntriesByType("resource");
912
- for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || ct.test(i.name)) && i.startTime >= n) {
913
- let e = st(i.name);
922
+ for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || ut.test(i.name)) && i.startTime >= n) {
923
+ let e = lt(i.name);
914
924
  e && (t = e, n = i.startTime);
915
925
  }
916
926
  return t;
@@ -922,7 +932,7 @@ function z(e) {
922
932
  totalFrames: t?.totalVideoFrames ?? 0
923
933
  };
924
934
  }
925
- var ut = class {
935
+ var ft = class {
926
936
  video;
927
937
  baseFrames = 0;
928
938
  baseDropped = 0;
@@ -945,7 +955,7 @@ var ut = class {
945
955
  };
946
956
  }
947
957
  };
948
- function dt(e, t) {
958
+ function pt(e, t) {
949
959
  let n = [
950
960
  ["playing", () => t("playing")],
951
961
  ["waiting", () => t("buffering")],
@@ -962,8 +972,8 @@ function dt(e, t) {
962
972
  }
963
973
  //#endregion
964
974
  //#region src/core/engine/native.ts
965
- var ft = 2e3, pt = 3, B = 500, mt = 6e3, ht = .25, gt = 250, _t = .05, vt = 4, yt = 12e3, bt = .25, xt = 1e3;
966
- function St(e) {
975
+ var mt = 2e3, ht = 3, B = 500, gt = 6e3, _t = .25, vt = 250, yt = .05, bt = 4, xt = 12e3, St = .25, Ct = 1e3;
976
+ function wt(e) {
967
977
  try {
968
978
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
969
979
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -979,7 +989,7 @@ function H() {
979
989
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
980
990
  return e || t;
981
991
  }
982
- function Ct() {
992
+ function Tt() {
983
993
  if (typeof navigator > "u" || !H()) return !1;
984
994
  let e = navigator.userAgent ?? "";
985
995
  return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
@@ -1014,7 +1024,7 @@ var U = class {
1014
1024
  frameCounter;
1015
1025
  detachFrames = null;
1016
1026
  constructor(e) {
1017
- this.deps = e, this.frameCounter = new ut(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
1027
+ this.deps = e, this.frameCounter = new ft(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
1018
1028
  }
1019
1029
  async load() {
1020
1030
  this.detachFrames ??= this.frameCounter.attach();
@@ -1035,7 +1045,7 @@ var U = class {
1035
1045
  type: "error",
1036
1046
  error: new n("INTERNAL", 0, "native HLS playback error"),
1037
1047
  fatal: !0
1038
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Tt(t.manifestUrl, t.analytics?.sid), e.load();
1048
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Dt(t.manifestUrl, t.analytics?.sid), e.load();
1039
1049
  }
1040
1050
  startLoad() {
1041
1051
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -1063,7 +1073,7 @@ var U = class {
1063
1073
  };
1064
1074
  this.onEncrypted = (n) => {
1065
1075
  let a = n;
1066
- a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = St(a.initData), (async () => {
1076
+ a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = wt(a.initData), (async () => {
1067
1077
  try {
1068
1078
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
1069
1079
  initDataTypes: [a.initDataType],
@@ -1163,10 +1173,10 @@ var U = class {
1163
1173
  droppedFrames: t.dropped,
1164
1174
  decodedFrames: t.totalFrames
1165
1175
  };
1166
- if (this.cdnHost ||= lt(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1176
+ if (this.cdnHost ||= dt(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1167
1177
  n.isLive = !0;
1168
1178
  let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
1169
- Number.isFinite(r) && (n.atLiveEdge = r <= vt, !e.paused && r >= 0 && (n.latencySeconds = r));
1179
+ Number.isFinite(r) && (n.atLiveEdge = r <= bt, !e.paused && r >= 0 && (n.latencySeconds = r));
1170
1180
  } else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
1171
1181
  return n;
1172
1182
  }
@@ -1184,7 +1194,7 @@ var U = class {
1184
1194
  return;
1185
1195
  }
1186
1196
  let t = this.hiddenSince;
1187
- this.hiddenSince = null, t != null && e - t >= ft && this.armRefocus();
1197
+ this.hiddenSince = null, t != null && e - t >= mt && this.armRefocus();
1188
1198
  }, this.onPageShow = (e) => {
1189
1199
  e.persisted && this.armRefocus();
1190
1200
  }, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
@@ -1194,7 +1204,7 @@ var U = class {
1194
1204
  let e = this.liveEnd(), t = W, n = t(), r = 0, i = () => {
1195
1205
  if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
1196
1206
  r += B;
1197
- let a = this.liveEnd(), o = a != null && (e == null || a >= e + ht), s = Math.max(r, t() - n) >= mt;
1207
+ let a = this.liveEnd(), o = a != null && (e == null || a >= e + _t), s = Math.max(r, t() - n) >= gt;
1198
1208
  if (o || s && a != null) {
1199
1209
  this.snapToLive();
1200
1210
  return;
@@ -1214,9 +1224,9 @@ var U = class {
1214
1224
  }, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
1215
1225
  if (e.duration !== Infinity) return;
1216
1226
  this.checkEndStale();
1217
- let t = wt(e, e.currentTime);
1218
- t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= _t) && (this.bufferedAdvancedAt = W()), this.lastBufferedEnd = t);
1219
- }, gt);
1227
+ let t = Et(e, e.currentTime);
1228
+ t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= yt) && (this.bufferedAdvancedAt = W()), this.lastBufferedEnd = t);
1229
+ }, vt);
1220
1230
  }
1221
1231
  checkEndStale() {
1222
1232
  if (this.endedEmitted) return;
@@ -1224,14 +1234,14 @@ var U = class {
1224
1234
  this.lastTickAt = e;
1225
1235
  let n = this.liveEnd();
1226
1236
  if (n == null) return;
1227
- let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= bt;
1237
+ let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= St;
1228
1238
  this.lastSeekableEnd = n;
1229
1239
  let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
1230
- if (r || t > xt || a || i.paused) {
1240
+ if (r || t > Ct || a || i.paused) {
1231
1241
  this.edgeStampedAt = e;
1232
1242
  return;
1233
1243
  }
1234
- e - (this.edgeStampedAt ?? e) > yt && (this.endedEmitted = !0, this.deps.emit({
1244
+ e - (this.edgeStampedAt ?? e) > xt && (this.endedEmitted = !0, this.deps.emit({
1235
1245
  type: "ended",
1236
1246
  reason: "stalled"
1237
1247
  }));
@@ -1245,7 +1255,7 @@ var U = class {
1245
1255
  liveEdgeEstimate() {
1246
1256
  let e = this.deps.video;
1247
1257
  if (e.duration !== Infinity) return null;
1248
- let t = this.liveEnd(), n = wt(e, e.currentTime) ?? this.lastBufferedEnd;
1258
+ let t = this.liveEnd(), n = Et(e, e.currentTime) ?? this.lastBufferedEnd;
1249
1259
  if (n != null) {
1250
1260
  let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (W() - e) / 1e3));
1251
1261
  (t == null || r > t) && (t = r);
@@ -1261,7 +1271,7 @@ var U = class {
1261
1271
  snapToLive() {
1262
1272
  let e = this.deps.video, t = this.liveEnd();
1263
1273
  if (t == null) return;
1264
- let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - pt, r);
1274
+ let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - ht, r);
1265
1275
  try {
1266
1276
  e.currentTime = i;
1267
1277
  } catch {}
@@ -1282,7 +1292,7 @@ var U = class {
1282
1292
  function W() {
1283
1293
  return typeof performance < "u" ? performance.now() : Date.now();
1284
1294
  }
1285
- function wt(e, t) {
1295
+ function Et(e, t) {
1286
1296
  let n = e.buffered;
1287
1297
  if (!n || !Number.isFinite(t)) return null;
1288
1298
  for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
@@ -1291,7 +1301,7 @@ function wt(e, t) {
1291
1301
  }
1292
1302
  return null;
1293
1303
  }
1294
- function Tt(e, t) {
1304
+ function Dt(e, t) {
1295
1305
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
1296
1306
  }
1297
1307
  //#endregion
@@ -1308,13 +1318,13 @@ function G(e, t = Date.now()) {
1308
1318
  }
1309
1319
  //#endregion
1310
1320
  //#region src/core/drm/xhrBody.ts
1311
- var Et = 4096;
1312
- function Dt(e) {
1321
+ var Ot = 4096;
1322
+ function kt(e) {
1313
1323
  if (!e || typeof e != "object") return;
1314
1324
  let { response: t } = e;
1315
1325
  if (typeof t == "string") return t;
1316
1326
  let n;
1317
- if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength > Et)) try {
1327
+ if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength > Ot)) try {
1318
1328
  return new TextDecoder().decode(n);
1319
1329
  } catch {
1320
1330
  return;
@@ -1322,8 +1332,8 @@ function Dt(e) {
1322
1332
  }
1323
1333
  //#endregion
1324
1334
  //#region src/core/engine/prefetch.ts
1325
- var Ot = 15e3, kt = 5e3, At = 6;
1326
- function jt(e) {
1335
+ var At = 15e3, jt = 5e3, Mt = 6, Nt = 4e3, Pt = 2;
1336
+ function K(e) {
1327
1337
  try {
1328
1338
  let t = new URL(e);
1329
1339
  return t.searchParams.delete("CMCD"), t.toString();
@@ -1331,17 +1341,23 @@ function jt(e) {
1331
1341
  return e;
1332
1342
  }
1333
1343
  }
1334
- var Mt = class {
1344
+ var Ft = class {
1335
1345
  cmcd;
1336
1346
  entries = /* @__PURE__ */ new Map();
1337
1347
  keyed = /* @__PURE__ */ new Set();
1338
1348
  perTrack = /* @__PURE__ */ new Map();
1349
+ hints = /* @__PURE__ */ new Map();
1339
1350
  stats = {
1340
1351
  started: 0,
1341
1352
  served: 0,
1342
1353
  missed: 0,
1343
1354
  failed: 0,
1344
- expired: 0
1355
+ expired: 0,
1356
+ hintStarted: 0,
1357
+ hintServed: 0,
1358
+ hintFailed: 0,
1359
+ hintExpired: 0,
1360
+ hintDropped: 0
1345
1361
  };
1346
1362
  constructor(e = {}) {
1347
1363
  this.cmcd = e;
@@ -1354,32 +1370,58 @@ var Mt = class {
1354
1370
  }
1355
1371
  prefetch(e, t, n) {
1356
1372
  if (!this.isActive(t)) return;
1357
- let r = jt(e);
1373
+ let r = K(e);
1358
1374
  if (this.entries.has(r)) return;
1359
1375
  let i = this.perTrack.get(t) ?? 0;
1360
- if (i >= At) return;
1361
- this.perTrack.set(t, i + 1);
1362
- let a = new AbortController(), o = {
1376
+ i >= Mt || (this.perTrack.set(t, i + 1), this.start(r, this.withCmcd(e, t, n), !1, At), this.stats.started += 1);
1377
+ }
1378
+ prefetchHint(e, t) {
1379
+ let n = K(e);
1380
+ if (this.entries.has(n)) return;
1381
+ let r = this.hints.get(t) ?? [];
1382
+ for (; r.length >= Pt;) {
1383
+ let e = r.shift();
1384
+ e !== void 0 && this.drop(e) && (this.stats.hintDropped += 1);
1385
+ }
1386
+ r.push(n), this.hints.set(t, r), this.start(n, this.withCmcd(e, t, "media"), !0, Nt), this.stats.hintStarted += 1;
1387
+ }
1388
+ dropHints(e) {
1389
+ for (let t of this.hints.get(e) ?? []) this.drop(t) && (this.stats.hintDropped += 1);
1390
+ this.hints.delete(e);
1391
+ }
1392
+ drop(e) {
1393
+ let t = this.entries.get(e);
1394
+ return t ? (this.entries.delete(e), t.abort.abort(), !0) : !1;
1395
+ }
1396
+ start(e, t, n, r) {
1397
+ let i = new AbortController(), a = {
1363
1398
  started: performance.now(),
1364
1399
  first: 0,
1400
+ end: 0,
1401
+ hint: n,
1402
+ headers: Promise.resolve(),
1365
1403
  bytes: Promise.resolve(null),
1366
- abort: a
1367
- };
1368
- o.bytes = fetch(this.withCmcd(e, t, n), {
1404
+ abort: i
1405
+ }, o = () => {};
1406
+ a.headers = new Promise((e) => o = e), a.bytes = fetch(t, {
1369
1407
  credentials: "omit",
1370
1408
  mode: "cors",
1371
- signal: a.signal
1372
- }).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
- this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
1374
- }, Ot);
1409
+ signal: i.signal
1410
+ }).then(async (e) => {
1411
+ if (a.first = performance.now(), o(), !e.ok) return null;
1412
+ let t = await e.arrayBuffer();
1413
+ return a.end = performance.now(), t;
1414
+ }).catch(() => null).finally(o), this.entries.set(e, a), setTimeout(() => {
1415
+ this.entries.get(e) === a && (this.entries.delete(e), i.abort(), n ? this.stats.hintExpired += 1 : this.stats.expired += 1);
1416
+ }, r);
1375
1417
  }
1376
1418
  take(e) {
1377
- let t = jt(e), n = this.entries.get(t);
1419
+ let t = K(e), n = this.entries.get(t);
1378
1420
  return n && this.entries.delete(t), n;
1379
1421
  }
1380
1422
  destroy() {
1381
1423
  for (let e of this.entries.values()) e.abort.abort();
1382
- this.entries.clear();
1424
+ this.entries.clear(), this.hints.clear();
1383
1425
  }
1384
1426
  withCmcd(e, t, n) {
1385
1427
  let { sessionId: r, contentId: i } = this.cmcd;
@@ -1394,40 +1436,51 @@ var Mt = class {
1394
1436
  }
1395
1437
  }
1396
1438
  };
1397
- function Nt(t) {
1439
+ function It(t) {
1398
1440
  let n = e.DefaultConfig?.loader;
1399
1441
  if (typeof n != "function") return;
1400
1442
  class r extends n {
1401
1443
  served = !1;
1402
1444
  cancelled = !1;
1403
- stats = Pt();
1445
+ entry;
1446
+ stats = Lt();
1404
1447
  load(e, n, r) {
1405
1448
  let i = e.rangeEnd ? void 0 : t.take(e.url);
1406
1449
  if (!i) {
1407
1450
  super.load(e, n, r);
1408
1451
  return;
1409
1452
  }
1410
- this.served = !0;
1411
- let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || kt, s = setTimeout(() => {
1412
- !this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
1413
- }, o);
1414
- i.bytes.then((o) => {
1415
- if (clearTimeout(s), this.cancelled || !this.served) return;
1416
- if (!o) {
1417
- t.stats.failed += 1, this.served = !1, super.load(e, n, r);
1453
+ this.served = !0, this.entry = i;
1454
+ let a = performance.now(), o = () => {
1455
+ i.hint ? t.stats.hintFailed += 1 : t.stats.failed += 1;
1456
+ }, s = () => {
1457
+ !this.cancelled && this.served && (i.abort.abort(), o(), this.served = !1, this.entry = void 0, super.load(e, n, r));
1458
+ }, c = n?.loadPolicy, l = c?.maxTimeToFirstByteMs || jt, u = setTimeout(s, l);
1459
+ i.headers.then(() => {
1460
+ clearTimeout(u);
1461
+ let e = c?.maxLoadTimeMs;
1462
+ e && (u = setTimeout(s, Math.max(0, e - (performance.now() - a))));
1463
+ }), i.bytes.then((s) => {
1464
+ if (clearTimeout(u), this.cancelled || !this.served) return;
1465
+ if (!s) {
1466
+ o(), this.served = !1, super.load(e, n, r);
1418
1467
  return;
1419
1468
  }
1420
- t.stats.served += 1;
1421
1469
  let c = this.stats;
1422
- c.loading.start = a, c.loading.first = Math.max(a, i.first || a), c.loading.end = performance.now(), c.loaded = c.total = o.byteLength, r.onSuccess({
1470
+ if (i.hint) {
1471
+ t.stats.hintServed += 1;
1472
+ let e = performance.now(), n = Math.max(0, (i.end || e) - (i.first || e)), r = Math.max(0, (i.first || e) - a);
1473
+ c.loading.end = e, c.loading.first = e - n, c.loading.start = c.loading.first - r;
1474
+ } else t.stats.served += 1, c.loading.start = a, c.loading.first = Math.max(a, i.first || a), c.loading.end = performance.now();
1475
+ c.loaded = c.total = s.byteLength, this.entry = void 0, r.onSuccess({
1423
1476
  url: e.url,
1424
- data: o
1477
+ data: s
1425
1478
  }, c, e, null);
1426
1479
  });
1427
1480
  }
1428
1481
  abort() {
1429
1482
  if (this.served) {
1430
- this.cancelled = !0, this.stats.aborted = !0;
1483
+ this.cancelled = !0, this.stats.aborted = !0, this.entry?.abort.abort(), this.entry = void 0;
1431
1484
  return;
1432
1485
  }
1433
1486
  super.abort();
@@ -1435,7 +1488,7 @@ function Nt(t) {
1435
1488
  }
1436
1489
  return r;
1437
1490
  }
1438
- function Pt() {
1491
+ function Lt() {
1439
1492
  return {
1440
1493
  aborted: !1,
1441
1494
  loaded: 0,
@@ -1459,10 +1512,10 @@ function Pt() {
1459
1512
  }
1460
1513
  };
1461
1514
  }
1462
- function Ft(e) {
1515
+ function Rt(e) {
1463
1516
  return e === "audio" ? "audio" : "main";
1464
1517
  }
1465
- function It(e, t) {
1518
+ function zt(e, t) {
1466
1519
  let n = [];
1467
1520
  t.initSegment?.url && !t.initSegment.data && n.push({
1468
1521
  url: t.initSegment.url,
@@ -1479,18 +1532,29 @@ function It(e, t) {
1479
1532
  });
1480
1533
  return n;
1481
1534
  }
1535
+ function Bt(e) {
1536
+ let t = e, n = t?.preloadHint;
1537
+ if (!n || !t?.url || n.TYPE !== "PART" || n["BYTERANGE-START"] !== void 0 || n["BYTERANGE-LENGTH"] !== void 0) return null;
1538
+ let r = n.URI;
1539
+ if (typeof r != "string" || !r) return null;
1540
+ try {
1541
+ return new URL(r, t.url).toString();
1542
+ } catch {
1543
+ return null;
1544
+ }
1545
+ }
1482
1546
  //#endregion
1483
1547
  //#region src/core/percentile.ts
1484
- function K(e, t) {
1548
+ function q(e, t) {
1485
1549
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
1486
1550
  }
1487
1551
  //#endregion
1488
1552
  //#region src/core/engine/hls.ts
1489
- function Lt() {
1553
+ function Vt() {
1490
1554
  return e.isSupported();
1491
1555
  }
1492
- var Rt = 1e6, zt = 20, Bt = 1e4, Vt = 3, Ht = 5, Ut = 3, Wt = 1e4, Gt = 3e4, Kt = 12e3, qt = 3e3, Jt = .02, Yt = 6e3, Xt = .5, Zt = 3, Qt = .5, $t = 1.1, en = .25, tn = 5e3, nn = 4e3, rn = 2, an = 5, on = 2, sn = 2, cn = 4, ln = 4, un = 2e3, dn = 3e4, fn = 1, pn = 2;
1493
- function mn(e, t, n) {
1556
+ var Ht = 3, Ut = 1e6, Wt = 20, Gt = 1e4, Kt = 3, qt = 5, Jt = 3, Yt = 1e4, Xt = 3e4, Zt = 12e3, Qt = 3e3, $t = .02, en = 6e3, tn = .5, nn = 3, rn = .5, an = 1.1, on = .25, sn = 5e3, cn = 4e3, ln = 2, un = 5, dn = 2, fn = 2, pn = 4, mn = 4, hn = 2e3, gn = 3e4, _n = 1, vn = 2;
1557
+ function yn(e, t, n) {
1494
1558
  if (n <= 0 || t < 0 || t >= e.length) return t;
1495
1559
  let r = (t, n) => e[t].width === e[n].width && e[t].height === e[n].height, i = (t) => {
1496
1560
  for (; t + 1 < e.length && r(t + 1, t);) t++;
@@ -1499,11 +1563,11 @@ function mn(e, t, n) {
1499
1563
  for (let t = 0; t < n && a + 1 < e.length; t++) a = i(a + 1);
1500
1564
  return a;
1501
1565
  }
1502
- var hn = .2, gn = 30, _n = 2, vn = 2, yn = 2, bn = 9, xn = .5, Sn = 64, Cn = 1e4, wn = 8, Tn = .6, En = .4, Dn = .4, On = 2, kn = 6e4, q = .5, An = 3.5, jn = 300;
1503
- function Mn(e) {
1566
+ var bn = .2, xn = 30, Sn = 2, Cn = 2, wn = 2, Tn = 9, En = .5, Dn = 64, On = 1e4, kn = 8, An = .6, jn = .4, Mn = .4, Nn = 2, Pn = 6e4, J = .5, Fn = 3.5, In = 300;
1567
+ function Ln(e) {
1504
1568
  return (e?.part ?? e?.frag)?.stats;
1505
1569
  }
1506
- function Nn() {
1570
+ function Rn() {
1507
1571
  if (typeof navigator > "u") return 0;
1508
1572
  try {
1509
1573
  let e = navigator.connection?.rtt;
@@ -1512,20 +1576,20 @@ function Nn() {
1512
1576
  return 0;
1513
1577
  }
1514
1578
  }
1515
- function Pn(e) {
1579
+ function zn(e) {
1516
1580
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
1517
1581
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
1518
1582
  return;
1519
1583
  }
1520
- e.liveSyncDuration ??= yn;
1521
- let t = Math.max(12, e.liveSyncDuration + bn);
1522
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Fn(e, e.liveSyncDuration);
1584
+ e.liveSyncDuration ??= wn;
1585
+ let t = Math.max(12, e.liveSyncDuration + Tn);
1586
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Bn(e, e.liveSyncDuration);
1523
1587
  }
1524
- function Fn(e, t) {
1588
+ function Bn(e, t) {
1525
1589
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
1526
1590
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
1527
1591
  }
1528
- var In = class {
1592
+ var Vn = class {
1529
1593
  name = "hls";
1530
1594
  hls = null;
1531
1595
  deps;
@@ -1619,7 +1683,7 @@ var In = class {
1619
1683
  frameCounter;
1620
1684
  detachFrames = null;
1621
1685
  constructor(e) {
1622
- this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.frameCounter = new ut(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1686
+ this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.frameCounter = new ft(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1623
1687
  }
1624
1688
  async load() {
1625
1689
  this.detachFrames ??= this.frameCounter.attach();
@@ -1632,7 +1696,7 @@ var In = class {
1632
1696
  });
1633
1697
  return;
1634
1698
  }
1635
- e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ue(r), qe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1699
+ e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ge(r), Ye()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1636
1700
  let e = this.hls;
1637
1701
  if (document.visibilityState !== "visible" || !e) return;
1638
1702
  let t = e.liveSyncPosition;
@@ -1655,7 +1719,7 @@ var In = class {
1655
1719
  }
1656
1720
  this.loadSuspended = !0;
1657
1721
  }
1658
- }, tn));
1722
+ }, sn));
1659
1723
  }
1660
1724
  resumeLoading() {
1661
1725
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1687,7 +1751,7 @@ var In = class {
1687
1751
  let t = e.liveSyncPosition;
1688
1752
  if (typeof t != "number" || !Number.isFinite(t)) return;
1689
1753
  let { video: n } = this.deps;
1690
- n.currentTime <= t + xn || (n.currentTime = t);
1754
+ n.currentTime <= t + En || (n.currentTime = t);
1691
1755
  }
1692
1756
  reanchorPartTimeline(e, t) {
1693
1757
  let { frag: n, part: r } = t;
@@ -1699,7 +1763,7 @@ var In = class {
1699
1763
  let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
1700
1764
  if (!s) return;
1701
1765
  let c = a.startPTS - s.start;
1702
- if (!(!Number.isFinite(c) || Math.abs(c) < Jt)) {
1766
+ if (!(!Number.isFinite(c) || Math.abs(c) < $t)) {
1703
1767
  for (let e of i.fragments) e && e.setStart(e.start + c);
1704
1768
  i.fragmentHint?.setStart(i.fragmentHint.start + c), this.deps.debug === !0 && console.info(`havik-player: LL-HLS timeline re-anchored by ${c >= 0 ? "+" : ""}${c.toFixed(3)}s at sn ${n.sn} (level ${n.level})`);
1705
1769
  }
@@ -1727,7 +1791,7 @@ var In = class {
1727
1791
  videoEncryptionScheme: F.scheme,
1728
1792
  audioEncryptionScheme: F.scheme
1729
1793
  },
1730
- ...M() ? { requestMediaKeySystemAccessFunc: He(t) } : {},
1794
+ ...N() ? { requestMediaKeySystemAccessFunc: We(t) } : {},
1731
1795
  licenseXhrSetup: (e, t) => {
1732
1796
  let o = performance.now(), s = () => {
1733
1797
  e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a), this.licenseRequested = !0, e.addEventListener("loadend", () => {
@@ -1739,7 +1803,7 @@ var In = class {
1739
1803
  return;
1740
1804
  }
1741
1805
  let l = this.hls, u, d = new Promise((e) => {
1742
- u = setTimeout(() => e(void 0), Wt);
1806
+ u = setTimeout(() => e(void 0), Yt);
1743
1807
  });
1744
1808
  return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
1745
1809
  if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
@@ -1754,35 +1818,37 @@ var In = class {
1754
1818
  } } : {},
1755
1819
  ...c
1756
1820
  };
1757
- if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !f.fLoader) {
1758
- let e = new Mt({
1821
+ this.prefetch?.destroy(), this.prefetch = null;
1822
+ let p = !1, m = !1, h = u && this.deps.mediaDuringKey !== !1, g = this.deps.preloadHints === !0;
1823
+ if ((h || g) && !f.fLoader) {
1824
+ let e = new Ft({
1759
1825
  sessionId: n.analytics?.sid,
1760
1826
  contentId: n.matchUrn
1761
- }), t = Nt(e);
1762
- t && (this.prefetch = e, f.fLoader = t);
1827
+ }), t = It(e);
1828
+ t && (this.prefetch = e, p = h, m = g, f.fLoader = t);
1763
1829
  }
1764
- Pn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
1765
- let p = new e(f);
1766
- if (this.hls = p, this.armHoldBack(p, f), p.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(p, t)), p.on(e.Events.MANIFEST_PARSED, () => {
1767
- this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(p), this.measureLadder(p), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
1768
- }), p.on(e.Events.FRAG_BUFFERED, (e, t) => {
1830
+ zn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
1831
+ let _ = new e(f);
1832
+ if (this.hls = _, this.armHoldBack(_, f), _.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(_, t)), _.on(e.Events.MANIFEST_PARSED, () => {
1833
+ this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(_), this.measureLadder(_), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
1834
+ }), _.on(e.Events.FRAG_BUFFERED, (e, t) => {
1769
1835
  t?.frag?.type === "main" && (this.kickKind !== "dead" && this.clearKick(), (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
1770
1836
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1771
- }, Gt)));
1772
- }), p.on(e.Events.FRAG_LOADING, (e, t) => {
1837
+ }, Xt)));
1838
+ }), _.on(e.Events.FRAG_LOADING, (e, t) => {
1773
1839
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1774
- }), p.on(e.Events.FRAG_LOADED, (e, t) => {
1840
+ }), _.on(e.Events.FRAG_LOADED, (e, t) => {
1775
1841
  t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
1776
- let n = t?.frag, r = Mn(t), i = r?.loaded;
1842
+ let n = t?.frag, r = Ln(t), i = r?.loaded;
1777
1843
  typeof i == "number" && (this.bytesLoaded += i), !this.reportedFirstBytes && typeof i == "number" && i > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1778
1844
  let a = r?.loading;
1779
- a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length > Sn && this.requestTimesMs.shift()), this.sampleHoldBack(t);
1845
+ a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length > Dn && this.requestTimesMs.shift()), this.sampleHoldBack(t);
1780
1846
  let o = n?.url;
1781
1847
  if (o) {
1782
- let e = st(o);
1848
+ let e = lt(o);
1783
1849
  e && (this.cdnHost = e);
1784
1850
  }
1785
- }), p.on(e.Events.LEVEL_LOADED, (e, t) => {
1851
+ }), _.on(e.Events.LEVEL_LOADED, (e, t) => {
1786
1852
  let n = t?.stats?.loaded;
1787
1853
  if (typeof n == "number" && (this.playlistBytesLoaded += n), this.reportedFirstPlaylist || (this.reportedFirstPlaylist = !0, l({ type: "firstPlaylist" })), this.detectedLowLatency) return;
1788
1854
  let r = t.details;
@@ -1790,31 +1856,47 @@ var In = class {
1790
1856
  type: "lowLatencyDetected",
1791
1857
  value: !0
1792
1858
  }));
1793
- }), p.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
1859
+ }), _.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch && m) {
1860
+ let t = this.prefetch, n = this.deps.video, r = (e, r) => {
1861
+ if (n.paused) return;
1862
+ let i = e;
1863
+ if (!i?.live || !i.partList?.length || typeof i.edge != "number") return;
1864
+ let a = n.buffered, o = a.length ? a.end(a.length - 1) : 0;
1865
+ if (i.edge - o > Ht * (i.partTarget || .5)) return;
1866
+ let s = Bt(e);
1867
+ s && t.prefetchHint(s, r);
1868
+ };
1869
+ _.on(e.Events.LEVEL_LOADED, (e, t) => {
1870
+ t.level === _.loadLevel && r(t.details, "main");
1871
+ }), _.on(e.Events.AUDIO_TRACK_LOADED, (e, t) => {
1872
+ t?.id === _.audioTrack && r(t?.details, "audio");
1873
+ }), _.on(e.Events.LEVEL_SWITCHING, () => t.dropHints("main")), _.on(e.Events.AUDIO_TRACK_SWITCHING, () => t.dropHints("audio"));
1874
+ }
1875
+ if (this.prefetch && p) {
1794
1876
  let t = this.prefetch;
1795
- p.on(e.Events.KEY_LOADING, (e, n) => {
1796
- let r = n?.frag, i = Ft(r?.type);
1797
- if (r && t.isActive(i)) for (let e of It(p, r)) t.prefetch(e.url, i, e.kind);
1798
- }), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Ft(n?.frag?.type)));
1877
+ _.on(e.Events.KEY_LOADING, (e, n) => {
1878
+ let r = n?.frag, i = Rt(r?.type);
1879
+ if (r && t.isActive(i)) for (let e of zt(_, r)) t.prefetch(e.url, i, e.kind);
1880
+ }), _.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Rt(n?.frag?.type)));
1799
1881
  }
1800
- p.on(e.Events.KEY_LOADED, () => {
1882
+ _.on(e.Events.KEY_LOADED, () => {
1801
1883
  u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
1802
1884
  }), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1803
1885
  this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.adaptHoldBack(), this.checkFrameDrops();
1804
- }, qt), p.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1886
+ }, Qt), _.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1805
1887
  this.renditionSwitches += 1;
1806
- let n = this.lastLevelIndex >= 0 ? p.levels[this.lastLevelIndex] : void 0, r = p.levels[t.level];
1888
+ let n = this.lastLevelIndex >= 0 ? _.levels[this.lastLevelIndex] : void 0, r = _.levels[t.level];
1807
1889
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, this.armFrameDropGrace(), l({
1808
1890
  type: "qualitychange",
1809
1891
  index: t.level
1810
1892
  });
1811
- }), p.on(e.Events.AUDIO_TRACK_SWITCHED, (e, t) => l({
1893
+ }), _.on(e.Events.AUDIO_TRACK_SWITCHED, (e, t) => l({
1812
1894
  type: "audiotrackchange",
1813
1895
  id: t.id
1814
- })), p.on(e.Events.SUBTITLE_TRACK_SWITCH, (e, t) => l({
1896
+ })), _.on(e.Events.SUBTITLE_TRACK_SWITCH, (e, t) => l({
1815
1897
  type: "texttrackchange",
1816
1898
  id: t.id
1817
- })), p.on(e.Events.ERROR, (e, t) => this.onError(t)), p.loadSource(n.manifestUrl), p.attachMedia(t);
1899
+ })), _.on(e.Events.ERROR, (e, t) => this.onError(t)), _.loadSource(n.manifestUrl), _.attachMedia(t);
1818
1900
  }
1819
1901
  getQualityLevels() {
1820
1902
  return this.hls ? this.hls.levels.map((e, t) => ({
@@ -1852,9 +1934,9 @@ var In = class {
1852
1934
  let o = e.config ?? {}, s = typeof self < "u" && self.devicePixelRatio > 0 ? self.devicePixelRatio : 1, c = o.ignoreDevicePixelRatio ? 1 : s;
1853
1935
  c = Math.min(c, o.maxDevicePixelRatio ?? Infinity);
1854
1936
  let l = t.getMaxLevelByMediaSize(e.levels, i * c, a * c), u = this.deps.sizeCapHeadroom;
1855
- if (u == null && s >= pn) return l;
1856
- let d = u ?? fn, f = Number.isNaN(d) ? fn : d === Infinity ? e.levels.length : Math.max(0, Math.floor(d));
1857
- return mn(e.levels, l, f);
1937
+ if (u == null && s >= vn) return l;
1938
+ let d = u ?? _n, f = Number.isNaN(d) ? _n : d === Infinity ? e.levels.length : Math.max(0, Math.floor(d));
1939
+ return yn(e.levels, l, f);
1858
1940
  }
1859
1941
  onMediaResize() {
1860
1942
  if (!this.sizeCapManaged) return;
@@ -1869,7 +1951,7 @@ var In = class {
1869
1951
  return;
1870
1952
  }
1871
1953
  this.capTimer && clearTimeout(this.capTimer);
1872
- let t = e > this.sizeCapLevel ? un : dn;
1954
+ let t = e > this.sizeCapLevel ? hn : gn;
1873
1955
  this.capTimer = setTimeout(() => {
1874
1956
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1875
1957
  }, t);
@@ -1879,9 +1961,9 @@ var In = class {
1879
1961
  this.ladderHeights = t.length ? [...new Set(t)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = e.levels.length ? Math.round(Math.max(...e.levels.map((e) => e.bitrate)) / 1e3) : 0;
1880
1962
  }
1881
1963
  dropLevelsWidevineCannotPlay(e) {
1882
- this.removeLevelsWhere(e, (e) => Je(e) !== !0);
1964
+ this.removeLevelsWhere(e, (e) => Xe(e) !== !0);
1883
1965
  let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
1884
- for (let n of t) Ke(n).then((t) => {
1966
+ for (let n of t) Je(n).then((t) => {
1885
1967
  t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
1886
1968
  });
1887
1969
  }
@@ -1892,7 +1974,7 @@ var In = class {
1892
1974
  a && I(a) && t(a) && (r.push(n), i.add(a));
1893
1975
  }), !r.length) return !1;
1894
1976
  let a = [...i].join(", ");
1895
- if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Je(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1977
+ if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Xe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1896
1978
  for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
1897
1979
  return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
1898
1980
  }
@@ -2000,7 +2082,7 @@ var In = class {
2000
2082
  return;
2001
2083
  }
2002
2084
  let e = Date.now() - this.lastAdvanceMs;
2003
- !this.chaseSuspended && e > Yt && this.suspendChasing(), e > Kt && this.emitEnded("stalled");
2085
+ !this.chaseSuspended && e > en && this.suspendChasing(), e > Zt && this.emitEnded("stalled");
2004
2086
  }
2005
2087
  resetStarvationWindow() {
2006
2088
  this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
@@ -2015,7 +2097,7 @@ var In = class {
2015
2097
  this.resetStarvationWindow();
2016
2098
  return;
2017
2099
  }
2018
- let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < Yt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > nn, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = z(t), c = o - s, l = c !== this.starvedFrames;
2100
+ let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < en, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > cn, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = z(t), c = o - s, l = c !== this.starvedFrames;
2019
2101
  if (this.starvedFrames = c, !a || l) {
2020
2102
  (t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
2021
2103
  return;
@@ -2024,12 +2106,12 @@ var In = class {
2024
2106
  this.resetStarvationWindow();
2025
2107
  return;
2026
2108
  }
2027
- if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > cn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= on && (this.clearKick(), this.starvationRebuilds < sn)) {
2109
+ if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > pn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= dn && (this.clearKick(), this.starvationRebuilds < fn)) {
2028
2110
  this.starvationRebuilds += 1, this.resetStarvationWindow(), this.clearRecoveryReset(), console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
2029
2111
  return;
2030
2112
  }
2031
- let u = i && this.starvedTicks >= rn, d = !i && this.deadTicks >= cn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= ln;
2032
- if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= an))) {
2113
+ let u = i && this.starvedTicks >= ln, d = !i && this.deadTicks >= pn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= mn;
2114
+ if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= un))) {
2033
2115
  this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, this.kickKind = d ? "dead" : "quiet", this.clearRecoveryReset(), console.warn(d ? "havik-player: video starved while hls.js keeps loading media it never plays (dead pipeline at the live edge) — restarting the load" : "havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
2034
2116
  try {
2035
2117
  e.stopLoad(), e.startLoad(-1);
@@ -2044,7 +2126,7 @@ var In = class {
2044
2126
  let t = e.latency, n = e.targetLatency;
2045
2127
  if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
2046
2128
  let r = t - n;
2047
- !this.catchUpEngaged && r > Xt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Xt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
2129
+ !this.catchUpEngaged && r > tn ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= tn && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
2048
2130
  let i = this.catchUpEngaged ? this.catchUpRate : 1;
2049
2131
  e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
2050
2132
  }
@@ -2057,7 +2139,7 @@ var In = class {
2057
2139
  }), n < 0 ? 0 : n;
2058
2140
  }
2059
2141
  armFrameDropGrace() {
2060
- this.fpsGraceTicks > 0 || (this.fpsGraceTicks = vn, this.fpsBadTicks = 0);
2142
+ this.fpsGraceTicks > 0 || (this.fpsGraceTicks = Cn, this.fpsBadTicks = 0);
2061
2143
  }
2062
2144
  resetFrameDropWindow() {
2063
2145
  this.fpsLastFrames = -1, this.fpsLastDropped = -1, this.fpsBadTicks = 0;
@@ -2069,7 +2151,7 @@ var In = class {
2069
2151
  return;
2070
2152
  }
2071
2153
  let { totalFrames: n, dropped: r } = z(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
2072
- if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < gn || o < 0) {
2154
+ if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < xn || o < 0) {
2073
2155
  this.fpsBadTicks = 0;
2074
2156
  return;
2075
2157
  }
@@ -2077,11 +2159,11 @@ var In = class {
2077
2159
  --this.fpsGraceTicks, this.fpsBadTicks = 0;
2078
2160
  return;
2079
2161
  }
2080
- if (o <= hn * a) {
2162
+ if (o <= bn * a) {
2081
2163
  this.fpsBadTicks = 0;
2082
2164
  return;
2083
2165
  }
2084
- if (this.fpsBadTicks += 1, this.fpsBadTicks < _n) return;
2166
+ if (this.fpsBadTicks += 1, this.fpsBadTicks < Sn) return;
2085
2167
  this.fpsBadTicks = 0;
2086
2168
  let s = e.levels, c = s[e.currentLevel];
2087
2169
  if (!c) return;
@@ -2098,22 +2180,22 @@ var In = class {
2098
2180
  return;
2099
2181
  }
2100
2182
  let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
2101
- if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min($t, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
2183
+ if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(an, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
2102
2184
  this.resetChaseWindow();
2103
2185
  return;
2104
2186
  }
2105
- if (this.chaseLatency < 0 || this.chaseLatency - n >= Qt) {
2187
+ if (this.chaseLatency < 0 || this.chaseLatency - n >= rn) {
2106
2188
  this.chaseLatency = n, this.chaseTicks = 0;
2107
2189
  return;
2108
2190
  }
2109
- if (this.chaseTicks += 1, this.chaseTicks < Zt) return;
2191
+ if (this.chaseTicks += 1, this.chaseTicks < nn) return;
2110
2192
  this.resetChaseWindow();
2111
2193
  let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
2112
2194
  if (!(a > 1)) return;
2113
2195
  let o = e.targetLatency;
2114
2196
  if (typeof o != "number" || !(o > 0)) return;
2115
2197
  let s = Math.min(n, a - 1);
2116
- s < o + en || (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({
2198
+ s < o + on || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s, this.deps.emit({
2117
2199
  type: "livetargetchange",
2118
2200
  change: {
2119
2201
  targetSeconds: s,
@@ -2130,13 +2212,13 @@ var In = class {
2130
2212
  if (!this.holdBackEnabled || this.holdBackPriorChecked || !e || (this.holdBackPriorChecked = !0, this.holdBackApplied > 0 || this.holdBackStepCount > 0)) return;
2131
2213
  let t = e.targetLatency;
2132
2214
  if (this.holdBackBase < 0 && typeof t == "number" && t > 0 && (this.holdBackBase = t), this.holdBackBase < 0) return;
2133
- let n = Nn();
2134
- if (!(n >= jn)) return;
2135
- let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase + q);
2215
+ let n = Rn();
2216
+ if (!(n >= In)) return;
2217
+ let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase + J);
2136
2218
  i > r && (this.holdBackStepCount = 1, this.moveHoldBack(e, r, i, "connection-rtt", `connection rtt ${n} ms`));
2137
2219
  }
2138
2220
  holdBackCeiling(e) {
2139
- let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t : An, r = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
2221
+ let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t : Fn, r = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
2140
2222
  return r > 1 ? Math.min(n, r - 1) : n;
2141
2223
  }
2142
2224
  sampleHoldBack(e) {
@@ -2145,7 +2227,7 @@ var In = class {
2145
2227
  if (t !== "main" && t !== "audio") return;
2146
2228
  let n = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag?.duration;
2147
2229
  if (typeof n != "number" || !(n > 0)) return;
2148
- let r = Mn(e)?.loading;
2230
+ let r = Ln(e)?.loading;
2149
2231
  if (!r || !(r.start > 0) || !(r.end > 0)) return;
2150
2232
  let i = r.first > r.start ? r.first : r.end, a = Math.max(0, i - r.start) / (n * 1e3);
2151
2233
  this.holdBackSamples.push({
@@ -2160,30 +2242,30 @@ var In = class {
2160
2242
  this.holdBackSlowTicks = 0, this.holdBackFastSince = 0, this.holdBackSamples = [];
2161
2243
  return;
2162
2244
  }
2163
- let t = Date.now(), n = t - Cn, r = this.holdBackSamples, i = 0;
2245
+ let t = Date.now(), n = t - On, r = this.holdBackSamples, i = 0;
2164
2246
  for (; i < r.length && r[i].t < n;) i += 1;
2165
2247
  i > 0 && r.splice(0, i);
2166
2248
  let a = e.targetLatency;
2167
2249
  if (typeof a != "number" || !(a > 0)) return;
2168
2250
  this.holdBackBase < 0 && (this.holdBackBase = a);
2169
2251
  let o = this.holdBackBase, s = this.holdBackCeiling(e);
2170
- if (r.length < wn) {
2252
+ if (r.length < kn) {
2171
2253
  this.holdBackSlowTicks = 0;
2172
2254
  return;
2173
2255
  }
2174
- let c = r.map((e) => e.ratio).sort((e, t) => e - t), l = K(c, 95), u = K(c, 50), d = Math.round(l * 1e3);
2175
- if (l >= Tn && u >= En) {
2176
- if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks < On) return;
2256
+ let c = r.map((e) => e.ratio).sort((e, t) => e - t), l = q(c, 95), u = q(c, 50), d = Math.round(l * 1e3);
2257
+ if (l >= An && u >= jn) {
2258
+ if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks < Nn) return;
2177
2259
  this.holdBackSlowTicks = 0;
2178
- let t = Math.ceil((s - o) / q), n = Math.ceil((a - o) / q - 1e-9);
2260
+ let t = Math.ceil((s - o) / J), n = Math.ceil((a - o) / J - 1e-9);
2179
2261
  if (n > this.holdBackStepCount && (this.holdBackStepCount = n), this.holdBackStepCount >= t) return;
2180
2262
  this.holdBackStepCount += 1;
2181
- let r = Math.min(s, o + this.holdBackStepCount * q);
2263
+ let r = Math.min(s, o + this.holdBackStepCount * J);
2182
2264
  if (r <= a) return;
2183
2265
  this.moveHoldBack(e, a, r, "slow-fetches", `part fetches slow (first byte p50 ${Math.round(u * 1e3)} / p95 ${d} ms per 1 s of media)`);
2184
2266
  return;
2185
2267
  }
2186
- if (this.holdBackSlowTicks = 0, l >= Dn) {
2268
+ if (this.holdBackSlowTicks = 0, l >= Mn) {
2187
2269
  this.holdBackFastSince = 0;
2188
2270
  return;
2189
2271
  }
@@ -2191,9 +2273,9 @@ var In = class {
2191
2273
  this.holdBackFastSince = t;
2192
2274
  return;
2193
2275
  }
2194
- if (t - this.holdBackFastSince < kn || (this.holdBackFastSince = t, this.holdBackStepCount === 0 || a !== this.holdBackApplied)) return;
2276
+ if (t - this.holdBackFastSince < Pn || (this.holdBackFastSince = t, this.holdBackStepCount === 0 || a !== this.holdBackApplied)) return;
2195
2277
  --this.holdBackStepCount;
2196
- let f = Math.max(o, o + this.holdBackStepCount * q);
2278
+ let f = Math.max(o, o + this.holdBackStepCount * J);
2197
2279
  f >= a || this.moveHoldBack(e, a, f, "fast-fetches", `part fetches fast again (p95 first byte ${d} ms per 1 s of media)`);
2198
2280
  }
2199
2281
  moveHoldBack(e, t, n, r, i) {
@@ -2234,14 +2316,14 @@ var In = class {
2234
2316
  } catch {}
2235
2317
  }
2236
2318
  startEstimate() {
2237
- return this.deps.rememberBandwidth === !1 ? Rt : Ie() ?? Rt;
2319
+ return this.deps.rememberBandwidth === !1 ? Ut : Le() ?? Ut;
2238
2320
  }
2239
2321
  maybeRememberBandwidth(e) {
2240
- if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < zt) return;
2322
+ if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Wt) return;
2241
2323
  let t = Date.now();
2242
- if (!e && t - this.bwSavedAt < Bt) return;
2324
+ if (!e && t - this.bwSavedAt < Gt) return;
2243
2325
  let n = this.hls?.bandwidthEstimate;
2244
- typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Le(n));
2326
+ typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Re(n));
2245
2327
  }
2246
2328
  destroy() {
2247
2329
  if (this.maybeRememberBandwidth(!0), this.detachFrames?.(), this.detachFrames = null, this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
@@ -2259,7 +2341,7 @@ var In = class {
2259
2341
  scheduleLicenseRetry(t) {
2260
2342
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
2261
2343
  let n = t.response?.code ?? 0;
2262
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Ut) return !1;
2344
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Jt) return !1;
2263
2345
  this.licenseRecoveries += 1;
2264
2346
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
2265
2347
  return this.licenseRetryTimer = setTimeout(() => {
@@ -2291,7 +2373,7 @@ var In = class {
2291
2373
  return;
2292
2374
  }
2293
2375
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
2294
- if (this.networkRecoveries < Ht) {
2376
+ if (this.networkRecoveries < qt) {
2295
2377
  this.networkRecoveries += 1;
2296
2378
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
2297
2379
  this.networkRetryTimer = setTimeout(() => {
@@ -2308,7 +2390,7 @@ var In = class {
2308
2390
  return;
2309
2391
  }
2310
2392
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
2311
- if (this.mediaRecoveries < Vt) {
2393
+ if (this.mediaRecoveries < Kt) {
2312
2394
  this.mediaRecoveries += 1, n.recoverMediaError();
2313
2395
  return;
2314
2396
  }
@@ -2329,18 +2411,18 @@ var In = class {
2329
2411
  }
2330
2412
  }
2331
2413
  toError(t, r = "PLAYBACK") {
2332
- let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(Dt(t.networkDetails)) : void 0;
2414
+ let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(kt(t.networkDetails)) : void 0;
2333
2415
  return new n(r === "DRM" ? a(o, l) : o === 401 ? "UNAUTHORIZED" : o === 403 ? "FORBIDDEN" : "INTERNAL", o, `${r} error: ${s}${c ? ` (${c})` : ""}`, l ? { serverCode: l } : void 0);
2334
2416
  }
2335
- }, Ln = 15e3, Rn = 6e5, zn = 3e5, Bn = 100, J = 1, Vn = 1e3, Hn = 3e4, Un = 1e3, Wn = {
2417
+ }, Hn = 15e3, Un = 6e5, Wn = 3e5, Gn = 100, Y = 1, Kn = 1e3, qn = 3e4, Jn = 1e3, Yn = {
2336
2418
  inline: "PRESENTATION_INLINE",
2337
2419
  fullscreen: "PRESENTATION_FULLSCREEN",
2338
2420
  pip: "PRESENTATION_PIP"
2339
- }, Gn = {
2421
+ }, Xn = {
2340
2422
  widevine: "KEY_SYSTEM_WIDEVINE",
2341
2423
  fairplay: "KEY_SYSTEM_FAIRPLAY",
2342
2424
  none: "KEY_SYSTEM_NONE"
2343
- }, Kn = /* @__PURE__ */ new Set([
2425
+ }, Zn = /* @__PURE__ */ new Set([
2344
2426
  "INVALID_URN",
2345
2427
  "NOT_FOUND",
2346
2428
  "GEO_DENIED",
@@ -2351,7 +2433,7 @@ var In = class {
2351
2433
  "FORBIDDEN",
2352
2434
  "RATE_LIMITED",
2353
2435
  "TIMEOUT"
2354
- ]), Y = {
2436
+ ]), X = {
2355
2437
  idle: "PLAYER_STATE_IDLE",
2356
2438
  waiting: "PLAYER_STATE_WAITING",
2357
2439
  loading: "PLAYER_STATE_LOADING",
@@ -2361,7 +2443,7 @@ var In = class {
2361
2443
  ended: "PLAYER_STATE_ENDED",
2362
2444
  error: "PLAYER_STATE_ERROR"
2363
2445
  };
2364
- function qn(e) {
2446
+ function Qn(e) {
2365
2447
  try {
2366
2448
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
2367
2449
  return !n || r.length === 0 || n !== "feed" && !n.startsWith("feed-") ? void 0 : (t.hostname = [n.replace(/^feed/, "beacons"), ...r].join("."), t.pathname = "", t.search = "", t.origin);
@@ -2369,8 +2451,8 @@ function qn(e) {
2369
2451
  return;
2370
2452
  }
2371
2453
  }
2372
- var Jn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Yn = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), Z = /* @__PURE__ */ new Set(), Xn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2373
- function Zn(e) {
2454
+ var $n = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), er = /* @__PURE__ */ new Set(), Z = /* @__PURE__ */ new Set(), Q = /* @__PURE__ */ new Set(), tr = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2455
+ function nr(e) {
2374
2456
  if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
2375
2457
  let t;
2376
2458
  try {
@@ -2379,19 +2461,19 @@ function Zn(e) {
2379
2461
  } catch {
2380
2462
  return;
2381
2463
  }
2382
- if (Yn.has(t) && !X.has(t)) {
2383
- X.add(t), _(Xn(new URL(t).origin));
2384
- for (let e of Z) e.noteCspBlocked();
2464
+ if (er.has(t) && !Z.has(t)) {
2465
+ Z.add(t), _(tr(new URL(t).origin));
2466
+ for (let e of Q) e.noteCspBlocked();
2385
2467
  }
2386
2468
  }
2387
- function Qn(e, t) {
2469
+ function rr(e, t) {
2388
2470
  return _(t, e), { disabledReason: t };
2389
2471
  }
2390
- function $n(e, t, n) {
2391
- if (n) return t && !Jn(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2472
+ function ir(e, t, n) {
2473
+ if (n) return t && !$n(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2392
2474
  if (t) return { endpoint: t };
2393
- if (t !== void 0) return Qn("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).");
2394
- let r = qn(e);
2475
+ if (t !== void 0) return rr("empty-endpoint", "analytics is disabled: no QoE beacons will be sent. analytics.endpoint was supplied but empty. Pass a real beacons origin, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, or omit the option to derive it from baseUrl (or analytics: false to opt out).");
2476
+ let r = Qn(e);
2395
2477
  if (r) return { endpoint: r };
2396
2478
  let i;
2397
2479
  try {
@@ -2399,9 +2481,9 @@ function $n(e, t, n) {
2399
2481
  } catch {
2400
2482
  i = e;
2401
2483
  }
2402
- return Qn(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).`);
2484
+ return rr(i, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${i}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
2403
2485
  }
2404
- var er = class {
2486
+ var ar = class {
2405
2487
  opts;
2406
2488
  url;
2407
2489
  cspKey;
@@ -2483,8 +2565,8 @@ var er = class {
2483
2565
  constructor(e) {
2484
2566
  this.opts = {
2485
2567
  ...e,
2486
- heartbeatMs: e.heartbeatMs ?? Ln,
2487
- idleMs: e.idleMs ?? Rn
2568
+ heartbeatMs: e.heartbeatMs ?? Hn,
2569
+ idleMs: e.idleMs ?? Un
2488
2570
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
2489
2571
  try {
2490
2572
  let e = new URL(this.url);
@@ -2501,11 +2583,11 @@ var er = class {
2501
2583
  sdkVersion: this.opts.sdkVersion,
2502
2584
  ...this.opts.environment
2503
2585
  };
2504
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Vn), 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 && Yn.add(this.cspKey), document.addEventListener("securitypolicyviolation", Zn), Z.add(this), this.noteCspBlocked(), this.onVisibility());
2586
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Kn), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.cspKey && er.add(this.cspKey), document.addEventListener("securitypolicyviolation", nr), Q.add(this), this.noteCspBlocked(), this.onVisibility());
2505
2587
  }
2506
2588
  checkSuspension(e) {
2507
2589
  if (this.endedFlag || !this.opts.idleMs) return !1;
2508
- let t = Math.max(this.opts.idleMs, zn);
2590
+ let t = Math.max(this.opts.idleMs, Wn);
2509
2591
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
2510
2592
  }
2511
2593
  syncIdle(e) {
@@ -2519,21 +2601,21 @@ var er = class {
2519
2601
  noteStateChange(e, t, n, r) {
2520
2602
  if (this.endedFlag || e === t) return;
2521
2603
  let i = this.now();
2522
- if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(J, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(J, 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") {
2604
+ if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(Y, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(Y, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
2523
2605
  this.stallIsSeekInduced = this.seekInduced(i);
2524
2606
  let e = !this.isHidden && !this.stallIsSeekInduced;
2525
- e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(J, Math.round(this.playingTotalMs)));
2607
+ e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(Y, Math.round(this.playingTotalMs)));
2526
2608
  } else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
2527
2609
  this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
2528
2610
  let a = {
2529
- fromState: Y[e] ?? "PLAYER_STATE_UNSPECIFIED",
2530
- toState: Y[t] ?? "PLAYER_STATE_UNSPECIFIED",
2531
- presentation: Wn[this.presentation]
2611
+ fromState: X[e] ?? "PLAYER_STATE_UNSPECIFIED",
2612
+ toState: X[t] ?? "PLAYER_STATE_UNSPECIFIED",
2613
+ presentation: Yn[this.presentation]
2532
2614
  }, o = this.causeOf(e, t, i);
2533
2615
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
2534
2616
  }
2535
2617
  seekInduced(e) {
2536
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < Un;
2618
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < Jn;
2537
2619
  }
2538
2620
  causeOf(e, t, n) {
2539
2621
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -2570,25 +2652,25 @@ var er = class {
2570
2652
  }
2571
2653
  this.muteChanges += 1;
2572
2654
  let r = this.now();
2573
- n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(J, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
2655
+ n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(Y, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
2574
2656
  }
2575
2657
  notePresentation(e) {
2576
2658
  this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
2577
2659
  }
2578
2660
  notePlayIntent() {
2579
- this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = J), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = J), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = J), this.drmSetupMs > 0 && (this.drmSetupMs = J));
2661
+ this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = Y), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = Y), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = Y), this.drmSetupMs > 0 && (this.drmSetupMs = Y));
2580
2662
  }
2581
2663
  noteReady() {
2582
- this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(J, this.now() - this.startupAnchorMs));
2664
+ this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(Y, this.now() - this.startupAnchorMs));
2583
2665
  }
2584
2666
  noteFirstPlaylist() {
2585
- this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(J, this.now() - this.startupAnchorMs));
2667
+ this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(Y, this.now() - this.startupAnchorMs));
2586
2668
  }
2587
2669
  noteDrmReady() {
2588
- this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(J, this.now() - this.startupAnchorMs));
2670
+ this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(Y, this.now() - this.startupAnchorMs));
2589
2671
  }
2590
2672
  noteFirstBytes() {
2591
- this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(J, this.now() - this.startupAnchorMs));
2673
+ this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(Y, this.now() - this.startupAnchorMs));
2592
2674
  }
2593
2675
  noteSeek() {
2594
2676
  this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
@@ -2607,7 +2689,7 @@ var er = class {
2607
2689
  let r = n ?? "";
2608
2690
  if (r !== "") return /^fragLoad/i.test(r) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /^(manifest|level|audioTrack|subtitleTrack)/i.test(r) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(r) ? "ERROR_STAGE_DRM" : /parsing|append|buffer|remux|decrypt|media/i.test(r) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
2609
2691
  if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
2610
- if (Kn.has(e)) return "ERROR_STAGE_RESOLVE";
2692
+ if (Zn.has(e)) return "ERROR_STAGE_RESOLVE";
2611
2693
  let i = t ?? "";
2612
2694
  return /frag|segment/i.test(i) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /manifest|level|playlist/i.test(i) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(i) ? "ERROR_STAGE_DRM" : /buffer|decode|media|append/i.test(i) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
2613
2695
  }
@@ -2639,7 +2721,7 @@ var er = class {
2639
2721
  let l = t.droppedFrames ?? 0;
2640
2722
  l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
2641
2723
  let u = t.renditionSwitches ?? 0;
2642
- u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = Y[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
2724
+ u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = X[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
2643
2725
  let d = this.mutedTotalMs;
2644
2726
  this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
2645
2727
  let f = t.upshifts ?? 0;
@@ -2654,20 +2736,20 @@ var er = class {
2654
2736
  if (this.lastRequestCount = g, _ > 0) {
2655
2737
  o.requestCountDelta = _;
2656
2738
  let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
2657
- n.length > 0 && (o.requestTimeP50Ms = K(n, 50), o.requestTimeP95Ms = K(n, 95));
2739
+ n.length > 0 && (o.requestTimeP50Ms = q(n, 50), o.requestTimeP95Ms = q(n, 95));
2658
2740
  }
2659
2741
  typeof t.latencySeconds == "number" && typeof t.targetLatencySeconds == "number" && (o.driftMs = Math.round((t.latencySeconds - t.targetLatencySeconds) * 1e3)), typeof t.playbackRate == "number" && t.playbackRate > 0 && (o.playbackRate = t.playbackRate), t.qualityPinned === !0 && (o.qualityPinned = !0), t.cdnHost && (o.cdnHost = t.cdnHost), this.maybeEmitMediaInfo(t), this.enqueue({ heartbeat: o }), this.flush(), s > 0 && this.noteFirstBytes();
2660
2742
  }
2661
2743
  maybeEmitMediaInfo(e) {
2662
2744
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
2663
2745
  let t = {};
2664
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Gn[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);
2746
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Xn[e.keySystem]), e.drmSecurityLevel && (t.drmSecurityLevel = e.drmSecurityLevel), e.ladderHeights?.length && (t.ladderHeights = e.ladderHeights), e.ladderTopBitrateKbps && (t.ladderTopBitrateKbps = e.ladderTopBitrateKbps), e.lowLatency && (t.lowLatency = !0);
2665
2747
  let n = JSON.stringify(t);
2666
2748
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
2667
2749
  }
2668
2750
  end(e, t) {
2669
2751
  if (this.endedFlag) return;
2670
- this.endedFlag = !0, Z.delete(this);
2752
+ this.endedFlag = !0, Q.delete(this);
2671
2753
  let n = t ?? this.now();
2672
2754
  this.playingSinceMs !== null && (this.playingTotalMs += n - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += n - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += n - this.bufferingSinceMs, this.bufferingSinceMs = null), this.mutedSinceMs !== null && (this.mutedTotalMs += n - this.mutedSinceMs, this.mutedSinceMs = null), this.waitingSinceMs !== null && (this.waitingTotalMs += n - this.waitingSinceMs, this.waitingSinceMs = null), this.isPlaying = !1, this.syncActive(n), this.closePresentation(n), this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.timer &&= (clearInterval(this.timer), null), this.idleTimer &&= (clearTimeout(this.idleTimer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), document.removeEventListener("freeze", this.onFreeze), document.removeEventListener("resume", this.onResume));
2673
2755
  let r = this.safeSample();
@@ -2681,7 +2763,7 @@ var er = class {
2681
2763
  let c = r?.positionMs ?? 0;
2682
2764
  c > 0 && (i.exitPositionMs = Math.round(c)), this.activeTotalMs > 0 && (i.activeWatchTimeMs = Math.round(this.activeTotalMs)), this.mutedTotalMs > 0 && (i.mutedTimeMs = Math.round(this.mutedTotalMs));
2683
2765
  let l = e !== "END_REASON_ENDED";
2684
- l && this.lastStallMs > 0 && n - this.lastStallMs <= Hn && (i.abandonAfterStallMs = Math.max(J, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Hn && (i.abandonAfterErrorMs = Math.max(J, 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);
2766
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= qn && (i.abandonAfterStallMs = Math.max(Y, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= qn && (i.abandonAfterErrorMs = Math.max(Y, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
2685
2767
  let u = r?.decodedFrames ?? this.lastDecoded;
2686
2768
  u > 0 && (i.decodedFramesTotal = u), e === "END_REASON_STOPPED" && this.startupTimeMs === 0 && this.lastErrorStage === null && (e = "END_REASON_ABORTED", i.reason = e), this.startupTimeMs === 0 && e !== "END_REASON_ABORTED" && (i.failedStage = this.lastErrorStage ?? (this.manifestLoadMs === 0 ? "ERROR_STAGE_MANIFEST" : this.firstFragLoadMs === 0 ? "ERROR_STAGE_FIRST_SEGMENT" : "ERROR_STAGE_OTHER")), this.pending.push(this.wrap({ sessionEnd: i })), this.flush(e === "END_REASON_PAGEHIDE");
2687
2769
  }
@@ -2701,13 +2783,13 @@ var er = class {
2701
2783
  };
2702
2784
  }
2703
2785
  noteCspBlocked() {
2704
- this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(Xn(new URL(this.url).origin)));
2786
+ this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(tr(new URL(this.url).origin)));
2705
2787
  }
2706
2788
  cspBlocked() {
2707
- return !!this.cspKey && X.has(this.cspKey);
2789
+ return !!this.cspKey && Z.has(this.cspKey);
2708
2790
  }
2709
2791
  enqueue(e) {
2710
- if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Bn;) {
2792
+ if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Gn;) {
2711
2793
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
2712
2794
  this.pending.splice(e >= 0 ? e : 0, 1);
2713
2795
  }
@@ -2734,7 +2816,7 @@ var er = class {
2734
2816
  };
2735
2817
  //#endregion
2736
2818
  //#region src/core/environment.ts
2737
- function tr() {
2819
+ function or() {
2738
2820
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
2739
2821
  let e;
2740
2822
  try {
@@ -2759,14 +2841,14 @@ function tr() {
2759
2841
  integration: "INTEGRATION_KIND_IFRAME"
2760
2842
  };
2761
2843
  }
2762
- function nr() {
2844
+ function sr() {
2763
2845
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
2764
2846
  let e = navigator.userAgentData, t = e?.platform ?? "";
2765
2847
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
2766
2848
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
2767
2849
  return e?.mobile ?? (typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1 && n > 0 && n < 900) ? n >= 600 ? "DEVICE_CLASS_TABLET" : "DEVICE_CLASS_PHONE" : e || n >= 900 || /mac|win|linux|chrome os/i.test(t) ? "DEVICE_CLASS_DESKTOP" : "DEVICE_CLASS_OTHER";
2768
2850
  }
2769
- function rr() {
2851
+ function cr() {
2770
2852
  let e = typeof navigator < "u" ? navigator.connection : void 0;
2771
2853
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
2772
2854
  let t = {
@@ -2785,17 +2867,17 @@ function rr() {
2785
2867
  }
2786
2868
  return typeof e.downlink == "number" && e.downlink > 0 && (i.downlinkKbps = Math.round(e.downlink * 1e3)), typeof e.rtt == "number" && e.rtt > 0 && (i.rttMs = Math.round(e.rtt)), e.saveData && (i.saveData = !0), i;
2787
2869
  }
2788
- function ir(e) {
2789
- let t = tr(), n = {
2790
- deviceClass: nr(),
2870
+ function lr(e) {
2871
+ let t = or(), n = {
2872
+ deviceClass: sr(),
2791
2873
  integration: t.integration,
2792
- ...rr()
2874
+ ...cr()
2793
2875
  };
2794
2876
  t.host && (n.host = t.host), typeof screen < "u" && screen.width > 0 && (n.screenWidth = screen.width, n.screenHeight = screen.height), typeof window < "u" && window.devicePixelRatio > 0 && (n.devicePixelRatio = Math.round(window.devicePixelRatio * 100) / 100);
2795
2877
  let r = e.getBoundingClientRect?.();
2796
2878
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
2797
2879
  }
2798
- async function ar() {
2880
+ async function ur() {
2799
2881
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
2800
2882
  if (!e?.getHighEntropyValues) return {};
2801
2883
  try {
@@ -2807,7 +2889,7 @@ async function ar() {
2807
2889
  }
2808
2890
  //#endregion
2809
2891
  //#region src/core/version.ts
2810
- var or = "2.23.3", sr = {
2892
+ var dr = "2.24.0", fr = {
2811
2893
  accent: "#E1B600",
2812
2894
  accentText: "#1B1C23",
2813
2895
  background: "#0e0f13",
@@ -2818,7 +2900,7 @@ var or = "2.23.3", sr = {
2818
2900
  border: "rgba(255, 255, 255, 0.1)",
2819
2901
  radius: "8px",
2820
2902
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
2821
- }, cr = {
2903
+ }, pr = {
2822
2904
  accent: "--havik-accent",
2823
2905
  accentText: "--havik-accent-text",
2824
2906
  background: "--havik-bg",
@@ -2830,26 +2912,26 @@ var or = "2.23.3", sr = {
2830
2912
  radius: "--havik-radius",
2831
2913
  fontFamily: "--havik-font"
2832
2914
  };
2833
- function lr(e, t) {
2915
+ function mr(e, t) {
2834
2916
  let n = {
2835
- ...sr,
2917
+ ...fr,
2836
2918
  ...t
2837
2919
  };
2838
- for (let t of Object.keys(cr)) e.style.setProperty(cr[t], n[t]);
2920
+ for (let t of Object.keys(pr)) e.style.setProperty(pr[t], n[t]);
2839
2921
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
2840
2922
  }
2841
2923
  //#endregion
2842
2924
  //#region src/ui/styles.ts
2843
- var ur = "havik-player-styles", dr = "\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", fr = /* @__PURE__ */ new WeakMap();
2844
- function pr(e = document, t) {
2845
- let n = e.querySelector(`style#${ur}`);
2846
- if (n && (!t || fr.get(n) === t)) return;
2925
+ var hr = "havik-player-styles", gr = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", _r = /* @__PURE__ */ new WeakMap();
2926
+ function vr(e = document, t) {
2927
+ let n = e.querySelector(`style#${hr}`);
2928
+ if (n && (!t || _r.get(n) === t)) return;
2847
2929
  let r = e.createElement("style");
2848
- r.id = ur, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = dr, fr.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2930
+ r.id = hr, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = gr, _r.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2849
2931
  }
2850
2932
  //#endregion
2851
2933
  //#region src/ui/icons.ts
2852
- var mr = {
2934
+ var yr = {
2853
2935
  play: "<path d=\"M8 5v14l11-7z\"/>",
2854
2936
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
2855
2937
  volumeHigh: "<path d=\"M3 10v4h4l5 5V5L7 10H3zm13.5 2a4.5 4.5 0 0 0-2.5-4v8a4.5 4.5 0 0 0 2.5-4zm-2.5-9v2.06A7 7 0 0 1 14 19v2a9 9 0 0 0 0-18z\"/>",
@@ -2862,12 +2944,12 @@ var mr = {
2862
2944
  liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
2863
2945
  retry: "<path d=\"M17.65 6.35A8 8 0 1 0 19.73 13h-2.08A6 6 0 1 1 12 6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"/>"
2864
2946
  };
2865
- function Q(e) {
2866
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${mr[e]}</svg>`;
2947
+ function $(e) {
2948
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${yr[e]}</svg>`;
2867
2949
  }
2868
2950
  //#endregion
2869
2951
  //#region src/ui/controls.ts
2870
- var hr = 3e3, gr = 250, _r = /* @__PURE__ */ new Set([
2952
+ var br = 3e3, xr = 250, Sr = /* @__PURE__ */ new Set([
2871
2953
  "GONE",
2872
2954
  "NOT_FOUND",
2873
2955
  "GEO_DENIED",
@@ -2875,15 +2957,15 @@ var hr = 3e3, gr = 250, _r = /* @__PURE__ */ new Set([
2875
2957
  "UNAUTHORIZED",
2876
2958
  "DRM_DEVICE_REVOKED"
2877
2959
  ]);
2878
- function vr(e) {
2960
+ function Cr(e) {
2879
2961
  let t = "This match isn't available in your country";
2880
2962
  return e ? `${t} (${e})` : t;
2881
2963
  }
2882
- var yr = "This device can't play protected video";
2883
- function br(e) {
2884
- return new xr(e);
2964
+ var wr = "This device can't play protected video";
2965
+ function Tr(e) {
2966
+ return new Er(e);
2885
2967
  }
2886
- var xr = class {
2968
+ var Er = class {
2887
2969
  root;
2888
2970
  video;
2889
2971
  player;
@@ -2931,7 +3013,7 @@ var xr = class {
2931
3013
  scrubbing = !1;
2932
3014
  offFns = [];
2933
3015
  constructor(e) {
2934
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? hr, 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, pr(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");
3016
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? br, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, vr(this.doc, e.cspNonce), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
2935
3017
  let t = (e, t, n) => {
2936
3018
  let r = this.doc.createElement(e);
2937
3019
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -2942,12 +3024,12 @@ var xr = class {
2942
3024
  "aria-label": r,
2943
3025
  title: r
2944
3026
  });
2945
- return i.innerHTML = Q(n), i;
3027
+ return i.innerHTML = $(n), i;
2946
3028
  };
2947
3029
  this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
2948
3030
  type: "button",
2949
3031
  "aria-label": "Play"
2950
- }), this.center.innerHTML = Q("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", {
3032
+ }), this.center.innerHTML = $("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
2951
3033
  role: "slider",
2952
3034
  "aria-label": "Seek",
2953
3035
  "aria-valuemin": "0",
@@ -2965,7 +3047,7 @@ var xr = class {
2965
3047
  "aria-label": "Volume"
2966
3048
  });
2967
3049
  let a = t("div", "havik-vol");
2968
- a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Q("liveDot");
3050
+ a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = $("liveDot");
2969
3051
  let o = this.doc.createElement("span");
2970
3052
  o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
2971
3053
  let s = t("div", "havik-spacer");
@@ -3017,7 +3099,7 @@ var xr = class {
3017
3099
  let t = this.surfaceWasHidden;
3018
3100
  this.tapTimer = setTimeout(() => {
3019
3101
  this.tapTimer = void 0, this.toggleBar(t);
3020
- }, gr);
3102
+ }, xr);
3021
3103
  }
3022
3104
  toggleBar(e) {
3023
3105
  e ? this.poke() : this.hideIfIdle();
@@ -3037,7 +3119,7 @@ var xr = class {
3037
3119
  this.statusOverlays && (e === "ended" ? t = "ended" : e === "error" ? t = "error" : e === "waiting" ? t = "waiting" : !this.hasPlayed && (e === "idle" || e === "paused") && (t = "preplay")), this.renderStatus(t);
3038
3120
  }
3039
3121
  statusMessageFor(e) {
3040
- return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? vr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? yr : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
3122
+ return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? Cr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? wr : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
3041
3123
  }
3042
3124
  renderStatus(e) {
3043
3125
  let t = this.statusMessageFor(e);
@@ -3049,12 +3131,12 @@ var xr = class {
3049
3131
  }
3050
3132
  if (e === "preplay") {
3051
3133
  let e = this.doc.createElement("button");
3052
- e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Q("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
3134
+ e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = $("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
3053
3135
  } else {
3054
3136
  let r = this.doc.createElement("div");
3055
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !_r.has(this.lastError.code)) {
3137
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Sr.has(this.lastError.code)) {
3056
3138
  let e = this.doc.createElement("button");
3057
- e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Q("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
3139
+ e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${$("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
3058
3140
  }
3059
3141
  }
3060
3142
  this.root.append(n), this.statusBox = n, this.show();
@@ -3093,7 +3175,7 @@ var xr = class {
3093
3175
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
3094
3176
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
3095
3177
  }
3096
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Sr(this.video.currentTime)} / ${Sr(this.video.duration)}`);
3178
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Dr(this.video.currentTime)} / ${Dr(this.video.duration)}`);
3097
3179
  }
3098
3180
  syncLive() {
3099
3181
  let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
@@ -3143,17 +3225,17 @@ var xr = class {
3143
3225
  renderQualityMenu() {
3144
3226
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
3145
3227
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
3146
- for (let n of e) this.menu.append(this.menuItem(Cr(n), t === n.index, () => this.player.setQuality(n.index)));
3228
+ for (let n of e) this.menu.append(this.menuItem(Or(n), t === n.index, () => this.player.setQuality(n.index)));
3147
3229
  }
3148
3230
  renderAudioMenu() {
3149
3231
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
3150
3232
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
3151
- for (let t of e) this.menu.append(this.menuItem(wr(t), t.default, () => this.player.setAudioTrack(t.id)));
3233
+ for (let t of e) this.menu.append(this.menuItem(kr(t), t.default, () => this.player.setAudioTrack(t.id)));
3152
3234
  }
3153
3235
  renderCcMenu() {
3154
3236
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
3155
3237
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
3156
- for (let t of e) this.menu.append(this.menuItem(Tr(t), !1, () => this.player.setTextTrack(t.id)));
3238
+ for (let t of e) this.menu.append(this.menuItem(Ar(t), !1, () => this.player.setTextTrack(t.id)));
3157
3239
  }
3158
3240
  onTracksChanged() {
3159
3241
  this.openMenu && this.renderMenu(this.openMenu);
@@ -3241,7 +3323,7 @@ var xr = class {
3241
3323
  }
3242
3324
  }
3243
3325
  setIcon(e, t) {
3244
- e.innerHTML = Q(t);
3326
+ e.innerHTML = $(t);
3245
3327
  }
3246
3328
  destroy() {
3247
3329
  this.hideTimer && clearTimeout(this.hideTimer), this.tapTimer && clearTimeout(this.tapTimer);
@@ -3258,41 +3340,41 @@ var xr = class {
3258
3340
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
3259
3341
  }
3260
3342
  };
3261
- function Sr(e) {
3343
+ function Dr(e) {
3262
3344
  (!Number.isFinite(e) || e < 0) && (e = 0);
3263
3345
  let t = Math.floor(e % 60), n = Math.floor(e / 60 % 60), r = Math.floor(e / 3600), i = r > 0 ? String(n).padStart(2, "0") : String(n), a = String(t).padStart(2, "0");
3264
3346
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
3265
3347
  }
3266
- function Cr(e) {
3348
+ function Or(e) {
3267
3349
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
3268
3350
  }
3269
- function wr(e) {
3351
+ function kr(e) {
3270
3352
  return e.name || e.lang || `Track ${e.id}`;
3271
3353
  }
3272
- function Tr(e) {
3354
+ function Ar(e) {
3273
3355
  return e.name || e.lang || `Track ${e.id}`;
3274
3356
  }
3275
3357
  //#endregion
3276
3358
  //#region src/managed/index.ts
3277
- var Er = 6e3, Dr = 45e3, Or = 2e3, kr = 3, Ar = 5e3, jr = 2e3, Mr = 48e4, Nr = "keySystemLicenseRequestFailed";
3278
- function Pr(e) {
3359
+ var jr = 6e3, Mr = 45e3, Nr = 2e3, Pr = 3, Fr = 5e3, Ir = 2e3, Lr = 48e4, Rr = "keySystemLicenseRequestFailed";
3360
+ function zr(e) {
3279
3361
  if (e.env !== void 0 && e.baseUrl !== void 0) throw new n("INTERNAL", 0, `createPlayer: pass env OR baseUrl, not both (got env=${JSON.stringify(e.env)} and baseUrl=${JSON.stringify(e.baseUrl)})`);
3280
- if (e.env !== void 0) return at(e.env);
3362
+ if (e.env !== void 0) return st(e.env);
3281
3363
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
3282
3364
  return e.baseUrl;
3283
3365
  }
3284
- async function Fr(e) {
3366
+ async function Br(e) {
3285
3367
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
3286
- let t = Pr(e);
3368
+ let t = zr(e);
3287
3369
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
3288
3370
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
3289
- let r = new Ir({
3371
+ let r = new Vr({
3290
3372
  ...e,
3291
3373
  baseUrl: t
3292
3374
  });
3293
3375
  return await r.start(), r;
3294
3376
  }
3295
- var Ir = class {
3377
+ var Vr = class {
3296
3378
  opts;
3297
3379
  abort = new AbortController();
3298
3380
  listeners = {};
@@ -3366,7 +3448,7 @@ var Ir = class {
3366
3448
  };
3367
3449
  }
3368
3450
  beginArming(e, t, n = !1) {
3369
- let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
3451
+ let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
3370
3452
  r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
3371
3453
  }
3372
3454
  beginArmingByPolling(e) {
@@ -3387,7 +3469,7 @@ var Ir = class {
3387
3469
  setTimeout(() => {
3388
3470
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
3389
3471
  phase: i ? "unavailable" : "tooEarly",
3390
- retryInMs: Dr,
3472
+ retryInMs: Mr,
3391
3473
  attempt: 1,
3392
3474
  elapsedMs: 0,
3393
3475
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -3426,13 +3508,13 @@ var Ir = class {
3426
3508
  !a && !p() && h();
3427
3509
  }, e);
3428
3510
  };
3429
- _(Er), this.armingSub = E({
3511
+ _(jr), this.armingSub = D({
3430
3512
  eventsBaseUrl: t,
3431
3513
  matchUrn: this.opts.matchUrn,
3432
3514
  credential: this.opts.credential,
3433
- onAlive: () => _(Dr),
3515
+ onAlive: () => _(Mr),
3434
3516
  onState: (e) => {
3435
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Or);
3517
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Nr);
3436
3518
  },
3437
3519
  onError: () => h()
3438
3520
  });
@@ -3455,7 +3537,7 @@ var Ir = class {
3455
3537
  let n = await c(this.opts.credential);
3456
3538
  if (this.destroyed || t !== this.loadGen) return;
3457
3539
  this.setState("loading");
3458
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = dt(this.opts.video, (e) => {
3540
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = pt(this.opts.video, (e) => {
3459
3541
  this._state !== "ended" && this._state !== "error" && this.setState(e);
3460
3542
  });
3461
3543
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -3477,26 +3559,26 @@ var Ir = class {
3477
3559
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
3478
3560
  let i = e.analytics?.sid;
3479
3561
  if (!i) return;
3480
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = $n(this.opts.baseUrl, a, e.analytics?.endpoint);
3562
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = ir(this.opts.baseUrl, a, e.analytics?.endpoint);
3481
3563
  if (!o) {
3482
3564
  s && setTimeout(() => {
3483
3565
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
3484
3566
  }, 0);
3485
3567
  return;
3486
3568
  }
3487
- let c = this.opts.video, l = new er({
3569
+ let c = this.opts.video, l = new ar({
3488
3570
  endpoint: o,
3489
3571
  sid: i,
3490
3572
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
3491
- sdkVersion: or,
3492
- environment: ir(c),
3573
+ sdkVersion: dr,
3574
+ environment: lr(c),
3493
3575
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
3494
3576
  onIdle: () => this.onAnalyticsIdle(t),
3495
3577
  onBlocked: (e) => setTimeout(() => {
3496
3578
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
3497
3579
  }, 0),
3498
3580
  sample: () => {
3499
- let e = this.engine?.getStats() ?? ot, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
3581
+ let e = this.engine?.getStats() ?? ct, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
3500
3582
  return {
3501
3583
  ...e,
3502
3584
  bufferedMs: Math.round(t * 1e3),
@@ -3510,7 +3592,7 @@ var Ir = class {
3510
3592
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
3511
3593
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
3512
3594
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
3513
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), ar().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3595
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), ur().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3514
3596
  }
3515
3597
  currentPresentation() {
3516
3598
  let e = this.opts.video;
@@ -3525,7 +3607,7 @@ var Ir = class {
3525
3607
  video: this.opts.video,
3526
3608
  descriptor: e,
3527
3609
  credential: t,
3528
- deviceId: A(),
3610
+ deviceId: j(),
3529
3611
  userId: this.opts.userId,
3530
3612
  lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
3531
3613
  snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
@@ -3534,6 +3616,7 @@ var Ir = class {
3534
3616
  adaptiveHoldBack: this.opts.adaptiveHoldBack,
3535
3617
  adaptiveHoldBackCeiling: this.opts.adaptiveHoldBackCeiling,
3536
3618
  mediaDuringKey: this.opts.mediaDuringKey,
3619
+ preloadHints: this.opts.preloadHints,
3537
3620
  debug: this.opts.debug,
3538
3621
  deferLoad: r,
3539
3622
  hlsConfig: i,
@@ -3541,9 +3624,9 @@ var Ir = class {
3541
3624
  freshLicenseUrl: () => this.refreshLicense()
3542
3625
  }, o = this.opts.engine ?? "auto";
3543
3626
  if (o === "native") return new U(a);
3544
- if (o === "hls") return new In(a);
3545
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && V(this.opts.video) && H() || !e.drmEnabled && Ct() && V(this.opts.video)) return new U(a);
3546
- if (Lt()) return new In(a);
3627
+ if (o === "hls") return new Vn(a);
3628
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && V(this.opts.video) && H() || !e.drmEnabled && Tt() && V(this.opts.video)) return new U(a);
3629
+ if (Vt()) return new Vn(a);
3547
3630
  if (V(this.opts.video)) return new U(a);
3548
3631
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
3549
3632
  }
@@ -3594,11 +3677,11 @@ var Ir = class {
3594
3677
  }
3595
3678
  startLiveState(e) {
3596
3679
  if (this.opts.liveStateEvents === !1) return;
3597
- let t = this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
3680
+ let t = this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
3598
3681
  if (!t) return;
3599
3682
  this.closeLiveState();
3600
- let r = 0, i = !1;
3601
- this.liveStateSub = E({
3683
+ let i = 0, a = !1;
3684
+ this.liveStateSub = D({
3602
3685
  eventsBaseUrl: t,
3603
3686
  matchUrn: this.opts.matchUrn,
3604
3687
  credential: this.opts.credential,
@@ -3606,10 +3689,16 @@ var Ir = class {
3606
3689
  this.destroyed || e !== this.loadGen || (t.state === "gone" ? this.onStreamEnded(!0, t.reason ?? "match_ended") : t.state === "ended" ? this.onStreamEnded(!1, t.reason) : t.state === "live" && this.endedHandled && this.scheduleRejoin(e));
3607
3690
  },
3608
3691
  onAlive: () => {
3609
- r = 0, i = !1;
3692
+ i = 0, a = !1;
3610
3693
  },
3611
- onError: () => {
3612
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= kr && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
3694
+ onError: (o) => {
3695
+ if (!(this.destroyed || e !== this.loadGen || a) && !this.endedHandled) {
3696
+ if (o instanceof E && (o.terminal || o.status === 404)) {
3697
+ a = !0, this.emit("warning", new n(r(o.status), o.status, `live-state events answered HTTP ${o.status} for ${this.opts.matchUrn}: the match is ` + (o.terminal ? "gone, so the subscription stopped" : "not in the catalog (ended and dropped, or not listed yet), so it retries every 5 min") + " — end-of-stream detection falls back to the HLS staleness watchdog."));
3698
+ return;
3699
+ }
3700
+ i += 1, i >= Pr && (a = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${i} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`)));
3701
+ }
3613
3702
  }
3614
3703
  });
3615
3704
  }
@@ -3623,7 +3712,7 @@ var Ir = class {
3623
3712
  return;
3624
3713
  }
3625
3714
  let e = this.hiddenAtMs;
3626
- this.hiddenAtMs = null, e != null && Date.now() - e >= Ar && this.resyncLiveState();
3715
+ this.hiddenAtMs = null, e != null && Date.now() - e >= Fr && this.resyncLiveState();
3627
3716
  }, this.onReturnPageShow = (e) => {
3628
3717
  e.persisted && this.resyncLiveState();
3629
3718
  }, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
@@ -3655,7 +3744,7 @@ var Ir = class {
3655
3744
  scheduleRejoin(e) {
3656
3745
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
3657
3746
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
3658
- }, Math.random() * Or));
3747
+ }, Math.random() * Nr));
3659
3748
  }
3660
3749
  cancelRejoin() {
3661
3750
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -3679,7 +3768,7 @@ var Ir = class {
3679
3768
  }
3680
3769
  t.controls = !1;
3681
3770
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
3682
- r && r.insertBefore(n, t), n.appendChild(t), lr(n, this.opts.theme), this.container = n, this.controlBar = br({
3771
+ r && r.insertBefore(n, t), n.appendChild(t), mr(n, this.opts.theme), this.container = n, this.controlBar = Tr({
3683
3772
  root: n,
3684
3773
  video: t,
3685
3774
  player: this,
@@ -3717,7 +3806,7 @@ var Ir = class {
3717
3806
  }
3718
3807
  startStats() {
3719
3808
  this.stopStats();
3720
- let e = Math.max(500, this.opts.statsIntervalMs ?? jr);
3809
+ let e = Math.max(500, this.opts.statsIntervalMs ?? Ir);
3721
3810
  this.statsTimer = setInterval(() => {
3722
3811
  if (!this.engine) return;
3723
3812
  let e = this.engine.getStats();
@@ -3728,14 +3817,14 @@ var Ir = class {
3728
3817
  this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
3729
3818
  }
3730
3819
  isStaleLicenseDenial(e) {
3731
- return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Nr || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : G(this._descriptor?.drm?.widevine?.licenseUrl);
3820
+ return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Rr || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : G(this._descriptor?.drm?.widevine?.licenseUrl);
3732
3821
  }
3733
3822
  scheduleLicenseRefresh() {
3734
3823
  if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
3735
3824
  typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
3736
3825
  document.visibilityState !== "visible" || this.destroyed || G(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
3737
3826
  }, document.addEventListener("visibilitychange", this.onRefocus));
3738
- let e = this.opts.licenseRefreshMs ?? Mr;
3827
+ let e = this.opts.licenseRefreshMs ?? Lr;
3739
3828
  e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
3740
3829
  }
3741
3830
  stopRefresh() {
@@ -3792,7 +3881,7 @@ var Ir = class {
3792
3881
  this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
3793
3882
  }
3794
3883
  getStats() {
3795
- return this.engine?.getStats() ?? ot;
3884
+ return this.engine?.getStats() ?? ct;
3796
3885
  }
3797
3886
  getQualityLevels() {
3798
3887
  return this.engine?.getQualityLevels() ?? [];
@@ -3900,12 +3989,12 @@ var Ir = class {
3900
3989
  };
3901
3990
  //#endregion
3902
3991
  //#region src/embed/protocol.ts
3903
- function $(e) {
3992
+ function Hr(e) {
3904
3993
  return !!e && typeof e == "object" && typeof e.type == "string" && e.type.startsWith("oddin:");
3905
3994
  }
3906
3995
  //#endregion
3907
3996
  //#region src/embed/host.ts
3908
- function Lr(e) {
3997
+ function Ur(e) {
3909
3998
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
3910
3999
  if (!e.src) throw Error("mountEmbed: opts.src is required");
3911
4000
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -3914,7 +4003,7 @@ function Lr(e) {
3914
4003
  let r = document.createElement("iframe");
3915
4004
  r.src = t.toString(), r.allow = "autoplay; encrypted-media; fullscreen", r.setAttribute("allowfullscreen", ""), r.referrerPolicy = "no-referrer", r.setAttribute("sandbox", e.sandbox ?? "allow-scripts allow-same-origin allow-presentation"), r.style.cssText = "border:0;width:100%;height:100%;display:block", e.container.appendChild(r);
3916
4005
  let i = /* @__PURE__ */ new Set(), a = (t) => {
3917
- if (t.source !== r.contentWindow || t.origin !== n || !$(t.data)) return;
4006
+ if (t.source !== r.contentWindow || t.origin !== n || !Hr(t.data)) return;
3918
4007
  let a = t.data;
3919
4008
  a.type === "oddin:ready" && a.protocol !== 1 && console.warn(`havik-player: embed protocol v${a.protocol} != host v1. Pin the embed page version to the SDK version to avoid skew.`), e.onEvent?.(a), i.forEach((e) => e(a));
3920
4009
  };
@@ -3964,15 +4053,15 @@ function Lr(e) {
3964
4053
  }
3965
4054
  //#endregion
3966
4055
  //#region src/embed/page.ts
3967
- var Rr = /^[A-Za-z0-9:_.-]{1,128}$/;
3968
- function zr(e) {
4056
+ var Wr = /^[A-Za-z0-9:_.-]{1,128}$/;
4057
+ function Gr(e) {
3969
4058
  if (typeof e == "boolean") return e;
3970
4059
  if (typeof e == "object" && e) {
3971
4060
  let t = e.endpoint;
3972
4061
  return typeof t == "string" ? { endpoint: t } : {};
3973
4062
  }
3974
4063
  }
3975
- function Br() {
4064
+ function Kr() {
3976
4065
  let e = window.HAVIK_EMBED_CONFIG;
3977
4066
  if (e) return {
3978
4067
  baseUrl: e.baseUrl ?? "",
@@ -3982,7 +4071,7 @@ function Br() {
3982
4071
  autoplay: e.autoplay ?? !0,
3983
4072
  muted: e.muted ?? !0,
3984
4073
  waitForLive: e.waitForLive ?? !0,
3985
- analytics: zr(e.analytics)
4074
+ analytics: Gr(e.analytics)
3986
4075
  };
3987
4076
  let t = new URLSearchParams(location.search);
3988
4077
  return {
@@ -3995,9 +4084,9 @@ function Br() {
3995
4084
  waitForLive: !0
3996
4085
  };
3997
4086
  }
3998
- async function Vr() {
3999
- let e = Br();
4000
- Ur();
4087
+ async function qr() {
4088
+ let e = Kr();
4089
+ Yr();
4001
4090
  let t = document.createElement("video");
4002
4091
  t.setAttribute("playsinline", ""), t.muted = e.muted ?? !0, t.style.cssText = "width:100%;height:100%;object-fit:contain;background:#000;aspect-ratio:auto", document.body.appendChild(t);
4003
4092
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -4053,12 +4142,12 @@ async function Vr() {
4053
4142
  message: e.message,
4054
4143
  ...e.country === void 0 ? {} : { country: e.country }
4055
4144
  })), e.on("autoplayblocked", () => {
4056
- i({ type: "oddin:autoplayblocked" }), Hr(t, e);
4145
+ i({ type: "oddin:autoplayblocked" }), Jr(t, e);
4057
4146
  });
4058
4147
  }, s = async (r) => {
4059
4148
  a?.destroy(), a = null;
4060
4149
  try {
4061
- let n = await Fr({
4150
+ let n = await Br({
4062
4151
  video: t,
4063
4152
  baseUrl: e.baseUrl,
4064
4153
  matchUrn: r,
@@ -4121,30 +4210,30 @@ async function Vr() {
4121
4210
  a?.retry();
4122
4211
  break;
4123
4212
  case "oddin:load":
4124
- typeof e.matchUrn == "string" && Rr.test(e.matchUrn) && s(e.matchUrn);
4213
+ typeof e.matchUrn == "string" && Wr.test(e.matchUrn) && s(e.matchUrn);
4125
4214
  break;
4126
4215
  case "oddin:destroy": c();
4127
4216
  }
4128
4217
  }, u = (e) => {
4129
- r && e.origin === r && $(e.data) && l(e.data);
4218
+ r && e.origin === r && Hr(e.data) && l(e.data);
4130
4219
  };
4131
4220
  r && window.addEventListener("message", u), window.addEventListener("pagehide", c, { once: !0 }), await s(e.matchUrn), i({
4132
4221
  type: "oddin:ready",
4133
4222
  protocol: 1
4134
4223
  });
4135
4224
  }
4136
- function Hr(e, t) {
4225
+ function Jr(e, t) {
4137
4226
  if (document.getElementById("havik-tap")) return;
4138
4227
  let n = document.createElement("button");
4139
4228
  n.id = "havik-tap", n.textContent = "▶ Tap to play", n.style.cssText = "position:fixed;inset:0;width:100%;height:100%;border:0;background:rgba(0,0,0,.55);color:#fff;font:600 18px system-ui,sans-serif;cursor:pointer;z-index:9", n.addEventListener("click", () => {
4140
4229
  n.remove(), t.play();
4141
4230
  }), document.body.appendChild(n);
4142
4231
  }
4143
- function Ur() {
4232
+ function Yr() {
4144
4233
  let e = document.createElement("style");
4145
4234
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
4146
4235
  }
4147
4236
  //#endregion
4148
- export { sr as ODDIN_THEME, n as PlaybackError, lr as applyTheme, at as baseUrlForEnv, Vr as bootEmbed, Ee as clearDeviceId, Re as clearRememberedBandwidth, Fr as createPlayer, D as deriveEventsBaseUrl, tt as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, A as getDeviceId, rt as isLowLatencyManifest, $ as isOddinMessage, Oe as licenseRequestHeaders, Lr as mountEmbed, fe as pollToLive, y as resolveStream, E as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
4237
+ export { E as LiveStateHttpError, fr as ODDIN_THEME, n as PlaybackError, mr as applyTheme, st as baseUrlForEnv, qr as bootEmbed, De as clearDeviceId, ze as clearRememberedBandwidth, Br as createPlayer, O as deriveEventsBaseUrl, rt as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, j as getDeviceId, at as isLowLatencyManifest, Hr as isOddinMessage, ke as licenseRequestHeaders, Ur as mountEmbed, fe as pollToLive, y as resolveStream, D as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
4149
4238
 
4150
4239
  //# sourceMappingURL=index.js.map