@oddin-gg/havik-player 2.17.0 → 2.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -174,7 +174,7 @@ function ue(e, t) {
174
174
  t?.addEventListener("abort", a, { once: !0 });
175
175
  });
176
176
  }
177
- async function v(e, t, r) {
177
+ async function de(e, t, r) {
178
178
  let i = ae(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
179
179
  for (;;) {
180
180
  if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
@@ -200,21 +200,21 @@ async function v(e, t, r) {
200
200
  }
201
201
  //#endregion
202
202
  //#region src/core/resolve.ts
203
- async function y(e) {
203
+ async function v(e) {
204
204
  if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
205
205
  let t = await p(d(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
206
206
  credential: e.credential,
207
207
  signal: e.signal,
208
208
  apiHeaders: e.apiHeaders
209
209
  });
210
- if (!t.ok) throw await de(t);
211
- return me(await t.json(), e.matchUrn);
210
+ if (!t.ok) throw await fe(t);
211
+ return he(await t.json(), e.matchUrn);
212
212
  }
213
- function b(e) {
214
- let t = () => y(e);
215
- return e.waitForLive ? v(t, e.waitForLive, e.signal) : t();
213
+ function y(e) {
214
+ let t = () => v(e);
215
+ return e.waitForLive ? de(t, e.waitForLive, e.signal) : t();
216
216
  }
217
- async function de(e) {
217
+ async function fe(e) {
218
218
  let t = f(e.headers.get("retry-after")), i = e.headers.get("x-request-id") ?? e.headers.get("x-amzn-requestid") ?? void 0, a = e.statusText || `HTTP ${e.status}`, o, s;
219
219
  try {
220
220
  let t = await e.json();
@@ -230,7 +230,7 @@ async function de(e) {
230
230
  liveStartsAtMs: s
231
231
  });
232
232
  }
233
- var fe = /* @__PURE__ */ new Set([
233
+ var pe = /* @__PURE__ */ new Set([
234
234
  "matchUrn",
235
235
  "protocol",
236
236
  "drmEnabled",
@@ -241,7 +241,7 @@ var fe = /* @__PURE__ */ new Set([
241
241
  "expiresAt",
242
242
  "analytics"
243
243
  ]);
244
- function x(e, t) {
244
+ function b(e, t) {
245
245
  let r;
246
246
  try {
247
247
  r = new URL(t);
@@ -251,7 +251,7 @@ function x(e, t) {
251
251
  if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
252
252
  return t;
253
253
  }
254
- function pe(e) {
254
+ function me(e) {
255
255
  if (e !== void 0) {
256
256
  if (typeof e == "string" && !e.endsWith("/")) try {
257
257
  let t = new URL(e);
@@ -260,62 +260,62 @@ function pe(e) {
260
260
  g(`server analytics.endpoint ${JSON.stringify(e)} ignored: not a bare https origin.`);
261
261
  }
262
262
  }
263
- function me(e, t) {
263
+ function he(e, t) {
264
264
  if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
265
265
  let r = e.drmEnabled ?? !!e.drm, i = {
266
266
  matchUrn: e.matchUrn ?? t,
267
267
  protocol: "hls",
268
268
  drmEnabled: r,
269
- manifestUrl: x("manifestUrl", e.manifestUrl),
269
+ manifestUrl: b("manifestUrl", e.manifestUrl),
270
270
  serverTime: e.serverTime ?? ""
271
271
  };
272
272
  if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid) {
273
273
  i.analytics = { sid: e.analytics.sid };
274
- let t = pe(e.analytics.endpoint);
274
+ let t = me(e.analytics.endpoint);
275
275
  t && (i.analytics.endpoint = t);
276
276
  }
277
277
  if (r && e.drm) {
278
278
  let t = {};
279
- e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: x("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
280
- licenseUrl: x("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
281
- certificateUrl: x("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
279
+ e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: b("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
280
+ licenseUrl: b("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
281
+ certificateUrl: b("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
282
282
  }), (t.widevine || t.fairplay) && (i.drm = t);
283
283
  }
284
284
  let a = {};
285
- for (let [t, n] of Object.entries(e)) fe.has(t) || (a[t] = n);
285
+ for (let [t, n] of Object.entries(e)) pe.has(t) || (a[t] = n);
286
286
  return Object.keys(a).length > 0 && (i.extensions = a), i;
287
287
  }
288
288
  //#endregion
289
289
  //#region src/core/fullscreen.ts
290
- function he(e) {
290
+ function ge(e) {
291
291
  return e.ownerDocument ?? document;
292
292
  }
293
- function ge(e) {
293
+ function _e(e) {
294
294
  return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
295
295
  }
296
- function S(e, t) {
297
- let n = ge(he(e));
296
+ function x(e, t) {
297
+ let n = _e(ge(e));
298
298
  return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
299
299
  }
300
- async function C(e, t) {
300
+ async function S(e, t) {
301
301
  let n = t ?? e;
302
302
  if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
303
303
  if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
304
304
  let r = e;
305
305
  return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
306
306
  }
307
- async function w(e, t) {
307
+ async function C(e, t) {
308
308
  let n = e;
309
309
  if (n.webkitDisplayingFullscreen) {
310
310
  n.webkitExitFullscreen?.();
311
311
  return;
312
312
  }
313
- let r = he(e), i = ge(r);
313
+ let r = ge(e), i = _e(r);
314
314
  i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
315
315
  }
316
316
  //#endregion
317
317
  //#region src/core/catalog.ts
318
- async function _e(e) {
318
+ async function ve(e) {
319
319
  let t = new URLSearchParams();
320
320
  e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
321
321
  let i = t.toString(), a = d(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
@@ -333,12 +333,12 @@ async function _e(e) {
333
333
  };
334
334
  if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
335
335
  return {
336
- tournaments: ve(await s.json()),
336
+ tournaments: ye(await s.json()),
337
337
  etag: s.headers.get("etag") ?? void 0,
338
338
  notModified: !1
339
339
  };
340
340
  }
341
- function ve(e) {
341
+ function ye(e) {
342
342
  return (e.tournaments ?? []).map((e) => {
343
343
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
344
344
  return {
@@ -360,7 +360,7 @@ function ve(e) {
360
360
  };
361
361
  });
362
362
  }
363
- async function ye(e) {
363
+ async function be(e) {
364
364
  let t = d(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
365
365
  e.etag && i.set("If-None-Match", e.etag);
366
366
  let a = await p(t, {
@@ -380,13 +380,13 @@ async function ye(e) {
380
380
  };
381
381
  if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
382
382
  return {
383
- tournament: be(await a.json()),
383
+ tournament: xe(await a.json()),
384
384
  etag: a.headers.get("etag") ?? void 0,
385
385
  notModified: !1,
386
386
  notFound: !1
387
387
  };
388
388
  }
389
- function be(e) {
389
+ function xe(e) {
390
390
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
391
391
  return {
392
392
  urn: t,
@@ -406,17 +406,17 @@ function be(e) {
406
406
  }))
407
407
  };
408
408
  }
409
- function xe(e) {
409
+ function Se(e) {
410
410
  return e.tournaments.flatMap((e) => e.matches);
411
411
  }
412
412
  //#endregion
413
413
  //#region src/core/poll.ts
414
- var Se = /* @__PURE__ */ new Set([
414
+ var Ce = /* @__PURE__ */ new Set([
415
415
  "NOT_FOUND",
416
416
  "GONE",
417
417
  "INVALID_URN"
418
418
  ]);
419
- function Ce(e) {
419
+ function we(e) {
420
420
  let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
421
421
  u || (a = setTimeout(m, t));
422
422
  }, m = async () => {
@@ -449,7 +449,7 @@ function Ce(e) {
449
449
  } catch (t) {
450
450
  if (!i.signal.aborted) {
451
451
  let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
452
- Se.has(r.code) && (u = !0), e.onError?.(r);
452
+ Ce.has(r.code) && (u = !0), e.onError?.(r);
453
453
  }
454
454
  } finally {
455
455
  f();
@@ -461,9 +461,9 @@ function Ce(e) {
461
461
  }
462
462
  //#endregion
463
463
  //#region src/core/events.ts
464
- var we = 45e3;
465
- function T(e) {
466
- let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? we, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
464
+ var Te = 45e3;
465
+ function w(e) {
466
+ let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? Te, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
467
467
  if (a.signal.aborted) return t();
468
468
  let n = setTimeout(t, e);
469
469
  a.signal.addEventListener("abort", () => {
@@ -545,7 +545,7 @@ function T(e) {
545
545
  o || (o = !0, a.abort());
546
546
  } };
547
547
  }
548
- function E(e) {
548
+ function T(e) {
549
549
  try {
550
550
  let t = new URL(e);
551
551
  return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
@@ -555,27 +555,27 @@ function E(e) {
555
555
  }
556
556
  //#endregion
557
557
  //#region src/core/drm/deviceId.ts
558
- var D = "havik.player.deviceId", O;
559
- function k() {
560
- if (O) return O;
558
+ var E = "havik.player.deviceId", D;
559
+ function O() {
560
+ if (D) return D;
561
561
  try {
562
- let e = globalThis.localStorage?.getItem(D);
563
- if (e) return O = e, e;
562
+ let e = globalThis.localStorage?.getItem(E);
563
+ if (e) return D = e, e;
564
564
  } catch {}
565
- let e = Ee();
566
- O = e;
565
+ let e = De();
566
+ D = e;
567
567
  try {
568
- globalThis.localStorage?.setItem(D, e);
568
+ globalThis.localStorage?.setItem(E, e);
569
569
  } catch {}
570
570
  return e;
571
571
  }
572
- function Te() {
573
- O = void 0;
572
+ function Ee() {
573
+ D = void 0;
574
574
  try {
575
- globalThis.localStorage?.removeItem(D);
575
+ globalThis.localStorage?.removeItem(E);
576
576
  } catch {}
577
577
  }
578
- function Ee() {
578
+ function De() {
579
579
  let e = globalThis.crypto;
580
580
  if (e && typeof e.randomUUID == "function") return e.randomUUID();
581
581
  let t = /* @__PURE__ */ new Uint8Array(16);
@@ -587,21 +587,69 @@ function Ee() {
587
587
  }
588
588
  //#endregion
589
589
  //#region src/core/drm/headers.ts
590
- function De(e, t, n = {}) {
590
+ function Oe(e, t, n = {}) {
591
591
  let r = {
592
592
  "x-api-key": t.apiKey,
593
593
  "X-Match-Urn": e.matchUrn,
594
- "X-Device-Id": n.deviceId ?? k(),
594
+ "X-Device-Id": n.deviceId ?? O(),
595
595
  "Content-Type": "application/octet-stream"
596
596
  };
597
597
  return n.userId && (r["X-User-Id"] = n.userId), r;
598
598
  }
599
599
  //#endregion
600
+ //#region src/core/bandwidthMemory.ts
601
+ var k = "havik.player.bandwidth", ke = .8, Ae = 2e7, je = 3e5;
602
+ function Me() {
603
+ return globalThis.navigator?.connection;
604
+ }
605
+ function Ne() {
606
+ let e = Me()?.type;
607
+ return typeof e == "string" && e !== "" && e !== "unknown" ? e : "any";
608
+ }
609
+ function Pe() {
610
+ let e = Me()?.downlink;
611
+ return typeof e == "number" && Number.isFinite(e) && e > 0 ? e * 1e6 : void 0;
612
+ }
613
+ function Fe() {
614
+ try {
615
+ let e = globalThis.localStorage?.getItem(k);
616
+ if (!e) return {};
617
+ let t = JSON.parse(e);
618
+ return t && typeof t == "object" && !Array.isArray(t) ? t : {};
619
+ } catch {
620
+ return {};
621
+ }
622
+ }
623
+ function Ie(e = Date.now()) {
624
+ let t = Fe()[Ne()];
625
+ if (!t || typeof t.bps != "number" || typeof t.at != "number" || !Number.isFinite(t.bps) || t.bps <= 0) return;
626
+ let n = e - t.at;
627
+ if (n < 0 || n > 2592e5) return;
628
+ let r = Pe(), i = r === void 0 ? t.bps : Math.min(t.bps, r);
629
+ return Math.round(Math.min(Ae, Math.max(je, i * ke)));
630
+ }
631
+ function Le(e, t = Date.now()) {
632
+ if (!Number.isFinite(e) || e <= 0) return;
633
+ let n = Fe();
634
+ n[Ne()] = {
635
+ bps: Math.round(e),
636
+ at: t
637
+ };
638
+ try {
639
+ globalThis.localStorage?.setItem(k, JSON.stringify(n));
640
+ } catch {}
641
+ }
642
+ function Re() {
643
+ try {
644
+ globalThis.localStorage?.removeItem(k);
645
+ } catch {}
646
+ }
647
+ //#endregion
600
648
  //#region src/core/drm/cdm.ts
601
- var A = /* @__PURE__ */ new WeakMap();
602
- function Oe(e, t) {
603
- let n = A.get(e);
604
- n || (n = /* @__PURE__ */ new Map(), A.set(e, n));
649
+ var ze = /* @__PURE__ */ new WeakMap();
650
+ function Be(e, t) {
651
+ let n = ze.get(e);
652
+ n || (n = /* @__PURE__ */ new Map(), ze.set(e, n));
605
653
  let r = n.get(t.keySystem);
606
654
  if (r) return r;
607
655
  let i = t.createMediaKeys().catch((e) => {
@@ -609,22 +657,22 @@ function Oe(e, t) {
609
657
  });
610
658
  return n.set(t.keySystem, i), i;
611
659
  }
612
- function j() {
660
+ function A() {
613
661
  return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
614
662
  }
615
- var M = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
616
- function ke(e) {
663
+ var j = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
664
+ function Ve(e) {
617
665
  return e.startsWith("com.widevine");
618
666
  }
619
- function N(e, t) {
620
- if (!ke(e)) return t;
667
+ function M(e, t) {
668
+ if (!Ve(e)) return t;
621
669
  let n = (e, t) => {
622
670
  let n = e.videoCapabilities;
623
671
  return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
624
- let n = M.indexOf(e.robustness);
625
- return n === -1 || M.indexOf(t) > n;
672
+ let n = j.indexOf(e.robustness);
673
+ return n === -1 || j.indexOf(t) > n;
626
674
  });
627
- }, r = M.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
675
+ }, r = j.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
628
676
  ...t,
629
677
  videoCapabilities: t.videoCapabilities?.map((t) => ({
630
678
  ...t,
@@ -633,53 +681,53 @@ function N(e, t) {
633
681
  })));
634
682
  return [...t, ...r];
635
683
  }
636
- function P(e) {
637
- return (t, n) => j() ? navigator.requestMediaKeySystemAccess(t, N(t, n)).then((t) => ({
684
+ function He(e) {
685
+ return (t, n) => A() ? navigator.requestMediaKeySystemAccess(t, M(t, n)).then((t) => ({
638
686
  keySystem: t.keySystem,
639
687
  getConfiguration: () => t.getConfiguration(),
640
- createMediaKeys: () => Oe(e, t)
688
+ createMediaKeys: () => Be(e, t)
641
689
  })) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
642
690
  }
643
- var F = {
691
+ var N = {
644
692
  video: "SW_SECURE_DECODE",
645
693
  audio: "SW_SECURE_CRYPTO",
646
694
  scheme: "cbcs"
647
695
  };
648
- function Ae(e) {
649
- if (!j()) return;
696
+ function Ue(e) {
697
+ if (!A()) return;
650
698
  let t = (e, t) => ({
651
699
  contentType: e,
652
700
  robustness: t,
653
- encryptionScheme: F.scheme
701
+ encryptionScheme: N.scheme
654
702
  });
655
- P(e)("com.widevine.alpha", [{
703
+ He(e)("com.widevine.alpha", [{
656
704
  initDataTypes: ["cenc"],
657
705
  distinctiveIdentifier: "optional",
658
706
  persistentState: "optional",
659
707
  sessionTypes: ["temporary"],
660
- audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", F.audio)],
661
- videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", F.video)]
708
+ audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", N.audio)],
709
+ videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", N.video)]
662
710
  }]).then((e) => e.createMediaKeys()).catch(() => {});
663
711
  }
664
- function I(e) {
665
- let t = L(e);
712
+ function P(e) {
713
+ let t = F(e);
666
714
  if (/^avc[13]/.test(t)) return "avc";
667
715
  if (/^(hvc1|hev1)/.test(t)) return "hevc";
668
716
  if (/^(dvh1|dvhe)/.test(t)) return "dv";
669
717
  if (t.startsWith("av01")) return "av1";
670
718
  if (/^vp0?9/.test(t)) return "vp9";
671
719
  }
672
- function L(e) {
720
+ function F(e) {
673
721
  return (e ?? "").trim().toLowerCase();
674
722
  }
675
- var R = {
723
+ var We = {
676
724
  hevc: "hvc1.1.6.L93.90",
677
725
  dv: "dvh1.05.06",
678
726
  av1: "av01.0.05M.08",
679
727
  vp9: "vp09.00.10.08"
680
- }, je = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Map();
681
- function Me(e) {
682
- let t = L(e), n = je.get(t);
728
+ }, Ge = /* @__PURE__ */ new Map(), I = /* @__PURE__ */ new Map();
729
+ function Ke(e) {
730
+ let t = F(e), n = Ge.get(t);
683
731
  if (n) return n;
684
732
  let r = {
685
733
  initDataTypes: ["cenc"],
@@ -688,32 +736,32 @@ function Me(e) {
688
736
  sessionTypes: ["temporary"],
689
737
  videoCapabilities: [{
690
738
  contentType: `video/mp4; codecs="${e.trim()}"`,
691
- robustness: F.video,
692
- encryptionScheme: F.scheme
739
+ robustness: N.video,
740
+ encryptionScheme: N.scheme
693
741
  }]
694
742
  }, i = (async () => {
695
743
  try {
696
- return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", N("com.widevine.alpha", [r])), !0;
744
+ return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", M("com.widevine.alpha", [r])), !0;
697
745
  } catch {
698
746
  return !1;
699
747
  }
700
- })().then((e) => (z.set(t, e), e));
701
- return je.set(t, i), i;
748
+ })().then((e) => (I.set(t, e), e));
749
+ return Ge.set(t, i), i;
702
750
  }
703
- function Ne() {
704
- if (j()) for (let e of Object.values(R)) Me(e);
751
+ function qe() {
752
+ if (A()) for (let e of Object.values(We)) Ke(e);
705
753
  }
706
- function Pe(e) {
707
- let t = I(e);
708
- if (t) return t === "avc" ? !0 : z.get(L(e)) ?? z.get(L(R[t]));
754
+ function Je(e) {
755
+ let t = P(e);
756
+ if (t) return t === "avc" ? !0 : I.get(F(e)) ?? I.get(F(We[t]));
709
757
  }
710
758
  //#endregion
711
759
  //#region src/core/drm/support.ts
712
- var Fe = 5e3, Ie = "video/mp4; codecs=\"avc1.42E01E\"", Le = "audio/mp4; codecs=\"mp4a.40.2\"", Re = {
760
+ var Ye = 5e3, Xe = "video/mp4; codecs=\"avc1.42E01E\"", Ze = "audio/mp4; codecs=\"mp4a.40.2\"", Qe = {
713
761
  widevine: ["com.widevine.alpha"],
714
762
  fairplay: ["com.apple.fps"]
715
763
  };
716
- function ze(e) {
764
+ function $e(e) {
717
765
  return e === "fairplay" ? [{
718
766
  initDataTypes: [
719
767
  "sinf",
@@ -721,30 +769,30 @@ function ze(e) {
721
769
  "cenc"
722
770
  ],
723
771
  videoCapabilities: [{
724
- contentType: Ie,
772
+ contentType: Xe,
725
773
  robustness: "",
726
774
  encryptionScheme: "cbcs"
727
775
  }],
728
776
  audioCapabilities: [{
729
- contentType: Le,
777
+ contentType: Ze,
730
778
  robustness: "",
731
779
  encryptionScheme: "cbcs"
732
780
  }]
733
- }] : N("com.widevine.alpha", [{
781
+ }] : M("com.widevine.alpha", [{
734
782
  initDataTypes: ["cenc"],
735
783
  videoCapabilities: [{
736
- contentType: Ie,
737
- robustness: F.video,
738
- encryptionScheme: F.scheme
784
+ contentType: Xe,
785
+ robustness: N.video,
786
+ encryptionScheme: N.scheme
739
787
  }],
740
788
  audioCapabilities: [{
741
- contentType: Le,
742
- robustness: F.audio,
743
- encryptionScheme: F.scheme
789
+ contentType: Ze,
790
+ robustness: N.audio,
791
+ encryptionScheme: N.scheme
744
792
  }]
745
793
  }]);
746
794
  }
747
- function Be(e, t) {
795
+ function et(e, t) {
748
796
  return new Promise((n, r) => {
749
797
  let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
750
798
  e.then((e) => {
@@ -754,8 +802,8 @@ function Be(e, t) {
754
802
  });
755
803
  });
756
804
  }
757
- async function Ve(e = {}) {
758
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Fe, r = {};
805
+ async function tt(e = {}) {
806
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ye, r = {};
759
807
  if (typeof window < "u" && window.isSecureContext === !1) return {
760
808
  verdict: "insecure-context",
761
809
  detail: r
@@ -767,7 +815,7 @@ async function Ve(e = {}) {
767
815
  };
768
816
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
769
817
  for (let e of t) {
770
- let t = Re[e];
818
+ let t = Qe[e];
771
819
  if (!t) {
772
820
  r[e] = "unknown system";
773
821
  continue;
@@ -778,7 +826,7 @@ async function Ve(e = {}) {
778
826
  break;
779
827
  }
780
828
  try {
781
- return await Be((await Be(i(n, ze(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
829
+ return await et((await et(i(n, $e(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
782
830
  verdict: "supported",
783
831
  system: e,
784
832
  detail: r
@@ -802,37 +850,37 @@ async function Ve(e = {}) {
802
850
  }
803
851
  //#endregion
804
852
  //#region src/core/manifest.ts
805
- var He = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
806
- function Ue(e) {
807
- return He.test(e);
853
+ var nt = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
854
+ function rt(e) {
855
+ return nt.test(e);
808
856
  }
809
857
  //#endregion
810
858
  //#region src/core/env.ts
811
- var We = {
859
+ var it = {
812
860
  integration: "https://feed-dev.oddin-video.gg",
813
861
  production: "https://feed.oddin-video.gg"
814
862
  };
815
- function Ge(e) {
816
- let t = Object.prototype.hasOwnProperty.call(We, e) ? We[e] : void 0;
863
+ function L(e) {
864
+ let t = Object.prototype.hasOwnProperty.call(it, e) ? it[e] : void 0;
817
865
  if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
818
866
  return t;
819
867
  }
820
868
  //#endregion
821
869
  //#region src/core/stats.ts
822
- var Ke = { droppedFrames: 0 };
823
- function qe(e) {
870
+ var R = { droppedFrames: 0 };
871
+ function z(e) {
824
872
  try {
825
873
  return new URL(e).host;
826
874
  } catch {
827
875
  return "";
828
876
  }
829
877
  }
830
- var Je = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
831
- function Ye(e) {
878
+ var at = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
879
+ function ot(e) {
832
880
  if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
833
881
  let t = "", n = -1, r = performance.getEntriesByType("resource");
834
- for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Je.test(i.name)) && i.startTime >= n) {
835
- let e = qe(i.name);
882
+ for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || at.test(i.name)) && i.startTime >= n) {
883
+ let e = z(i.name);
836
884
  e && (t = e, n = i.startTime);
837
885
  }
838
886
  return t;
@@ -844,7 +892,7 @@ function B(e) {
844
892
  totalFrames: t?.totalVideoFrames ?? 0
845
893
  };
846
894
  }
847
- var Xe = class {
895
+ var st = class {
848
896
  video;
849
897
  baseFrames = 0;
850
898
  baseDropped = 0;
@@ -867,7 +915,7 @@ var Xe = class {
867
915
  };
868
916
  }
869
917
  };
870
- function Ze(e, t) {
918
+ function ct(e, t) {
871
919
  let n = [
872
920
  ["playing", () => t("playing")],
873
921
  ["waiting", () => t("buffering")],
@@ -884,8 +932,8 @@ function Ze(e, t) {
884
932
  }
885
933
  //#endregion
886
934
  //#region src/core/engine/native.ts
887
- var Qe = 2e3, $e = 3, V = 500, et = 6e3, tt = .25, nt = 250, rt = .05, it = 4, at = 12e3, ot = .25, st = 1e3;
888
- function ct(e) {
935
+ var lt = 2e3, ut = 3, V = 500, dt = 6e3, ft = .25, pt = 250, mt = .05, ht = 4, gt = 12e3, _t = .25, vt = 1e3;
936
+ function yt(e) {
889
937
  try {
890
938
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
891
939
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -901,7 +949,7 @@ function U() {
901
949
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
902
950
  return e || t;
903
951
  }
904
- function lt() {
952
+ function bt() {
905
953
  if (typeof navigator > "u" || !U()) return !1;
906
954
  let e = navigator.userAgent ?? "";
907
955
  return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
@@ -936,7 +984,7 @@ var W = class {
936
984
  frameCounter;
937
985
  detachFrames = null;
938
986
  constructor(e) {
939
- this.deps = e, this.frameCounter = new Xe(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
987
+ this.deps = e, this.frameCounter = new st(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
940
988
  }
941
989
  async load() {
942
990
  this.detachFrames ??= this.frameCounter.attach();
@@ -957,7 +1005,7 @@ var W = class {
957
1005
  type: "error",
958
1006
  error: new n("INTERNAL", 0, "native HLS playback error"),
959
1007
  fatal: !0
960
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = dt(t.manifestUrl, t.analytics?.sid), e.load();
1008
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = St(t.manifestUrl, t.analytics?.sid), e.load();
961
1009
  }
962
1010
  startLoad() {
963
1011
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -979,7 +1027,7 @@ var W = class {
979
1027
  });
980
1028
  this.onEncrypted = (n) => {
981
1029
  let i = n;
982
- i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = ct(i.initData), (async () => {
1030
+ i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = yt(i.initData), (async () => {
983
1031
  try {
984
1032
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
985
1033
  initDataTypes: [i.initDataType],
@@ -1078,10 +1126,10 @@ var W = class {
1078
1126
  droppedFrames: t.dropped,
1079
1127
  decodedFrames: t.totalFrames
1080
1128
  };
1081
- if (this.cdnHost ||= Ye(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1129
+ if (this.cdnHost ||= ot(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
1082
1130
  n.isLive = !0;
1083
1131
  let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
1084
- Number.isFinite(r) && (n.atLiveEdge = r <= it, !e.paused && r >= 0 && (n.latencySeconds = r));
1132
+ Number.isFinite(r) && (n.atLiveEdge = r <= ht, !e.paused && r >= 0 && (n.latencySeconds = r));
1085
1133
  } else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
1086
1134
  return n;
1087
1135
  }
@@ -1099,7 +1147,7 @@ var W = class {
1099
1147
  return;
1100
1148
  }
1101
1149
  let t = this.hiddenSince;
1102
- this.hiddenSince = null, t != null && e - t >= Qe && this.armRefocus();
1150
+ this.hiddenSince = null, t != null && e - t >= lt && this.armRefocus();
1103
1151
  }, this.onPageShow = (e) => {
1104
1152
  e.persisted && this.armRefocus();
1105
1153
  }, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
@@ -1109,7 +1157,7 @@ var W = class {
1109
1157
  let e = this.liveEnd(), t = G, n = t(), r = 0, i = () => {
1110
1158
  if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
1111
1159
  r += V;
1112
- let a = this.liveEnd(), o = a != null && (e == null || a >= e + tt), s = Math.max(r, t() - n) >= et;
1160
+ let a = this.liveEnd(), o = a != null && (e == null || a >= e + ft), s = Math.max(r, t() - n) >= dt;
1113
1161
  if (o || s && a != null) {
1114
1162
  this.snapToLive();
1115
1163
  return;
@@ -1129,9 +1177,9 @@ var W = class {
1129
1177
  }, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
1130
1178
  if (e.duration !== Infinity) return;
1131
1179
  this.checkEndStale();
1132
- let t = ut(e, e.currentTime);
1133
- t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= rt) && (this.bufferedAdvancedAt = G()), this.lastBufferedEnd = t);
1134
- }, nt);
1180
+ let t = xt(e, e.currentTime);
1181
+ t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= mt) && (this.bufferedAdvancedAt = G()), this.lastBufferedEnd = t);
1182
+ }, pt);
1135
1183
  }
1136
1184
  checkEndStale() {
1137
1185
  if (this.endedEmitted) return;
@@ -1139,14 +1187,14 @@ var W = class {
1139
1187
  this.lastTickAt = e;
1140
1188
  let n = this.liveEnd();
1141
1189
  if (n == null) return;
1142
- let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= ot;
1190
+ let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= _t;
1143
1191
  this.lastSeekableEnd = n;
1144
1192
  let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
1145
- if (r || t > st || a || i.paused) {
1193
+ if (r || t > vt || a || i.paused) {
1146
1194
  this.edgeStampedAt = e;
1147
1195
  return;
1148
1196
  }
1149
- e - (this.edgeStampedAt ?? e) > at && (this.endedEmitted = !0, this.deps.emit({
1197
+ e - (this.edgeStampedAt ?? e) > gt && (this.endedEmitted = !0, this.deps.emit({
1150
1198
  type: "ended",
1151
1199
  reason: "stalled"
1152
1200
  }));
@@ -1160,7 +1208,7 @@ var W = class {
1160
1208
  liveEdgeEstimate() {
1161
1209
  let e = this.deps.video;
1162
1210
  if (e.duration !== Infinity) return null;
1163
- let t = this.liveEnd(), n = ut(e, e.currentTime) ?? this.lastBufferedEnd;
1211
+ let t = this.liveEnd(), n = xt(e, e.currentTime) ?? this.lastBufferedEnd;
1164
1212
  if (n != null) {
1165
1213
  let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (G() - e) / 1e3));
1166
1214
  (t == null || r > t) && (t = r);
@@ -1176,7 +1224,7 @@ var W = class {
1176
1224
  snapToLive() {
1177
1225
  let e = this.deps.video, t = this.liveEnd();
1178
1226
  if (t == null) return;
1179
- let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - $e, r);
1227
+ let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - ut, r);
1180
1228
  try {
1181
1229
  e.currentTime = i;
1182
1230
  } catch {}
@@ -1197,7 +1245,7 @@ var W = class {
1197
1245
  function G() {
1198
1246
  return typeof performance < "u" ? performance.now() : Date.now();
1199
1247
  }
1200
- function ut(e, t) {
1248
+ function xt(e, t) {
1201
1249
  let n = e.buffered;
1202
1250
  if (!n || !Number.isFinite(t)) return null;
1203
1251
  for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
@@ -1206,7 +1254,7 @@ function ut(e, t) {
1206
1254
  }
1207
1255
  return null;
1208
1256
  }
1209
- function dt(e, t) {
1257
+ function St(e, t) {
1210
1258
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
1211
1259
  }
1212
1260
  //#endregion
@@ -1223,8 +1271,8 @@ function K(e, t = Date.now()) {
1223
1271
  }
1224
1272
  //#endregion
1225
1273
  //#region src/core/engine/prefetch.ts
1226
- var ft = 15e3, pt = 5e3, mt = 6;
1227
- function ht(e) {
1274
+ var Ct = 15e3, wt = 5e3, Tt = 6;
1275
+ function Et(e) {
1228
1276
  try {
1229
1277
  let t = new URL(e);
1230
1278
  return t.searchParams.delete("CMCD"), t.toString();
@@ -1232,7 +1280,7 @@ function ht(e) {
1232
1280
  return e;
1233
1281
  }
1234
1282
  }
1235
- var gt = class {
1283
+ var Dt = class {
1236
1284
  cmcd;
1237
1285
  entries = /* @__PURE__ */ new Map();
1238
1286
  keyed = /* @__PURE__ */ new Set();
@@ -1255,10 +1303,10 @@ var gt = class {
1255
1303
  }
1256
1304
  prefetch(e, t, n) {
1257
1305
  if (!this.isActive(t)) return;
1258
- let r = ht(e);
1306
+ let r = Et(e);
1259
1307
  if (this.entries.has(r)) return;
1260
1308
  let i = this.perTrack.get(t) ?? 0;
1261
- if (i >= mt) return;
1309
+ if (i >= Tt) return;
1262
1310
  this.perTrack.set(t, i + 1);
1263
1311
  let a = new AbortController(), o = {
1264
1312
  started: performance.now(),
@@ -1272,10 +1320,10 @@ var gt = class {
1272
1320
  signal: a.signal
1273
1321
  }).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
1274
1322
  this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
1275
- }, ft);
1323
+ }, Ct);
1276
1324
  }
1277
1325
  take(e) {
1278
- let t = ht(e), n = this.entries.get(t);
1326
+ let t = Et(e), n = this.entries.get(t);
1279
1327
  return n && this.entries.delete(t), n;
1280
1328
  }
1281
1329
  destroy() {
@@ -1295,13 +1343,13 @@ var gt = class {
1295
1343
  }
1296
1344
  }
1297
1345
  };
1298
- function _t(t) {
1346
+ function Ot(t) {
1299
1347
  let n = e.DefaultConfig?.loader;
1300
1348
  if (typeof n != "function") return;
1301
1349
  class r extends n {
1302
1350
  served = !1;
1303
1351
  cancelled = !1;
1304
- stats = vt();
1352
+ stats = kt();
1305
1353
  load(e, n, r) {
1306
1354
  let i = e.rangeEnd ? void 0 : t.take(e.url);
1307
1355
  if (!i) {
@@ -1309,7 +1357,7 @@ function _t(t) {
1309
1357
  return;
1310
1358
  }
1311
1359
  this.served = !0;
1312
- let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || pt, s = setTimeout(() => {
1360
+ let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || wt, s = setTimeout(() => {
1313
1361
  !this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
1314
1362
  }, o);
1315
1363
  i.bytes.then((o) => {
@@ -1336,7 +1384,7 @@ function _t(t) {
1336
1384
  }
1337
1385
  return r;
1338
1386
  }
1339
- function vt() {
1387
+ function kt() {
1340
1388
  return {
1341
1389
  aborted: !1,
1342
1390
  loaded: 0,
@@ -1360,10 +1408,10 @@ function vt() {
1360
1408
  }
1361
1409
  };
1362
1410
  }
1363
- function q(e) {
1411
+ function At(e) {
1364
1412
  return e === "audio" ? "audio" : "main";
1365
1413
  }
1366
- function yt(e, t) {
1414
+ function jt(e, t) {
1367
1415
  let n = [];
1368
1416
  t.initSegment?.url && !t.initSegment.data && n.push({
1369
1417
  url: t.initSegment.url,
@@ -1382,24 +1430,24 @@ function yt(e, t) {
1382
1430
  }
1383
1431
  //#endregion
1384
1432
  //#region src/core/engine/hls.ts
1385
- function bt() {
1433
+ function Mt() {
1386
1434
  return e.isSupported();
1387
1435
  }
1388
- var xt = 3, St = 5, Ct = 3, wt = 1e4, Tt = 3e4, Et = 12e3, Dt = 3e3, Ot = .02, kt = 6e3, At = .5, jt = 3, Mt = .5, Nt = 1.1, Pt = .25, Ft = 5e3, It = 4e3, Lt = 2, Rt = 5, zt = 2, Bt = 2, Vt = 4, Ht = 4, Ut = 2e3, Wt = 3e4, Gt = .2, Kt = 30, qt = 2, Jt = 2, Yt = 9, Xt = .5, Zt = 64;
1389
- function Qt(e) {
1436
+ var Nt = 1e6, Pt = 20, Ft = 1e4, It = 3, Lt = 5, Rt = 3, zt = 1e4, Bt = 3e4, Vt = 12e3, Ht = 3e3, Ut = .02, Wt = 6e3, Gt = .5, Kt = 3, qt = .5, Jt = 1.1, Yt = .25, Xt = 5e3, Zt = 4e3, Qt = 2, $t = 5, en = 2, tn = 2, nn = 4, rn = 4, an = 2e3, on = 3e4, sn = .2, cn = 30, ln = 2, un = 2, dn = 9, fn = .5, pn = 64;
1437
+ function mn(e) {
1390
1438
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
1391
1439
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
1392
1440
  return;
1393
1441
  }
1394
- e.liveSyncDuration ??= Jt;
1395
- let t = Math.max(12, e.liveSyncDuration + Yt);
1396
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), $t(e, e.liveSyncDuration);
1442
+ e.liveSyncDuration ??= un;
1443
+ let t = Math.max(12, e.liveSyncDuration + dn);
1444
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), hn(e, e.liveSyncDuration);
1397
1445
  }
1398
- function $t(e, t) {
1446
+ function hn(e, t) {
1399
1447
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
1400
1448
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
1401
1449
  }
1402
- var en = class {
1450
+ var gn = class {
1403
1451
  name = "hls";
1404
1452
  hls = null;
1405
1453
  deps;
@@ -1451,6 +1499,8 @@ var en = class {
1451
1499
  starvedFrames = 0;
1452
1500
  deadTicks = 0;
1453
1501
  mainFragsSinceTick = 0;
1502
+ bwFragsLoaded = 0;
1503
+ bwSavedAt = 0;
1454
1504
  recentMainFrags = [];
1455
1505
  chaseSuspended = !1;
1456
1506
  savedLiveMaxLatency;
@@ -1481,7 +1531,7 @@ var en = class {
1481
1531
  frameCounter;
1482
1532
  detachFrames = null;
1483
1533
  constructor(e) {
1484
- this.deps = e, this.frameCounter = new Xe(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1534
+ this.deps = e, this.frameCounter = new st(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1485
1535
  }
1486
1536
  async load() {
1487
1537
  this.detachFrames ??= this.frameCounter.attach();
@@ -1494,7 +1544,7 @@ var en = class {
1494
1544
  });
1495
1545
  return;
1496
1546
  }
1497
- e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Ne()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1547
+ e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ue(r), qe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1498
1548
  let e = this.hls;
1499
1549
  if (document.visibilityState !== "visible" || !e) return;
1500
1550
  let t = e.liveSyncPosition;
@@ -1517,7 +1567,7 @@ var en = class {
1517
1567
  }
1518
1568
  this.loadSuspended = !0;
1519
1569
  }
1520
- }, Ft));
1570
+ }, Xt));
1521
1571
  }
1522
1572
  resumeLoading() {
1523
1573
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1549,7 +1599,7 @@ var en = class {
1549
1599
  let t = e.liveSyncPosition;
1550
1600
  if (typeof t != "number" || !Number.isFinite(t)) return;
1551
1601
  let { video: n } = this.deps;
1552
- n.currentTime <= t + Xt || (n.currentTime = t);
1602
+ n.currentTime <= t + fn || (n.currentTime = t);
1553
1603
  }
1554
1604
  reanchorPartTimeline(e, t) {
1555
1605
  let { frag: n, part: r } = t;
@@ -1561,7 +1611,7 @@ var en = class {
1561
1611
  let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
1562
1612
  if (!s) return;
1563
1613
  let c = a.startPTS - s.start;
1564
- if (!(!Number.isFinite(c) || Math.abs(c) < Ot)) {
1614
+ if (!(!Number.isFinite(c) || Math.abs(c) < Ut)) {
1565
1615
  for (let e of i.fragments) e && e.setStart(e.start + c);
1566
1616
  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})`);
1567
1617
  }
@@ -1577,19 +1627,19 @@ var en = class {
1577
1627
  liveDurationInfinity: !0,
1578
1628
  maxBufferHole: .5,
1579
1629
  maxLiveSyncPlaybackRate: d ? 1 : 1.1,
1580
- abrEwmaDefaultEstimate: 1e6,
1630
+ abrEwmaDefaultEstimate: this.startEstimate(),
1581
1631
  capLevelToPlayerSize: !1,
1582
1632
  ...this.loadStarted ? {} : { autoStartLoad: !1 },
1583
1633
  ...u ? {
1584
1634
  emeEnabled: !0,
1585
1635
  drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
1586
1636
  drmSystemOptions: {
1587
- videoRobustness: F.video,
1588
- audioRobustness: F.audio,
1589
- videoEncryptionScheme: F.scheme,
1590
- audioEncryptionScheme: F.scheme
1637
+ videoRobustness: N.video,
1638
+ audioRobustness: N.audio,
1639
+ videoEncryptionScheme: N.scheme,
1640
+ audioEncryptionScheme: N.scheme
1591
1641
  },
1592
- ...j() ? { requestMediaKeySystemAccessFunc: P(t) } : {},
1642
+ ...A() ? { requestMediaKeySystemAccessFunc: He(t) } : {},
1593
1643
  licenseXhrSetup: (e, t) => {
1594
1644
  let o = performance.now(), s = () => {
1595
1645
  e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a), this.licenseRequested = !0, e.addEventListener("loadend", () => {
@@ -1601,7 +1651,7 @@ var en = class {
1601
1651
  return;
1602
1652
  }
1603
1653
  let l = this.hls, u, d = new Promise((e) => {
1604
- u = setTimeout(() => e(void 0), wt);
1654
+ u = setTimeout(() => e(void 0), zt);
1605
1655
  });
1606
1656
  return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
1607
1657
  if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
@@ -1617,31 +1667,31 @@ var en = class {
1617
1667
  ...c
1618
1668
  };
1619
1669
  if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !f.fLoader) {
1620
- let e = new gt({
1670
+ let e = new Dt({
1621
1671
  sessionId: n.analytics?.sid,
1622
1672
  contentId: n.matchUrn
1623
- }), t = _t(e);
1673
+ }), t = Ot(e);
1624
1674
  t && (this.prefetch = e, f.fLoader = t);
1625
1675
  }
1626
- Qt(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
1676
+ mn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
1627
1677
  let p = new e(f);
1628
1678
  if (this.hls = p, p.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(p, t)), p.on(e.Events.MANIFEST_PARSED, () => {
1629
1679
  this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(p), this.measureLadder(p), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
1630
1680
  }), p.on(e.Events.FRAG_BUFFERED, (e, t) => {
1631
1681
  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(() => {
1632
1682
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1633
- }, Tt)));
1683
+ }, Bt)));
1634
1684
  }), p.on(e.Events.FRAG_LOADING, (e, t) => {
1635
1685
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1636
1686
  }), p.on(e.Events.FRAG_LOADED, (e, t) => {
1637
- t?.frag?.type === "main" && (this.mainFragsSinceTick += 1);
1687
+ t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
1638
1688
  let n = t?.frag?.stats, r = n?.loaded;
1639
1689
  typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1640
1690
  let i = n?.loading;
1641
- 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 > Zt && this.requestTimesMs.shift());
1691
+ 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 > pn && this.requestTimesMs.shift());
1642
1692
  let a = t?.frag?.url;
1643
1693
  if (a) {
1644
- let e = qe(a);
1694
+ let e = z(a);
1645
1695
  e && (this.cdnHost = e);
1646
1696
  }
1647
1697
  }), p.on(e.Events.LEVEL_LOADED, (e, t) => {
@@ -1655,15 +1705,15 @@ var en = class {
1655
1705
  }), p.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
1656
1706
  let t = this.prefetch;
1657
1707
  p.on(e.Events.KEY_LOADING, (e, n) => {
1658
- let r = n?.frag, i = q(r?.type);
1659
- if (r && t.isActive(i)) for (let e of yt(p, r)) t.prefetch(e.url, i, e.kind);
1660
- }), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(q(n?.frag?.type)));
1708
+ let r = n?.frag, i = At(r?.type);
1709
+ if (r && t.isActive(i)) for (let e of jt(p, r)) t.prefetch(e.url, i, e.kind);
1710
+ }), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(At(n?.frag?.type)));
1661
1711
  }
1662
1712
  p.on(e.Events.KEY_LOADED, () => {
1663
1713
  u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
1664
1714
  }), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1665
1715
  this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
1666
- }, Dt), p.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1716
+ }, Ht), p.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1667
1717
  this.renditionSwitches += 1;
1668
1718
  let n = this.lastLevelIndex >= 0 ? p.levels[this.lastLevelIndex] : void 0, r = p.levels[t.level];
1669
1719
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
@@ -1727,7 +1777,7 @@ var en = class {
1727
1777
  return;
1728
1778
  }
1729
1779
  this.capTimer && clearTimeout(this.capTimer);
1730
- let t = e > this.sizeCapLevel ? Ut : Wt;
1780
+ let t = e > this.sizeCapLevel ? an : on;
1731
1781
  this.capTimer = setTimeout(() => {
1732
1782
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1733
1783
  }, t);
@@ -1737,9 +1787,9 @@ var en = class {
1737
1787
  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;
1738
1788
  }
1739
1789
  dropLevelsWidevineCannotPlay(e) {
1740
- this.removeLevelsWhere(e, (e) => Pe(e) !== !0);
1741
- let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
1742
- for (let n of t) Me(n).then((t) => {
1790
+ this.removeLevelsWhere(e, (e) => Je(e) !== !0);
1791
+ let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && P(e) !== "avc" && !!P(e)));
1792
+ for (let n of t) Ke(n).then((t) => {
1743
1793
  t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
1744
1794
  });
1745
1795
  }
@@ -1747,10 +1797,10 @@ var en = class {
1747
1797
  let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
1748
1798
  if (n.forEach((e, n) => {
1749
1799
  let a = e.videoCodec;
1750
- a && I(a) && t(a) && (r.push(n), i.add(a));
1800
+ a && P(a) && t(a) && (r.push(n), i.add(a));
1751
1801
  }), !r.length) return !1;
1752
1802
  let a = [...i].join(", ");
1753
- 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;
1803
+ if (!n.some((e, t) => r.includes(t) ? !1 : !P(e.videoCodec) || Je(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1754
1804
  for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
1755
1805
  return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
1756
1806
  }
@@ -1856,7 +1906,7 @@ var en = class {
1856
1906
  return;
1857
1907
  }
1858
1908
  let e = Date.now() - this.lastAdvanceMs;
1859
- !this.chaseSuspended && e > kt && this.suspendChasing(), e > Et && this.emitEnded("stalled");
1909
+ !this.chaseSuspended && e > Wt && this.suspendChasing(), e > Vt && this.emitEnded("stalled");
1860
1910
  }
1861
1911
  resetStarvationWindow() {
1862
1912
  this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
@@ -1871,7 +1921,7 @@ var en = class {
1871
1921
  this.resetStarvationWindow();
1872
1922
  return;
1873
1923
  }
1874
- let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < kt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > It, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
1924
+ let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < Wt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Zt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
1875
1925
  if (this.starvedFrames = c, !a || l) {
1876
1926
  (t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
1877
1927
  return;
@@ -1880,12 +1930,12 @@ var en = class {
1880
1930
  this.resetStarvationWindow();
1881
1931
  return;
1882
1932
  }
1883
- 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 > Vt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= zt && (this.clearKick(), this.starvationRebuilds < Bt)) {
1933
+ 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 > nn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= en && (this.clearKick(), this.starvationRebuilds < tn)) {
1884
1934
  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");
1885
1935
  return;
1886
1936
  }
1887
- let u = i && this.starvedTicks >= Lt, d = !i && this.deadTicks >= Vt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Ht;
1888
- if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= Rt))) {
1937
+ let u = i && this.starvedTicks >= Qt, d = !i && this.deadTicks >= nn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= rn;
1938
+ if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= $t))) {
1889
1939
  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");
1890
1940
  try {
1891
1941
  e.stopLoad(), e.startLoad(-1);
@@ -1900,7 +1950,7 @@ var en = class {
1900
1950
  let t = e.latency, n = e.targetLatency;
1901
1951
  if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
1902
1952
  let r = t - n;
1903
- !this.catchUpEngaged && r > At ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= At && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
1953
+ !this.catchUpEngaged && r > Gt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Gt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
1904
1954
  let i = this.catchUpEngaged ? this.catchUpRate : 1;
1905
1955
  e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
1906
1956
  }
@@ -1922,15 +1972,15 @@ var en = class {
1922
1972
  return;
1923
1973
  }
1924
1974
  let { totalFrames: n, dropped: r } = B(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
1925
- if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Kt || o < 0) {
1975
+ if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < cn || o < 0) {
1926
1976
  this.fpsBadTicks = 0;
1927
1977
  return;
1928
1978
  }
1929
- if (o <= Gt * a) {
1979
+ if (o <= sn * a) {
1930
1980
  this.fpsBadTicks = 0;
1931
1981
  return;
1932
1982
  }
1933
- if (this.fpsBadTicks += 1, this.fpsBadTicks < qt) return;
1983
+ if (this.fpsBadTicks += 1, this.fpsBadTicks < ln) return;
1934
1984
  this.fpsBadTicks = 0;
1935
1985
  let s = e.levels, c = s[e.currentLevel];
1936
1986
  if (!c) return;
@@ -1947,20 +1997,20 @@ var en = class {
1947
1997
  return;
1948
1998
  }
1949
1999
  let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
1950
- if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Nt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
2000
+ if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Jt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
1951
2001
  this.resetChaseWindow();
1952
2002
  return;
1953
2003
  }
1954
- if (this.chaseLatency < 0 || this.chaseLatency - n >= Mt) {
2004
+ if (this.chaseLatency < 0 || this.chaseLatency - n >= qt) {
1955
2005
  this.chaseLatency = n, this.chaseTicks = 0;
1956
2006
  return;
1957
2007
  }
1958
- if (this.chaseTicks += 1, this.chaseTicks < jt) return;
2008
+ if (this.chaseTicks += 1, this.chaseTicks < Kt) return;
1959
2009
  this.resetChaseWindow();
1960
2010
  let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
1961
2011
  if (!(a > 1)) return;
1962
2012
  let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
1963
- s < o + Pt || (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);
2013
+ s < o + Yt || (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);
1964
2014
  }
1965
2015
  suspendChasing() {
1966
2016
  let e = this.hls;
@@ -1989,8 +2039,18 @@ var en = class {
1989
2039
  this.deps.video.pause();
1990
2040
  } catch {}
1991
2041
  }
2042
+ startEstimate() {
2043
+ return this.deps.rememberBandwidth === !1 ? Nt : Ie() ?? Nt;
2044
+ }
2045
+ maybeRememberBandwidth(e) {
2046
+ if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Pt) return;
2047
+ let t = Date.now();
2048
+ if (!e && t - this.bwSavedAt < Ft) return;
2049
+ let n = this.hls?.bandwidthEstimate;
2050
+ typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Le(n));
2051
+ }
1992
2052
  destroy() {
1993
- if (this.detachFrames?.(), this.detachFrames = null, this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
2053
+ if (this.maybeRememberBandwidth(!0), this.detachFrames?.(), this.detachFrames = null, this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
1994
2054
  try {
1995
2055
  this.hls.destroy();
1996
2056
  } catch (e) {
@@ -2005,7 +2065,7 @@ var en = class {
2005
2065
  scheduleLicenseRetry(t) {
2006
2066
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
2007
2067
  let n = t.response?.code ?? 0;
2008
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Ct) return !1;
2068
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Rt) return !1;
2009
2069
  this.licenseRecoveries += 1;
2010
2070
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
2011
2071
  return this.licenseRetryTimer = setTimeout(() => {
@@ -2037,7 +2097,7 @@ var en = class {
2037
2097
  return;
2038
2098
  }
2039
2099
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
2040
- if (this.networkRecoveries < St) {
2100
+ if (this.networkRecoveries < Lt) {
2041
2101
  this.networkRecoveries += 1;
2042
2102
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
2043
2103
  this.networkRetryTimer = setTimeout(() => {
@@ -2054,7 +2114,7 @@ var en = class {
2054
2114
  return;
2055
2115
  }
2056
2116
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
2057
- if (this.mediaRecoveries < xt) {
2117
+ if (this.mediaRecoveries < It) {
2058
2118
  this.mediaRecoveries += 1, n.recoverMediaError();
2059
2119
  return;
2060
2120
  }
@@ -2078,19 +2138,19 @@ var en = class {
2078
2138
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
2079
2139
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
2080
2140
  }
2081
- }, tn = 15e3, nn = 6e5, rn = 3e5, an = 100, J = 1, on = 1e3, sn = 3e4, cn = 1e3, ln = {
2141
+ }, _n = 15e3, vn = 6e5, yn = 3e5, bn = 100, q = 1, xn = 1e3, Sn = 3e4, Cn = 1e3, wn = {
2082
2142
  inline: "PRESENTATION_INLINE",
2083
2143
  fullscreen: "PRESENTATION_FULLSCREEN",
2084
2144
  pip: "PRESENTATION_PIP"
2085
- }, un = {
2145
+ }, Tn = {
2086
2146
  widevine: "KEY_SYSTEM_WIDEVINE",
2087
2147
  fairplay: "KEY_SYSTEM_FAIRPLAY",
2088
2148
  none: "KEY_SYSTEM_NONE"
2089
2149
  };
2090
- function dn(e, t) {
2150
+ function En(e, t) {
2091
2151
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
2092
2152
  }
2093
- var fn = /* @__PURE__ */ new Set([
2153
+ var Dn = /* @__PURE__ */ new Set([
2094
2154
  "INVALID_URN",
2095
2155
  "NOT_FOUND",
2096
2156
  "GONE",
@@ -2100,7 +2160,7 @@ var fn = /* @__PURE__ */ new Set([
2100
2160
  "FORBIDDEN",
2101
2161
  "RATE_LIMITED",
2102
2162
  "TIMEOUT"
2103
- ]), Y = {
2163
+ ]), J = {
2104
2164
  idle: "PLAYER_STATE_IDLE",
2105
2165
  waiting: "PLAYER_STATE_WAITING",
2106
2166
  loading: "PLAYER_STATE_LOADING",
@@ -2110,7 +2170,7 @@ var fn = /* @__PURE__ */ new Set([
2110
2170
  ended: "PLAYER_STATE_ENDED",
2111
2171
  error: "PLAYER_STATE_ERROR"
2112
2172
  };
2113
- function pn(e) {
2173
+ function On(e) {
2114
2174
  try {
2115
2175
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
2116
2176
  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);
@@ -2118,8 +2178,8 @@ function pn(e) {
2118
2178
  return;
2119
2179
  }
2120
2180
  }
2121
- var mn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), hn = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), Z = /* @__PURE__ */ new Set(), gn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2122
- function _n(e) {
2181
+ var kn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), An = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), jn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
2182
+ function Mn(e) {
2123
2183
  if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
2124
2184
  let t;
2125
2185
  try {
@@ -2128,19 +2188,19 @@ function _n(e) {
2128
2188
  } catch {
2129
2189
  return;
2130
2190
  }
2131
- if (hn.has(t) && !X.has(t)) {
2132
- X.add(t), g(gn(new URL(t).origin));
2133
- for (let e of Z) e.noteCspBlocked();
2191
+ if (An.has(t) && !Y.has(t)) {
2192
+ Y.add(t), g(jn(new URL(t).origin));
2193
+ for (let e of X) e.noteCspBlocked();
2134
2194
  }
2135
2195
  }
2136
- function vn(e, t) {
2196
+ function Nn(e, t) {
2137
2197
  return g(t, e), { disabledReason: t };
2138
2198
  }
2139
- function yn(e, t, n) {
2140
- if (n) return t && !mn(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2199
+ function Pn(e, t, n) {
2200
+ if (n) return t && !kn(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
2141
2201
  if (t) return { endpoint: t };
2142
- if (t !== void 0) return vn("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).");
2143
- let r = pn(e);
2202
+ if (t !== void 0) return Nn("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).");
2203
+ let r = On(e);
2144
2204
  if (r) return { endpoint: r };
2145
2205
  let i;
2146
2206
  try {
@@ -2148,9 +2208,9 @@ function yn(e, t, n) {
2148
2208
  } catch {
2149
2209
  i = e;
2150
2210
  }
2151
- return vn(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).`);
2211
+ return Nn(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).`);
2152
2212
  }
2153
- var bn = class {
2213
+ var Fn = class {
2154
2214
  opts;
2155
2215
  url;
2156
2216
  cspKey;
@@ -2232,8 +2292,8 @@ var bn = class {
2232
2292
  constructor(e) {
2233
2293
  this.opts = {
2234
2294
  ...e,
2235
- heartbeatMs: e.heartbeatMs ?? tn,
2236
- idleMs: e.idleMs ?? nn
2295
+ heartbeatMs: e.heartbeatMs ?? _n,
2296
+ idleMs: e.idleMs ?? vn
2237
2297
  }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
2238
2298
  try {
2239
2299
  let e = new URL(this.url);
@@ -2250,11 +2310,11 @@ var bn = class {
2250
2310
  sdkVersion: this.opts.sdkVersion,
2251
2311
  ...this.opts.environment
2252
2312
  };
2253
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), on), 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 && hn.add(this.cspKey), document.addEventListener("securitypolicyviolation", _n), Z.add(this), this.noteCspBlocked(), this.onVisibility());
2313
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), xn), 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 && An.add(this.cspKey), document.addEventListener("securitypolicyviolation", Mn), X.add(this), this.noteCspBlocked(), this.onVisibility());
2254
2314
  }
2255
2315
  checkSuspension(e) {
2256
2316
  if (this.endedFlag || !this.opts.idleMs) return !1;
2257
- let t = Math.max(this.opts.idleMs, rn);
2317
+ let t = Math.max(this.opts.idleMs, yn);
2258
2318
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
2259
2319
  }
2260
2320
  syncIdle(e) {
@@ -2268,21 +2328,21 @@ var bn = class {
2268
2328
  noteStateChange(e, t, n, r) {
2269
2329
  if (this.endedFlag || e === t) return;
2270
2330
  let i = this.now();
2271
- if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(J, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(J, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
2331
+ if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(q, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(q, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
2272
2332
  this.stallIsSeekInduced = this.seekInduced(i);
2273
2333
  let e = !this.isHidden && !this.stallIsSeekInduced;
2274
- e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(J, Math.round(this.playingTotalMs)));
2334
+ e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(q, Math.round(this.playingTotalMs)));
2275
2335
  } else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
2276
2336
  this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
2277
2337
  let a = {
2278
- fromState: Y[e] ?? "PLAYER_STATE_UNSPECIFIED",
2279
- toState: Y[t] ?? "PLAYER_STATE_UNSPECIFIED",
2280
- presentation: ln[this.presentation]
2338
+ fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
2339
+ toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
2340
+ presentation: wn[this.presentation]
2281
2341
  }, o = this.causeOf(e, t, i);
2282
2342
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
2283
2343
  }
2284
2344
  seekInduced(e) {
2285
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < cn;
2345
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < Cn;
2286
2346
  }
2287
2347
  causeOf(e, t, n) {
2288
2348
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -2319,25 +2379,25 @@ var bn = class {
2319
2379
  }
2320
2380
  this.muteChanges += 1;
2321
2381
  let r = this.now();
2322
- n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(J, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
2382
+ n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(q, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
2323
2383
  }
2324
2384
  notePresentation(e) {
2325
2385
  this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
2326
2386
  }
2327
2387
  notePlayIntent() {
2328
- this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = J), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = J), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = J), this.drmSetupMs > 0 && (this.drmSetupMs = J));
2388
+ this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = q), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = q), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = q), this.drmSetupMs > 0 && (this.drmSetupMs = q));
2329
2389
  }
2330
2390
  noteReady() {
2331
- this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(J, this.now() - this.startupAnchorMs));
2391
+ this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(q, this.now() - this.startupAnchorMs));
2332
2392
  }
2333
2393
  noteFirstPlaylist() {
2334
- this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(J, this.now() - this.startupAnchorMs));
2394
+ this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(q, this.now() - this.startupAnchorMs));
2335
2395
  }
2336
2396
  noteDrmReady() {
2337
- this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(J, this.now() - this.startupAnchorMs));
2397
+ this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(q, this.now() - this.startupAnchorMs));
2338
2398
  }
2339
2399
  noteFirstBytes() {
2340
- this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(J, this.now() - this.startupAnchorMs));
2400
+ this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(q, this.now() - this.startupAnchorMs));
2341
2401
  }
2342
2402
  noteSeek() {
2343
2403
  this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
@@ -2356,7 +2416,7 @@ var bn = class {
2356
2416
  let r = n ?? "";
2357
2417
  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";
2358
2418
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
2359
- if (fn.has(e)) return "ERROR_STAGE_RESOLVE";
2419
+ if (Dn.has(e)) return "ERROR_STAGE_RESOLVE";
2360
2420
  let i = t ?? "";
2361
2421
  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";
2362
2422
  }
@@ -2388,7 +2448,7 @@ var bn = class {
2388
2448
  let l = t.droppedFrames ?? 0;
2389
2449
  l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
2390
2450
  let u = t.renditionSwitches ?? 0;
2391
- u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = Y[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
2451
+ u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = J[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
2392
2452
  let d = this.mutedTotalMs;
2393
2453
  this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
2394
2454
  let f = t.upshifts ?? 0;
@@ -2403,20 +2463,20 @@ var bn = class {
2403
2463
  if (this.lastRequestCount = g, _ > 0) {
2404
2464
  o.requestCountDelta = _;
2405
2465
  let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
2406
- n.length > 0 && (o.requestTimeP50Ms = dn(n, 50), o.requestTimeP95Ms = dn(n, 95));
2466
+ n.length > 0 && (o.requestTimeP50Ms = En(n, 50), o.requestTimeP95Ms = En(n, 95));
2407
2467
  }
2408
2468
  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();
2409
2469
  }
2410
2470
  maybeEmitMediaInfo(e) {
2411
2471
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
2412
2472
  let t = {};
2413
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = un[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);
2473
+ 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);
2414
2474
  let n = JSON.stringify(t);
2415
2475
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
2416
2476
  }
2417
2477
  end(e, t) {
2418
2478
  if (this.endedFlag) return;
2419
- this.endedFlag = !0, Z.delete(this);
2479
+ this.endedFlag = !0, X.delete(this);
2420
2480
  let n = t ?? this.now();
2421
2481
  this.playingSinceMs !== null && (this.playingTotalMs += n - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += n - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += n - this.bufferingSinceMs, this.bufferingSinceMs = null), this.mutedSinceMs !== null && (this.mutedTotalMs += n - this.mutedSinceMs, this.mutedSinceMs = null), this.waitingSinceMs !== null && (this.waitingTotalMs += n - this.waitingSinceMs, this.waitingSinceMs = null), this.isPlaying = !1, this.syncActive(n), this.closePresentation(n), this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.timer &&= (clearInterval(this.timer), null), this.idleTimer &&= (clearTimeout(this.idleTimer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), document.removeEventListener("freeze", this.onFreeze), document.removeEventListener("resume", this.onResume));
2422
2482
  let r = this.safeSample();
@@ -2430,7 +2490,7 @@ var bn = class {
2430
2490
  let c = r?.positionMs ?? 0;
2431
2491
  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));
2432
2492
  let l = e !== "END_REASON_ENDED";
2433
- l && this.lastStallMs > 0 && n - this.lastStallMs <= sn && (i.abandonAfterStallMs = Math.max(J, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= sn && (i.abandonAfterErrorMs = Math.max(J, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
2493
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= Sn && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Sn && (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);
2434
2494
  let u = r?.decodedFrames ?? this.lastDecoded;
2435
2495
  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");
2436
2496
  }
@@ -2450,13 +2510,13 @@ var bn = class {
2450
2510
  };
2451
2511
  }
2452
2512
  noteCspBlocked() {
2453
- this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(gn(new URL(this.url).origin)));
2513
+ this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(jn(new URL(this.url).origin)));
2454
2514
  }
2455
2515
  cspBlocked() {
2456
- return !!this.cspKey && X.has(this.cspKey);
2516
+ return !!this.cspKey && Y.has(this.cspKey);
2457
2517
  }
2458
2518
  enqueue(e) {
2459
- if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > an;) {
2519
+ if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > bn;) {
2460
2520
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
2461
2521
  this.pending.splice(e >= 0 ? e : 0, 1);
2462
2522
  }
@@ -2483,7 +2543,7 @@ var bn = class {
2483
2543
  };
2484
2544
  //#endregion
2485
2545
  //#region src/core/environment.ts
2486
- function xn() {
2546
+ function In() {
2487
2547
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
2488
2548
  let e;
2489
2549
  try {
@@ -2508,14 +2568,14 @@ function xn() {
2508
2568
  integration: "INTEGRATION_KIND_IFRAME"
2509
2569
  };
2510
2570
  }
2511
- function Sn() {
2571
+ function Ln() {
2512
2572
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
2513
2573
  let e = navigator.userAgentData, t = e?.platform ?? "";
2514
2574
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
2515
2575
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
2516
2576
  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";
2517
2577
  }
2518
- function Cn() {
2578
+ function Rn() {
2519
2579
  let e = typeof navigator < "u" ? navigator.connection : void 0;
2520
2580
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
2521
2581
  let t = {
@@ -2534,17 +2594,17 @@ function Cn() {
2534
2594
  }
2535
2595
  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;
2536
2596
  }
2537
- function wn(e) {
2538
- let t = xn(), n = {
2539
- deviceClass: Sn(),
2597
+ function zn(e) {
2598
+ let t = In(), n = {
2599
+ deviceClass: Ln(),
2540
2600
  integration: t.integration,
2541
- ...Cn()
2601
+ ...Rn()
2542
2602
  };
2543
2603
  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);
2544
2604
  let r = e.getBoundingClientRect?.();
2545
2605
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
2546
2606
  }
2547
- async function Tn() {
2607
+ async function Bn() {
2548
2608
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
2549
2609
  if (!e?.getHighEntropyValues) return {};
2550
2610
  try {
@@ -2556,7 +2616,7 @@ async function Tn() {
2556
2616
  }
2557
2617
  //#endregion
2558
2618
  //#region src/core/version.ts
2559
- var En = "2.17.0", Dn = {
2619
+ var Vn = "2.18.0", Hn = {
2560
2620
  accent: "#E1B600",
2561
2621
  accentText: "#1B1C23",
2562
2622
  background: "#0e0f13",
@@ -2567,7 +2627,7 @@ var En = "2.17.0", Dn = {
2567
2627
  border: "rgba(255, 255, 255, 0.1)",
2568
2628
  radius: "8px",
2569
2629
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
2570
- }, On = {
2630
+ }, Un = {
2571
2631
  accent: "--havik-accent",
2572
2632
  accentText: "--havik-accent-text",
2573
2633
  background: "--havik-bg",
@@ -2579,26 +2639,26 @@ var En = "2.17.0", Dn = {
2579
2639
  radius: "--havik-radius",
2580
2640
  fontFamily: "--havik-font"
2581
2641
  };
2582
- function kn(e, t) {
2642
+ function Wn(e, t) {
2583
2643
  let n = {
2584
- ...Dn,
2644
+ ...Hn,
2585
2645
  ...t
2586
2646
  };
2587
- for (let t of Object.keys(On)) e.style.setProperty(On[t], n[t]);
2647
+ for (let t of Object.keys(Un)) e.style.setProperty(Un[t], n[t]);
2588
2648
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
2589
2649
  }
2590
2650
  //#endregion
2591
2651
  //#region src/ui/styles.ts
2592
- var An = "havik-player-styles", jn = "\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", Mn = /* @__PURE__ */ new WeakMap();
2593
- function Nn(e = document, t) {
2594
- let n = e.querySelector(`style#${An}`);
2595
- if (n && (!t || Mn.get(n) === t)) return;
2652
+ var Gn = "havik-player-styles", Kn = "\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();
2653
+ function qn(e = document, t) {
2654
+ let n = e.querySelector(`style#${Gn}`);
2655
+ if (n && (!t || Z.get(n) === t)) return;
2596
2656
  let r = e.createElement("style");
2597
- r.id = An, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = jn, Mn.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2657
+ r.id = Gn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Kn, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
2598
2658
  }
2599
2659
  //#endregion
2600
2660
  //#region src/ui/icons.ts
2601
- var Pn = {
2661
+ var Jn = {
2602
2662
  play: "<path d=\"M8 5v14l11-7z\"/>",
2603
2663
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
2604
2664
  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\"/>",
@@ -2612,20 +2672,20 @@ var Pn = {
2612
2672
  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\"/>"
2613
2673
  };
2614
2674
  function Q(e) {
2615
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Pn[e]}</svg>`;
2675
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Jn[e]}</svg>`;
2616
2676
  }
2617
2677
  //#endregion
2618
2678
  //#region src/ui/controls.ts
2619
- var Fn = 3e3, In = 250, Ln = /* @__PURE__ */ new Set([
2679
+ var Yn = 3e3, Xn = 250, Zn = /* @__PURE__ */ new Set([
2620
2680
  "GONE",
2621
2681
  "NOT_FOUND",
2622
2682
  "INVALID_URN",
2623
2683
  "UNAUTHORIZED"
2624
2684
  ]);
2625
- function Rn(e) {
2626
- return new zn(e);
2685
+ function Qn(e) {
2686
+ return new $n(e);
2627
2687
  }
2628
- var zn = class {
2688
+ var $n = class {
2629
2689
  root;
2630
2690
  video;
2631
2691
  player;
@@ -2672,7 +2732,7 @@ var zn = class {
2672
2732
  scrubbing = !1;
2673
2733
  offFns = [];
2674
2734
  constructor(e) {
2675
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Fn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, Nn(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");
2735
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Yn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, qn(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");
2676
2736
  let t = (e, t, n) => {
2677
2737
  let r = this.doc.createElement(e);
2678
2738
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -2758,7 +2818,7 @@ var zn = class {
2758
2818
  let t = this.surfaceWasHidden;
2759
2819
  this.tapTimer = setTimeout(() => {
2760
2820
  this.tapTimer = void 0, this.toggleBar(t);
2761
- }, In);
2821
+ }, Xn);
2762
2822
  }
2763
2823
  toggleBar(e) {
2764
2824
  e ? this.poke() : this.hideIfIdle();
@@ -2793,7 +2853,7 @@ var zn = class {
2793
2853
  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);
2794
2854
  } else {
2795
2855
  let r = this.doc.createElement("div");
2796
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Ln.has(this.lastError.code)) {
2856
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Zn.has(this.lastError.code)) {
2797
2857
  let e = this.doc.createElement("button");
2798
2858
  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);
2799
2859
  }
@@ -2834,7 +2894,7 @@ var zn = class {
2834
2894
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
2835
2895
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
2836
2896
  }
2837
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Bn(this.video.currentTime)} / ${Bn(this.video.duration)}`);
2897
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${er(this.video.currentTime)} / ${er(this.video.duration)}`);
2838
2898
  }
2839
2899
  syncLive() {
2840
2900
  let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
@@ -2884,17 +2944,17 @@ var zn = class {
2884
2944
  renderQualityMenu() {
2885
2945
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
2886
2946
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
2887
- for (let n of e) this.menu.append(this.menuItem(Vn(n), t === n.index, () => this.player.setQuality(n.index)));
2947
+ for (let n of e) this.menu.append(this.menuItem(tr(n), t === n.index, () => this.player.setQuality(n.index)));
2888
2948
  }
2889
2949
  renderAudioMenu() {
2890
2950
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
2891
2951
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
2892
- for (let t of e) this.menu.append(this.menuItem(Hn(t), t.default, () => this.player.setAudioTrack(t.id)));
2952
+ for (let t of e) this.menu.append(this.menuItem(nr(t), t.default, () => this.player.setAudioTrack(t.id)));
2893
2953
  }
2894
2954
  renderCcMenu() {
2895
2955
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
2896
2956
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
2897
- for (let t of e) this.menu.append(this.menuItem(Un(t), !1, () => this.player.setTextTrack(t.id)));
2957
+ for (let t of e) this.menu.append(this.menuItem(rr(t), !1, () => this.player.setTextTrack(t.id)));
2898
2958
  }
2899
2959
  onTracksChanged() {
2900
2960
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2914,11 +2974,11 @@ var zn = class {
2914
2974
  }
2915
2975
  async toggleFullscreen() {
2916
2976
  try {
2917
- S(this.video, this.root) ? await w(this.video, this.root) : await C(this.video, this.root);
2977
+ x(this.video, this.root) ? await C(this.video, this.root) : await S(this.video, this.root);
2918
2978
  } catch {}
2919
2979
  }
2920
2980
  syncFullscreen() {
2921
- let e = S(this.video, this.root);
2981
+ let e = x(this.video, this.root);
2922
2982
  this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
2923
2983
  }
2924
2984
  poke() {
@@ -2995,41 +3055,41 @@ var zn = class {
2995
3055
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
2996
3056
  }
2997
3057
  };
2998
- function Bn(e) {
3058
+ function er(e) {
2999
3059
  (!Number.isFinite(e) || e < 0) && (e = 0);
3000
3060
  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");
3001
3061
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
3002
3062
  }
3003
- function Vn(e) {
3063
+ function tr(e) {
3004
3064
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
3005
3065
  }
3006
- function Hn(e) {
3066
+ function nr(e) {
3007
3067
  return e.name || e.lang || `Track ${e.id}`;
3008
3068
  }
3009
- function Un(e) {
3069
+ function rr(e) {
3010
3070
  return e.name || e.lang || `Track ${e.id}`;
3011
3071
  }
3012
3072
  //#endregion
3013
3073
  //#region src/managed/index.ts
3014
- var Wn = 6e3, Gn = 45e3, Kn = 2e3, qn = 3, Jn = 5e3, Yn = 2e3, Xn = 48e4, Zn = "keySystemLicenseRequestFailed";
3015
- function Qn(e) {
3074
+ var ir = 6e3, ar = 45e3, or = 2e3, sr = 3, cr = 5e3, lr = 2e3, ur = 48e4, dr = "keySystemLicenseRequestFailed";
3075
+ function fr(e) {
3016
3076
  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)})`);
3017
- if (e.env !== void 0) return Ge(e.env);
3077
+ if (e.env !== void 0) return L(e.env);
3018
3078
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
3019
3079
  return e.baseUrl;
3020
3080
  }
3021
- async function $n(e) {
3081
+ async function pr(e) {
3022
3082
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
3023
- let t = Qn(e);
3083
+ let t = fr(e);
3024
3084
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
3025
3085
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
3026
- let r = new er({
3086
+ let r = new mr({
3027
3087
  ...e,
3028
3088
  baseUrl: t
3029
3089
  });
3030
3090
  return await r.start(), r;
3031
3091
  }
3032
- var er = class {
3092
+ var mr = class {
3033
3093
  opts;
3034
3094
  abort = new AbortController();
3035
3095
  listeners = {};
@@ -3080,7 +3140,7 @@ var er = class {
3080
3140
  this.opts.muted && (this.opts.video.muted = !0), this.opts.poster && (this.opts.video.poster = this.opts.poster), this.mountControls(), this.attachPipListeners(), this.attachEndedPlayGuard(), this.setState("loading");
3081
3141
  let e = ++this.loadGen, t = this.resolveOptions();
3082
3142
  try {
3083
- let n = await y(t);
3143
+ let n = await v(t);
3084
3144
  if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
3085
3145
  let e = this._lastError;
3086
3146
  throw this.destroy(), e;
@@ -3103,11 +3163,11 @@ var er = class {
3103
3163
  };
3104
3164
  }
3105
3165
  beginArming(e, t, n = !1) {
3106
- let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
3166
+ let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? T(this.opts.baseUrl);
3107
3167
  r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
3108
3168
  }
3109
3169
  beginArmingByPolling(e) {
3110
- b({
3170
+ y({
3111
3171
  ...this.resolveOptions(),
3112
3172
  signal: this.abort.signal,
3113
3173
  waitForLive: this.buildWaitConfig(e)
@@ -3124,7 +3184,7 @@ var er = class {
3124
3184
  setTimeout(() => {
3125
3185
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
3126
3186
  phase: i ? "unavailable" : "tooEarly",
3127
- retryInMs: Gn,
3187
+ retryInMs: ar,
3128
3188
  attempt: 1,
3129
3189
  elapsedMs: 0,
3130
3190
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -3141,7 +3201,7 @@ var er = class {
3141
3201
  }
3142
3202
  }
3143
3203
  }, h = () => {
3144
- a || s || p() || (s = !0, b({
3204
+ a || s || p() || (s = !0, y({
3145
3205
  ...this.resolveOptions(),
3146
3206
  signal: c.signal,
3147
3207
  waitForLive: this.buildWaitConfig(e)
@@ -3149,7 +3209,7 @@ var er = class {
3149
3209
  a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
3150
3210
  }));
3151
3211
  }, g = () => {
3152
- a || p() || y(this.resolveOptions()).then((e) => m(e)).catch((e) => {
3212
+ a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
3153
3213
  if (!(a || p())) {
3154
3214
  if (e instanceof n && o(e.code)) {
3155
3215
  h();
@@ -3163,13 +3223,13 @@ var er = class {
3163
3223
  !a && !p() && h();
3164
3224
  }, e);
3165
3225
  };
3166
- _(Wn), this.armingSub = T({
3226
+ _(ir), this.armingSub = w({
3167
3227
  eventsBaseUrl: t,
3168
3228
  matchUrn: this.opts.matchUrn,
3169
3229
  credential: this.opts.credential,
3170
- onAlive: () => _(Gn),
3230
+ onAlive: () => _(ar),
3171
3231
  onState: (e) => {
3172
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Kn);
3232
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * or);
3173
3233
  },
3174
3234
  onError: () => h()
3175
3235
  });
@@ -3192,7 +3252,7 @@ var er = class {
3192
3252
  let n = await s(this.opts.credential);
3193
3253
  if (this.destroyed || t !== this.loadGen) return;
3194
3254
  this.setState("loading");
3195
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Ze(this.opts.video, (e) => {
3255
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = ct(this.opts.video, (e) => {
3196
3256
  this._state !== "ended" && this._state !== "error" && this.setState(e);
3197
3257
  });
3198
3258
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -3214,26 +3274,26 @@ var er = class {
3214
3274
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
3215
3275
  let i = e.analytics?.sid;
3216
3276
  if (!i) return;
3217
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = yn(this.opts.baseUrl, a, e.analytics?.endpoint);
3277
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Pn(this.opts.baseUrl, a, e.analytics?.endpoint);
3218
3278
  if (!o) {
3219
3279
  s && setTimeout(() => {
3220
3280
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
3221
3281
  }, 0);
3222
3282
  return;
3223
3283
  }
3224
- let c = this.opts.video, l = new bn({
3284
+ let c = this.opts.video, l = new Fn({
3225
3285
  endpoint: o,
3226
3286
  sid: i,
3227
3287
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
3228
- sdkVersion: En,
3229
- environment: wn(c),
3288
+ sdkVersion: Vn,
3289
+ environment: zn(c),
3230
3290
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
3231
3291
  onIdle: () => this.onAnalyticsIdle(t),
3232
3292
  onBlocked: (e) => setTimeout(() => {
3233
3293
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
3234
3294
  }, 0),
3235
3295
  sample: () => {
3236
- let e = this.engine?.getStats() ?? Ke, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
3296
+ let e = this.engine?.getStats() ?? R, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
3237
3297
  return {
3238
3298
  ...e,
3239
3299
  bufferedMs: Math.round(t * 1e3),
@@ -3247,7 +3307,7 @@ var er = class {
3247
3307
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
3248
3308
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
3249
3309
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
3250
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Tn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3310
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Bn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
3251
3311
  }
3252
3312
  currentPresentation() {
3253
3313
  let e = this.opts.video;
@@ -3262,10 +3322,11 @@ var er = class {
3262
3322
  video: this.opts.video,
3263
3323
  descriptor: e,
3264
3324
  credential: t,
3265
- deviceId: k(),
3325
+ deviceId: O(),
3266
3326
  userId: this.opts.userId,
3267
3327
  lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
3268
3328
  snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
3329
+ rememberBandwidth: this.opts.rememberBandwidth,
3269
3330
  mediaDuringKey: this.opts.mediaDuringKey,
3270
3331
  debug: this.opts.debug,
3271
3332
  deferLoad: r,
@@ -3274,9 +3335,9 @@ var er = class {
3274
3335
  freshLicenseUrl: () => this.refreshLicense()
3275
3336
  }, o = this.opts.engine ?? "auto";
3276
3337
  if (o === "native") return new W(a);
3277
- if (o === "hls") return new en(a);
3278
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled && lt() && H(this.opts.video)) return new W(a);
3279
- if (bt()) return new en(a);
3338
+ if (o === "hls") return new gn(a);
3339
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled && bt() && H(this.opts.video)) return new W(a);
3340
+ if (Mt()) return new gn(a);
3280
3341
  if (H(this.opts.video)) return new W(a);
3281
3342
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
3282
3343
  }
@@ -3324,11 +3385,11 @@ var er = class {
3324
3385
  }
3325
3386
  startLiveState(e) {
3326
3387
  if (this.opts.liveStateEvents === !1) return;
3327
- let t = this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
3388
+ let t = this.opts.eventsBaseUrl ?? T(this.opts.baseUrl);
3328
3389
  if (!t) return;
3329
3390
  this.closeLiveState();
3330
3391
  let r = 0, i = !1;
3331
- this.liveStateSub = T({
3392
+ this.liveStateSub = w({
3332
3393
  eventsBaseUrl: t,
3333
3394
  matchUrn: this.opts.matchUrn,
3334
3395
  credential: this.opts.credential,
@@ -3339,7 +3400,7 @@ var er = class {
3339
3400
  r = 0, i = !1;
3340
3401
  },
3341
3402
  onError: () => {
3342
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= qn && (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.`))));
3403
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= sr && (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.`))));
3343
3404
  }
3344
3405
  });
3345
3406
  }
@@ -3353,7 +3414,7 @@ var er = class {
3353
3414
  return;
3354
3415
  }
3355
3416
  let e = this.hiddenAtMs;
3356
- this.hiddenAtMs = null, e != null && Date.now() - e >= Jn && this.resyncLiveState();
3417
+ this.hiddenAtMs = null, e != null && Date.now() - e >= cr && this.resyncLiveState();
3357
3418
  }, this.onReturnPageShow = (e) => {
3358
3419
  e.persisted && this.resyncLiveState();
3359
3420
  }, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
@@ -3385,7 +3446,7 @@ var er = class {
3385
3446
  scheduleRejoin(e) {
3386
3447
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
3387
3448
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
3388
- }, Math.random() * Kn));
3449
+ }, Math.random() * or));
3389
3450
  }
3390
3451
  cancelRejoin() {
3391
3452
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -3409,7 +3470,7 @@ var er = class {
3409
3470
  }
3410
3471
  t.controls = !1;
3411
3472
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
3412
- r && r.insertBefore(n, t), n.appendChild(t), kn(n, this.opts.theme), this.container = n, this.controlBar = Rn({
3473
+ r && r.insertBefore(n, t), n.appendChild(t), Wn(n, this.opts.theme), this.container = n, this.controlBar = Qn({
3413
3474
  root: n,
3414
3475
  video: t,
3415
3476
  player: this,
@@ -3447,7 +3508,7 @@ var er = class {
3447
3508
  }
3448
3509
  startStats() {
3449
3510
  this.stopStats();
3450
- let e = Math.max(500, this.opts.statsIntervalMs ?? Yn);
3511
+ let e = Math.max(500, this.opts.statsIntervalMs ?? lr);
3451
3512
  this.statsTimer = setInterval(() => {
3452
3513
  if (!this.engine) return;
3453
3514
  let e = this.engine.getStats();
@@ -3458,14 +3519,14 @@ var er = class {
3458
3519
  this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
3459
3520
  }
3460
3521
  isStaleLicenseDenial(e) {
3461
- return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Zn || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
3522
+ return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== dr || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
3462
3523
  }
3463
3524
  scheduleLicenseRefresh() {
3464
3525
  if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
3465
3526
  typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
3466
3527
  document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
3467
3528
  }, document.addEventListener("visibilitychange", this.onRefocus));
3468
- let e = this.opts.licenseRefreshMs ?? Xn;
3529
+ let e = this.opts.licenseRefreshMs ?? ur;
3469
3530
  e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
3470
3531
  }
3471
3532
  stopRefresh() {
@@ -3477,7 +3538,7 @@ var er = class {
3477
3538
  if (this.refreshInFlight?.engine === e) return this.refreshInFlight.promise;
3478
3539
  let t = (async () => {
3479
3540
  try {
3480
- let t = await y(this.resolveOptions());
3541
+ let t = await v(this.resolveOptions());
3481
3542
  if (this.destroyed || this.engine !== e) return;
3482
3543
  let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
3483
3544
  return (n || r) && (e.setLicenseUrls({
@@ -3522,7 +3583,7 @@ var er = class {
3522
3583
  this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
3523
3584
  }
3524
3585
  getStats() {
3525
- return this.engine?.getStats() ?? Ke;
3586
+ return this.engine?.getStats() ?? R;
3526
3587
  }
3527
3588
  getQualityLevels() {
3528
3589
  return this.engine?.getQualityLevels() ?? [];
@@ -3561,10 +3622,10 @@ var er = class {
3561
3622
  e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
3562
3623
  }
3563
3624
  async enterFullscreen() {
3564
- return !this.destroyed && C(this.opts.video, this.container ?? void 0);
3625
+ return !this.destroyed && S(this.opts.video, this.container ?? void 0);
3565
3626
  }
3566
3627
  async exitFullscreen() {
3567
- await w(this.opts.video, this.container ?? void 0);
3628
+ await C(this.opts.video, this.container ?? void 0);
3568
3629
  }
3569
3630
  retry() {
3570
3631
  return this.reload();
@@ -3574,7 +3635,7 @@ var er = class {
3574
3635
  let e = ++this.loadGen;
3575
3636
  this.teardownPlayback();
3576
3637
  try {
3577
- let t = await b({
3638
+ let t = await y({
3578
3639
  ...this.resolveOptions(),
3579
3640
  waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
3580
3641
  });
@@ -3632,7 +3693,7 @@ function $(e) {
3632
3693
  }
3633
3694
  //#endregion
3634
3695
  //#region src/embed/host.ts
3635
- function tr(e) {
3696
+ function hr(e) {
3636
3697
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
3637
3698
  if (!e.src) throw Error("mountEmbed: opts.src is required");
3638
3699
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -3691,15 +3752,15 @@ function tr(e) {
3691
3752
  }
3692
3753
  //#endregion
3693
3754
  //#region src/embed/page.ts
3694
- var nr = /^[A-Za-z0-9:_.-]{1,128}$/;
3695
- function rr(e) {
3755
+ var gr = /^[A-Za-z0-9:_.-]{1,128}$/;
3756
+ function _r(e) {
3696
3757
  if (typeof e == "boolean") return e;
3697
3758
  if (typeof e == "object" && e) {
3698
3759
  let t = e.endpoint;
3699
3760
  return typeof t == "string" ? { endpoint: t } : {};
3700
3761
  }
3701
3762
  }
3702
- function ir() {
3763
+ function vr() {
3703
3764
  let e = window.HAVIK_EMBED_CONFIG;
3704
3765
  if (e) return {
3705
3766
  baseUrl: e.baseUrl ?? "",
@@ -3709,7 +3770,7 @@ function ir() {
3709
3770
  autoplay: e.autoplay ?? !0,
3710
3771
  muted: e.muted ?? !0,
3711
3772
  waitForLive: e.waitForLive ?? !0,
3712
- analytics: rr(e.analytics)
3773
+ analytics: _r(e.analytics)
3713
3774
  };
3714
3775
  let t = new URLSearchParams(location.search);
3715
3776
  return {
@@ -3722,9 +3783,9 @@ function ir() {
3722
3783
  waitForLive: !0
3723
3784
  };
3724
3785
  }
3725
- async function ar() {
3726
- let e = ir();
3727
- sr();
3786
+ async function yr() {
3787
+ let e = vr();
3788
+ xr();
3728
3789
  let t = document.createElement("video");
3729
3790
  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);
3730
3791
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -3779,12 +3840,12 @@ async function ar() {
3779
3840
  code: e.code,
3780
3841
  message: e.message
3781
3842
  })), e.on("autoplayblocked", () => {
3782
- i({ type: "oddin:autoplayblocked" }), or(t, e);
3843
+ i({ type: "oddin:autoplayblocked" }), br(t, e);
3783
3844
  });
3784
3845
  }, s = async (r) => {
3785
3846
  a?.destroy(), a = null;
3786
3847
  try {
3787
- let n = await $n({
3848
+ let n = await pr({
3788
3849
  video: t,
3789
3850
  baseUrl: e.baseUrl,
3790
3851
  matchUrn: r,
@@ -3846,7 +3907,7 @@ async function ar() {
3846
3907
  a?.retry();
3847
3908
  break;
3848
3909
  case "oddin:load":
3849
- typeof e.matchUrn == "string" && nr.test(e.matchUrn) && s(e.matchUrn);
3910
+ typeof e.matchUrn == "string" && gr.test(e.matchUrn) && s(e.matchUrn);
3850
3911
  break;
3851
3912
  case "oddin:destroy": c();
3852
3913
  }
@@ -3858,18 +3919,18 @@ async function ar() {
3858
3919
  protocol: 1
3859
3920
  });
3860
3921
  }
3861
- function or(e, t) {
3922
+ function br(e, t) {
3862
3923
  if (document.getElementById("havik-tap")) return;
3863
3924
  let n = document.createElement("button");
3864
3925
  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", () => {
3865
3926
  n.remove(), t.play();
3866
3927
  }), document.body.appendChild(n);
3867
3928
  }
3868
- function sr() {
3929
+ function xr() {
3869
3930
  let e = document.createElement("style");
3870
3931
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
3871
3932
  }
3872
3933
  //#endregion
3873
- export { Dn as ODDIN_THEME, n as PlaybackError, kn as applyTheme, Ge as baseUrlForEnv, ar as bootEmbed, Te as clearDeviceId, $n 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, tr as mountEmbed, v as pollToLive, b as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
3934
+ export { Hn as ODDIN_THEME, n as PlaybackError, Wn as applyTheme, L as baseUrlForEnv, yr as bootEmbed, Ee as clearDeviceId, Re as clearRememberedBandwidth, pr as createPlayer, T as deriveEventsBaseUrl, tt as detectDrmSupport, S as enterVideoFullscreen, C as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, O as getDeviceId, rt as isLowLatencyManifest, $ as isOddinMessage, Oe as licenseRequestHeaders, hr as mountEmbed, de as pollToLive, y as resolveStream, w as subscribeLiveState, x as videoFullscreenActive, we as watchStatus };
3874
3935
 
3875
3936
  //# sourceMappingURL=index.js.map