@oddin-gg/havik-player 2.16.6 → 2.16.8

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
@@ -676,9 +676,9 @@ var R = {
676
676
  dv: "dvh1.05.06",
677
677
  av1: "av01.0.05M.08",
678
678
  vp9: "vp09.00.10.08"
679
- }, z = /* @__PURE__ */ new Map(), B = /* @__PURE__ */ new Map();
680
- function je(e) {
681
- let t = L(e), n = z.get(t);
679
+ }, je = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Map();
680
+ function Me(e) {
681
+ let t = L(e), n = je.get(t);
682
682
  if (n) return n;
683
683
  let r = {
684
684
  initDataTypes: ["cenc"],
@@ -696,23 +696,23 @@ function je(e) {
696
696
  } catch {
697
697
  return !1;
698
698
  }
699
- })().then((e) => (B.set(t, e), e));
700
- return z.set(t, i), i;
699
+ })().then((e) => (z.set(t, e), e));
700
+ return je.set(t, i), i;
701
701
  }
702
- function Me() {
703
- if (j()) for (let e of Object.values(R)) je(e);
702
+ function Ne() {
703
+ if (j()) for (let e of Object.values(R)) Me(e);
704
704
  }
705
- function Ne(e) {
705
+ function Pe(e) {
706
706
  let t = I(e);
707
- if (t) return t === "avc" ? !0 : B.get(L(e)) ?? B.get(L(R[t]));
707
+ if (t) return t === "avc" ? !0 : z.get(L(e)) ?? z.get(L(R[t]));
708
708
  }
709
709
  //#endregion
710
710
  //#region src/core/drm/support.ts
711
- var Pe = 5e3, Fe = "video/mp4; codecs=\"avc1.42E01E\"", Ie = "audio/mp4; codecs=\"mp4a.40.2\"", Le = {
711
+ var Fe = 5e3, Ie = "video/mp4; codecs=\"avc1.42E01E\"", Le = "audio/mp4; codecs=\"mp4a.40.2\"", Re = {
712
712
  widevine: ["com.widevine.alpha"],
713
713
  fairplay: ["com.apple.fps"]
714
714
  };
715
- function Re(e) {
715
+ function ze(e) {
716
716
  return e === "fairplay" ? [{
717
717
  initDataTypes: [
718
718
  "sinf",
@@ -720,30 +720,30 @@ function Re(e) {
720
720
  "cenc"
721
721
  ],
722
722
  videoCapabilities: [{
723
- contentType: Fe,
723
+ contentType: Ie,
724
724
  robustness: "",
725
725
  encryptionScheme: "cbcs"
726
726
  }],
727
727
  audioCapabilities: [{
728
- contentType: Ie,
728
+ contentType: Le,
729
729
  robustness: "",
730
730
  encryptionScheme: "cbcs"
731
731
  }]
732
732
  }] : N("com.widevine.alpha", [{
733
733
  initDataTypes: ["cenc"],
734
734
  videoCapabilities: [{
735
- contentType: Fe,
735
+ contentType: Ie,
736
736
  robustness: F.video,
737
737
  encryptionScheme: F.scheme
738
738
  }],
739
739
  audioCapabilities: [{
740
- contentType: Ie,
740
+ contentType: Le,
741
741
  robustness: F.audio,
742
742
  encryptionScheme: F.scheme
743
743
  }]
744
744
  }]);
745
745
  }
746
- function ze(e, t) {
746
+ function Be(e, t) {
747
747
  return new Promise((n, r) => {
748
748
  let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
749
749
  e.then((e) => {
@@ -753,8 +753,8 @@ function ze(e, t) {
753
753
  });
754
754
  });
755
755
  }
756
- async function Be(e = {}) {
757
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Pe, r = {};
756
+ async function Ve(e = {}) {
757
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Fe, r = {};
758
758
  if (typeof window < "u" && window.isSecureContext === !1) return {
759
759
  verdict: "insecure-context",
760
760
  detail: r
@@ -766,7 +766,7 @@ async function Be(e = {}) {
766
766
  };
767
767
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
768
768
  for (let e of t) {
769
- let t = Le[e];
769
+ let t = Re[e];
770
770
  if (!t) {
771
771
  r[e] = "unknown system";
772
772
  continue;
@@ -777,7 +777,7 @@ async function Be(e = {}) {
777
777
  break;
778
778
  }
779
779
  try {
780
- return await ze((await ze(i(n, Re(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
780
+ return await Be((await Be(i(n, ze(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
781
781
  verdict: "supported",
782
782
  system: e,
783
783
  detail: r
@@ -801,49 +801,49 @@ async function Be(e = {}) {
801
801
  }
802
802
  //#endregion
803
803
  //#region src/core/manifest.ts
804
- var Ve = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
805
- function He(e) {
806
- return Ve.test(e);
804
+ var He = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
805
+ function Ue(e) {
806
+ return He.test(e);
807
807
  }
808
808
  //#endregion
809
809
  //#region src/core/env.ts
810
- var Ue = {
810
+ var We = {
811
811
  integration: "https://feed-dev.oddin-video.gg",
812
812
  production: "https://feed.oddin-video.gg"
813
813
  };
814
- function We(e) {
815
- let t = Object.prototype.hasOwnProperty.call(Ue, e) ? Ue[e] : void 0;
814
+ function Ge(e) {
815
+ let t = Object.prototype.hasOwnProperty.call(We, e) ? We[e] : void 0;
816
816
  if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
817
817
  return t;
818
818
  }
819
819
  //#endregion
820
820
  //#region src/core/stats.ts
821
- var Ge = { droppedFrames: 0 };
822
- function Ke(e) {
821
+ var Ke = { droppedFrames: 0 };
822
+ function qe(e) {
823
823
  try {
824
824
  return new URL(e).host;
825
825
  } catch {
826
826
  return "";
827
827
  }
828
828
  }
829
- var qe = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
830
- function Je(e) {
829
+ var Je = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
830
+ function Ye(e) {
831
831
  if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
832
832
  let t = "", n = -1, r = performance.getEntriesByType("resource");
833
- for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || qe.test(i.name)) && i.startTime >= n) {
834
- let e = Ke(i.name);
833
+ for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Je.test(i.name)) && i.startTime >= n) {
834
+ let e = qe(i.name);
835
835
  e && (t = e, n = i.startTime);
836
836
  }
837
837
  return t;
838
838
  }
839
- function V(e) {
839
+ function B(e) {
840
840
  let t = e.getVideoPlaybackQuality?.();
841
841
  return {
842
842
  dropped: t?.droppedVideoFrames ?? 0,
843
843
  totalFrames: t?.totalVideoFrames ?? 0
844
844
  };
845
845
  }
846
- var Ye = class {
846
+ var Xe = class {
847
847
  video;
848
848
  baseFrames = 0;
849
849
  baseDropped = 0;
@@ -853,7 +853,7 @@ var Ye = class {
853
853
  this.video = e;
854
854
  }
855
855
  read() {
856
- let e = V(this.video);
856
+ let e = B(this.video);
857
857
  return e.totalFrames < this.lastFrames && (this.baseFrames += this.lastFrames), e.dropped < this.lastDropped && (this.baseDropped += this.lastDropped), this.lastFrames = e.totalFrames, this.lastDropped = e.dropped, {
858
858
  dropped: this.baseDropped + e.dropped,
859
859
  totalFrames: this.baseFrames + e.totalFrames
@@ -866,7 +866,7 @@ var Ye = class {
866
866
  };
867
867
  }
868
868
  };
869
- function Xe(e, t) {
869
+ function Ze(e, t) {
870
870
  let n = [
871
871
  ["playing", () => t("playing")],
872
872
  ["waiting", () => t("buffering")],
@@ -883,8 +883,8 @@ function Xe(e, t) {
883
883
  }
884
884
  //#endregion
885
885
  //#region src/core/engine/native.ts
886
- var Ze = 2e3, Qe = 3, H = 500, $e = 6e3, et = .25;
887
- function tt(e) {
886
+ var Qe = 2e3, $e = 3, V = 500, et = 6e3, tt = .25, nt = 250, rt = .05;
887
+ function it(e) {
888
888
  try {
889
889
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
890
890
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -892,20 +892,20 @@ function tt(e) {
892
892
  return;
893
893
  }
894
894
  }
895
- function U(e) {
895
+ function H(e) {
896
896
  return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
897
897
  }
898
- function W() {
898
+ function U() {
899
899
  if (typeof window > "u") return !1;
900
900
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
901
901
  return e || t;
902
902
  }
903
- function nt() {
904
- if (typeof navigator > "u" || !W()) return !1;
903
+ function at() {
904
+ if (typeof navigator > "u" || !U()) return !1;
905
905
  let e = navigator.userAgent ?? "";
906
906
  return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
907
907
  }
908
- var G = class {
908
+ var W = class {
909
909
  name = "native";
910
910
  deps;
911
911
  onLoaded;
@@ -918,6 +918,10 @@ var G = class {
918
918
  onPageShow = null;
919
919
  hiddenSince = null;
920
920
  refocusTimer = null;
921
+ edgeTimer = null;
922
+ onEdgeReset = null;
923
+ lastBufferedEnd = null;
924
+ bufferedAdvancedAt = null;
921
925
  fairplayKeyIV;
922
926
  loadStarted;
923
927
  preloadTouched = !1;
@@ -927,12 +931,12 @@ var G = class {
927
931
  frameCounter;
928
932
  detachFrames = null;
929
933
  constructor(e) {
930
- this.deps = e, this.frameCounter = new Ye(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
934
+ this.deps = e, this.frameCounter = new Xe(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
931
935
  }
932
936
  async load() {
933
937
  this.detachFrames ??= this.frameCounter.attach();
934
938
  let { video: e, descriptor: t, emit: r } = this.deps;
935
- if (this.watchRefocus(), this.loadStarted || (this.preloadTouched = !0, this.savedPreload = e.getAttribute("preload"), e.preload = "none"), t.drmEnabled) {
939
+ if (this.watchRefocus(), this.watchBufferedEnd(), this.loadStarted || (this.preloadTouched = !0, this.savedPreload = e.getAttribute("preload"), e.preload = "none"), t.drmEnabled) {
936
940
  if (!t.drm?.fairplay) {
937
941
  r({
938
942
  type: "error",
@@ -948,7 +952,7 @@ var G = class {
948
952
  type: "error",
949
953
  error: new n("INTERNAL", 0, "native HLS playback error"),
950
954
  fatal: !0
951
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = rt(t.manifestUrl, t.analytics?.sid), e.load();
955
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = st(t.manifestUrl, t.analytics?.sid), e.load();
952
956
  }
953
957
  startLoad() {
954
958
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -970,7 +974,7 @@ var G = class {
970
974
  });
971
975
  this.onEncrypted = (n) => {
972
976
  let i = n;
973
- i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = tt(i.initData), (async () => {
977
+ i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = it(i.initData), (async () => {
974
978
  try {
975
979
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
976
980
  initDataTypes: [i.initDataType],
@@ -1069,51 +1073,73 @@ var G = class {
1069
1073
  droppedFrames: t.dropped,
1070
1074
  decodedFrames: t.totalFrames
1071
1075
  };
1072
- if (this.cdnHost ||= Je(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1073
- if (n.isLive = !0, e.seekable.length > 0) {
1074
- let t = e.seekable.end(e.seekable.length - 1);
1075
- n.atLiveEdge = e.currentTime >= t - 2;
1076
- let r = t - e.currentTime;
1077
- Number.isFinite(r) && r >= 0 && (n.latencySeconds = r);
1078
- }
1076
+ if (this.cdnHost ||= Ye(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1077
+ n.isLive = !0;
1078
+ let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
1079
+ Number.isFinite(r) && (n.atLiveEdge = r <= 2, !e.paused && r >= 0 && (n.latencySeconds = r));
1079
1080
  } else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
1080
1081
  return n;
1081
1082
  }
1082
1083
  stop() {
1084
+ this.unwatchBufferedEnd();
1083
1085
  try {
1084
1086
  this.deps.video.pause();
1085
1087
  } catch {}
1086
1088
  }
1087
1089
  watchRefocus() {
1088
1090
  this.deps.snapToLiveOnRefocus === !1 || typeof document > "u" || this.onVisibility || (this.onVisibility = () => {
1089
- let e = typeof performance < "u" ? performance.now() : Date.now();
1091
+ let e = G();
1090
1092
  if (document.visibilityState === "hidden") {
1091
1093
  this.hiddenSince = e, this.cancelRefocus();
1092
1094
  return;
1093
1095
  }
1094
1096
  let t = this.hiddenSince;
1095
- this.hiddenSince = null, t != null && e - t >= Ze && this.armRefocus();
1097
+ this.hiddenSince = null, t != null && e - t >= Qe && this.armRefocus();
1096
1098
  }, this.onPageShow = (e) => {
1097
1099
  e.persisted && this.armRefocus();
1098
1100
  }, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
1099
1101
  }
1100
1102
  armRefocus() {
1101
1103
  if (this.cancelRefocus(), Number.isFinite(this.deps.video.duration)) return;
1102
- let e = this.liveEnd(), t = () => typeof performance < "u" ? performance.now() : Date.now(), n = t(), r = 0, i = () => {
1104
+ let e = this.liveEnd(), t = G, n = t(), r = 0, i = () => {
1103
1105
  if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
1104
- r += H;
1105
- let a = this.liveEnd(), o = a != null && (e == null || a >= e + et), s = Math.max(r, t() - n) >= $e;
1106
+ r += V;
1107
+ let a = this.liveEnd(), o = a != null && (e == null || a >= e + tt), s = Math.max(r, t() - n) >= et;
1106
1108
  if (o || s && a != null) {
1107
1109
  this.snapToLive();
1108
1110
  return;
1109
1111
  }
1110
- this.refocusTimer = setTimeout(i, H);
1112
+ this.refocusTimer = setTimeout(i, V);
1111
1113
  };
1112
- this.refocusTimer = setTimeout(i, H);
1114
+ this.refocusTimer = setTimeout(i, V);
1113
1115
  }
1114
1116
  cancelRefocus() {
1115
1117
  this.refocusTimer != null && clearTimeout(this.refocusTimer), this.refocusTimer = null;
1116
1118
  }
1119
+ watchBufferedEnd() {
1120
+ if (this.edgeTimer != null) return;
1121
+ let { video: e } = this.deps;
1122
+ this.onEdgeReset = () => {
1123
+ this.lastBufferedEnd = null, this.bufferedAdvancedAt = null;
1124
+ }, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
1125
+ if (e.duration !== Infinity) return;
1126
+ let t = ot(e, e.currentTime);
1127
+ t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= rt) && (this.bufferedAdvancedAt = G()), this.lastBufferedEnd = t);
1128
+ }, nt);
1129
+ }
1130
+ unwatchBufferedEnd() {
1131
+ this.edgeTimer != null && clearInterval(this.edgeTimer), this.edgeTimer = null, this.onEdgeReset &&= (this.deps.video.removeEventListener("seeking", this.onEdgeReset), this.deps.video.removeEventListener("emptied", this.onEdgeReset), null), this.lastBufferedEnd = null, this.bufferedAdvancedAt = null;
1132
+ }
1133
+ liveEdgeEstimate() {
1134
+ let e = this.deps.video;
1135
+ if (e.duration !== Infinity) return null;
1136
+ let t = this.liveEnd(), n = ot(e, e.currentTime) ?? this.lastBufferedEnd;
1137
+ if (n != null) {
1138
+ let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (G() - e) / 1e3));
1139
+ (t == null || r > t) && (t = r);
1140
+ }
1141
+ return t != null && Number.isFinite(t) ? t : null;
1142
+ }
1117
1143
  liveEnd() {
1118
1144
  let e = this.deps.video;
1119
1145
  if (e.duration !== Infinity || e.seekable.length === 0) return null;
@@ -1123,13 +1149,13 @@ var G = class {
1123
1149
  snapToLive() {
1124
1150
  let e = this.deps.video, t = this.liveEnd();
1125
1151
  if (t == null) return;
1126
- let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - Qe, r);
1152
+ let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - $e, r);
1127
1153
  try {
1128
1154
  e.currentTime = i;
1129
1155
  } catch {}
1130
1156
  }
1131
1157
  destroy() {
1132
- this.detachFrames?.(), this.detachFrames = null, this.cancelRefocus(), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onPageShow && typeof window < "u" && (window.removeEventListener("pageshow", this.onPageShow), this.onPageShow = null);
1158
+ this.detachFrames?.(), this.detachFrames = null, this.cancelRefocus(), this.unwatchBufferedEnd(), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onPageShow && typeof window < "u" && (window.removeEventListener("pageshow", this.onPageShow), this.onPageShow = null);
1133
1159
  let { video: e } = this.deps;
1134
1160
  this.onLoaded && e.removeEventListener("loadedmetadata", this.onLoaded), this.onError && e.removeEventListener("error", this.onError), this.onEncrypted && e.removeEventListener("encrypted", this.onEncrypted), this.keySession?.close().catch(() => {}), this.keySession = null, this.fairplayArmed = !1, this.fairplayKeyIV = void 0;
1135
1161
  try {
@@ -1141,7 +1167,19 @@ var G = class {
1141
1167
  } catch {}
1142
1168
  }
1143
1169
  };
1144
- function rt(e, t) {
1170
+ function G() {
1171
+ return typeof performance < "u" ? performance.now() : Date.now();
1172
+ }
1173
+ function ot(e, t) {
1174
+ let n = e.buffered;
1175
+ if (!n || !Number.isFinite(t)) return null;
1176
+ for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
1177
+ let t = n.end(e);
1178
+ return Number.isFinite(t) ? t : null;
1179
+ }
1180
+ return null;
1181
+ }
1182
+ function st(e, t) {
1145
1183
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
1146
1184
  }
1147
1185
  //#endregion
@@ -1158,8 +1196,8 @@ function K(e, t = Date.now()) {
1158
1196
  }
1159
1197
  //#endregion
1160
1198
  //#region src/core/engine/prefetch.ts
1161
- var it = 15e3, at = 5e3, ot = 6;
1162
- function st(e) {
1199
+ var ct = 15e3, lt = 5e3, ut = 6;
1200
+ function dt(e) {
1163
1201
  try {
1164
1202
  let t = new URL(e);
1165
1203
  return t.searchParams.delete("CMCD"), t.toString();
@@ -1167,7 +1205,7 @@ function st(e) {
1167
1205
  return e;
1168
1206
  }
1169
1207
  }
1170
- var ct = class {
1208
+ var ft = class {
1171
1209
  cmcd;
1172
1210
  entries = /* @__PURE__ */ new Map();
1173
1211
  keyed = /* @__PURE__ */ new Set();
@@ -1190,10 +1228,10 @@ var ct = class {
1190
1228
  }
1191
1229
  prefetch(e, t, n) {
1192
1230
  if (!this.isActive(t)) return;
1193
- let r = st(e);
1231
+ let r = dt(e);
1194
1232
  if (this.entries.has(r)) return;
1195
1233
  let i = this.perTrack.get(t) ?? 0;
1196
- if (i >= ot) return;
1234
+ if (i >= ut) return;
1197
1235
  this.perTrack.set(t, i + 1);
1198
1236
  let a = new AbortController(), o = {
1199
1237
  started: performance.now(),
@@ -1207,10 +1245,10 @@ var ct = class {
1207
1245
  signal: a.signal
1208
1246
  }).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
1209
1247
  this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
1210
- }, it);
1248
+ }, ct);
1211
1249
  }
1212
1250
  take(e) {
1213
- let t = st(e), n = this.entries.get(t);
1251
+ let t = dt(e), n = this.entries.get(t);
1214
1252
  return n && this.entries.delete(t), n;
1215
1253
  }
1216
1254
  destroy() {
@@ -1230,13 +1268,13 @@ var ct = class {
1230
1268
  }
1231
1269
  }
1232
1270
  };
1233
- function lt(t) {
1271
+ function pt(t) {
1234
1272
  let n = e.DefaultConfig?.loader;
1235
1273
  if (typeof n != "function") return;
1236
1274
  class r extends n {
1237
1275
  served = !1;
1238
1276
  cancelled = !1;
1239
- stats = ut();
1277
+ stats = mt();
1240
1278
  load(e, n, r) {
1241
1279
  let i = e.rangeEnd ? void 0 : t.take(e.url);
1242
1280
  if (!i) {
@@ -1244,7 +1282,7 @@ function lt(t) {
1244
1282
  return;
1245
1283
  }
1246
1284
  this.served = !0;
1247
- let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || at, s = setTimeout(() => {
1285
+ let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || lt, s = setTimeout(() => {
1248
1286
  !this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
1249
1287
  }, o);
1250
1288
  i.bytes.then((o) => {
@@ -1271,7 +1309,7 @@ function lt(t) {
1271
1309
  }
1272
1310
  return r;
1273
1311
  }
1274
- function ut() {
1312
+ function mt() {
1275
1313
  return {
1276
1314
  aborted: !1,
1277
1315
  loaded: 0,
@@ -1295,10 +1333,10 @@ function ut() {
1295
1333
  }
1296
1334
  };
1297
1335
  }
1298
- function dt(e) {
1336
+ function ht(e) {
1299
1337
  return e === "audio" ? "audio" : "main";
1300
1338
  }
1301
- function ft(e, t) {
1339
+ function gt(e, t) {
1302
1340
  let n = [];
1303
1341
  t.initSegment?.url && !t.initSegment.data && n.push({
1304
1342
  url: t.initSegment.url,
@@ -1317,24 +1355,24 @@ function ft(e, t) {
1317
1355
  }
1318
1356
  //#endregion
1319
1357
  //#region src/core/engine/hls.ts
1320
- function pt() {
1358
+ function _t() {
1321
1359
  return e.isSupported();
1322
1360
  }
1323
- var mt = 3, ht = 5, gt = 3, _t = 1e4, vt = 3e4, yt = 12e3, bt = 3e3, xt = 6e3, St = .5, Ct = 3, wt = .5, Tt = 1.1, Et = .25, Dt = 5e3, Ot = 4e3, kt = 2, At = 5, jt = 2, Mt = 2, Nt = 4, Pt = 4, Ft = 2e3, It = 3e4, Lt = .2, Rt = 30, zt = 2, Bt = 2, Vt = 9, Ht = .5, Ut = 64;
1324
- function Wt(e) {
1361
+ var vt = 3, yt = 5, bt = 3, xt = 1e4, St = 3e4, Ct = 12e3, wt = 3e3, Tt = .02, Et = 6e3, Dt = .5, Ot = 3, kt = .5, At = 1.1, jt = .25, Mt = 5e3, Nt = 4e3, Pt = 2, Ft = 5, It = 2, Lt = 2, Rt = 4, zt = 4, Bt = 2e3, Vt = 3e4, Ht = .2, Ut = 30, Wt = 2, Gt = 2, Kt = 9, qt = .5, Jt = 64;
1362
+ function Yt(e) {
1325
1363
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
1326
1364
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
1327
1365
  return;
1328
1366
  }
1329
- e.liveSyncDuration ??= Bt;
1330
- let t = Math.max(12, e.liveSyncDuration + Vt);
1331
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Gt(e, e.liveSyncDuration);
1367
+ e.liveSyncDuration ??= Gt;
1368
+ let t = Math.max(12, e.liveSyncDuration + Kt);
1369
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Xt(e, e.liveSyncDuration);
1332
1370
  }
1333
- function Gt(e, t) {
1371
+ function Xt(e, t) {
1334
1372
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
1335
1373
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
1336
1374
  }
1337
- var Kt = class {
1375
+ var Zt = class {
1338
1376
  name = "hls";
1339
1377
  hls = null;
1340
1378
  deps;
@@ -1414,11 +1452,11 @@ var Kt = class {
1414
1452
  frameCounter;
1415
1453
  detachFrames = null;
1416
1454
  constructor(e) {
1417
- this.deps = e, this.frameCounter = new Ye(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1455
+ this.deps = e, this.frameCounter = new Xe(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1418
1456
  }
1419
1457
  async load() {
1420
1458
  this.detachFrames ??= this.frameCounter.attach();
1421
- let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = U(r) && W(), o = !!e.drm?.widevine?.licenseUrl && !a;
1459
+ let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = H(r) && U(), o = !!e.drm?.widevine?.licenseUrl && !a;
1422
1460
  if (e.drmEnabled && !o) {
1423
1461
  i({
1424
1462
  type: "error",
@@ -1427,7 +1465,7 @@ var Kt = class {
1427
1465
  });
1428
1466
  return;
1429
1467
  }
1430
- e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Me()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1468
+ e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Ne()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1431
1469
  let e = this.hls;
1432
1470
  if (document.visibilityState !== "visible" || !e) return;
1433
1471
  let t = e.liveSyncPosition;
@@ -1450,7 +1488,7 @@ var Kt = class {
1450
1488
  }
1451
1489
  this.loadSuspended = !0;
1452
1490
  }
1453
- }, Dt));
1491
+ }, Mt));
1454
1492
  }
1455
1493
  resumeLoading() {
1456
1494
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1482,7 +1520,22 @@ var Kt = class {
1482
1520
  let t = e.liveSyncPosition;
1483
1521
  if (typeof t != "number" || !Number.isFinite(t)) return;
1484
1522
  let { video: n } = this.deps;
1485
- n.currentTime <= t + Ht || (n.currentTime = t);
1523
+ n.currentTime <= t + qt || (n.currentTime = t);
1524
+ }
1525
+ reanchorPartTimeline(e, t) {
1526
+ let { frag: n, part: r } = t;
1527
+ if (!r || r.index !== 0 || n.type !== "main" || typeof n.sn != "number") return;
1528
+ let i = e.levels[n.level]?.details;
1529
+ if (!i?.live) return;
1530
+ let a = r.elementaryStreams.video ?? r.elementaryStreams.audiovideo ?? r.elementaryStreams.audio;
1531
+ if (!a) return;
1532
+ let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
1533
+ if (!s) return;
1534
+ let c = a.startPTS - s.start;
1535
+ if (!(!Number.isFinite(c) || Math.abs(c) < Tt)) {
1536
+ for (let e of i.fragments) e && e.setStart(e.start + c);
1537
+ 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})`);
1538
+ }
1486
1539
  }
1487
1540
  startHls() {
1488
1541
  let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
@@ -1518,7 +1571,7 @@ var Kt = class {
1518
1571
  return;
1519
1572
  }
1520
1573
  let l = this.hls, u, d = new Promise((e) => {
1521
- u = setTimeout(() => e(void 0), _t);
1574
+ u = setTimeout(() => e(void 0), xt);
1522
1575
  });
1523
1576
  return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
1524
1577
  if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
@@ -1534,20 +1587,20 @@ var Kt = class {
1534
1587
  ...c
1535
1588
  };
1536
1589
  if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
1537
- let e = new ct({
1590
+ let e = new ft({
1538
1591
  sessionId: n.analytics?.sid,
1539
1592
  contentId: n.matchUrn
1540
- }), t = lt(e);
1593
+ }), t = pt(e);
1541
1594
  t && (this.prefetch = e, d.fLoader = t);
1542
1595
  }
1543
- Wt(d), this.catchUpRate = typeof d.maxLiveSyncPlaybackRate == "number" ? d.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (d.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = d.autoStartLoad !== !1;
1596
+ Yt(d), this.catchUpRate = typeof d.maxLiveSyncPlaybackRate == "number" ? d.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (d.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = d.autoStartLoad !== !1;
1544
1597
  let f = new e(d);
1545
- if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
1598
+ if (this.hls = f, f.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(f, t)), f.on(e.Events.MANIFEST_PARSED, () => {
1546
1599
  this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(f), this.measureLadder(f), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
1547
1600
  }), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
1548
1601
  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(() => {
1549
1602
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1550
- }, vt)));
1603
+ }, St)));
1551
1604
  }), f.on(e.Events.FRAG_LOADING, (e, t) => {
1552
1605
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1553
1606
  }), f.on(e.Events.FRAG_LOADED, (e, t) => {
@@ -1555,10 +1608,10 @@ var Kt = class {
1555
1608
  let n = t?.frag?.stats, r = n?.loaded;
1556
1609
  typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1557
1610
  let i = n?.loading;
1558
- i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Ut && this.requestTimesMs.shift());
1611
+ i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Jt && this.requestTimesMs.shift());
1559
1612
  let a = t?.frag?.url;
1560
1613
  if (a) {
1561
- let e = Ke(a);
1614
+ let e = qe(a);
1562
1615
  e && (this.cdnHost = e);
1563
1616
  }
1564
1617
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => {
@@ -1572,15 +1625,15 @@ var Kt = class {
1572
1625
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
1573
1626
  let t = this.prefetch;
1574
1627
  f.on(e.Events.KEY_LOADING, (e, n) => {
1575
- let r = n?.frag, i = dt(r?.type);
1576
- if (r && t.isActive(i)) for (let e of ft(f, r)) t.prefetch(e.url, i, e.kind);
1577
- }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(dt(n?.frag?.type)));
1628
+ let r = n?.frag, i = ht(r?.type);
1629
+ if (r && t.isActive(i)) for (let e of gt(f, r)) t.prefetch(e.url, i, e.kind);
1630
+ }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(ht(n?.frag?.type)));
1578
1631
  }
1579
1632
  f.on(e.Events.KEY_LOADED, () => {
1580
1633
  u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
1581
1634
  }), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1582
1635
  this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
1583
- }, bt), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1636
+ }, wt), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1584
1637
  this.renditionSwitches += 1;
1585
1638
  let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
1586
1639
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
@@ -1644,7 +1697,7 @@ var Kt = class {
1644
1697
  return;
1645
1698
  }
1646
1699
  this.capTimer && clearTimeout(this.capTimer);
1647
- let t = e > this.sizeCapLevel ? Ft : It;
1700
+ let t = e > this.sizeCapLevel ? Bt : Vt;
1648
1701
  this.capTimer = setTimeout(() => {
1649
1702
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1650
1703
  }, t);
@@ -1654,9 +1707,9 @@ var Kt = class {
1654
1707
  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;
1655
1708
  }
1656
1709
  dropLevelsWidevineCannotPlay(e) {
1657
- this.removeLevelsWhere(e, (e) => Ne(e) !== !0);
1710
+ this.removeLevelsWhere(e, (e) => Pe(e) !== !0);
1658
1711
  let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
1659
- for (let n of t) je(n).then((t) => {
1712
+ for (let n of t) Me(n).then((t) => {
1660
1713
  t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
1661
1714
  });
1662
1715
  }
@@ -1667,7 +1720,7 @@ var Kt = class {
1667
1720
  a && I(a) && t(a) && (r.push(n), i.add(a));
1668
1721
  }), !r.length) return !1;
1669
1722
  let a = [...i].join(", ");
1670
- if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Ne(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1723
+ if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Pe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1671
1724
  for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
1672
1725
  return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
1673
1726
  }
@@ -1765,7 +1818,7 @@ var Kt = class {
1765
1818
  return;
1766
1819
  }
1767
1820
  let e = Date.now() - this.lastAdvanceMs;
1768
- !this.chaseSuspended && e > xt && this.suspendChasing(), e > yt && this.emitEnded("stalled");
1821
+ !this.chaseSuspended && e > Et && this.suspendChasing(), e > Ct && this.emitEnded("stalled");
1769
1822
  }
1770
1823
  resetStarvationWindow() {
1771
1824
  this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
@@ -1780,7 +1833,7 @@ var Kt = class {
1780
1833
  this.resetStarvationWindow();
1781
1834
  return;
1782
1835
  }
1783
- let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < xt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Ot, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = V(t), c = o - s, l = c !== this.starvedFrames;
1836
+ let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < Et, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Nt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
1784
1837
  if (this.starvedFrames = c, !a || l) {
1785
1838
  (t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
1786
1839
  return;
@@ -1789,12 +1842,12 @@ var Kt = class {
1789
1842
  this.resetStarvationWindow();
1790
1843
  return;
1791
1844
  }
1792
- 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 > Nt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= jt && (this.clearKick(), this.starvationRebuilds < Mt)) {
1845
+ 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 > Rt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= It && (this.clearKick(), this.starvationRebuilds < Lt)) {
1793
1846
  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");
1794
1847
  return;
1795
1848
  }
1796
- let u = i && this.starvedTicks >= kt, d = !i && this.deadTicks >= Nt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Pt;
1797
- if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= At))) {
1849
+ let u = i && this.starvedTicks >= Pt, d = !i && this.deadTicks >= Rt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= zt;
1850
+ if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= Ft))) {
1798
1851
  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");
1799
1852
  try {
1800
1853
  e.stopLoad(), e.startLoad(-1);
@@ -1809,7 +1862,7 @@ var Kt = class {
1809
1862
  let t = e.latency, n = e.targetLatency;
1810
1863
  if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
1811
1864
  let r = t - n;
1812
- !this.catchUpEngaged && r > St ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= St && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
1865
+ !this.catchUpEngaged && r > Dt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Dt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
1813
1866
  let i = this.catchUpEngaged ? this.catchUpRate : 1;
1814
1867
  e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
1815
1868
  }
@@ -1830,16 +1883,16 @@ var Kt = class {
1830
1883
  this.resetFrameDropWindow();
1831
1884
  return;
1832
1885
  }
1833
- let { totalFrames: n, dropped: r } = V(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
1834
- if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Rt || o < 0) {
1886
+ let { totalFrames: n, dropped: r } = B(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
1887
+ if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Ut || o < 0) {
1835
1888
  this.fpsBadTicks = 0;
1836
1889
  return;
1837
1890
  }
1838
- if (o <= Lt * a) {
1891
+ if (o <= Ht * a) {
1839
1892
  this.fpsBadTicks = 0;
1840
1893
  return;
1841
1894
  }
1842
- if (this.fpsBadTicks += 1, this.fpsBadTicks < zt) return;
1895
+ if (this.fpsBadTicks += 1, this.fpsBadTicks < Wt) return;
1843
1896
  this.fpsBadTicks = 0;
1844
1897
  let s = e.levels, c = s[e.currentLevel];
1845
1898
  if (!c) return;
@@ -1856,20 +1909,20 @@ var Kt = class {
1856
1909
  return;
1857
1910
  }
1858
1911
  let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
1859
- if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Tt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
1912
+ if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(At, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
1860
1913
  this.resetChaseWindow();
1861
1914
  return;
1862
1915
  }
1863
- if (this.chaseLatency < 0 || this.chaseLatency - n >= wt) {
1916
+ if (this.chaseLatency < 0 || this.chaseLatency - n >= kt) {
1864
1917
  this.chaseLatency = n, this.chaseTicks = 0;
1865
1918
  return;
1866
1919
  }
1867
- if (this.chaseTicks += 1, this.chaseTicks < Ct) return;
1920
+ if (this.chaseTicks += 1, this.chaseTicks < Ot) return;
1868
1921
  this.resetChaseWindow();
1869
1922
  let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
1870
1923
  if (!(a > 1)) return;
1871
1924
  let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
1872
- s < o + Et || (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);
1925
+ s < o + jt || (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);
1873
1926
  }
1874
1927
  suspendChasing() {
1875
1928
  let e = this.hls;
@@ -1914,7 +1967,7 @@ var Kt = class {
1914
1967
  scheduleLicenseRetry(t) {
1915
1968
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
1916
1969
  let n = t.response?.code ?? 0;
1917
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= gt) return !1;
1970
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= bt) return !1;
1918
1971
  this.licenseRecoveries += 1;
1919
1972
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
1920
1973
  return this.licenseRetryTimer = setTimeout(() => {
@@ -1946,7 +1999,7 @@ var Kt = class {
1946
1999
  return;
1947
2000
  }
1948
2001
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
1949
- if (this.networkRecoveries < ht) {
2002
+ if (this.networkRecoveries < yt) {
1950
2003
  this.networkRecoveries += 1;
1951
2004
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
1952
2005
  this.networkRetryTimer = setTimeout(() => {
@@ -1963,7 +2016,7 @@ var Kt = class {
1963
2016
  return;
1964
2017
  }
1965
2018
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
1966
- if (this.mediaRecoveries < mt) {
2019
+ if (this.mediaRecoveries < vt) {
1967
2020
  this.mediaRecoveries += 1, n.recoverMediaError();
1968
2021
  return;
1969
2022
  }
@@ -1987,19 +2040,19 @@ var Kt = class {
1987
2040
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
1988
2041
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
1989
2042
  }
1990
- }, qt = 15e3, Jt = 6e5, Yt = 3e5, Xt = 100, q = 1, Zt = 1e3, Qt = 3e4, $t = 1e3, en = {
2043
+ }, Qt = 15e3, $t = 6e5, en = 3e5, tn = 100, q = 1, nn = 1e3, rn = 3e4, an = 1e3, on = {
1991
2044
  inline: "PRESENTATION_INLINE",
1992
2045
  fullscreen: "PRESENTATION_FULLSCREEN",
1993
2046
  pip: "PRESENTATION_PIP"
1994
- }, tn = {
2047
+ }, sn = {
1995
2048
  widevine: "KEY_SYSTEM_WIDEVINE",
1996
2049
  fairplay: "KEY_SYSTEM_FAIRPLAY",
1997
2050
  none: "KEY_SYSTEM_NONE"
1998
2051
  };
1999
- function nn(e, t) {
2052
+ function cn(e, t) {
2000
2053
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
2001
2054
  }
2002
- var rn = /* @__PURE__ */ new Set([
2055
+ var ln = /* @__PURE__ */ new Set([
2003
2056
  "INVALID_URN",
2004
2057
  "NOT_FOUND",
2005
2058
  "GONE",
@@ -2019,7 +2072,7 @@ var rn = /* @__PURE__ */ new Set([
2019
2072
  ended: "PLAYER_STATE_ENDED",
2020
2073
  error: "PLAYER_STATE_ERROR"
2021
2074
  };
2022
- function an(e) {
2075
+ function un(e) {
2023
2076
  try {
2024
2077
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
2025
2078
  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);
@@ -2027,8 +2080,8 @@ function an(e) {
2027
2080
  return;
2028
2081
  }
2029
2082
  }
2030
- var on = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), sn = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), cn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2031
- function ln(e) {
2083
+ var dn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), fn = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), pn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2084
+ function mn(e) {
2032
2085
  if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
2033
2086
  let t;
2034
2087
  try {
@@ -2037,19 +2090,19 @@ function ln(e) {
2037
2090
  } catch {
2038
2091
  return;
2039
2092
  }
2040
- if (sn.has(t) && !Y.has(t)) {
2041
- Y.add(t), g(cn(new URL(t).origin));
2093
+ if (fn.has(t) && !Y.has(t)) {
2094
+ Y.add(t), g(pn(new URL(t).origin));
2042
2095
  for (let e of X) e.noteCspBlocked();
2043
2096
  }
2044
2097
  }
2045
- function un(e, t) {
2098
+ function hn(e, t) {
2046
2099
  return g(t, e), { disabledReason: t };
2047
2100
  }
2048
- function dn(e, t, n) {
2049
- if (n) return t && !on(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2101
+ function gn(e, t, n) {
2102
+ if (n) return t && !dn(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2050
2103
  if (t) return { endpoint: t };
2051
- if (t !== void 0) return un("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).");
2052
- let r = an(e);
2104
+ if (t !== void 0) return hn("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).");
2105
+ let r = un(e);
2053
2106
  if (r) return { endpoint: r };
2054
2107
  let i;
2055
2108
  try {
@@ -2057,9 +2110,9 @@ function dn(e, t, n) {
2057
2110
  } catch {
2058
2111
  i = e;
2059
2112
  }
2060
- return un(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).`);
2113
+ return hn(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).`);
2061
2114
  }
2062
- var fn = class {
2115
+ var _n = class {
2063
2116
  opts;
2064
2117
  url;
2065
2118
  cspKey;
@@ -2141,8 +2194,8 @@ var fn = class {
2141
2194
  constructor(e) {
2142
2195
  this.opts = {
2143
2196
  ...e,
2144
- heartbeatMs: e.heartbeatMs ?? qt,
2145
- idleMs: e.idleMs ?? Jt
2197
+ heartbeatMs: e.heartbeatMs ?? Qt,
2198
+ idleMs: e.idleMs ?? $t
2146
2199
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
2147
2200
  try {
2148
2201
  let e = new URL(this.url);
@@ -2159,11 +2212,11 @@ var fn = class {
2159
2212
  sdkVersion: this.opts.sdkVersion,
2160
2213
  ...this.opts.environment
2161
2214
  };
2162
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Zt), 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 && sn.add(this.cspKey), document.addEventListener("securitypolicyviolation", ln), X.add(this), this.noteCspBlocked(), this.onVisibility());
2215
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), nn), 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 && fn.add(this.cspKey), document.addEventListener("securitypolicyviolation", mn), X.add(this), this.noteCspBlocked(), this.onVisibility());
2163
2216
  }
2164
2217
  checkSuspension(e) {
2165
2218
  if (this.endedFlag || !this.opts.idleMs) return !1;
2166
- let t = Math.max(this.opts.idleMs, Yt);
2219
+ let t = Math.max(this.opts.idleMs, en);
2167
2220
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
2168
2221
  }
2169
2222
  syncIdle(e) {
@@ -2186,12 +2239,12 @@ var fn = class {
2186
2239
  let a = {
2187
2240
  fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
2188
2241
  toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
2189
- presentation: en[this.presentation]
2242
+ presentation: on[this.presentation]
2190
2243
  }, o = this.causeOf(e, t, i);
2191
2244
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
2192
2245
  }
2193
2246
  seekInduced(e) {
2194
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < $t;
2247
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < an;
2195
2248
  }
2196
2249
  causeOf(e, t, n) {
2197
2250
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -2265,7 +2318,7 @@ var fn = class {
2265
2318
  let r = n ?? "";
2266
2319
  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";
2267
2320
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
2268
- if (rn.has(e)) return "ERROR_STAGE_RESOLVE";
2321
+ if (ln.has(e)) return "ERROR_STAGE_RESOLVE";
2269
2322
  let i = t ?? "";
2270
2323
  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";
2271
2324
  }
@@ -2312,14 +2365,14 @@ var fn = class {
2312
2365
  if (this.lastRequestCount = g, _ > 0) {
2313
2366
  o.requestCountDelta = _;
2314
2367
  let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
2315
- n.length > 0 && (o.requestTimeP50Ms = nn(n, 50), o.requestTimeP95Ms = nn(n, 95));
2368
+ n.length > 0 && (o.requestTimeP50Ms = cn(n, 50), o.requestTimeP95Ms = cn(n, 95));
2316
2369
  }
2317
2370
  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();
2318
2371
  }
2319
2372
  maybeEmitMediaInfo(e) {
2320
2373
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
2321
2374
  let t = {};
2322
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = tn[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);
2375
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = sn[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);
2323
2376
  let n = JSON.stringify(t);
2324
2377
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
2325
2378
  }
@@ -2339,7 +2392,7 @@ var fn = class {
2339
2392
  let c = r?.positionMs ?? 0;
2340
2393
  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));
2341
2394
  let l = e !== "END_REASON_ENDED";
2342
- l && this.lastStallMs > 0 && n - this.lastStallMs <= Qt && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Qt && (i.abandonAfterErrorMs = Math.max(q, 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);
2395
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= rn && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= rn && (i.abandonAfterErrorMs = Math.max(q, 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);
2343
2396
  let u = r?.decodedFrames ?? this.lastDecoded;
2344
2397
  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");
2345
2398
  }
@@ -2359,13 +2412,13 @@ var fn = class {
2359
2412
  };
2360
2413
  }
2361
2414
  noteCspBlocked() {
2362
- this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(cn(new URL(this.url).origin)));
2415
+ this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(pn(new URL(this.url).origin)));
2363
2416
  }
2364
2417
  cspBlocked() {
2365
2418
  return !!this.cspKey && Y.has(this.cspKey);
2366
2419
  }
2367
2420
  enqueue(e) {
2368
- if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Xt;) {
2421
+ if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > tn;) {
2369
2422
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
2370
2423
  this.pending.splice(e >= 0 ? e : 0, 1);
2371
2424
  }
@@ -2392,7 +2445,7 @@ var fn = class {
2392
2445
  };
2393
2446
  //#endregion
2394
2447
  //#region src/core/environment.ts
2395
- function pn() {
2448
+ function vn() {
2396
2449
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
2397
2450
  let e;
2398
2451
  try {
@@ -2417,14 +2470,14 @@ function pn() {
2417
2470
  integration: "INTEGRATION_KIND_IFRAME"
2418
2471
  };
2419
2472
  }
2420
- function mn() {
2473
+ function yn() {
2421
2474
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
2422
2475
  let e = navigator.userAgentData, t = e?.platform ?? "";
2423
2476
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
2424
2477
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
2425
2478
  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";
2426
2479
  }
2427
- function hn() {
2480
+ function bn() {
2428
2481
  let e = typeof navigator < "u" ? navigator.connection : void 0;
2429
2482
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
2430
2483
  let t = {
@@ -2443,17 +2496,17 @@ function hn() {
2443
2496
  }
2444
2497
  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;
2445
2498
  }
2446
- function gn(e) {
2447
- let t = pn(), n = {
2448
- deviceClass: mn(),
2499
+ function xn(e) {
2500
+ let t = vn(), n = {
2501
+ deviceClass: yn(),
2449
2502
  integration: t.integration,
2450
- ...hn()
2503
+ ...bn()
2451
2504
  };
2452
2505
  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);
2453
2506
  let r = e.getBoundingClientRect?.();
2454
2507
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
2455
2508
  }
2456
- async function _n() {
2509
+ async function Sn() {
2457
2510
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
2458
2511
  if (!e?.getHighEntropyValues) return {};
2459
2512
  try {
@@ -2465,7 +2518,7 @@ async function _n() {
2465
2518
  }
2466
2519
  //#endregion
2467
2520
  //#region src/core/version.ts
2468
- var vn = "2.16.6", yn = {
2521
+ var Cn = "2.16.8", wn = {
2469
2522
  accent: "#E1B600",
2470
2523
  accentText: "#1B1C23",
2471
2524
  background: "#0e0f13",
@@ -2476,7 +2529,7 @@ var vn = "2.16.6", yn = {
2476
2529
  border: "rgba(255, 255, 255, 0.1)",
2477
2530
  radius: "8px",
2478
2531
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
2479
- }, bn = {
2532
+ }, Tn = {
2480
2533
  accent: "--havik-accent",
2481
2534
  accentText: "--havik-accent-text",
2482
2535
  background: "--havik-bg",
@@ -2488,26 +2541,26 @@ var vn = "2.16.6", yn = {
2488
2541
  radius: "--havik-radius",
2489
2542
  fontFamily: "--havik-font"
2490
2543
  };
2491
- function xn(e, t) {
2544
+ function En(e, t) {
2492
2545
  let n = {
2493
- ...yn,
2546
+ ...wn,
2494
2547
  ...t
2495
2548
  };
2496
- for (let t of Object.keys(bn)) e.style.setProperty(bn[t], n[t]);
2549
+ for (let t of Object.keys(Tn)) e.style.setProperty(Tn[t], n[t]);
2497
2550
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
2498
2551
  }
2499
2552
  //#endregion
2500
2553
  //#region src/ui/styles.ts
2501
- var Sn = "havik-player-styles", Cn = "\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", Z = /* @__PURE__ */ new WeakMap();
2502
- function wn(e = document, t) {
2503
- let n = e.querySelector(`style#${Sn}`);
2504
- if (n && (!t || Z.get(n) === t)) return;
2554
+ var Dn = "havik-player-styles", On = "\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", kn = /* @__PURE__ */ new WeakMap();
2555
+ function An(e = document, t) {
2556
+ let n = e.querySelector(`style#${Dn}`);
2557
+ if (n && (!t || kn.get(n) === t)) return;
2505
2558
  let r = e.createElement("style");
2506
- r.id = Sn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Cn, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2559
+ r.id = Dn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = On, kn.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2507
2560
  }
2508
2561
  //#endregion
2509
2562
  //#region src/ui/icons.ts
2510
- var Tn = {
2563
+ var jn = {
2511
2564
  play: "<path d=\"M8 5v14l11-7z\"/>",
2512
2565
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
2513
2566
  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\"/>",
@@ -2520,21 +2573,21 @@ var Tn = {
2520
2573
  liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
2521
2574
  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\"/>"
2522
2575
  };
2523
- function Q(e) {
2524
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Tn[e]}</svg>`;
2576
+ function Z(e) {
2577
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${jn[e]}</svg>`;
2525
2578
  }
2526
2579
  //#endregion
2527
2580
  //#region src/ui/controls.ts
2528
- var En = 3e3, Dn = 250, On = /* @__PURE__ */ new Set([
2581
+ var Mn = 3e3, Nn = 250, Pn = /* @__PURE__ */ new Set([
2529
2582
  "GONE",
2530
2583
  "NOT_FOUND",
2531
2584
  "INVALID_URN",
2532
2585
  "UNAUTHORIZED"
2533
2586
  ]);
2534
- function kn(e) {
2535
- return new An(e);
2587
+ function Fn(e) {
2588
+ return new In(e);
2536
2589
  }
2537
- var An = class {
2590
+ var In = class {
2538
2591
  root;
2539
2592
  video;
2540
2593
  player;
@@ -2580,7 +2633,7 @@ var An = class {
2580
2633
  scrubbing = !1;
2581
2634
  offFns = [];
2582
2635
  constructor(e) {
2583
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? En, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, wn(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");
2636
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Mn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, An(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");
2584
2637
  let t = (e, t, n) => {
2585
2638
  let r = this.doc.createElement(e);
2586
2639
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -2591,12 +2644,12 @@ var An = class {
2591
2644
  "aria-label": r,
2592
2645
  title: r
2593
2646
  });
2594
- return i.innerHTML = Q(n), i;
2647
+ return i.innerHTML = Z(n), i;
2595
2648
  };
2596
2649
  this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
2597
2650
  type: "button",
2598
2651
  "aria-label": "Play"
2599
- }), 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", {
2652
+ }), this.center.innerHTML = Z("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", {
2600
2653
  role: "slider",
2601
2654
  "aria-label": "Seek",
2602
2655
  "aria-valuemin": "0",
@@ -2614,7 +2667,7 @@ var An = class {
2614
2667
  "aria-label": "Volume"
2615
2668
  });
2616
2669
  let a = t("div", "havik-vol");
2617
- a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Q("liveDot");
2670
+ a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Z("liveDot");
2618
2671
  let o = this.doc.createElement("span");
2619
2672
  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";
2620
2673
  let s = t("div", "havik-spacer");
@@ -2666,7 +2719,7 @@ var An = class {
2666
2719
  let t = this.surfaceWasHidden;
2667
2720
  this.tapTimer = setTimeout(() => {
2668
2721
  this.tapTimer = void 0, this.toggleBar(t);
2669
- }, Dn);
2722
+ }, Nn);
2670
2723
  }
2671
2724
  toggleBar(e) {
2672
2725
  e ? this.poke() : this.hideIfIdle();
@@ -2698,12 +2751,12 @@ var An = class {
2698
2751
  }
2699
2752
  if (e === "preplay") {
2700
2753
  let e = this.doc.createElement("button");
2701
- 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);
2754
+ e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Z("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
2702
2755
  } else {
2703
2756
  let r = this.doc.createElement("div");
2704
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !On.has(this.lastError.code)) {
2757
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Pn.has(this.lastError.code)) {
2705
2758
  let e = this.doc.createElement("button");
2706
- 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);
2759
+ e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Z("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
2707
2760
  }
2708
2761
  }
2709
2762
  this.root.append(n), this.statusBox = n, this.show();
@@ -2742,7 +2795,7 @@ var An = class {
2742
2795
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
2743
2796
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
2744
2797
  }
2745
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${jn(this.video.currentTime)} / ${jn(this.video.duration)}`);
2798
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Ln(this.video.currentTime)} / ${Ln(this.video.duration)}`);
2746
2799
  }
2747
2800
  syncLive() {
2748
2801
  let e = this.player.getStats(), t = e.isLive !== !1;
@@ -2792,17 +2845,17 @@ var An = class {
2792
2845
  renderQualityMenu() {
2793
2846
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
2794
2847
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
2795
- for (let n of e) this.menu.append(this.menuItem(Mn(n), t === n.index, () => this.player.setQuality(n.index)));
2848
+ for (let n of e) this.menu.append(this.menuItem(Rn(n), t === n.index, () => this.player.setQuality(n.index)));
2796
2849
  }
2797
2850
  renderAudioMenu() {
2798
2851
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
2799
2852
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
2800
- for (let t of e) this.menu.append(this.menuItem(Nn(t), t.default, () => this.player.setAudioTrack(t.id)));
2853
+ for (let t of e) this.menu.append(this.menuItem(zn(t), t.default, () => this.player.setAudioTrack(t.id)));
2801
2854
  }
2802
2855
  renderCcMenu() {
2803
2856
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
2804
2857
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
2805
- for (let t of e) this.menu.append(this.menuItem(Pn(t), !1, () => this.player.setTextTrack(t.id)));
2858
+ for (let t of e) this.menu.append(this.menuItem(Bn(t), !1, () => this.player.setTextTrack(t.id)));
2806
2859
  }
2807
2860
  onTracksChanged() {
2808
2861
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2886,7 +2939,7 @@ var An = class {
2886
2939
  }
2887
2940
  }
2888
2941
  setIcon(e, t) {
2889
- e.innerHTML = Q(t);
2942
+ e.innerHTML = Z(t);
2890
2943
  }
2891
2944
  destroy() {
2892
2945
  this.hideTimer && clearTimeout(this.hideTimer), this.tapTimer && clearTimeout(this.tapTimer);
@@ -2903,41 +2956,41 @@ var An = class {
2903
2956
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
2904
2957
  }
2905
2958
  };
2906
- function jn(e) {
2959
+ function Ln(e) {
2907
2960
  (!Number.isFinite(e) || e < 0) && (e = 0);
2908
2961
  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");
2909
2962
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
2910
2963
  }
2911
- function Mn(e) {
2964
+ function Rn(e) {
2912
2965
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
2913
2966
  }
2914
- function Nn(e) {
2967
+ function zn(e) {
2915
2968
  return e.name || e.lang || `Track ${e.id}`;
2916
2969
  }
2917
- function Pn(e) {
2970
+ function Bn(e) {
2918
2971
  return e.name || e.lang || `Track ${e.id}`;
2919
2972
  }
2920
2973
  //#endregion
2921
2974
  //#region src/managed/index.ts
2922
- var Fn = 6e3, In = 45e3, Ln = 2e3, Rn = 3, zn = 2e3, Bn = 48e4, Vn = "keySystemLicenseRequestFailed";
2923
- function Hn(e) {
2975
+ var Vn = 6e3, Q = 45e3, Hn = 2e3, Un = 3, Wn = 2e3, Gn = 48e4, Kn = "keySystemLicenseRequestFailed";
2976
+ function qn(e) {
2924
2977
  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)})`);
2925
- if (e.env !== void 0) return We(e.env);
2978
+ if (e.env !== void 0) return Ge(e.env);
2926
2979
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
2927
2980
  return e.baseUrl;
2928
2981
  }
2929
- async function Un(e) {
2982
+ async function Jn(e) {
2930
2983
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
2931
- let t = Hn(e);
2984
+ let t = qn(e);
2932
2985
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
2933
2986
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
2934
- let r = new Wn({
2987
+ let r = new Yn({
2935
2988
  ...e,
2936
2989
  baseUrl: t
2937
2990
  });
2938
2991
  return await r.start(), r;
2939
2992
  }
2940
- var Wn = class {
2993
+ var Yn = class {
2941
2994
  opts;
2942
2995
  abort = new AbortController();
2943
2996
  listeners = {};
@@ -3028,7 +3081,7 @@ var Wn = class {
3028
3081
  setTimeout(() => {
3029
3082
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
3030
3083
  phase: i ? "unavailable" : "tooEarly",
3031
- retryInMs: In,
3084
+ retryInMs: Q,
3032
3085
  attempt: 1,
3033
3086
  elapsedMs: 0,
3034
3087
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -3067,13 +3120,13 @@ var Wn = class {
3067
3120
  !a && !p() && h();
3068
3121
  }, e);
3069
3122
  };
3070
- _(Fn), this.armingSub = T({
3123
+ _(Vn), this.armingSub = T({
3071
3124
  eventsBaseUrl: t,
3072
3125
  matchUrn: this.opts.matchUrn,
3073
3126
  credential: this.opts.credential,
3074
- onAlive: () => _(In),
3127
+ onAlive: () => _(Q),
3075
3128
  onState: (e) => {
3076
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Ln);
3129
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Hn);
3077
3130
  },
3078
3131
  onError: () => h()
3079
3132
  });
@@ -3096,7 +3149,7 @@ var Wn = class {
3096
3149
  let n = await s(this.opts.credential);
3097
3150
  if (this.destroyed || t !== this.loadGen) return;
3098
3151
  this.setState("loading");
3099
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Xe(this.opts.video, (e) => {
3152
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Ze(this.opts.video, (e) => {
3100
3153
  this._state !== "ended" && this._state !== "error" && this.setState(e);
3101
3154
  });
3102
3155
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -3118,26 +3171,26 @@ var Wn = class {
3118
3171
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
3119
3172
  let i = e.analytics?.sid;
3120
3173
  if (!i) return;
3121
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = dn(this.opts.baseUrl, a, e.analytics?.endpoint);
3174
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = gn(this.opts.baseUrl, a, e.analytics?.endpoint);
3122
3175
  if (!o) {
3123
3176
  s && setTimeout(() => {
3124
3177
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
3125
3178
  }, 0);
3126
3179
  return;
3127
3180
  }
3128
- let c = this.opts.video, l = new fn({
3181
+ let c = this.opts.video, l = new _n({
3129
3182
  endpoint: o,
3130
3183
  sid: i,
3131
3184
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
3132
- sdkVersion: vn,
3133
- environment: gn(c),
3185
+ sdkVersion: Cn,
3186
+ environment: xn(c),
3134
3187
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
3135
3188
  onIdle: () => this.onAnalyticsIdle(t),
3136
3189
  onBlocked: (e) => setTimeout(() => {
3137
3190
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
3138
3191
  }, 0),
3139
3192
  sample: () => {
3140
- let e = this.engine?.getStats() ?? Ge, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
3193
+ let e = this.engine?.getStats() ?? Ke, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
3141
3194
  return {
3142
3195
  ...e,
3143
3196
  bufferedMs: Math.round(t * 1e3),
@@ -3151,7 +3204,7 @@ var Wn = class {
3151
3204
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
3152
3205
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
3153
3206
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
3154
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), _n().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3207
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Sn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3155
3208
  }
3156
3209
  currentPresentation() {
3157
3210
  let e = this.opts.video;
@@ -3177,11 +3230,11 @@ var Wn = class {
3177
3230
  emit: (e) => this.onEngineEvent(e),
3178
3231
  freshLicenseUrl: () => this.refreshLicense()
3179
3232
  }, o = this.opts.engine ?? "auto";
3180
- if (o === "native") return new G(a);
3181
- if (o === "hls") return new Kt(a);
3182
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && U(this.opts.video) && W() || !e.drmEnabled && nt() && U(this.opts.video)) return new G(a);
3183
- if (pt()) return new Kt(a);
3184
- if (U(this.opts.video)) return new G(a);
3233
+ if (o === "native") return new W(a);
3234
+ if (o === "hls") return new Zt(a);
3235
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled && at() && H(this.opts.video)) return new W(a);
3236
+ if (_t()) return new Zt(a);
3237
+ if (H(this.opts.video)) return new W(a);
3185
3238
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
3186
3239
  }
3187
3240
  onEngineEvent(e) {
@@ -3243,7 +3296,7 @@ var Wn = class {
3243
3296
  r = 0, i = !1;
3244
3297
  },
3245
3298
  onError: () => {
3246
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Rn && (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.`))));
3299
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Un && (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.`))));
3247
3300
  }
3248
3301
  });
3249
3302
  }
@@ -3265,7 +3318,7 @@ var Wn = class {
3265
3318
  scheduleRejoin(e) {
3266
3319
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
3267
3320
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
3268
- }, Math.random() * Ln));
3321
+ }, Math.random() * Hn));
3269
3322
  }
3270
3323
  cancelRejoin() {
3271
3324
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -3289,7 +3342,7 @@ var Wn = class {
3289
3342
  }
3290
3343
  t.controls = !1;
3291
3344
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
3292
- r && r.insertBefore(n, t), n.appendChild(t), xn(n, this.opts.theme), this.container = n, this.controlBar = kn({
3345
+ r && r.insertBefore(n, t), n.appendChild(t), En(n, this.opts.theme), this.container = n, this.controlBar = Fn({
3293
3346
  root: n,
3294
3347
  video: t,
3295
3348
  player: this,
@@ -3320,7 +3373,7 @@ var Wn = class {
3320
3373
  }
3321
3374
  startStats() {
3322
3375
  this.stopStats();
3323
- let e = Math.max(500, this.opts.statsIntervalMs ?? zn);
3376
+ let e = Math.max(500, this.opts.statsIntervalMs ?? Wn);
3324
3377
  this.statsTimer = setInterval(() => {
3325
3378
  if (!this.engine) return;
3326
3379
  let e = this.engine.getStats();
@@ -3331,14 +3384,14 @@ var Wn = class {
3331
3384
  this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
3332
3385
  }
3333
3386
  isStaleLicenseDenial(e) {
3334
- return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Vn || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
3387
+ return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Kn || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
3335
3388
  }
3336
3389
  scheduleLicenseRefresh() {
3337
3390
  if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
3338
3391
  typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
3339
3392
  document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
3340
3393
  }, document.addEventListener("visibilitychange", this.onRefocus));
3341
- let e = this.opts.licenseRefreshMs ?? Bn;
3394
+ let e = this.opts.licenseRefreshMs ?? Gn;
3342
3395
  e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
3343
3396
  }
3344
3397
  stopRefresh() {
@@ -3394,7 +3447,7 @@ var Wn = class {
3394
3447
  this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
3395
3448
  }
3396
3449
  getStats() {
3397
- return this.engine?.getStats() ?? Ge;
3450
+ return this.engine?.getStats() ?? Ke;
3398
3451
  }
3399
3452
  getQualityLevels() {
3400
3453
  return this.engine?.getQualityLevels() ?? [];
@@ -3504,7 +3557,7 @@ function $(e) {
3504
3557
  }
3505
3558
  //#endregion
3506
3559
  //#region src/embed/host.ts
3507
- function Gn(e) {
3560
+ function Xn(e) {
3508
3561
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
3509
3562
  if (!e.src) throw Error("mountEmbed: opts.src is required");
3510
3563
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -3563,15 +3616,15 @@ function Gn(e) {
3563
3616
  }
3564
3617
  //#endregion
3565
3618
  //#region src/embed/page.ts
3566
- var Kn = /^[A-Za-z0-9:_.-]{1,128}$/;
3567
- function qn(e) {
3619
+ var Zn = /^[A-Za-z0-9:_.-]{1,128}$/;
3620
+ function Qn(e) {
3568
3621
  if (typeof e == "boolean") return e;
3569
3622
  if (typeof e == "object" && e) {
3570
3623
  let t = e.endpoint;
3571
3624
  return typeof t == "string" ? { endpoint: t } : {};
3572
3625
  }
3573
3626
  }
3574
- function Jn() {
3627
+ function $n() {
3575
3628
  let e = window.HAVIK_EMBED_CONFIG;
3576
3629
  if (e) return {
3577
3630
  baseUrl: e.baseUrl ?? "",
@@ -3581,7 +3634,7 @@ function Jn() {
3581
3634
  autoplay: e.autoplay ?? !0,
3582
3635
  muted: e.muted ?? !0,
3583
3636
  waitForLive: e.waitForLive ?? !0,
3584
- analytics: qn(e.analytics)
3637
+ analytics: Qn(e.analytics)
3585
3638
  };
3586
3639
  let t = new URLSearchParams(location.search);
3587
3640
  return {
@@ -3594,9 +3647,9 @@ function Jn() {
3594
3647
  waitForLive: !0
3595
3648
  };
3596
3649
  }
3597
- async function Yn() {
3598
- let e = Jn();
3599
- Zn();
3650
+ async function er() {
3651
+ let e = $n();
3652
+ nr();
3600
3653
  let t = document.createElement("video");
3601
3654
  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);
3602
3655
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -3651,12 +3704,12 @@ async function Yn() {
3651
3704
  code: e.code,
3652
3705
  message: e.message
3653
3706
  })), e.on("autoplayblocked", () => {
3654
- i({ type: "oddin:autoplayblocked" }), Xn(t, e);
3707
+ i({ type: "oddin:autoplayblocked" }), tr(t, e);
3655
3708
  });
3656
3709
  }, s = async (r) => {
3657
3710
  a?.destroy(), a = null;
3658
3711
  try {
3659
- let n = await Un({
3712
+ let n = await Jn({
3660
3713
  video: t,
3661
3714
  baseUrl: e.baseUrl,
3662
3715
  matchUrn: r,
@@ -3718,7 +3771,7 @@ async function Yn() {
3718
3771
  a?.retry();
3719
3772
  break;
3720
3773
  case "oddin:load":
3721
- typeof e.matchUrn == "string" && Kn.test(e.matchUrn) && s(e.matchUrn);
3774
+ typeof e.matchUrn == "string" && Zn.test(e.matchUrn) && s(e.matchUrn);
3722
3775
  break;
3723
3776
  case "oddin:destroy": c();
3724
3777
  }
@@ -3730,18 +3783,18 @@ async function Yn() {
3730
3783
  protocol: 1
3731
3784
  });
3732
3785
  }
3733
- function Xn(e, t) {
3786
+ function tr(e, t) {
3734
3787
  if (document.getElementById("havik-tap")) return;
3735
3788
  let n = document.createElement("button");
3736
3789
  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", () => {
3737
3790
  n.remove(), t.play();
3738
3791
  }), document.body.appendChild(n);
3739
3792
  }
3740
- function Zn() {
3793
+ function nr() {
3741
3794
  let e = document.createElement("style");
3742
3795
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
3743
3796
  }
3744
3797
  //#endregion
3745
- export { yn as ODDIN_THEME, n as PlaybackError, xn as applyTheme, We as baseUrlForEnv, Yn as bootEmbed, Te as clearDeviceId, Un as createPlayer, E as deriveEventsBaseUrl, Be as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, k as getDeviceId, He as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, Gn as mountEmbed, v as pollToLive, b as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
3798
+ export { wn as ODDIN_THEME, n as PlaybackError, En as applyTheme, Ge as baseUrlForEnv, er as bootEmbed, Te as clearDeviceId, Jn as createPlayer, E as deriveEventsBaseUrl, Ve as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, k as getDeviceId, Ue as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, Xn as mountEmbed, v as pollToLive, b as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
3746
3799
 
3747
3800
  //# sourceMappingURL=index.js.map