@oddin-gg/havik-player 2.11.1 → 2.13.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
@@ -110,42 +110,48 @@ function m(e) {
110
110
  return e instanceof Error ? e.message : String(e);
111
111
  }
112
112
  //#endregion
113
+ //#region src/core/warnOnce.ts
114
+ var h = /* @__PURE__ */ new Set();
115
+ function g(e, t = e) {
116
+ h.has(t) || (h.add(t), console.warn(`havik-player: ${e}`));
117
+ }
118
+ //#endregion
113
119
  //#region src/core/waitForLive.ts
114
- var h = 1e3, g = 3e4, _ = 6e5, ee = 3e5, te = 1e3, ne = {
120
+ var _ = 1e3, ee = 3e4, te = 6e5, ne = 3e5, re = 1e3, ie = {
115
121
  TOO_EARLY: "tooEarly",
116
122
  UNAVAILABLE: "unavailable",
117
123
  RATE_LIMITED: "rateLimited",
118
124
  NETWORK: "network"
119
125
  };
120
- function re(e) {
121
- let t = e === !0 || e === !1 ? {} : e, n = Math.max(te, t.floorMs ?? h), r = Math.max(n, t.ceilMs ?? g), i = Math.max(0, t.imminentMs ?? _), a = Math.max(r, t.sanityFloorMs ?? ee);
126
+ function ae(e) {
127
+ let t = e === !0 || e === !1 ? {} : e, n = Math.max(re, t.floorMs ?? _), r = Math.max(n, t.ceilMs ?? ee), i = Math.max(0, t.imminentMs ?? te), a = Math.max(r, t.sanityFloorMs ?? ne);
122
128
  return {
123
129
  timeoutMs: t.timeoutMs,
124
130
  floorMs: n,
125
131
  ceilMs: r,
126
132
  imminentMs: i,
127
133
  sanityFloorMs: a,
128
- kickoffMs: ie(t.kickoffAt),
134
+ kickoffMs: oe(t.kickoffAt),
129
135
  jitter: t.jitter ?? !0,
130
136
  onState: t.onState
131
137
  };
132
138
  }
133
- function ie(e) {
139
+ function oe(e) {
134
140
  if (e == null) return;
135
141
  if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
136
142
  let t = Date.parse(e);
137
143
  return Number.isFinite(t) ? t : void 0;
138
144
  }
139
- function ae(e, t, n) {
145
+ function se(e, t, n) {
140
146
  return Math.min(n, Math.max(t, e));
141
147
  }
142
- function oe(e) {
148
+ function ce(e) {
143
149
  return Math.round(e * (1 + .15 * Math.random()));
144
150
  }
145
- function se(e, t, n, r) {
151
+ function le(e, t, n, r) {
146
152
  let i = r ?? n.kickoffMs, a = i == null ? void 0 : Math.max(0, i - t), o = Math.max(n.floorMs, e ?? 0);
147
153
  if (a == null || a <= n.imminentMs) return {
148
- delay: ae(e ?? n.floorMs, o, n.ceilMs),
154
+ delay: se(e ?? n.floorMs, o, n.ceilMs),
149
155
  ttkMs: a
150
156
  };
151
157
  let s = Math.min(Math.floor(a / 10), n.sanityFloorMs, a);
@@ -154,7 +160,7 @@ function se(e, t, n, r) {
154
160
  ttkMs: a
155
161
  };
156
162
  }
157
- function ce(e, t) {
163
+ function ue(e, t) {
158
164
  return new Promise((r, i) => {
159
165
  if (t?.aborted) {
160
166
  i(new n("ABORTED", 0, "wait-for-live aborted"));
@@ -168,8 +174,8 @@ function ce(e, t) {
168
174
  t?.addEventListener("abort", a, { once: !0 });
169
175
  });
170
176
  }
171
- async function v(e, t, r) {
172
- let i = re(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
177
+ async function de(e, t, r) {
178
+ let i = ae(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
173
179
  for (;;) {
174
180
  if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
175
181
  try {
@@ -177,38 +183,38 @@ async function v(e, t, r) {
177
183
  } catch (e) {
178
184
  if (!(e instanceof n) || !o(e.code)) throw e;
179
185
  c += 1, e.liveStartsAtMs != null && Number.isFinite(e.liveStartsAtMs) && (l = e.liveStartsAtMs);
180
- let t = Date.now(), u = se(e.retryAfterMs, t, i, l), d = u.ttkMs, f = u.delay;
181
- if (i.jitter && (f = oe(f)), t + f > s) throw new n("TIMEOUT", e.httpStatus, `timed out after ${i.timeoutMs}ms waiting for the stream to go live`, {
186
+ let t = Date.now(), u = le(e.retryAfterMs, t, i, l), d = u.ttkMs, f = u.delay;
187
+ if (i.jitter && (f = ce(f)), t + f > s) throw new n("TIMEOUT", e.httpStatus, `timed out after ${i.timeoutMs}ms waiting for the stream to go live`, {
182
188
  retryAfterMs: e.retryAfterMs,
183
189
  cause: e
184
190
  });
185
191
  i.onState?.({
186
- phase: ne[e.code] ?? "unavailable",
192
+ phase: ie[e.code] ?? "unavailable",
187
193
  retryInMs: f,
188
194
  attempt: c,
189
195
  elapsedMs: t - a,
190
196
  ttkMs: d
191
- }), await ce(f, r);
197
+ }), await ue(f, r);
192
198
  }
193
199
  }
194
200
  }
195
201
  //#endregion
196
202
  //#region src/core/resolve.ts
197
- async function y(e) {
203
+ async function v(e) {
198
204
  if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
199
205
  let t = await p(d(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
200
206
  credential: e.credential,
201
207
  signal: e.signal,
202
208
  apiHeaders: e.apiHeaders
203
209
  });
204
- if (!t.ok) throw await le(t);
205
- return de(await t.json(), e.matchUrn);
210
+ if (!t.ok) throw await fe(t);
211
+ return he(await t.json(), e.matchUrn);
206
212
  }
207
- function b(e) {
208
- let t = () => y(e);
209
- 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();
210
216
  }
211
- async function le(e) {
217
+ async function fe(e) {
212
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;
213
219
  try {
214
220
  let t = await e.json();
@@ -224,7 +230,7 @@ async function le(e) {
224
230
  liveStartsAtMs: s
225
231
  });
226
232
  }
227
- var ue = /* @__PURE__ */ new Set([
233
+ var pe = /* @__PURE__ */ new Set([
228
234
  "matchUrn",
229
235
  "protocol",
230
236
  "drmEnabled",
@@ -235,7 +241,7 @@ var ue = /* @__PURE__ */ new Set([
235
241
  "expiresAt",
236
242
  "analytics"
237
243
  ]);
238
- function x(e, t) {
244
+ function b(e, t) {
239
245
  let r;
240
246
  try {
241
247
  r = new URL(t);
@@ -245,57 +251,71 @@ function x(e, t) {
245
251
  if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
246
252
  return t;
247
253
  }
248
- function de(e, t) {
254
+ function me(e) {
255
+ if (e !== void 0) {
256
+ if (typeof e == "string" && !e.endsWith("/")) try {
257
+ let t = new URL(e);
258
+ if (t.protocol === "https:" && t.href === `${t.origin}/`) return t.origin;
259
+ } catch {}
260
+ g(`server analytics.endpoint ${JSON.stringify(e)} ignored: not a bare https origin.`);
261
+ }
262
+ }
263
+ function he(e, t) {
249
264
  if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
250
265
  let r = e.drmEnabled ?? !!e.drm, i = {
251
266
  matchUrn: e.matchUrn ?? t,
252
267
  protocol: "hls",
253
268
  drmEnabled: r,
254
- manifestUrl: x("manifestUrl", e.manifestUrl),
269
+ manifestUrl: b("manifestUrl", e.manifestUrl),
255
270
  serverTime: e.serverTime ?? ""
256
271
  };
257
- if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid && (i.analytics = { sid: e.analytics.sid }), r && e.drm) {
272
+ if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid) {
273
+ i.analytics = { sid: e.analytics.sid };
274
+ let t = me(e.analytics.endpoint);
275
+ t && (i.analytics.endpoint = t);
276
+ }
277
+ if (r && e.drm) {
258
278
  let t = {};
259
- e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: x("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
260
- licenseUrl: x("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
261
- 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)
262
282
  }), (t.widevine || t.fairplay) && (i.drm = t);
263
283
  }
264
284
  let a = {};
265
- for (let [t, n] of Object.entries(e)) ue.has(t) || (a[t] = n);
285
+ for (let [t, n] of Object.entries(e)) pe.has(t) || (a[t] = n);
266
286
  return Object.keys(a).length > 0 && (i.extensions = a), i;
267
287
  }
268
288
  //#endregion
269
289
  //#region src/core/fullscreen.ts
270
- function S(e) {
290
+ function ge(e) {
271
291
  return e.ownerDocument ?? document;
272
292
  }
273
- function C(e) {
293
+ function x(e) {
274
294
  return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
275
295
  }
276
- function w(e, t) {
277
- let n = C(S(e));
296
+ function S(e, t) {
297
+ let n = x(ge(e));
278
298
  return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
279
299
  }
280
- async function T(e, t) {
300
+ async function C(e, t) {
281
301
  let n = t ?? e;
282
302
  if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
283
303
  if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
284
304
  let r = e;
285
305
  return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
286
306
  }
287
- async function E(e, t) {
307
+ async function w(e, t) {
288
308
  let n = e;
289
309
  if (n.webkitDisplayingFullscreen) {
290
310
  n.webkitExitFullscreen?.();
291
311
  return;
292
312
  }
293
- let r = S(e), i = C(r);
313
+ let r = ge(e), i = x(r);
294
314
  i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
295
315
  }
296
316
  //#endregion
297
317
  //#region src/core/catalog.ts
298
- async function fe(e) {
318
+ async function _e(e) {
299
319
  let t = new URLSearchParams();
300
320
  e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
301
321
  let i = t.toString(), a = d(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
@@ -313,12 +333,12 @@ async function fe(e) {
313
333
  };
314
334
  if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
315
335
  return {
316
- tournaments: pe(await s.json()),
336
+ tournaments: ve(await s.json()),
317
337
  etag: s.headers.get("etag") ?? void 0,
318
338
  notModified: !1
319
339
  };
320
340
  }
321
- function pe(e) {
341
+ function ve(e) {
322
342
  return (e.tournaments ?? []).map((e) => {
323
343
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
324
344
  return {
@@ -340,7 +360,7 @@ function pe(e) {
340
360
  };
341
361
  });
342
362
  }
343
- async function me(e) {
363
+ async function ye(e) {
344
364
  let t = d(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
345
365
  e.etag && i.set("If-None-Match", e.etag);
346
366
  let a = await p(t, {
@@ -360,13 +380,13 @@ async function me(e) {
360
380
  };
361
381
  if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
362
382
  return {
363
- tournament: he(await a.json()),
383
+ tournament: be(await a.json()),
364
384
  etag: a.headers.get("etag") ?? void 0,
365
385
  notModified: !1,
366
386
  notFound: !1
367
387
  };
368
388
  }
369
- function he(e) {
389
+ function be(e) {
370
390
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
371
391
  return {
372
392
  urn: t,
@@ -386,12 +406,17 @@ function he(e) {
386
406
  }))
387
407
  };
388
408
  }
389
- function ge(e) {
409
+ function xe(e) {
390
410
  return e.tournaments.flatMap((e) => e.matches);
391
411
  }
392
412
  //#endregion
393
413
  //#region src/core/poll.ts
394
- function _e(e) {
414
+ var Se = /* @__PURE__ */ new Set([
415
+ "NOT_FOUND",
416
+ "GONE",
417
+ "INVALID_URN"
418
+ ]);
419
+ function Ce(e) {
395
420
  let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
396
421
  u || (a = setTimeout(m, t));
397
422
  }, m = async () => {
@@ -422,7 +447,10 @@ function _e(e) {
422
447
  }));
423
448
  }
424
449
  } catch (t) {
425
- i.signal.aborted || e.onError?.(t instanceof n ? t : new n("NETWORK", 0, String(t)));
450
+ if (!i.signal.aborted) {
451
+ let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
452
+ Se.has(r.code) && (u = !0), e.onError?.(r);
453
+ }
426
454
  } finally {
427
455
  f();
428
456
  }
@@ -433,9 +461,9 @@ function _e(e) {
433
461
  }
434
462
  //#endregion
435
463
  //#region src/core/events.ts
436
- var ve = 45e3;
437
- function D(e) {
438
- let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? ve, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
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) => {
439
467
  if (a.signal.aborted) return t();
440
468
  let n = setTimeout(t, e);
441
469
  a.signal.addEventListener("abort", () => {
@@ -516,7 +544,7 @@ function D(e) {
516
544
  o || (o = !0, a.abort());
517
545
  } };
518
546
  }
519
- function O(e) {
547
+ function E(e) {
520
548
  try {
521
549
  let t = new URL(e);
522
550
  return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
@@ -526,27 +554,27 @@ function O(e) {
526
554
  }
527
555
  //#endregion
528
556
  //#region src/core/drm/deviceId.ts
529
- var k = "havik.player.deviceId", A;
530
- function j() {
531
- if (A) return A;
557
+ var D = "havik.player.deviceId", O;
558
+ function k() {
559
+ if (O) return O;
532
560
  try {
533
- let e = globalThis.localStorage?.getItem(k);
534
- if (e) return A = e, e;
561
+ let e = globalThis.localStorage?.getItem(D);
562
+ if (e) return O = e, e;
535
563
  } catch {}
536
- let e = be();
537
- A = e;
564
+ let e = Ee();
565
+ O = e;
538
566
  try {
539
- globalThis.localStorage?.setItem(k, e);
567
+ globalThis.localStorage?.setItem(D, e);
540
568
  } catch {}
541
569
  return e;
542
570
  }
543
- function ye() {
544
- A = void 0;
571
+ function Te() {
572
+ O = void 0;
545
573
  try {
546
- globalThis.localStorage?.removeItem(k);
574
+ globalThis.localStorage?.removeItem(D);
547
575
  } catch {}
548
576
  }
549
- function be() {
577
+ function Ee() {
550
578
  let e = globalThis.crypto;
551
579
  if (e && typeof e.randomUUID == "function") return e.randomUUID();
552
580
  let t = /* @__PURE__ */ new Uint8Array(16);
@@ -558,21 +586,21 @@ function be() {
558
586
  }
559
587
  //#endregion
560
588
  //#region src/core/drm/headers.ts
561
- function xe(e, t, n = {}) {
589
+ function De(e, t, n = {}) {
562
590
  let r = {
563
591
  "x-api-key": t.apiKey,
564
592
  "X-Match-Urn": e.matchUrn,
565
- "X-Device-Id": n.deviceId ?? j(),
593
+ "X-Device-Id": n.deviceId ?? k(),
566
594
  "Content-Type": "application/octet-stream"
567
595
  };
568
596
  return n.userId && (r["X-User-Id"] = n.userId), r;
569
597
  }
570
598
  //#endregion
571
599
  //#region src/core/drm/cdm.ts
572
- var M = /* @__PURE__ */ new WeakMap();
573
- function Se(e, t) {
574
- let n = M.get(e);
575
- n || (n = /* @__PURE__ */ new Map(), M.set(e, n));
600
+ var A = /* @__PURE__ */ new WeakMap();
601
+ function Oe(e, t) {
602
+ let n = A.get(e);
603
+ n || (n = /* @__PURE__ */ new Map(), A.set(e, n));
576
604
  let r = n.get(t.keySystem);
577
605
  if (r) return r;
578
606
  let i = t.createMediaKeys().catch((e) => {
@@ -580,22 +608,22 @@ function Se(e, t) {
580
608
  });
581
609
  return n.set(t.keySystem, i), i;
582
610
  }
583
- function N() {
611
+ function j() {
584
612
  return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
585
613
  }
586
- var P = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
587
- function Ce(e) {
614
+ var M = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
615
+ function ke(e) {
588
616
  return e.startsWith("com.widevine");
589
617
  }
590
- function F(e, t) {
591
- if (!Ce(e)) return t;
618
+ function N(e, t) {
619
+ if (!ke(e)) return t;
592
620
  let n = (e, t) => {
593
621
  let n = e.videoCapabilities;
594
622
  return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
595
- let n = P.indexOf(e.robustness);
596
- return n === -1 || P.indexOf(t) > n;
623
+ let n = M.indexOf(e.robustness);
624
+ return n === -1 || M.indexOf(t) > n;
597
625
  });
598
- }, r = P.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
626
+ }, r = M.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
599
627
  ...t,
600
628
  videoCapabilities: t.videoCapabilities?.map((t) => ({
601
629
  ...t,
@@ -604,53 +632,53 @@ function F(e, t) {
604
632
  })));
605
633
  return [...t, ...r];
606
634
  }
607
- function we(e) {
608
- return (t, n) => N() ? navigator.requestMediaKeySystemAccess(t, F(t, n)).then((t) => ({
635
+ function P(e) {
636
+ return (t, n) => j() ? navigator.requestMediaKeySystemAccess(t, N(t, n)).then((t) => ({
609
637
  keySystem: t.keySystem,
610
638
  getConfiguration: () => t.getConfiguration(),
611
- createMediaKeys: () => Se(e, t)
639
+ createMediaKeys: () => Oe(e, t)
612
640
  })) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
613
641
  }
614
- var I = {
642
+ var F = {
615
643
  video: "SW_SECURE_DECODE",
616
644
  audio: "SW_SECURE_CRYPTO",
617
645
  scheme: "cbcs"
618
646
  };
619
- function Te(e) {
620
- if (!N()) return;
647
+ function Ae(e) {
648
+ if (!j()) return;
621
649
  let t = (e, t) => ({
622
650
  contentType: e,
623
651
  robustness: t,
624
- encryptionScheme: I.scheme
652
+ encryptionScheme: F.scheme
625
653
  });
626
- we(e)("com.widevine.alpha", [{
654
+ P(e)("com.widevine.alpha", [{
627
655
  initDataTypes: ["cenc"],
628
656
  distinctiveIdentifier: "optional",
629
657
  persistentState: "optional",
630
658
  sessionTypes: ["temporary"],
631
- audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", I.audio)],
632
- videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", I.video)]
659
+ audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", F.audio)],
660
+ videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", F.video)]
633
661
  }]).then((e) => e.createMediaKeys()).catch(() => {});
634
662
  }
635
- function L(e) {
636
- let t = R(e);
663
+ function I(e) {
664
+ let t = L(e);
637
665
  if (/^avc[13]/.test(t)) return "avc";
638
666
  if (/^(hvc1|hev1)/.test(t)) return "hevc";
639
667
  if (/^(dvh1|dvhe)/.test(t)) return "dv";
640
668
  if (t.startsWith("av01")) return "av1";
641
669
  if (/^vp0?9/.test(t)) return "vp9";
642
670
  }
643
- function R(e) {
671
+ function L(e) {
644
672
  return (e ?? "").trim().toLowerCase();
645
673
  }
646
- var Ee = {
674
+ var je = {
647
675
  hevc: "hvc1.1.6.L93.90",
648
676
  dv: "dvh1.05.06",
649
677
  av1: "av01.0.05M.08",
650
678
  vp9: "vp09.00.10.08"
651
- }, De = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Map();
652
- function Oe(e) {
653
- let t = R(e), n = De.get(t);
679
+ }, Me = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
680
+ function Ne(e) {
681
+ let t = L(e), n = Me.get(t);
654
682
  if (n) return n;
655
683
  let r = {
656
684
  initDataTypes: ["cenc"],
@@ -659,32 +687,32 @@ function Oe(e) {
659
687
  sessionTypes: ["temporary"],
660
688
  videoCapabilities: [{
661
689
  contentType: `video/mp4; codecs="${e.trim()}"`,
662
- robustness: I.video,
663
- encryptionScheme: I.scheme
690
+ robustness: F.video,
691
+ encryptionScheme: F.scheme
664
692
  }]
665
693
  }, i = (async () => {
666
694
  try {
667
- return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", F("com.widevine.alpha", [r])), !0;
695
+ return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", N("com.widevine.alpha", [r])), !0;
668
696
  } catch {
669
697
  return !1;
670
698
  }
671
- })().then((e) => (z.set(t, e), e));
672
- return De.set(t, i), i;
699
+ })().then((e) => (R.set(t, e), e));
700
+ return Me.set(t, i), i;
673
701
  }
674
- function ke() {
675
- if (N()) for (let e of Object.values(Ee)) Oe(e);
702
+ function Pe() {
703
+ if (j()) for (let e of Object.values(je)) Ne(e);
676
704
  }
677
- function Ae(e) {
678
- let t = L(e);
679
- if (t) return t === "avc" ? !0 : z.get(R(e)) ?? z.get(R(Ee[t]));
705
+ function Fe(e) {
706
+ let t = I(e);
707
+ if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(je[t]));
680
708
  }
681
709
  //#endregion
682
710
  //#region src/core/drm/support.ts
683
- var je = 5e3, Me = "video/mp4; codecs=\"avc1.42E01E\"", B = "audio/mp4; codecs=\"mp4a.40.2\"", Ne = {
711
+ var Ie = 5e3, Le = "video/mp4; codecs=\"avc1.42E01E\"", Re = "audio/mp4; codecs=\"mp4a.40.2\"", ze = {
684
712
  widevine: ["com.widevine.alpha"],
685
713
  fairplay: ["com.apple.fps"]
686
714
  };
687
- function Pe(e) {
715
+ function Be(e) {
688
716
  return e === "fairplay" ? [{
689
717
  initDataTypes: [
690
718
  "sinf",
@@ -692,30 +720,30 @@ function Pe(e) {
692
720
  "cenc"
693
721
  ],
694
722
  videoCapabilities: [{
695
- contentType: Me,
723
+ contentType: Le,
696
724
  robustness: "",
697
725
  encryptionScheme: "cbcs"
698
726
  }],
699
727
  audioCapabilities: [{
700
- contentType: B,
728
+ contentType: Re,
701
729
  robustness: "",
702
730
  encryptionScheme: "cbcs"
703
731
  }]
704
- }] : F("com.widevine.alpha", [{
732
+ }] : N("com.widevine.alpha", [{
705
733
  initDataTypes: ["cenc"],
706
734
  videoCapabilities: [{
707
- contentType: Me,
708
- robustness: I.video,
709
- encryptionScheme: I.scheme
735
+ contentType: Le,
736
+ robustness: F.video,
737
+ encryptionScheme: F.scheme
710
738
  }],
711
739
  audioCapabilities: [{
712
- contentType: B,
713
- robustness: I.audio,
714
- encryptionScheme: I.scheme
740
+ contentType: Re,
741
+ robustness: F.audio,
742
+ encryptionScheme: F.scheme
715
743
  }]
716
744
  }]);
717
745
  }
718
- function V(e, t) {
746
+ function Ve(e, t) {
719
747
  return new Promise((n, r) => {
720
748
  let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
721
749
  e.then((e) => {
@@ -725,8 +753,8 @@ function V(e, t) {
725
753
  });
726
754
  });
727
755
  }
728
- async function Fe(e = {}) {
729
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? je, r = {};
756
+ async function He(e = {}) {
757
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ie, r = {};
730
758
  if (typeof window < "u" && window.isSecureContext === !1) return {
731
759
  verdict: "insecure-context",
732
760
  detail: r
@@ -738,7 +766,7 @@ async function Fe(e = {}) {
738
766
  };
739
767
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
740
768
  for (let e of t) {
741
- let t = Ne[e];
769
+ let t = ze[e];
742
770
  if (!t) {
743
771
  r[e] = "unknown system";
744
772
  continue;
@@ -749,7 +777,7 @@ async function Fe(e = {}) {
749
777
  break;
750
778
  }
751
779
  try {
752
- return await V((await V(i(n, Pe(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
780
+ return await Ve((await Ve(i(n, Be(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
753
781
  verdict: "supported",
754
782
  system: e,
755
783
  detail: r
@@ -773,49 +801,49 @@ async function Fe(e = {}) {
773
801
  }
774
802
  //#endregion
775
803
  //#region src/core/manifest.ts
776
- var Ie = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
777
- function Le(e) {
778
- return Ie.test(e);
804
+ var Ue = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
805
+ function We(e) {
806
+ return Ue.test(e);
779
807
  }
780
808
  //#endregion
781
809
  //#region src/core/env.ts
782
- var H = {
810
+ var z = {
783
811
  integration: "https://feed-dev.oddin-video.gg",
784
812
  production: "https://feed.oddin-video.gg"
785
813
  };
786
- function U(e) {
787
- let t = Object.prototype.hasOwnProperty.call(H, e) ? H[e] : void 0;
814
+ function B(e) {
815
+ let t = Object.prototype.hasOwnProperty.call(z, e) ? z[e] : void 0;
788
816
  if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
789
817
  return t;
790
818
  }
791
819
  //#endregion
792
820
  //#region src/core/stats.ts
793
- var W = { droppedFrames: 0 };
794
- function G(e) {
821
+ var V = { droppedFrames: 0 };
822
+ function H(e) {
795
823
  try {
796
824
  return new URL(e).host;
797
825
  } catch {
798
826
  return "";
799
827
  }
800
828
  }
801
- var Re = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
802
- function ze(e) {
829
+ var Ge = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
830
+ function Ke(e) {
803
831
  if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
804
832
  let t = "", n = -1, r = performance.getEntriesByType("resource");
805
- for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Re.test(i.name)) && i.startTime >= n) {
806
- let e = G(i.name);
833
+ for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Ge.test(i.name)) && i.startTime >= n) {
834
+ let e = H(i.name);
807
835
  e && (t = e, n = i.startTime);
808
836
  }
809
837
  return t;
810
838
  }
811
- function K(e) {
839
+ function U(e) {
812
840
  let t = e.getVideoPlaybackQuality?.();
813
841
  return {
814
842
  dropped: t?.droppedVideoFrames ?? 0,
815
843
  totalFrames: t?.totalVideoFrames ?? 0
816
844
  };
817
845
  }
818
- function Be(e, t) {
846
+ function qe(e, t) {
819
847
  let n = [
820
848
  ["playing", () => t("playing")],
821
849
  ["waiting", () => t("buffering")],
@@ -832,7 +860,7 @@ function Be(e, t) {
832
860
  }
833
861
  //#endregion
834
862
  //#region src/core/engine/native.ts
835
- function Ve(e) {
863
+ function Je(e) {
836
864
  try {
837
865
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
838
866
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -840,15 +868,15 @@ function Ve(e) {
840
868
  return;
841
869
  }
842
870
  }
843
- function q(e) {
871
+ function W(e) {
844
872
  return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
845
873
  }
846
- function J() {
874
+ function G() {
847
875
  if (typeof window > "u") return !1;
848
876
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
849
877
  return e || t;
850
878
  }
851
- var Y = class {
879
+ var K = class {
852
880
  name = "native";
853
881
  deps;
854
882
  onLoaded;
@@ -884,7 +912,7 @@ var Y = class {
884
912
  type: "error",
885
913
  error: new n("INTERNAL", 0, "native HLS playback error"),
886
914
  fatal: !0
887
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = He(t.manifestUrl, t.analytics?.sid), e.load();
915
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Ye(t.manifestUrl, t.analytics?.sid), e.load();
888
916
  }
889
917
  startLoad() {
890
918
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -906,7 +934,7 @@ var Y = class {
906
934
  });
907
935
  this.onEncrypted = (n) => {
908
936
  let i = n;
909
- i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Ve(i.initData), (async () => {
937
+ i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Je(i.initData), (async () => {
910
938
  try {
911
939
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
912
940
  initDataTypes: [i.initDataType],
@@ -1001,11 +1029,11 @@ var Y = class {
1001
1029
  e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
1002
1030
  }
1003
1031
  getStats() {
1004
- let e = this.deps.video, t = K(e), n = {
1032
+ let e = this.deps.video, t = U(e), n = {
1005
1033
  droppedFrames: t.dropped,
1006
1034
  decodedFrames: t.totalFrames
1007
1035
  };
1008
- return this.cdnHost ||= ze(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity ? (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)) : Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1), n;
1036
+ return this.cdnHost ||= Ke(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity ? (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)) : Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1), n;
1009
1037
  }
1010
1038
  stop() {
1011
1039
  try {
@@ -1024,13 +1052,13 @@ var Y = class {
1024
1052
  } catch {}
1025
1053
  }
1026
1054
  };
1027
- function He(e, t) {
1055
+ function Ye(e, t) {
1028
1056
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
1029
1057
  }
1030
1058
  //#endregion
1031
1059
  //#region src/core/engine/prefetch.ts
1032
- var Ue = 15e3, We = 5e3, Ge = 6;
1033
- function Ke(e) {
1060
+ var Xe = 15e3, Ze = 5e3, Qe = 6;
1061
+ function $e(e) {
1034
1062
  try {
1035
1063
  let t = new URL(e);
1036
1064
  return t.searchParams.delete("CMCD"), t.toString();
@@ -1038,7 +1066,7 @@ function Ke(e) {
1038
1066
  return e;
1039
1067
  }
1040
1068
  }
1041
- var qe = class {
1069
+ var et = class {
1042
1070
  cmcd;
1043
1071
  entries = /* @__PURE__ */ new Map();
1044
1072
  keyed = /* @__PURE__ */ new Set();
@@ -1061,10 +1089,10 @@ var qe = class {
1061
1089
  }
1062
1090
  prefetch(e, t, n) {
1063
1091
  if (!this.isActive(t)) return;
1064
- let r = Ke(e);
1092
+ let r = $e(e);
1065
1093
  if (this.entries.has(r)) return;
1066
1094
  let i = this.perTrack.get(t) ?? 0;
1067
- if (i >= Ge) return;
1095
+ if (i >= Qe) return;
1068
1096
  this.perTrack.set(t, i + 1);
1069
1097
  let a = new AbortController(), o = {
1070
1098
  started: performance.now(),
@@ -1078,10 +1106,10 @@ var qe = class {
1078
1106
  signal: a.signal
1079
1107
  }).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
1080
1108
  this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
1081
- }, Ue);
1109
+ }, Xe);
1082
1110
  }
1083
1111
  take(e) {
1084
- let t = Ke(e), n = this.entries.get(t);
1112
+ let t = $e(e), n = this.entries.get(t);
1085
1113
  return n && this.entries.delete(t), n;
1086
1114
  }
1087
1115
  destroy() {
@@ -1101,13 +1129,13 @@ var qe = class {
1101
1129
  }
1102
1130
  }
1103
1131
  };
1104
- function Je(t) {
1132
+ function tt(t) {
1105
1133
  let n = e.DefaultConfig?.loader;
1106
1134
  if (typeof n != "function") return;
1107
1135
  class r extends n {
1108
1136
  served = !1;
1109
1137
  cancelled = !1;
1110
- stats = Ye();
1138
+ stats = nt();
1111
1139
  load(e, n, r) {
1112
1140
  let i = e.rangeEnd ? void 0 : t.take(e.url);
1113
1141
  if (!i) {
@@ -1115,7 +1143,7 @@ function Je(t) {
1115
1143
  return;
1116
1144
  }
1117
1145
  this.served = !0;
1118
- let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || We, s = setTimeout(() => {
1146
+ let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Ze, s = setTimeout(() => {
1119
1147
  !this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
1120
1148
  }, o);
1121
1149
  i.bytes.then((o) => {
@@ -1142,7 +1170,7 @@ function Je(t) {
1142
1170
  }
1143
1171
  return r;
1144
1172
  }
1145
- function Ye() {
1173
+ function nt() {
1146
1174
  return {
1147
1175
  aborted: !1,
1148
1176
  loaded: 0,
@@ -1166,10 +1194,10 @@ function Ye() {
1166
1194
  }
1167
1195
  };
1168
1196
  }
1169
- function Xe(e) {
1197
+ function rt(e) {
1170
1198
  return e === "audio" ? "audio" : "main";
1171
1199
  }
1172
- function Ze(e, t) {
1200
+ function it(e, t) {
1173
1201
  let n = [];
1174
1202
  t.initSegment?.url && !t.initSegment.data && n.push({
1175
1203
  url: t.initSegment.url,
@@ -1188,24 +1216,24 @@ function Ze(e, t) {
1188
1216
  }
1189
1217
  //#endregion
1190
1218
  //#region src/core/engine/hls.ts
1191
- function Qe() {
1219
+ function at() {
1192
1220
  return e.isSupported();
1193
1221
  }
1194
- var $e = 3, et = 5, tt = 3, nt = 3e4, rt = 12e3, it = 3e3, at = 6e3, ot = 5e3, st = 4e3, ct = 2, lt = 5, ut = 2, dt = 2, ft = 4, pt = 4, mt = 2e3, ht = 3e4, gt = 2, _t = 9, vt = .5, yt = 64;
1195
- function bt(e) {
1222
+ var ot = 3, st = 5, ct = 3, lt = 3e4, ut = 12e3, dt = 3e3, ft = 6e3, pt = 5e3, mt = 4e3, ht = 2, gt = 5, _t = 2, vt = 2, yt = 4, bt = 4, xt = 2e3, St = 3e4, Ct = 2, wt = 9, Tt = .5, Et = 64;
1223
+ function Dt(e) {
1196
1224
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
1197
1225
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
1198
1226
  return;
1199
1227
  }
1200
- e.liveSyncDuration ??= gt;
1201
- let t = Math.max(12, e.liveSyncDuration + _t);
1202
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), xt(e, e.liveSyncDuration);
1228
+ e.liveSyncDuration ??= Ct;
1229
+ let t = Math.max(12, e.liveSyncDuration + wt);
1230
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Ot(e, e.liveSyncDuration);
1203
1231
  }
1204
- function xt(e, t) {
1232
+ function Ot(e, t) {
1205
1233
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
1206
1234
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
1207
1235
  }
1208
- var St = class {
1236
+ var kt = class {
1209
1237
  name = "hls";
1210
1238
  hls = null;
1211
1239
  deps;
@@ -1273,7 +1301,7 @@ var St = class {
1273
1301
  this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1274
1302
  }
1275
1303
  async load() {
1276
- let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = q(r) && J(), o = !!e.drm?.widevine?.licenseUrl && !a;
1304
+ let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = W(r) && G(), o = !!e.drm?.widevine?.licenseUrl && !a;
1277
1305
  if (e.drmEnabled && !o) {
1278
1306
  i({
1279
1307
  type: "error",
@@ -1282,7 +1310,7 @@ var St = class {
1282
1310
  });
1283
1311
  return;
1284
1312
  }
1285
- e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Te(r), ke()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1313
+ e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Pe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1286
1314
  let e = this.hls;
1287
1315
  if (document.visibilityState !== "visible" || !e) return;
1288
1316
  let t = e.liveSyncPosition;
@@ -1305,7 +1333,7 @@ var St = class {
1305
1333
  }
1306
1334
  this.loadSuspended = !0;
1307
1335
  }
1308
- }, ot));
1336
+ }, pt));
1309
1337
  }
1310
1338
  resumeLoading() {
1311
1339
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1337,7 +1365,7 @@ var St = class {
1337
1365
  let t = e.liveSyncPosition;
1338
1366
  if (typeof t != "number" || !Number.isFinite(t)) return;
1339
1367
  let { video: n } = this.deps;
1340
- n.currentTime <= t + vt || (n.currentTime = t);
1368
+ n.currentTime <= t + Tt || (n.currentTime = t);
1341
1369
  }
1342
1370
  startHls() {
1343
1371
  let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
@@ -1356,12 +1384,12 @@ var St = class {
1356
1384
  emeEnabled: !0,
1357
1385
  drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
1358
1386
  drmSystemOptions: {
1359
- videoRobustness: I.video,
1360
- audioRobustness: I.audio,
1361
- videoEncryptionScheme: I.scheme,
1362
- audioEncryptionScheme: I.scheme
1387
+ videoRobustness: F.video,
1388
+ audioRobustness: F.audio,
1389
+ videoEncryptionScheme: F.scheme,
1390
+ audioEncryptionScheme: F.scheme
1363
1391
  },
1364
- ...N() ? { requestMediaKeySystemAccessFunc: we(t) } : {},
1392
+ ...j() ? { requestMediaKeySystemAccessFunc: P(t) } : {},
1365
1393
  licenseXhrSetup: (e, t) => {
1366
1394
  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;
1367
1395
  let o = performance.now();
@@ -1378,20 +1406,20 @@ var St = class {
1378
1406
  ...c
1379
1407
  };
1380
1408
  if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
1381
- let e = new qe({
1409
+ let e = new et({
1382
1410
  sessionId: n.analytics?.sid,
1383
1411
  contentId: n.matchUrn
1384
- }), t = Je(e);
1412
+ }), t = tt(e);
1385
1413
  t && (this.prefetch = e, d.fLoader = t);
1386
1414
  }
1387
- bt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1415
+ Dt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1388
1416
  let f = new e(d);
1389
1417
  if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
1390
1418
  this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(f), this.measureLadder(f), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
1391
1419
  }), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
1392
1420
  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(() => {
1393
1421
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1394
- }, nt)));
1422
+ }, lt)));
1395
1423
  }), f.on(e.Events.FRAG_LOADING, (e, t) => {
1396
1424
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1397
1425
  }), f.on(e.Events.FRAG_LOADED, (e, t) => {
@@ -1399,10 +1427,10 @@ var St = class {
1399
1427
  let n = t?.frag?.stats, r = n?.loaded;
1400
1428
  typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1401
1429
  let i = n?.loading;
1402
- 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 > yt && this.requestTimesMs.shift());
1430
+ 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 > Et && this.requestTimesMs.shift());
1403
1431
  let a = t?.frag?.url;
1404
1432
  if (a) {
1405
- let e = G(a);
1433
+ let e = H(a);
1406
1434
  e && (this.cdnHost = e);
1407
1435
  }
1408
1436
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => {
@@ -1416,15 +1444,15 @@ var St = class {
1416
1444
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
1417
1445
  let t = this.prefetch;
1418
1446
  f.on(e.Events.KEY_LOADING, (e, n) => {
1419
- let r = n?.frag, i = Xe(r?.type);
1420
- if (r && t.isActive(i)) for (let e of Ze(f, r)) t.prefetch(e.url, i, e.kind);
1421
- }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Xe(n?.frag?.type)));
1447
+ let r = n?.frag, i = rt(r?.type);
1448
+ if (r && t.isActive(i)) for (let e of it(f, r)) t.prefetch(e.url, i, e.kind);
1449
+ }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(rt(n?.frag?.type)));
1422
1450
  }
1423
1451
  f.on(e.Events.KEY_LOADED, () => {
1424
1452
  u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
1425
1453
  }), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1426
1454
  this.checkEndStale(), this.checkStarvation();
1427
- }, it), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1455
+ }, dt), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1428
1456
  this.renditionSwitches += 1;
1429
1457
  let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
1430
1458
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
@@ -1488,7 +1516,7 @@ var St = class {
1488
1516
  return;
1489
1517
  }
1490
1518
  this.capTimer && clearTimeout(this.capTimer);
1491
- let t = e > this.sizeCapLevel ? mt : ht;
1519
+ let t = e > this.sizeCapLevel ? xt : St;
1492
1520
  this.capTimer = setTimeout(() => {
1493
1521
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1494
1522
  }, t);
@@ -1498,9 +1526,9 @@ var St = class {
1498
1526
  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;
1499
1527
  }
1500
1528
  dropLevelsWidevineCannotPlay(e) {
1501
- this.removeLevelsWhere(e, (e) => Ae(e) !== !0);
1502
- let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && L(e) !== "avc" && !!L(e)));
1503
- for (let n of t) Oe(n).then((t) => {
1529
+ this.removeLevelsWhere(e, (e) => Fe(e) !== !0);
1530
+ let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
1531
+ for (let n of t) Ne(n).then((t) => {
1504
1532
  t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
1505
1533
  });
1506
1534
  }
@@ -1508,10 +1536,10 @@ var St = class {
1508
1536
  let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
1509
1537
  if (n.forEach((e, n) => {
1510
1538
  let a = e.videoCodec;
1511
- a && L(a) && t(a) && (r.push(n), i.add(a));
1539
+ a && I(a) && t(a) && (r.push(n), i.add(a));
1512
1540
  }), !r.length) return !1;
1513
1541
  let a = [...i].join(", ");
1514
- if (!n.some((e, t) => r.includes(t) ? !1 : !L(e.videoCodec) || Ae(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1542
+ if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Fe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
1515
1543
  for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
1516
1544
  return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
1517
1545
  }
@@ -1557,7 +1585,7 @@ var St = class {
1557
1585
  e.widevine && (this.licenseUrl = e.widevine);
1558
1586
  }
1559
1587
  getStats() {
1560
- let e = this.hls, t = K(this.deps.video), n = {
1588
+ let e = this.hls, t = U(this.deps.video), n = {
1561
1589
  droppedFrames: t.dropped,
1562
1590
  decodedFrames: t.totalFrames,
1563
1591
  lowLatency: this.detectedLowLatency,
@@ -1603,7 +1631,7 @@ var St = class {
1603
1631
  return;
1604
1632
  }
1605
1633
  let e = Date.now() - this.lastAdvanceMs;
1606
- !this.chaseSuspended && e > at && this.suspendChasing(), e > rt && this.emitEnded("stalled");
1634
+ !this.chaseSuspended && e > ft && this.suspendChasing(), e > ut && this.emitEnded("stalled");
1607
1635
  }
1608
1636
  resetStarvationWindow() {
1609
1637
  this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
@@ -1618,7 +1646,7 @@ var St = class {
1618
1646
  this.resetStarvationWindow();
1619
1647
  return;
1620
1648
  }
1621
- let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < at, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > st, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = K(t), c = o - s, l = c !== this.starvedFrames;
1649
+ let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < ft, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > mt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = U(t), c = o - s, l = c !== this.starvedFrames;
1622
1650
  if (this.starvedFrames = c, !a || l) {
1623
1651
  (t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
1624
1652
  return;
@@ -1627,12 +1655,12 @@ var St = class {
1627
1655
  this.resetStarvationWindow();
1628
1656
  return;
1629
1657
  }
1630
- 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 > ft && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= ut && (this.clearKick(), this.starvationRebuilds < dt)) {
1658
+ 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 > yt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= _t && (this.clearKick(), this.starvationRebuilds < vt)) {
1631
1659
  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");
1632
1660
  return;
1633
1661
  }
1634
- let u = i && this.starvedTicks >= ct, d = !i && this.deadTicks >= ft && this.recentMainFrags.reduce((e, t) => e + t, 0) >= pt;
1635
- if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= lt))) {
1662
+ let u = i && this.starvedTicks >= ht, d = !i && this.deadTicks >= yt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= bt;
1663
+ if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= gt))) {
1636
1664
  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");
1637
1665
  try {
1638
1666
  e.stopLoad(), e.startLoad(-1);
@@ -1681,7 +1709,7 @@ var St = class {
1681
1709
  scheduleLicenseRetry(t) {
1682
1710
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
1683
1711
  let n = t.response?.code ?? 0;
1684
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= tt) return !1;
1712
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= ct) return !1;
1685
1713
  this.licenseRecoveries += 1;
1686
1714
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
1687
1715
  return this.licenseRetryTimer = setTimeout(() => {
@@ -1713,7 +1741,7 @@ var St = class {
1713
1741
  return;
1714
1742
  }
1715
1743
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
1716
- if (this.networkRecoveries < et) {
1744
+ if (this.networkRecoveries < st) {
1717
1745
  this.networkRecoveries += 1;
1718
1746
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
1719
1747
  this.networkRetryTimer = setTimeout(() => {
@@ -1730,7 +1758,7 @@ var St = class {
1730
1758
  return;
1731
1759
  }
1732
1760
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
1733
- if (this.mediaRecoveries < $e) {
1761
+ if (this.mediaRecoveries < ot) {
1734
1762
  this.mediaRecoveries += 1, n.recoverMediaError();
1735
1763
  return;
1736
1764
  }
@@ -1754,19 +1782,19 @@ var St = class {
1754
1782
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
1755
1783
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
1756
1784
  }
1757
- }, Ct = 15e3, wt = 6e5, Tt = 3e5, Et = 100, X = 1, Dt = 1e3, Ot = 3e4, kt = 1e3, At = {
1785
+ }, At = 15e3, jt = 6e5, Mt = 3e5, Nt = 100, q = 1, Pt = 1e3, Ft = 3e4, It = 1e3, Lt = {
1758
1786
  inline: "PRESENTATION_INLINE",
1759
1787
  fullscreen: "PRESENTATION_FULLSCREEN",
1760
1788
  pip: "PRESENTATION_PIP"
1761
- }, jt = {
1789
+ }, Rt = {
1762
1790
  widevine: "KEY_SYSTEM_WIDEVINE",
1763
1791
  fairplay: "KEY_SYSTEM_FAIRPLAY",
1764
1792
  none: "KEY_SYSTEM_NONE"
1765
1793
  };
1766
- function Mt(e, t) {
1794
+ function zt(e, t) {
1767
1795
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
1768
1796
  }
1769
- var Nt = /* @__PURE__ */ new Set([
1797
+ var Bt = /* @__PURE__ */ new Set([
1770
1798
  "INVALID_URN",
1771
1799
  "NOT_FOUND",
1772
1800
  "GONE",
@@ -1776,7 +1804,7 @@ var Nt = /* @__PURE__ */ new Set([
1776
1804
  "FORBIDDEN",
1777
1805
  "RATE_LIMITED",
1778
1806
  "TIMEOUT"
1779
- ]), Z = {
1807
+ ]), J = {
1780
1808
  idle: "PLAYER_STATE_IDLE",
1781
1809
  waiting: "PLAYER_STATE_WAITING",
1782
1810
  loading: "PLAYER_STATE_LOADING",
@@ -1786,7 +1814,7 @@ var Nt = /* @__PURE__ */ new Set([
1786
1814
  ended: "PLAYER_STATE_ENDED",
1787
1815
  error: "PLAYER_STATE_ERROR"
1788
1816
  };
1789
- function Pt(e) {
1817
+ function Vt(e) {
1790
1818
  try {
1791
1819
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
1792
1820
  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);
@@ -1794,26 +1822,42 @@ function Pt(e) {
1794
1822
  return;
1795
1823
  }
1796
1824
  }
1797
- var Ft = /* @__PURE__ */ new Set();
1798
- function It(e, t) {
1799
- return Ft.has(e) || (Ft.add(e), console.warn(`havik-player: ${t}`)), { disabledReason: t };
1825
+ var Ht = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Ut = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), Wt = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
1826
+ function Gt(e) {
1827
+ if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
1828
+ let t;
1829
+ try {
1830
+ let n = new URL(e.blockedURI);
1831
+ t = n.origin + n.pathname;
1832
+ } catch {
1833
+ return;
1834
+ }
1835
+ if (Ut.has(t) && !Y.has(t)) {
1836
+ Y.add(t), g(Wt(new URL(t).origin));
1837
+ for (let e of X) e.noteCspBlocked();
1838
+ }
1839
+ }
1840
+ function Kt(e, t) {
1841
+ return g(t, e), { disabledReason: t };
1800
1842
  }
1801
- function Lt(e, t) {
1843
+ function qt(e, t, n) {
1844
+ if (n) return t && !Ht(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
1802
1845
  if (t) return { endpoint: t };
1803
- if (t !== void 0) return It("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).");
1804
- let n = Pt(e);
1805
- if (n) return { endpoint: n };
1806
- let r;
1846
+ if (t !== void 0) return Kt("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).");
1847
+ let r = Vt(e);
1848
+ if (r) return { endpoint: r };
1849
+ let i;
1807
1850
  try {
1808
- r = new URL(e).hostname || e;
1851
+ i = new URL(e).hostname || e;
1809
1852
  } catch {
1810
- r = e;
1853
+ i = e;
1811
1854
  }
1812
- return It(r, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${r}" — 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).`);
1855
+ return Kt(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).`);
1813
1856
  }
1814
- var Rt = class {
1857
+ var Jt = class {
1815
1858
  opts;
1816
1859
  url;
1860
+ cspKey;
1817
1861
  now;
1818
1862
  seq = 0;
1819
1863
  pending = [];
@@ -1881,6 +1925,7 @@ var Rt = class {
1881
1925
  firstPlaylistMs = 0;
1882
1926
  drmSetupMs = 0;
1883
1927
  onPagehide = () => this.end("END_REASON_PAGEHIDE");
1928
+ cspBlockedNoted = !1;
1884
1929
  onFreeze = () => {
1885
1930
  this.endedFlag || this.flush(!0);
1886
1931
  };
@@ -1891,9 +1936,16 @@ var Rt = class {
1891
1936
  constructor(e) {
1892
1937
  this.opts = {
1893
1938
  ...e,
1894
- heartbeatMs: e.heartbeatMs ?? Ct,
1895
- idleMs: e.idleMs ?? wt
1896
- }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs, this.startupAnchorMs = this.bornMs;
1939
+ heartbeatMs: e.heartbeatMs ?? At,
1940
+ idleMs: e.idleMs ?? jt
1941
+ }, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
1942
+ try {
1943
+ let e = new URL(this.url);
1944
+ this.cspKey = e.origin + e.pathname;
1945
+ } catch {
1946
+ this.cspKey = void 0;
1947
+ }
1948
+ this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs, this.startupAnchorMs = this.bornMs;
1897
1949
  }
1898
1950
  start() {
1899
1951
  if (this.endedFlag) return;
@@ -1902,11 +1954,11 @@ var Rt = class {
1902
1954
  sdkVersion: this.opts.sdkVersion,
1903
1955
  ...this.opts.environment
1904
1956
  };
1905
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Dt), 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.onVisibility());
1957
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Pt), 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 && Ut.add(this.cspKey), document.addEventListener("securitypolicyviolation", Gt), X.add(this), this.noteCspBlocked(), this.onVisibility());
1906
1958
  }
1907
1959
  checkSuspension(e) {
1908
1960
  if (this.endedFlag || !this.opts.idleMs) return !1;
1909
- let t = Math.max(this.opts.idleMs, Tt);
1961
+ let t = Math.max(this.opts.idleMs, Mt);
1910
1962
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
1911
1963
  }
1912
1964
  syncIdle(e) {
@@ -1920,21 +1972,21 @@ var Rt = class {
1920
1972
  noteStateChange(e, t, n, r) {
1921
1973
  if (this.endedFlag || e === t) return;
1922
1974
  let i = this.now();
1923
- if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(X, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(X, 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") {
1975
+ 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") {
1924
1976
  this.stallIsSeekInduced = this.seekInduced(i);
1925
1977
  let e = !this.isHidden && !this.stallIsSeekInduced;
1926
- e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(X, Math.round(this.playingTotalMs)));
1978
+ e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(q, Math.round(this.playingTotalMs)));
1927
1979
  } else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
1928
1980
  this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
1929
1981
  let a = {
1930
- fromState: Z[e] ?? "PLAYER_STATE_UNSPECIFIED",
1931
- toState: Z[t] ?? "PLAYER_STATE_UNSPECIFIED",
1932
- presentation: At[this.presentation]
1982
+ fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
1983
+ toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
1984
+ presentation: Lt[this.presentation]
1933
1985
  }, o = this.causeOf(e, t, i);
1934
1986
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
1935
1987
  }
1936
1988
  seekInduced(e) {
1937
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < kt;
1989
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < It;
1938
1990
  }
1939
1991
  causeOf(e, t, n) {
1940
1992
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -1971,25 +2023,25 @@ var Rt = class {
1971
2023
  }
1972
2024
  this.muteChanges += 1;
1973
2025
  let r = this.now();
1974
- 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(X, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
2026
+ 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();
1975
2027
  }
1976
2028
  notePresentation(e) {
1977
2029
  this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
1978
2030
  }
1979
2031
  notePlayIntent() {
1980
- this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = X), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = X), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = X), this.drmSetupMs > 0 && (this.drmSetupMs = X));
2032
+ 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));
1981
2033
  }
1982
2034
  noteReady() {
1983
- this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(X, this.now() - this.startupAnchorMs));
2035
+ this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(q, this.now() - this.startupAnchorMs));
1984
2036
  }
1985
2037
  noteFirstPlaylist() {
1986
- this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(X, this.now() - this.startupAnchorMs));
2038
+ this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(q, this.now() - this.startupAnchorMs));
1987
2039
  }
1988
2040
  noteDrmReady() {
1989
- this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(X, this.now() - this.startupAnchorMs));
2041
+ this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(q, this.now() - this.startupAnchorMs));
1990
2042
  }
1991
2043
  noteFirstBytes() {
1992
- this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(X, this.now() - this.startupAnchorMs));
2044
+ this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(q, this.now() - this.startupAnchorMs));
1993
2045
  }
1994
2046
  noteSeek() {
1995
2047
  this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
@@ -2008,7 +2060,7 @@ var Rt = class {
2008
2060
  let r = n ?? "";
2009
2061
  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";
2010
2062
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
2011
- if (Nt.has(e)) return "ERROR_STAGE_RESOLVE";
2063
+ if (Bt.has(e)) return "ERROR_STAGE_RESOLVE";
2012
2064
  let i = t ?? "";
2013
2065
  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";
2014
2066
  }
@@ -2024,7 +2076,7 @@ var Rt = class {
2024
2076
  heartbeat() {
2025
2077
  if (this.endedFlag) return;
2026
2078
  let e = this.now();
2027
- if (this.checkSuspension(e)) return;
2079
+ if (this.checkSuspension(e) || this.cspBlocked()) return;
2028
2080
  let t = this.opts.sample(), n = this.playingTotalMs;
2029
2081
  this.playingSinceMs !== null && (n += e - this.playingSinceMs);
2030
2082
  let r = this.hiddenTotalMs;
@@ -2040,7 +2092,7 @@ var Rt = class {
2040
2092
  let l = t.droppedFrames ?? 0;
2041
2093
  l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
2042
2094
  let u = t.renditionSwitches ?? 0;
2043
- 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 = Z[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
2095
+ 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";
2044
2096
  let d = this.mutedTotalMs;
2045
2097
  this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
2046
2098
  let f = t.upshifts ?? 0;
@@ -2055,20 +2107,20 @@ var Rt = class {
2055
2107
  if (this.lastRequestCount = g, _ > 0) {
2056
2108
  o.requestCountDelta = _;
2057
2109
  let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
2058
- n.length > 0 && (o.requestTimeP50Ms = Mt(n, 50), o.requestTimeP95Ms = Mt(n, 95));
2110
+ n.length > 0 && (o.requestTimeP50Ms = zt(n, 50), o.requestTimeP95Ms = zt(n, 95));
2059
2111
  }
2060
2112
  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();
2061
2113
  }
2062
2114
  maybeEmitMediaInfo(e) {
2063
2115
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
2064
2116
  let t = {};
2065
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = jt[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);
2117
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Rt[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);
2066
2118
  let n = JSON.stringify(t);
2067
2119
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
2068
2120
  }
2069
2121
  end(e, t) {
2070
2122
  if (this.endedFlag) return;
2071
- this.endedFlag = !0;
2123
+ this.endedFlag = !0, X.delete(this);
2072
2124
  let n = t ?? this.now();
2073
2125
  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));
2074
2126
  let r = this.safeSample();
@@ -2082,7 +2134,7 @@ var Rt = class {
2082
2134
  let c = r?.positionMs ?? 0;
2083
2135
  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));
2084
2136
  let l = e !== "END_REASON_ENDED";
2085
- l && this.lastStallMs > 0 && n - this.lastStallMs <= Ot && (i.abandonAfterStallMs = Math.max(X, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Ot && (i.abandonAfterErrorMs = Math.max(X, 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);
2137
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= Ft && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Ft && (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);
2086
2138
  let u = r?.decodedFrames ?? this.lastDecoded;
2087
2139
  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");
2088
2140
  }
@@ -2101,14 +2153,24 @@ var Rt = class {
2101
2153
  ...e
2102
2154
  };
2103
2155
  }
2156
+ noteCspBlocked() {
2157
+ this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(Wt(new URL(this.url).origin)));
2158
+ }
2159
+ cspBlocked() {
2160
+ return !!this.cspKey && Y.has(this.cspKey);
2161
+ }
2104
2162
  enqueue(e) {
2105
- for (this.pending.push(this.wrap(e)); this.pending.length > Et;) {
2163
+ if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Nt;) {
2106
2164
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
2107
2165
  this.pending.splice(e >= 0 ? e : 0, 1);
2108
2166
  }
2109
2167
  }
2110
2168
  flush(e = !1) {
2111
2169
  if (this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.pendingStart = null, this.pending.length === 0) return;
2170
+ if (this.cspBlocked()) {
2171
+ this.pending = [];
2172
+ return;
2173
+ }
2112
2174
  let t = JSON.stringify({ beacons: this.pending });
2113
2175
  if (this.pending = [], e) {
2114
2176
  let e = this.opts.sendBeacon ?? (typeof navigator < "u" && navigator.sendBeacon ? navigator.sendBeacon.bind(navigator) : void 0);
@@ -2125,7 +2187,7 @@ var Rt = class {
2125
2187
  };
2126
2188
  //#endregion
2127
2189
  //#region src/core/environment.ts
2128
- function zt() {
2190
+ function Yt() {
2129
2191
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
2130
2192
  let e;
2131
2193
  try {
@@ -2150,14 +2212,14 @@ function zt() {
2150
2212
  integration: "INTEGRATION_KIND_IFRAME"
2151
2213
  };
2152
2214
  }
2153
- function Bt() {
2215
+ function Xt() {
2154
2216
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
2155
2217
  let e = navigator.userAgentData, t = e?.platform ?? "";
2156
2218
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
2157
2219
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
2158
2220
  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";
2159
2221
  }
2160
- function Vt() {
2222
+ function Zt() {
2161
2223
  let e = typeof navigator < "u" ? navigator.connection : void 0;
2162
2224
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
2163
2225
  let t = {
@@ -2176,17 +2238,17 @@ function Vt() {
2176
2238
  }
2177
2239
  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;
2178
2240
  }
2179
- function Ht(e) {
2180
- let t = zt(), n = {
2181
- deviceClass: Bt(),
2241
+ function Qt(e) {
2242
+ let t = Yt(), n = {
2243
+ deviceClass: Xt(),
2182
2244
  integration: t.integration,
2183
- ...Vt()
2245
+ ...Zt()
2184
2246
  };
2185
2247
  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);
2186
2248
  let r = e.getBoundingClientRect?.();
2187
2249
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
2188
2250
  }
2189
- async function Ut() {
2251
+ async function $t() {
2190
2252
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
2191
2253
  if (!e?.getHighEntropyValues) return {};
2192
2254
  try {
@@ -2198,7 +2260,7 @@ async function Ut() {
2198
2260
  }
2199
2261
  //#endregion
2200
2262
  //#region src/core/version.ts
2201
- var Wt = "2.11.1", Gt = {
2263
+ var en = "2.13.0", tn = {
2202
2264
  accent: "#E1B600",
2203
2265
  accentText: "#1B1C23",
2204
2266
  background: "#0e0f13",
@@ -2209,7 +2271,7 @@ var Wt = "2.11.1", Gt = {
2209
2271
  border: "rgba(255, 255, 255, 0.1)",
2210
2272
  radius: "8px",
2211
2273
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
2212
- }, Kt = {
2274
+ }, nn = {
2213
2275
  accent: "--havik-accent",
2214
2276
  accentText: "--havik-accent-text",
2215
2277
  background: "--havik-bg",
@@ -2221,25 +2283,25 @@ var Wt = "2.11.1", Gt = {
2221
2283
  radius: "--havik-radius",
2222
2284
  fontFamily: "--havik-font"
2223
2285
  };
2224
- function qt(e, t) {
2286
+ function rn(e, t) {
2225
2287
  let n = {
2226
- ...Gt,
2288
+ ...tn,
2227
2289
  ...t
2228
2290
  };
2229
- for (let t of Object.keys(Kt)) e.style.setProperty(Kt[t], n[t]);
2291
+ for (let t of Object.keys(nn)) e.style.setProperty(nn[t], n[t]);
2230
2292
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
2231
2293
  }
2232
2294
  //#endregion
2233
2295
  //#region src/ui/styles.ts
2234
- var Jt = "havik-player-styles", Yt = "\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.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";
2235
- function Xt(e = document) {
2236
- if (e.getElementById(Jt)) return;
2296
+ var an = "havik-player-styles", on = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.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";
2297
+ function sn(e = document) {
2298
+ if (e.getElementById(an)) return;
2237
2299
  let t = e.createElement("style");
2238
- t.id = Jt, t.textContent = Yt, e.head.appendChild(t);
2300
+ t.id = an, t.textContent = on, e.head.appendChild(t);
2239
2301
  }
2240
2302
  //#endregion
2241
2303
  //#region src/ui/icons.ts
2242
- var Zt = {
2304
+ var cn = {
2243
2305
  play: "<path d=\"M8 5v14l11-7z\"/>",
2244
2306
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
2245
2307
  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\"/>",
@@ -2252,21 +2314,21 @@ var Zt = {
2252
2314
  liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
2253
2315
  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\"/>"
2254
2316
  };
2255
- function Q(e) {
2256
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Zt[e]}</svg>`;
2317
+ function Z(e) {
2318
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${cn[e]}</svg>`;
2257
2319
  }
2258
2320
  //#endregion
2259
2321
  //#region src/ui/controls.ts
2260
- var Qt = 3e3, $t = /* @__PURE__ */ new Set([
2322
+ var ln = 3e3, un = /* @__PURE__ */ new Set([
2261
2323
  "GONE",
2262
2324
  "NOT_FOUND",
2263
2325
  "INVALID_URN",
2264
2326
  "UNAUTHORIZED"
2265
2327
  ]);
2266
- function en(e) {
2267
- return new tn(e);
2328
+ function dn(e) {
2329
+ return new fn(e);
2268
2330
  }
2269
- var tn = class {
2331
+ var fn = class {
2270
2332
  root;
2271
2333
  video;
2272
2334
  player;
@@ -2308,7 +2370,7 @@ var tn = class {
2308
2370
  scrubbing = !1;
2309
2371
  offFns = [];
2310
2372
  constructor(e) {
2311
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Qt, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, Xt(this.doc), 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");
2373
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? ln, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, sn(this.doc), 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");
2312
2374
  let t = (e, t, n) => {
2313
2375
  let r = this.doc.createElement(e);
2314
2376
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -2319,12 +2381,12 @@ var tn = class {
2319
2381
  "aria-label": r,
2320
2382
  title: r
2321
2383
  });
2322
- return i.innerHTML = Q(n), i;
2384
+ return i.innerHTML = Z(n), i;
2323
2385
  };
2324
2386
  this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
2325
2387
  type: "button",
2326
2388
  "aria-label": "Play"
2327
- }), this.center.innerHTML = Q("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
2389
+ }), this.center.innerHTML = Z("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
2328
2390
  role: "slider",
2329
2391
  "aria-label": "Seek",
2330
2392
  "aria-valuemin": "0",
@@ -2342,7 +2404,7 @@ var tn = class {
2342
2404
  "aria-label": "Volume"
2343
2405
  });
2344
2406
  let a = t("div", "havik-vol");
2345
- a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Q("liveDot");
2407
+ a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Z("liveDot");
2346
2408
  let o = this.doc.createElement("span");
2347
2409
  o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
2348
2410
  let s = t("div", "havik-spacer");
@@ -2396,12 +2458,12 @@ var tn = class {
2396
2458
  }
2397
2459
  if (e === "preplay") {
2398
2460
  let e = this.doc.createElement("button");
2399
- 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);
2461
+ e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Z("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
2400
2462
  } else {
2401
2463
  let r = this.doc.createElement("div");
2402
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !$t.has(this.lastError.code)) {
2464
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !un.has(this.lastError.code)) {
2403
2465
  let e = this.doc.createElement("button");
2404
- 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);
2466
+ e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Z("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
2405
2467
  }
2406
2468
  }
2407
2469
  this.root.append(n), this.statusBox = n, this.show();
@@ -2440,7 +2502,7 @@ var tn = class {
2440
2502
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
2441
2503
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
2442
2504
  }
2443
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${nn(this.video.currentTime)} / ${nn(this.video.duration)}`);
2505
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Q(this.video.currentTime)} / ${Q(this.video.duration)}`);
2444
2506
  }
2445
2507
  syncLive() {
2446
2508
  let e = this.player.getStats(), t = e.isLive !== !1;
@@ -2490,17 +2552,17 @@ var tn = class {
2490
2552
  renderQualityMenu() {
2491
2553
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
2492
2554
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
2493
- for (let n of e) this.menu.append(this.menuItem(rn(n), t === n.index, () => this.player.setQuality(n.index)));
2555
+ for (let n of e) this.menu.append(this.menuItem(pn(n), t === n.index, () => this.player.setQuality(n.index)));
2494
2556
  }
2495
2557
  renderAudioMenu() {
2496
2558
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
2497
2559
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
2498
- for (let t of e) this.menu.append(this.menuItem(an(t), t.default, () => this.player.setAudioTrack(t.id)));
2560
+ for (let t of e) this.menu.append(this.menuItem(mn(t), t.default, () => this.player.setAudioTrack(t.id)));
2499
2561
  }
2500
2562
  renderCcMenu() {
2501
2563
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
2502
2564
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
2503
- for (let t of e) this.menu.append(this.menuItem(on(t), !1, () => this.player.setTextTrack(t.id)));
2565
+ for (let t of e) this.menu.append(this.menuItem(hn(t), !1, () => this.player.setTextTrack(t.id)));
2504
2566
  }
2505
2567
  onTracksChanged() {
2506
2568
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2520,11 +2582,11 @@ var tn = class {
2520
2582
  }
2521
2583
  async toggleFullscreen() {
2522
2584
  try {
2523
- w(this.video, this.root) ? await E(this.video, this.root) : await T(this.video, this.root);
2585
+ S(this.video, this.root) ? await w(this.video, this.root) : await C(this.video, this.root);
2524
2586
  } catch {}
2525
2587
  }
2526
2588
  syncFullscreen() {
2527
- let e = w(this.video, this.root);
2589
+ let e = S(this.video, this.root);
2528
2590
  this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
2529
2591
  }
2530
2592
  poke() {
@@ -2583,7 +2645,7 @@ var tn = class {
2583
2645
  }
2584
2646
  }
2585
2647
  setIcon(e, t) {
2586
- e.innerHTML = Q(t);
2648
+ e.innerHTML = Z(t);
2587
2649
  }
2588
2650
  destroy() {
2589
2651
  this.hideTimer && clearTimeout(this.hideTimer);
@@ -2600,41 +2662,41 @@ var tn = class {
2600
2662
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
2601
2663
  }
2602
2664
  };
2603
- function nn(e) {
2665
+ function Q(e) {
2604
2666
  (!Number.isFinite(e) || e < 0) && (e = 0);
2605
2667
  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");
2606
2668
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
2607
2669
  }
2608
- function rn(e) {
2670
+ function pn(e) {
2609
2671
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
2610
2672
  }
2611
- function an(e) {
2673
+ function mn(e) {
2612
2674
  return e.name || e.lang || `Track ${e.id}`;
2613
2675
  }
2614
- function on(e) {
2676
+ function hn(e) {
2615
2677
  return e.name || e.lang || `Track ${e.id}`;
2616
2678
  }
2617
2679
  //#endregion
2618
2680
  //#region src/managed/index.ts
2619
- var sn = 6e3, cn = 45e3, ln = 2e3, un = 3, dn = 2e3, fn = 48e4;
2620
- function pn(e) {
2681
+ var gn = 6e3, _n = 45e3, vn = 2e3, yn = 3, bn = 2e3, xn = 48e4;
2682
+ function Sn(e) {
2621
2683
  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)})`);
2622
- if (e.env !== void 0) return U(e.env);
2684
+ if (e.env !== void 0) return B(e.env);
2623
2685
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
2624
2686
  return e.baseUrl;
2625
2687
  }
2626
- async function mn(e) {
2688
+ async function Cn(e) {
2627
2689
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
2628
- let t = pn(e);
2690
+ let t = Sn(e);
2629
2691
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
2630
2692
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
2631
- let r = new hn({
2693
+ let r = new wn({
2632
2694
  ...e,
2633
2695
  baseUrl: t
2634
2696
  });
2635
2697
  return await r.start(), r;
2636
2698
  }
2637
- var hn = class {
2699
+ var wn = class {
2638
2700
  opts;
2639
2701
  abort = new AbortController();
2640
2702
  listeners = {};
@@ -2678,7 +2740,7 @@ var hn = class {
2678
2740
  this.opts.muted && (this.opts.video.muted = !0), this.opts.poster && (this.opts.video.poster = this.opts.poster), this.mountControls(), this.attachPipListeners(), this.setState("loading");
2679
2741
  let e = ++this.loadGen, t = this.resolveOptions();
2680
2742
  try {
2681
- let n = await y(t);
2743
+ let n = await v(t);
2682
2744
  if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
2683
2745
  let e = this._lastError;
2684
2746
  throw this.destroy(), e;
@@ -2701,11 +2763,11 @@ var hn = class {
2701
2763
  };
2702
2764
  }
2703
2765
  beginArming(e, t, n = !1) {
2704
- let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
2766
+ let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
2705
2767
  r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
2706
2768
  }
2707
2769
  beginArmingByPolling(e) {
2708
- b({
2770
+ y({
2709
2771
  ...this.resolveOptions(),
2710
2772
  signal: this.abort.signal,
2711
2773
  waitForLive: this.buildWaitConfig(e)
@@ -2722,7 +2784,7 @@ var hn = class {
2722
2784
  setTimeout(() => {
2723
2785
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
2724
2786
  phase: i ? "unavailable" : "tooEarly",
2725
- retryInMs: cn,
2787
+ retryInMs: _n,
2726
2788
  attempt: 1,
2727
2789
  elapsedMs: 0,
2728
2790
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -2739,7 +2801,7 @@ var hn = class {
2739
2801
  }
2740
2802
  }
2741
2803
  }, h = () => {
2742
- a || s || p() || (s = !0, b({
2804
+ a || s || p() || (s = !0, y({
2743
2805
  ...this.resolveOptions(),
2744
2806
  signal: c.signal,
2745
2807
  waitForLive: this.buildWaitConfig(e)
@@ -2747,7 +2809,7 @@ var hn = class {
2747
2809
  a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
2748
2810
  }));
2749
2811
  }, g = () => {
2750
- a || p() || y(this.resolveOptions()).then((e) => m(e)).catch((e) => {
2812
+ a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
2751
2813
  if (!(a || p())) {
2752
2814
  if (e instanceof n && o(e.code)) {
2753
2815
  h();
@@ -2761,13 +2823,13 @@ var hn = class {
2761
2823
  !a && !p() && h();
2762
2824
  }, e);
2763
2825
  };
2764
- _(sn), this.armingSub = D({
2826
+ _(gn), this.armingSub = T({
2765
2827
  eventsBaseUrl: t,
2766
2828
  matchUrn: this.opts.matchUrn,
2767
2829
  credential: this.opts.credential,
2768
- onAlive: () => _(cn),
2830
+ onAlive: () => _(_n),
2769
2831
  onState: (e) => {
2770
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * ln);
2832
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * vn);
2771
2833
  },
2772
2834
  onError: () => h()
2773
2835
  });
@@ -2790,7 +2852,7 @@ var hn = class {
2790
2852
  let n = await s(this.opts.credential);
2791
2853
  if (this.destroyed || t !== this.loadGen) return;
2792
2854
  this.setState("loading");
2793
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Be(this.opts.video, (e) => {
2855
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = qe(this.opts.video, (e) => {
2794
2856
  this._state !== "ended" && this._state !== "error" && this.setState(e);
2795
2857
  });
2796
2858
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -2812,23 +2874,26 @@ var hn = class {
2812
2874
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
2813
2875
  let i = e.analytics?.sid;
2814
2876
  if (!i) return;
2815
- let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Lt(this.opts.baseUrl, a);
2877
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = qt(this.opts.baseUrl, a, e.analytics?.endpoint);
2816
2878
  if (!o) {
2817
2879
  s && setTimeout(() => {
2818
2880
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
2819
2881
  }, 0);
2820
2882
  return;
2821
2883
  }
2822
- let c = this.opts.video, l = new Rt({
2884
+ let c = this.opts.video, l = new Jt({
2823
2885
  endpoint: o,
2824
2886
  sid: i,
2825
2887
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
2826
- sdkVersion: Wt,
2827
- environment: Ht(c),
2888
+ sdkVersion: en,
2889
+ environment: Qt(c),
2828
2890
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
2829
2891
  onIdle: () => this.onAnalyticsIdle(t),
2892
+ onBlocked: (e) => setTimeout(() => {
2893
+ this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
2894
+ }, 0),
2830
2895
  sample: () => {
2831
- let e = this.engine?.getStats() ?? W, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
2896
+ let e = this.engine?.getStats() ?? V, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
2832
2897
  return {
2833
2898
  ...e,
2834
2899
  bufferedMs: Math.round(t * 1e3),
@@ -2842,7 +2907,7 @@ var hn = class {
2842
2907
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
2843
2908
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
2844
2909
  c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
2845
- }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Ut().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2910
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), $t().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2846
2911
  }
2847
2912
  currentPresentation() {
2848
2913
  let e = this.opts.video;
@@ -2857,7 +2922,7 @@ var hn = class {
2857
2922
  video: this.opts.video,
2858
2923
  descriptor: e,
2859
2924
  credential: t,
2860
- deviceId: j(),
2925
+ deviceId: k(),
2861
2926
  userId: this.opts.userId,
2862
2927
  lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
2863
2928
  snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
@@ -2867,11 +2932,11 @@ var hn = class {
2867
2932
  hlsConfig: i,
2868
2933
  emit: (e) => this.onEngineEvent(e)
2869
2934
  }, o = this.opts.engine ?? "auto";
2870
- if (o === "native") return new Y(a);
2871
- if (o === "hls") return new St(a);
2872
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && q(this.opts.video) && J()) return new Y(a);
2873
- if (Qe()) return new St(a);
2874
- if (q(this.opts.video)) return new Y(a);
2935
+ if (o === "native") return new K(a);
2936
+ if (o === "hls") return new kt(a);
2937
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G()) return new K(a);
2938
+ if (at()) return new kt(a);
2939
+ if (W(this.opts.video)) return new K(a);
2875
2940
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
2876
2941
  }
2877
2942
  onEngineEvent(e) {
@@ -2908,11 +2973,11 @@ var hn = class {
2908
2973
  }
2909
2974
  startLiveState(e) {
2910
2975
  if (this.opts.liveStateEvents === !1) return;
2911
- let t = this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
2976
+ let t = this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
2912
2977
  if (!t) return;
2913
2978
  this.closeLiveState();
2914
2979
  let r = 0, i = !1;
2915
- this.liveStateSub = D({
2980
+ this.liveStateSub = T({
2916
2981
  eventsBaseUrl: t,
2917
2982
  matchUrn: this.opts.matchUrn,
2918
2983
  credential: this.opts.credential,
@@ -2923,7 +2988,7 @@ var hn = class {
2923
2988
  r = 0, i = !1;
2924
2989
  },
2925
2990
  onError: () => {
2926
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= un && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
2991
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= yn && (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.`))));
2927
2992
  }
2928
2993
  });
2929
2994
  }
@@ -2945,7 +3010,7 @@ var hn = class {
2945
3010
  scheduleRejoin(e) {
2946
3011
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
2947
3012
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
2948
- }, Math.random() * ln));
3013
+ }, Math.random() * vn));
2949
3014
  }
2950
3015
  cancelRejoin() {
2951
3016
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -2969,7 +3034,7 @@ var hn = class {
2969
3034
  }
2970
3035
  t.controls = !1;
2971
3036
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
2972
- r && r.insertBefore(n, t), n.appendChild(t), qt(n, this.opts.theme), this.container = n, this.controlBar = en({
3037
+ r && r.insertBefore(n, t), n.appendChild(t), rn(n, this.opts.theme), this.container = n, this.controlBar = dn({
2973
3038
  root: n,
2974
3039
  video: t,
2975
3040
  player: this,
@@ -2999,7 +3064,7 @@ var hn = class {
2999
3064
  }
3000
3065
  startStats() {
3001
3066
  this.stopStats();
3002
- let e = Math.max(500, this.opts.statsIntervalMs ?? dn);
3067
+ let e = Math.max(500, this.opts.statsIntervalMs ?? bn);
3003
3068
  this.statsTimer = setInterval(() => {
3004
3069
  if (!this.engine) return;
3005
3070
  let e = this.engine.getStats();
@@ -3011,7 +3076,7 @@ var hn = class {
3011
3076
  }
3012
3077
  scheduleLicenseRefresh() {
3013
3078
  this.stopRefresh();
3014
- let e = this.opts.licenseRefreshMs ?? fn;
3079
+ let e = this.opts.licenseRefreshMs ?? xn;
3015
3080
  e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
3016
3081
  }
3017
3082
  stopRefresh() {
@@ -3020,7 +3085,7 @@ var hn = class {
3020
3085
  async refreshLicense() {
3021
3086
  let e = this.engine;
3022
3087
  if (!this.destroyed && e) try {
3023
- let t = await y(this.resolveOptions());
3088
+ let t = await v(this.resolveOptions());
3024
3089
  if (this.destroyed || this.engine !== e) return;
3025
3090
  let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
3026
3091
  (n || r) && (e.setLicenseUrls({
@@ -3056,7 +3121,7 @@ var hn = class {
3056
3121
  this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
3057
3122
  }
3058
3123
  getStats() {
3059
- return this.engine?.getStats() ?? W;
3124
+ return this.engine?.getStats() ?? V;
3060
3125
  }
3061
3126
  getQualityLevels() {
3062
3127
  return this.engine?.getQualityLevels() ?? [];
@@ -3095,10 +3160,10 @@ var hn = class {
3095
3160
  e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
3096
3161
  }
3097
3162
  async enterFullscreen() {
3098
- return !this.destroyed && T(this.opts.video, this.container ?? void 0);
3163
+ return !this.destroyed && C(this.opts.video, this.container ?? void 0);
3099
3164
  }
3100
3165
  async exitFullscreen() {
3101
- await E(this.opts.video, this.container ?? void 0);
3166
+ await w(this.opts.video, this.container ?? void 0);
3102
3167
  }
3103
3168
  retry() {
3104
3169
  return this.reload();
@@ -3108,7 +3173,7 @@ var hn = class {
3108
3173
  let e = ++this.loadGen;
3109
3174
  this.teardownPlayback();
3110
3175
  try {
3111
- let t = await b({
3176
+ let t = await y({
3112
3177
  ...this.resolveOptions(),
3113
3178
  waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
3114
3179
  });
@@ -3166,7 +3231,7 @@ function $(e) {
3166
3231
  }
3167
3232
  //#endregion
3168
3233
  //#region src/embed/host.ts
3169
- function gn(e) {
3234
+ function Tn(e) {
3170
3235
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
3171
3236
  if (!e.src) throw Error("mountEmbed: opts.src is required");
3172
3237
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -3225,15 +3290,15 @@ function gn(e) {
3225
3290
  }
3226
3291
  //#endregion
3227
3292
  //#region src/embed/page.ts
3228
- var _n = /^[A-Za-z0-9:_.-]{1,128}$/;
3229
- function vn(e) {
3293
+ var En = /^[A-Za-z0-9:_.-]{1,128}$/;
3294
+ function Dn(e) {
3230
3295
  if (typeof e == "boolean") return e;
3231
3296
  if (typeof e == "object" && e) {
3232
3297
  let t = e.endpoint;
3233
3298
  return typeof t == "string" ? { endpoint: t } : {};
3234
3299
  }
3235
3300
  }
3236
- function yn() {
3301
+ function On() {
3237
3302
  let e = window.HAVIK_EMBED_CONFIG;
3238
3303
  if (e) return {
3239
3304
  baseUrl: e.baseUrl ?? "",
@@ -3243,7 +3308,7 @@ function yn() {
3243
3308
  autoplay: e.autoplay ?? !0,
3244
3309
  muted: e.muted ?? !0,
3245
3310
  waitForLive: e.waitForLive ?? !0,
3246
- analytics: vn(e.analytics)
3311
+ analytics: Dn(e.analytics)
3247
3312
  };
3248
3313
  let t = new URLSearchParams(location.search);
3249
3314
  return {
@@ -3256,9 +3321,9 @@ function yn() {
3256
3321
  waitForLive: !0
3257
3322
  };
3258
3323
  }
3259
- async function bn() {
3260
- let e = yn();
3261
- Sn();
3324
+ async function kn() {
3325
+ let e = On();
3326
+ jn();
3262
3327
  let t = document.createElement("video");
3263
3328
  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);
3264
3329
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -3313,12 +3378,12 @@ async function bn() {
3313
3378
  code: e.code,
3314
3379
  message: e.message
3315
3380
  })), e.on("autoplayblocked", () => {
3316
- i({ type: "oddin:autoplayblocked" }), xn(t, e);
3381
+ i({ type: "oddin:autoplayblocked" }), An(t, e);
3317
3382
  });
3318
3383
  }, s = async (r) => {
3319
3384
  a?.destroy(), a = null;
3320
3385
  try {
3321
- let n = await mn({
3386
+ let n = await Cn({
3322
3387
  video: t,
3323
3388
  baseUrl: e.baseUrl,
3324
3389
  matchUrn: r,
@@ -3380,7 +3445,7 @@ async function bn() {
3380
3445
  a?.retry();
3381
3446
  break;
3382
3447
  case "oddin:load":
3383
- typeof e.matchUrn == "string" && _n.test(e.matchUrn) && s(e.matchUrn);
3448
+ typeof e.matchUrn == "string" && En.test(e.matchUrn) && s(e.matchUrn);
3384
3449
  break;
3385
3450
  case "oddin:destroy": c();
3386
3451
  }
@@ -3392,18 +3457,18 @@ async function bn() {
3392
3457
  protocol: 1
3393
3458
  });
3394
3459
  }
3395
- function xn(e, t) {
3460
+ function An(e, t) {
3396
3461
  if (document.getElementById("havik-tap")) return;
3397
3462
  let n = document.createElement("button");
3398
3463
  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", () => {
3399
3464
  n.remove(), t.play();
3400
3465
  }), document.body.appendChild(n);
3401
3466
  }
3402
- function Sn() {
3467
+ function jn() {
3403
3468
  let e = document.createElement("style");
3404
3469
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
3405
3470
  }
3406
3471
  //#endregion
3407
- export { Gt as ODDIN_THEME, n as PlaybackError, qt as applyTheme, U as baseUrlForEnv, bn as bootEmbed, ye as clearDeviceId, mn as createPlayer, O as deriveEventsBaseUrl, Fe as detectDrmSupport, T as enterVideoFullscreen, E as exitVideoFullscreen, fe as fetchCatalog, me as fetchTournament, ge as flattenMatches, j as getDeviceId, Le as isLowLatencyManifest, $ as isOddinMessage, xe as licenseRequestHeaders, gn as mountEmbed, v as pollToLive, b as resolveStream, D as subscribeLiveState, w as videoFullscreenActive, _e as watchStatus };
3472
+ export { tn as ODDIN_THEME, n as PlaybackError, rn as applyTheme, B as baseUrlForEnv, kn as bootEmbed, Te as clearDeviceId, Cn as createPlayer, E as deriveEventsBaseUrl, He as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, k as getDeviceId, We as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, Tn as mountEmbed, de as pollToLive, y as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
3408
3473
 
3409
3474
  //# sourceMappingURL=index.js.map