@oddin-gg/havik-player 2.9.0 → 2.9.2

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
@@ -43,9 +43,12 @@ async function s(e) {
43
43
  if (!t || !t.apiKey) throw Error("havik-player: credential is missing an apiKey");
44
44
  return t;
45
45
  }
46
+ function c(e) {
47
+ return e === "live" || e === "ended" || e === "upcoming" ? e : "upcoming";
48
+ }
46
49
  //#endregion
47
50
  //#region src/core/http.ts
48
- function c(e, t) {
51
+ function l(e, t) {
49
52
  let r = e.replace(/\/+$/, ""), i;
50
53
  try {
51
54
  i = new URL(r + t);
@@ -55,14 +58,14 @@ function c(e, t) {
55
58
  if (i.protocol !== "https:" && i.protocol !== "http:") throw new n("INTERNAL", 0, `baseUrl must be http(s), got: ${JSON.stringify(e)}`);
56
59
  return i.toString();
57
60
  }
58
- function l(e) {
61
+ function u(e) {
59
62
  if (!e) return;
60
63
  let t = Number(e);
61
64
  if (Number.isFinite(t)) return Math.max(0, Math.round(t * 1e3));
62
65
  let n = Date.parse(e);
63
66
  if (!Number.isNaN(n)) return Math.max(0, n - Date.now());
64
67
  }
65
- async function u(e, t) {
68
+ async function d(e, t) {
66
69
  let r = await s(t.credential), i = t.headers ?? new Headers();
67
70
  if (t.apiHeaders) for (let [e, n] of Object.entries(t.apiHeaders)) i.has(e) || i.set(e, n);
68
71
  i.set("x-api-key", r.apiKey);
@@ -77,49 +80,49 @@ async function u(e, t) {
77
80
  mode: "cors"
78
81
  });
79
82
  } catch (e) {
80
- throw t.signal?.aborted ? new n("ABORTED", 0, "request aborted", { cause: e }) : new n("NETWORK", 0, `network request failed: ${d(e)}`, { cause: e });
83
+ throw t.signal?.aborted ? new n("ABORTED", 0, "request aborted", { cause: e }) : new n("NETWORK", 0, `network request failed: ${f(e)}`, { cause: e });
81
84
  }
82
85
  }
83
- function d(e) {
86
+ function f(e) {
84
87
  return e instanceof Error ? e.message : String(e);
85
88
  }
86
89
  //#endregion
87
90
  //#region src/core/waitForLive.ts
88
- var f = 1e3, p = 3e4, m = 6e5, h = 3e5, g = 1e3, _ = {
91
+ var p = 1e3, m = 3e4, h = 6e5, g = 3e5, _ = 1e3, ee = {
89
92
  TOO_EARLY: "tooEarly",
90
93
  UNAVAILABLE: "unavailable",
91
94
  RATE_LIMITED: "rateLimited",
92
95
  NETWORK: "network"
93
96
  };
94
- function ee(e) {
95
- let t = e === !0 || e === !1 ? {} : e, n = Math.max(g, t.floorMs ?? f), r = Math.max(n, t.ceilMs ?? p), i = Math.max(0, t.imminentMs ?? m), a = Math.max(r, t.sanityFloorMs ?? h);
97
+ function te(e) {
98
+ let t = e === !0 || e === !1 ? {} : e, n = Math.max(_, t.floorMs ?? p), r = Math.max(n, t.ceilMs ?? m), i = Math.max(0, t.imminentMs ?? h), a = Math.max(r, t.sanityFloorMs ?? g);
96
99
  return {
97
100
  timeoutMs: t.timeoutMs,
98
101
  floorMs: n,
99
102
  ceilMs: r,
100
103
  imminentMs: i,
101
104
  sanityFloorMs: a,
102
- kickoffMs: te(t.kickoffAt),
105
+ kickoffMs: ne(t.kickoffAt),
103
106
  jitter: t.jitter ?? !0,
104
107
  onState: t.onState
105
108
  };
106
109
  }
107
- function te(e) {
110
+ function ne(e) {
108
111
  if (e == null) return;
109
112
  if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
110
113
  let t = Date.parse(e);
111
114
  return Number.isFinite(t) ? t : void 0;
112
115
  }
113
- function ne(e, t, n) {
116
+ function re(e, t, n) {
114
117
  return Math.min(n, Math.max(t, e));
115
118
  }
116
- function re(e) {
119
+ function ie(e) {
117
120
  return Math.round(e * (1 + .15 * Math.random()));
118
121
  }
119
- function ie(e, t, n, r) {
122
+ function ae(e, t, n, r) {
120
123
  let i = r ?? n.kickoffMs, a = i == null ? void 0 : Math.max(0, i - t), o = Math.max(n.floorMs, e ?? 0);
121
124
  if (a == null || a <= n.imminentMs) return {
122
- delay: ne(e ?? n.floorMs, o, n.ceilMs),
125
+ delay: re(e ?? n.floorMs, o, n.ceilMs),
123
126
  ttkMs: a
124
127
  };
125
128
  let s = Math.min(Math.floor(a / 10), n.sanityFloorMs, a);
@@ -128,7 +131,7 @@ function ie(e, t, n, r) {
128
131
  ttkMs: a
129
132
  };
130
133
  }
131
- function ae(e, t) {
134
+ function oe(e, t) {
132
135
  return new Promise((r, i) => {
133
136
  if (t?.aborted) {
134
137
  i(new n("ABORTED", 0, "wait-for-live aborted"));
@@ -143,7 +146,7 @@ function ae(e, t) {
143
146
  });
144
147
  }
145
148
  async function v(e, t, r) {
146
- let i = ee(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
149
+ let i = te(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
147
150
  for (;;) {
148
151
  if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
149
152
  try {
@@ -151,18 +154,18 @@ async function v(e, t, r) {
151
154
  } catch (e) {
152
155
  if (!(e instanceof n) || !o(e.code)) throw e;
153
156
  c += 1, e.liveStartsAtMs != null && Number.isFinite(e.liveStartsAtMs) && (l = e.liveStartsAtMs);
154
- let t = Date.now(), u = ie(e.retryAfterMs, t, i, l), d = u.ttkMs, f = u.delay;
155
- if (i.jitter && (f = re(f)), t + f > s) throw new n("TIMEOUT", e.httpStatus, `timed out after ${i.timeoutMs}ms waiting for the stream to go live`, {
157
+ let t = Date.now(), u = ae(e.retryAfterMs, t, i, l), d = u.ttkMs, f = u.delay;
158
+ if (i.jitter && (f = ie(f)), t + f > s) throw new n("TIMEOUT", e.httpStatus, `timed out after ${i.timeoutMs}ms waiting for the stream to go live`, {
156
159
  retryAfterMs: e.retryAfterMs,
157
160
  cause: e
158
161
  });
159
162
  i.onState?.({
160
- phase: _[e.code] ?? "unavailable",
163
+ phase: ee[e.code] ?? "unavailable",
161
164
  retryInMs: f,
162
165
  attempt: c,
163
166
  elapsedMs: t - a,
164
167
  ttkMs: d
165
- }), await ae(f, r);
168
+ }), await oe(f, r);
166
169
  }
167
170
  }
168
171
  }
@@ -170,20 +173,20 @@ async function v(e, t, r) {
170
173
  //#region src/core/resolve.ts
171
174
  async function y(e) {
172
175
  if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
173
- let t = await u(c(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
176
+ let t = await d(l(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
174
177
  credential: e.credential,
175
178
  signal: e.signal,
176
179
  apiHeaders: e.apiHeaders
177
180
  });
178
- if (!t.ok) throw await oe(t);
179
- return ce(await t.json(), e.matchUrn);
181
+ if (!t.ok) throw await se(t);
182
+ return le(await t.json(), e.matchUrn);
180
183
  }
181
184
  function b(e) {
182
185
  let t = () => y(e);
183
186
  return e.waitForLive ? v(t, e.waitForLive, e.signal) : t();
184
187
  }
185
- async function oe(e) {
186
- let t = l(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;
188
+ async function se(e) {
189
+ let t = u(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;
187
190
  try {
188
191
  let t = await e.json();
189
192
  if (t?.error?.message && (a = t.error.message), t?.error?.code && (o = t.error.code), typeof t?.liveStartsAt == "string") {
@@ -198,7 +201,7 @@ async function oe(e) {
198
201
  liveStartsAtMs: s
199
202
  });
200
203
  }
201
- var se = /* @__PURE__ */ new Set([
204
+ var ce = /* @__PURE__ */ new Set([
202
205
  "matchUrn",
203
206
  "protocol",
204
207
  "drmEnabled",
@@ -219,7 +222,7 @@ function x(e, t) {
219
222
  if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
220
223
  return t;
221
224
  }
222
- function ce(e, t) {
225
+ function le(e, t) {
223
226
  if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
224
227
  let r = e.drmEnabled ?? !!e.drm, i = {
225
228
  matchUrn: e.matchUrn ?? t,
@@ -236,7 +239,7 @@ function ce(e, t) {
236
239
  }), (t.widevine || t.fairplay) && (i.drm = t);
237
240
  }
238
241
  let a = {};
239
- for (let [t, n] of Object.entries(e)) se.has(t) || (a[t] = n);
242
+ for (let [t, n] of Object.entries(e)) ce.has(t) || (a[t] = n);
240
243
  return Object.keys(a).length > 0 && (i.extensions = a), i;
241
244
  }
242
245
  //#endregion
@@ -244,11 +247,11 @@ function ce(e, t) {
244
247
  function S(e) {
245
248
  return e.ownerDocument ?? document;
246
249
  }
247
- function le(e) {
250
+ function ue(e) {
248
251
  return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
249
252
  }
250
253
  function C(e, t) {
251
- let n = le(S(e));
254
+ let n = ue(S(e));
252
255
  return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
253
256
  }
254
257
  async function w(e, t) {
@@ -264,17 +267,17 @@ async function T(e, t) {
264
267
  n.webkitExitFullscreen?.();
265
268
  return;
266
269
  }
267
- let r = S(e), i = le(r);
270
+ let r = S(e), i = ue(r);
268
271
  i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
269
272
  }
270
273
  //#endregion
271
274
  //#region src/core/catalog.ts
272
- async function ue(e) {
275
+ async function de(e) {
273
276
  let t = new URLSearchParams();
274
277
  e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
275
- let i = t.toString(), a = c(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
278
+ let i = t.toString(), a = l(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
276
279
  e.etag && o.set("If-None-Match", e.etag);
277
- let s = await u(a, {
280
+ let s = await d(a, {
278
281
  credential: e.credential,
279
282
  signal: e.signal,
280
283
  headers: o,
@@ -287,12 +290,12 @@ async function ue(e) {
287
290
  };
288
291
  if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
289
292
  return {
290
- tournaments: de(await s.json()),
293
+ tournaments: fe(await s.json()),
291
294
  etag: s.headers.get("etag") ?? void 0,
292
295
  notModified: !1
293
296
  };
294
297
  }
295
- function de(e) {
298
+ function fe(e) {
296
299
  return (e.tournaments ?? []).map((e) => {
297
300
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
298
301
  return {
@@ -303,7 +306,8 @@ function de(e) {
303
306
  matches: (e.matches ?? []).map((e) => ({
304
307
  matchUrn: e.matchUrn ?? "",
305
308
  matchName: e.matchName ?? "",
306
- status: e.status ?? "upcoming",
309
+ status: c(e.status),
310
+ statusRaw: e.status,
307
311
  datePlannedStart: e.datePlannedStart,
308
312
  tournamentUrn: t,
309
313
  tournamentName: n,
@@ -312,10 +316,10 @@ function de(e) {
312
316
  };
313
317
  });
314
318
  }
315
- async function fe(e) {
316
- let t = c(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
319
+ async function pe(e) {
320
+ let t = l(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
317
321
  e.etag && i.set("If-None-Match", e.etag);
318
- let a = await u(t, {
322
+ let a = await d(t, {
319
323
  credential: e.credential,
320
324
  signal: e.signal,
321
325
  headers: i,
@@ -332,13 +336,13 @@ async function fe(e) {
332
336
  };
333
337
  if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
334
338
  return {
335
- tournament: pe(await a.json()),
339
+ tournament: me(await a.json()),
336
340
  etag: a.headers.get("etag") ?? void 0,
337
341
  notModified: !1,
338
342
  notFound: !1
339
343
  };
340
344
  }
341
- function pe(e) {
345
+ function me(e) {
342
346
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
343
347
  return {
344
348
  urn: t,
@@ -348,7 +352,8 @@ function pe(e) {
348
352
  matches: (e.matches ?? []).map((e) => ({
349
353
  matchUrn: e.matchUrn ?? "",
350
354
  matchName: e.matchName ?? "",
351
- status: e.status ?? "upcoming",
355
+ status: c(e.status),
356
+ statusRaw: e.status,
352
357
  datePlannedStart: e.datePlannedStart,
353
358
  tournamentUrn: t,
354
359
  tournamentName: n,
@@ -356,50 +361,51 @@ function pe(e) {
356
361
  }))
357
362
  };
358
363
  }
359
- function me(e) {
364
+ function he(e) {
360
365
  return e.tournaments.flatMap((e) => e.matches);
361
366
  }
362
367
  //#endregion
363
368
  //#region src/core/poll.ts
364
- function he(e) {
365
- let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, l = !1, d = () => {
366
- l || (a = setTimeout(f, t));
367
- }, f = async () => {
369
+ function ge(e) {
370
+ let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
371
+ u || (a = setTimeout(p, t));
372
+ }, p = async () => {
368
373
  try {
369
- let t = c(e.baseUrl, `/v1/matches/${encodeURIComponent(e.matchUrn)}`), a = new Headers();
374
+ let t = l(e.baseUrl, `/v1/matches/${encodeURIComponent(e.matchUrn)}`), a = new Headers();
370
375
  o && a.set("If-None-Match", o);
371
- let l = await u(t, {
376
+ let u = await d(t, {
372
377
  credential: e.credential,
373
378
  signal: i.signal,
374
379
  headers: a,
375
380
  apiHeaders: e.apiHeaders
376
381
  });
377
- if (l.status !== 304) {
378
- if (!l.ok) throw new n(r(l.status), l.status, `match status request failed (HTTP ${l.status})`);
379
- o = l.headers.get("etag") ?? o;
380
- let t = await l.json(), i = t.status ?? "upcoming";
381
- i !== s && (s = i, e.onChange({
382
+ if (u.status !== 304) {
383
+ if (!u.ok) throw new n(r(u.status), u.status, `match status request failed (HTTP ${u.status})`);
384
+ o = u.headers.get("etag") ?? o;
385
+ let t = await u.json(), i = c(t.status), a = typeof t.status == "string" ? t.status : i;
386
+ a !== s && (s = a, e.onChange({
382
387
  matchUrn: t.matchUrn ?? e.matchUrn,
383
388
  matchName: t.matchName,
384
389
  status: i,
390
+ statusRaw: t.status,
385
391
  datePlannedStart: t.datePlannedStart
386
392
  }));
387
393
  }
388
394
  } catch (t) {
389
395
  i.signal.aborted || e.onError?.(t instanceof n ? t : new n("NETWORK", 0, String(t)));
390
396
  } finally {
391
- d();
397
+ f();
392
398
  }
393
399
  };
394
- return f(), { stop() {
395
- l = !0, i.abort(), a && clearTimeout(a);
400
+ return p(), { stop() {
401
+ u = !0, i.abort(), a && clearTimeout(a);
396
402
  } };
397
403
  }
398
404
  //#endregion
399
405
  //#region src/core/events.ts
400
- var ge = 45e3;
406
+ var _e = 45e3;
401
407
  function E(e) {
402
- let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? ge, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, l = (e) => new Promise((t) => {
408
+ let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? _e, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
403
409
  if (a.signal.aborted) return t();
404
410
  let n = setTimeout(t, e);
405
411
  a.signal.addEventListener("abort", () => {
@@ -448,11 +454,11 @@ function E(e) {
448
454
  try {
449
455
  let n = await s(e.credential);
450
456
  if (o) return;
451
- let a = c(e.eventsBaseUrl, `/v1/events/${encodeURIComponent(e.matchUrn)}`);
457
+ let a = l(e.eventsBaseUrl, `/v1/events/${encodeURIComponent(e.matchUrn)}`);
452
458
  i && (m = setTimeout(() => {
453
459
  p = `no response headers within ${i}ms`, u.abort();
454
460
  }, i));
455
- let l = await fetch(a, {
461
+ let c = await fetch(a, {
456
462
  method: "GET",
457
463
  headers: {
458
464
  "x-api-key": n.apiKey,
@@ -464,7 +470,7 @@ function E(e) {
464
470
  mode: "cors"
465
471
  });
466
472
  if (clearTimeout(m), o) return;
467
- !l.ok || !l.body ? e.onError?.(/* @__PURE__ */ Error(`live-state subscribe failed: HTTP ${l.status}`)) : await f(l.body, () => {
473
+ !c.ok || !c.body ? e.onError?.(/* @__PURE__ */ Error(`live-state subscribe failed: HTTP ${c.status}`)) : await f(c.body, () => {
468
474
  r = t;
469
475
  }, h);
470
476
  } catch (t) {
@@ -474,7 +480,7 @@ function E(e) {
474
480
  clearTimeout(m), a.signal.removeEventListener("abort", d), u.abort();
475
481
  }
476
482
  if (o) return;
477
- p && e.onError?.(/* @__PURE__ */ Error(`live-state subscribe idle: ${p} — reconnecting`)), await l(r), r = Math.min(n, r * 2);
483
+ p && e.onError?.(/* @__PURE__ */ Error(`live-state subscribe idle: ${p} — reconnecting`)), await c(r), r = Math.min(n, r * 2);
478
484
  }
479
485
  })(), { close() {
480
486
  o || (o = !0, a.abort());
@@ -497,20 +503,20 @@ function A() {
497
503
  let e = globalThis.localStorage?.getItem(O);
498
504
  if (e) return k = e, e;
499
505
  } catch {}
500
- let e = ve();
506
+ let e = ye();
501
507
  k = e;
502
508
  try {
503
509
  globalThis.localStorage?.setItem(O, e);
504
510
  } catch {}
505
511
  return e;
506
512
  }
507
- function _e() {
513
+ function ve() {
508
514
  k = void 0;
509
515
  try {
510
516
  globalThis.localStorage?.removeItem(O);
511
517
  } catch {}
512
518
  }
513
- function ve() {
519
+ function ye() {
514
520
  let e = globalThis.crypto;
515
521
  if (e && typeof e.randomUUID == "function") return e.randomUUID();
516
522
  let t = /* @__PURE__ */ new Uint8Array(16);
@@ -522,7 +528,7 @@ function ve() {
522
528
  }
523
529
  //#endregion
524
530
  //#region src/core/drm/headers.ts
525
- function ye(e, t, n = {}) {
531
+ function be(e, t, n = {}) {
526
532
  let r = {
527
533
  "x-api-key": t.apiKey,
528
534
  "X-Match-Urn": e.matchUrn,
@@ -534,7 +540,7 @@ function ye(e, t, n = {}) {
534
540
  //#endregion
535
541
  //#region src/core/drm/cdm.ts
536
542
  var j = /* @__PURE__ */ new WeakMap();
537
- function be(e, t) {
543
+ function xe(e, t) {
538
544
  let n = j.get(e);
539
545
  n || (n = /* @__PURE__ */ new Map(), j.set(e, n));
540
546
  let r = n.get(t.keySystem);
@@ -548,11 +554,11 @@ function M() {
548
554
  return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
549
555
  }
550
556
  var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
551
- function xe(e) {
557
+ function Se(e) {
552
558
  return e.startsWith("com.widevine");
553
559
  }
554
- function P(e, t) {
555
- if (!xe(e)) return t;
560
+ function Ce(e, t) {
561
+ if (!Se(e)) return t;
556
562
  let n = (e, t) => {
557
563
  let n = e.videoCapabilities;
558
564
  return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
@@ -568,20 +574,20 @@ function P(e, t) {
568
574
  })));
569
575
  return [...t, ...r];
570
576
  }
571
- function Se(e) {
572
- return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, P(t, n)).then((t) => ({
577
+ function we(e) {
578
+ return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, Ce(t, n)).then((t) => ({
573
579
  keySystem: t.keySystem,
574
580
  getConfiguration: () => t.getConfiguration(),
575
- createMediaKeys: () => be(e, t)
581
+ createMediaKeys: () => xe(e, t)
576
582
  })) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
577
583
  }
578
584
  //#endregion
579
585
  //#region src/core/drm/support.ts
580
- var Ce = 5e3, F = "video/mp4; codecs=\"avc1.42E01E\"", I = "audio/mp4; codecs=\"mp4a.40.2\"", we = {
586
+ var Te = 5e3, Ee = "video/mp4; codecs=\"avc1.42E01E\"", De = "audio/mp4; codecs=\"mp4a.40.2\"", Oe = {
581
587
  widevine: ["com.widevine.alpha"],
582
588
  fairplay: ["com.apple.fps"]
583
589
  };
584
- function Te(e) {
590
+ function ke(e) {
585
591
  return e === "fairplay" ? [{
586
592
  initDataTypes: [
587
593
  "sinf",
@@ -589,30 +595,30 @@ function Te(e) {
589
595
  "cenc"
590
596
  ],
591
597
  videoCapabilities: [{
592
- contentType: F,
598
+ contentType: Ee,
593
599
  robustness: "",
594
600
  encryptionScheme: "cbcs"
595
601
  }],
596
602
  audioCapabilities: [{
597
- contentType: I,
603
+ contentType: De,
598
604
  robustness: "",
599
605
  encryptionScheme: "cbcs"
600
606
  }]
601
- }] : P("com.widevine.alpha", [{
607
+ }] : Ce("com.widevine.alpha", [{
602
608
  initDataTypes: ["cenc"],
603
609
  videoCapabilities: [{
604
- contentType: F,
610
+ contentType: Ee,
605
611
  robustness: "SW_SECURE_DECODE",
606
612
  encryptionScheme: "cbcs"
607
613
  }],
608
614
  audioCapabilities: [{
609
- contentType: I,
615
+ contentType: De,
610
616
  robustness: "SW_SECURE_CRYPTO",
611
617
  encryptionScheme: "cbcs"
612
618
  }]
613
619
  }]);
614
620
  }
615
- function L(e, t) {
621
+ function P(e, t) {
616
622
  return new Promise((n, r) => {
617
623
  let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
618
624
  e.then((e) => {
@@ -622,8 +628,8 @@ function L(e, t) {
622
628
  });
623
629
  });
624
630
  }
625
- async function Ee(e = {}) {
626
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ce, r = {};
631
+ async function Ae(e = {}) {
632
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Te, r = {};
627
633
  if (typeof window < "u" && window.isSecureContext === !1) return {
628
634
  verdict: "insecure-context",
629
635
  detail: r
@@ -635,7 +641,7 @@ async function Ee(e = {}) {
635
641
  };
636
642
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
637
643
  for (let e of t) {
638
- let t = we[e];
644
+ let t = Oe[e];
639
645
  if (!t) {
640
646
  r[e] = "unknown system";
641
647
  continue;
@@ -646,7 +652,7 @@ async function Ee(e = {}) {
646
652
  break;
647
653
  }
648
654
  try {
649
- return await L((await L(i(n, Te(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
655
+ return await P((await P(i(n, ke(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
650
656
  verdict: "supported",
651
657
  system: e,
652
658
  detail: r
@@ -670,49 +676,49 @@ async function Ee(e = {}) {
670
676
  }
671
677
  //#endregion
672
678
  //#region src/core/manifest.ts
673
- var De = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
674
- function Oe(e) {
675
- return De.test(e);
679
+ var je = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
680
+ function Me(e) {
681
+ return je.test(e);
676
682
  }
677
683
  //#endregion
678
684
  //#region src/core/env.ts
679
- var R = {
685
+ var F = {
680
686
  integration: "https://feed-dev.oddin-video.gg",
681
687
  production: "https://feed.oddin-video.gg"
682
688
  };
683
- function z(e) {
684
- let t = Object.prototype.hasOwnProperty.call(R, e) ? R[e] : void 0;
689
+ function I(e) {
690
+ let t = Object.prototype.hasOwnProperty.call(F, e) ? F[e] : void 0;
685
691
  if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
686
692
  return t;
687
693
  }
688
694
  //#endregion
689
695
  //#region src/core/stats.ts
690
- var B = { droppedFrames: 0 };
691
- function V(e) {
696
+ var L = { droppedFrames: 0 };
697
+ function R(e) {
692
698
  try {
693
699
  return new URL(e).host;
694
700
  } catch {
695
701
  return "";
696
702
  }
697
703
  }
698
- var ke = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
699
- function Ae(e) {
704
+ var Ne = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
705
+ function Pe(e) {
700
706
  if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
701
707
  let t = "", n = -1, r = performance.getEntriesByType("resource");
702
- for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || ke.test(i.name)) && i.startTime >= n) {
703
- let e = V(i.name);
708
+ for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Ne.test(i.name)) && i.startTime >= n) {
709
+ let e = R(i.name);
704
710
  e && (t = e, n = i.startTime);
705
711
  }
706
712
  return t;
707
713
  }
708
- function H(e) {
714
+ function z(e) {
709
715
  let t = e.getVideoPlaybackQuality?.();
710
716
  return {
711
717
  dropped: t?.droppedVideoFrames ?? 0,
712
718
  totalFrames: t?.totalVideoFrames ?? 0
713
719
  };
714
720
  }
715
- function je(e, t) {
721
+ function Fe(e, t) {
716
722
  let n = [
717
723
  ["playing", () => t("playing")],
718
724
  ["waiting", () => t("buffering")],
@@ -729,7 +735,7 @@ function je(e, t) {
729
735
  }
730
736
  //#endregion
731
737
  //#region src/core/engine/native.ts
732
- function Me(e) {
738
+ function Ie(e) {
733
739
  try {
734
740
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
735
741
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -737,15 +743,15 @@ function Me(e) {
737
743
  return;
738
744
  }
739
745
  }
740
- function U(e) {
746
+ function B(e) {
741
747
  return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
742
748
  }
743
- function W() {
749
+ function V() {
744
750
  if (typeof window > "u") return !1;
745
751
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
746
752
  return e || t;
747
753
  }
748
- var G = class {
754
+ var H = class {
749
755
  name = "native";
750
756
  deps;
751
757
  onLoaded;
@@ -781,7 +787,7 @@ var G = class {
781
787
  type: "error",
782
788
  error: new n("INTERNAL", 0, "native HLS playback error"),
783
789
  fatal: !0
784
- }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Ne(t.manifestUrl, t.analytics?.sid), e.load();
790
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Le(t.manifestUrl, t.analytics?.sid), e.load();
785
791
  }
786
792
  startLoad() {
787
793
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -803,7 +809,7 @@ var G = class {
803
809
  });
804
810
  this.onEncrypted = (n) => {
805
811
  let i = n;
806
- i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Me(i.initData), (async () => {
812
+ i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Ie(i.initData), (async () => {
807
813
  try {
808
814
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
809
815
  initDataTypes: [i.initDataType],
@@ -898,11 +904,11 @@ var G = class {
898
904
  e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
899
905
  }
900
906
  getStats() {
901
- let e = this.deps.video, t = H(e), n = {
907
+ let e = this.deps.video, t = z(e), n = {
902
908
  droppedFrames: t.dropped,
903
909
  decodedFrames: t.totalFrames
904
910
  };
905
- return this.cdnHost ||= Ae(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)), n;
911
+ return this.cdnHost ||= Pe(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)), n;
906
912
  }
907
913
  stop() {
908
914
  try {
@@ -921,29 +927,29 @@ var G = class {
921
927
  } catch {}
922
928
  }
923
929
  };
924
- function Ne(e, t) {
930
+ function Le(e, t) {
925
931
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
926
932
  }
927
933
  //#endregion
928
934
  //#region src/core/engine/hls.ts
929
- function Pe() {
935
+ function Re() {
930
936
  return e.isSupported();
931
937
  }
932
- var Fe = 3, Ie = 5, Le = 3, Re = 3e4, ze = 12e3, Be = 3e3, K = 6e3, Ve = 5e3, He = 4e3, Ue = 2, We = 5, Ge = 2, Ke = 2, qe = 2e3, Je = 3e4, Ye = 2, Xe = 9, Ze = .5, Qe = 64;
933
- function $e(e) {
938
+ var ze = 3, Be = 5, Ve = 3, He = 3e4, Ue = 12e3, We = 3e3, U = 6e3, Ge = 5e3, Ke = 4e3, qe = 2, Je = 5, Ye = 2, Xe = 2, Ze = 2e3, Qe = 3e4, $e = 2, et = 9, tt = .5, nt = 64;
939
+ function rt(e) {
934
940
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
935
941
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
936
942
  return;
937
943
  }
938
- e.liveSyncDuration ??= Ye;
939
- let t = Math.max(12, e.liveSyncDuration + Xe);
940
- (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), et(e, e.liveSyncDuration);
944
+ e.liveSyncDuration ??= $e;
945
+ let t = Math.max(12, e.liveSyncDuration + et);
946
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), it(e, e.liveSyncDuration);
941
947
  }
942
- function et(e, t) {
948
+ function it(e, t) {
943
949
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
944
950
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
945
951
  }
946
- var q = class {
952
+ var W = class {
947
953
  name = "hls";
948
954
  hls = null;
949
955
  deps;
@@ -1002,7 +1008,7 @@ var q = class {
1002
1008
  this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1003
1009
  }
1004
1010
  async load() {
1005
- let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = U(r) && W(), o = !!e.drm?.widevine?.licenseUrl && !a;
1011
+ let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = B(r) && V(), o = !!e.drm?.widevine?.licenseUrl && !a;
1006
1012
  if (e.drmEnabled && !o) {
1007
1013
  i({
1008
1014
  type: "error",
@@ -1034,7 +1040,7 @@ var q = class {
1034
1040
  }
1035
1041
  this.loadSuspended = !0;
1036
1042
  }
1037
- }, Ve));
1043
+ }, Ge));
1038
1044
  }
1039
1045
  resumeLoading() {
1040
1046
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
@@ -1066,7 +1072,7 @@ var q = class {
1066
1072
  let t = e.liveSyncPosition;
1067
1073
  if (typeof t != "number" || !Number.isFinite(t)) return;
1068
1074
  let { video: n } = this.deps;
1069
- n.currentTime <= t + Ze || (n.currentTime = t);
1075
+ n.currentTime <= t + tt || (n.currentTime = t);
1070
1076
  }
1071
1077
  startHls() {
1072
1078
  let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
@@ -1090,7 +1096,7 @@ var q = class {
1090
1096
  videoEncryptionScheme: "cbcs",
1091
1097
  audioEncryptionScheme: "cbcs"
1092
1098
  },
1093
- ...M() ? { requestMediaKeySystemAccessFunc: Se(t) } : {},
1099
+ ...M() ? { requestMediaKeySystemAccessFunc: we(t) } : {},
1094
1100
  licenseXhrSetup: (e, t) => {
1095
1101
  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;
1096
1102
  let o = performance.now();
@@ -1106,7 +1112,7 @@ var q = class {
1106
1112
  } } : {},
1107
1113
  ...c
1108
1114
  };
1109
- $e(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1115
+ rt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1110
1116
  let f = new e(d);
1111
1117
  this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
1112
1118
  this.mediaRecoveries = 0, this.networkRecoveries = 0;
@@ -1115,17 +1121,17 @@ var q = class {
1115
1121
  }), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
1116
1122
  t?.frag?.type === "main" && (this.kickPending = !1, this.kickTicks = 0, (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
1117
1123
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1118
- }, Re)));
1124
+ }, He)));
1119
1125
  }), f.on(e.Events.FRAG_LOADING, (e, t) => {
1120
1126
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1121
1127
  }), f.on(e.Events.FRAG_LOADED, (e, t) => {
1122
1128
  let n = t?.frag?.stats, r = n?.loaded;
1123
1129
  typeof r == "number" && (this.bytesLoaded += r);
1124
1130
  let i = n?.loading;
1125
- 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 > Qe && this.requestTimesMs.shift());
1131
+ 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 > nt && this.requestTimesMs.shift());
1126
1132
  let a = t?.frag?.url;
1127
1133
  if (a) {
1128
- let e = V(a);
1134
+ let e = R(a);
1129
1135
  e && (this.cdnHost = e);
1130
1136
  }
1131
1137
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => {
@@ -1138,7 +1144,7 @@ var q = class {
1138
1144
  }));
1139
1145
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1140
1146
  this.checkEndStale(), this.checkStarvation();
1141
- }, Be), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1147
+ }, We), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1142
1148
  this.renditionSwitches += 1;
1143
1149
  let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
1144
1150
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
@@ -1202,7 +1208,7 @@ var q = class {
1202
1208
  return;
1203
1209
  }
1204
1210
  this.capTimer && clearTimeout(this.capTimer);
1205
- let t = e > this.sizeCapLevel ? qe : Je;
1211
+ let t = e > this.sizeCapLevel ? Ze : Qe;
1206
1212
  this.capTimer = setTimeout(() => {
1207
1213
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1208
1214
  }, t);
@@ -1249,7 +1255,7 @@ var q = class {
1249
1255
  e.widevine && (this.licenseUrl = e.widevine);
1250
1256
  }
1251
1257
  getStats() {
1252
- let e = this.hls, t = H(this.deps.video), n = {
1258
+ let e = this.hls, t = z(this.deps.video), n = {
1253
1259
  droppedFrames: t.dropped,
1254
1260
  decodedFrames: t.totalFrames,
1255
1261
  lowLatency: this.detectedLowLatency,
@@ -1295,7 +1301,7 @@ var q = class {
1295
1301
  return;
1296
1302
  }
1297
1303
  let e = Date.now() - this.lastAdvanceMs;
1298
- !this.chaseSuspended && e > K && this.suspendChasing(), e > ze && this.emitEnded("stalled");
1304
+ !this.chaseSuspended && e > U && this.suspendChasing(), e > Ue && this.emitEnded("stalled");
1299
1305
  }
1300
1306
  checkStarvation() {
1301
1307
  let e = this.hls, { video: t } = this.deps;
@@ -1304,17 +1310,17 @@ var q = class {
1304
1310
  this.starvedTicks = 0;
1305
1311
  return;
1306
1312
  }
1307
- let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < K, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > He;
1313
+ let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < U, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > Ke;
1308
1314
  if (!(t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused && n && r)) {
1309
1315
  this.starvedTicks = 0;
1310
1316
  return;
1311
1317
  }
1312
- if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks < Ue)) {
1313
- if (this.starvedTicks = 0, this.kickPending && this.kickTicks >= Ge && (this.kickPending = !1, this.kickTicks = 0, this.starvationRebuilds < Ke)) {
1318
+ if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks < qe)) {
1319
+ if (this.starvedTicks = 0, this.kickPending && this.kickTicks >= Ye && (this.kickPending = !1, this.kickTicks = 0, this.starvationRebuilds < Xe)) {
1314
1320
  this.starvationRebuilds += 1, 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");
1315
1321
  return;
1316
1322
  }
1317
- if (!(this.starvationKicks >= We)) {
1323
+ if (!(this.starvationKicks >= Je)) {
1318
1324
  this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, console.warn("havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
1319
1325
  try {
1320
1326
  e.stopLoad(), e.startLoad(-1);
@@ -1364,7 +1370,7 @@ var q = class {
1364
1370
  scheduleLicenseRetry(t) {
1365
1371
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
1366
1372
  let n = t.response?.code ?? 0;
1367
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Le) return !1;
1373
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Ve) return !1;
1368
1374
  this.licenseRecoveries += 1;
1369
1375
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
1370
1376
  return this.licenseRetryTimer = setTimeout(() => {
@@ -1396,7 +1402,7 @@ var q = class {
1396
1402
  return;
1397
1403
  }
1398
1404
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
1399
- if (this.networkRecoveries < Ie) {
1405
+ if (this.networkRecoveries < Be) {
1400
1406
  this.networkRecoveries += 1;
1401
1407
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
1402
1408
  this.networkRetryTimer = setTimeout(() => {
@@ -1413,7 +1419,7 @@ var q = class {
1413
1419
  return;
1414
1420
  }
1415
1421
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
1416
- if (this.mediaRecoveries < Fe) {
1422
+ if (this.mediaRecoveries < ze) {
1417
1423
  this.mediaRecoveries += 1, n.recoverMediaError();
1418
1424
  return;
1419
1425
  }
@@ -1437,19 +1443,19 @@ var q = class {
1437
1443
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
1438
1444
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
1439
1445
  }
1440
- }, tt = 15e3, nt = 6e5, rt = 3e5, it = 100, J = 1, at = 1e3, ot = 3e4, st = 1e3, ct = {
1446
+ }, at = 15e3, ot = 6e5, st = 3e5, ct = 100, G = 1, lt = 1e3, K = 3e4, ut = 1e3, dt = {
1441
1447
  inline: "PRESENTATION_INLINE",
1442
1448
  fullscreen: "PRESENTATION_FULLSCREEN",
1443
1449
  pip: "PRESENTATION_PIP"
1444
- }, lt = {
1450
+ }, ft = {
1445
1451
  widevine: "KEY_SYSTEM_WIDEVINE",
1446
1452
  fairplay: "KEY_SYSTEM_FAIRPLAY",
1447
1453
  none: "KEY_SYSTEM_NONE"
1448
1454
  };
1449
- function ut(e, t) {
1455
+ function q(e, t) {
1450
1456
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
1451
1457
  }
1452
- var dt = /* @__PURE__ */ new Set([
1458
+ var pt = /* @__PURE__ */ new Set([
1453
1459
  "INVALID_URN",
1454
1460
  "NOT_FOUND",
1455
1461
  "GONE",
@@ -1459,7 +1465,7 @@ var dt = /* @__PURE__ */ new Set([
1459
1465
  "FORBIDDEN",
1460
1466
  "RATE_LIMITED",
1461
1467
  "TIMEOUT"
1462
- ]), Y = {
1468
+ ]), J = {
1463
1469
  idle: "PLAYER_STATE_IDLE",
1464
1470
  waiting: "PLAYER_STATE_WAITING",
1465
1471
  loading: "PLAYER_STATE_LOADING",
@@ -1469,7 +1475,7 @@ var dt = /* @__PURE__ */ new Set([
1469
1475
  ended: "PLAYER_STATE_ENDED",
1470
1476
  error: "PLAYER_STATE_ERROR"
1471
1477
  };
1472
- function ft(e) {
1478
+ function mt(e) {
1473
1479
  try {
1474
1480
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
1475
1481
  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);
@@ -1477,7 +1483,24 @@ function ft(e) {
1477
1483
  return;
1478
1484
  }
1479
1485
  }
1480
- var pt = class {
1486
+ var Y = /* @__PURE__ */ new Set();
1487
+ function X(e, t) {
1488
+ return Y.has(e) || (Y.add(e), console.warn(`havik-player: ${t}`)), { disabledReason: t };
1489
+ }
1490
+ function ht(e, t) {
1491
+ if (t) return { endpoint: t };
1492
+ if (t !== void 0) return X("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).");
1493
+ let n = mt(e);
1494
+ if (n) return { endpoint: n };
1495
+ let r;
1496
+ try {
1497
+ r = new URL(e).hostname || e;
1498
+ } catch {
1499
+ r = e;
1500
+ }
1501
+ return X(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).`);
1502
+ }
1503
+ var gt = class {
1481
1504
  opts;
1482
1505
  url;
1483
1506
  now;
@@ -1555,8 +1578,8 @@ var pt = class {
1555
1578
  constructor(e) {
1556
1579
  this.opts = {
1557
1580
  ...e,
1558
- heartbeatMs: e.heartbeatMs ?? tt,
1559
- idleMs: e.idleMs ?? nt
1581
+ heartbeatMs: e.heartbeatMs ?? at,
1582
+ idleMs: e.idleMs ?? ot
1560
1583
  }, 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;
1561
1584
  }
1562
1585
  start() {
@@ -1566,11 +1589,11 @@ var pt = class {
1566
1589
  sdkVersion: this.opts.sdkVersion,
1567
1590
  ...this.opts.environment
1568
1591
  };
1569
- this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), at), 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());
1592
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), lt), 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());
1570
1593
  }
1571
1594
  checkSuspension(e) {
1572
1595
  if (this.endedFlag || !this.opts.idleMs) return !1;
1573
- let t = Math.max(this.opts.idleMs, rt);
1596
+ let t = Math.max(this.opts.idleMs, st);
1574
1597
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
1575
1598
  }
1576
1599
  syncIdle(e) {
@@ -1584,21 +1607,21 @@ var pt = class {
1584
1607
  noteStateChange(e, t, n, r) {
1585
1608
  if (this.endedFlag || e === t) return;
1586
1609
  let i = this.now();
1587
- if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(J, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(J, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
1610
+ if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(G, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(G, 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") {
1588
1611
  this.stallIsSeekInduced = this.seekInduced(i);
1589
1612
  let e = !this.isHidden && !this.stallIsSeekInduced;
1590
- e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(J, Math.round(this.playingTotalMs)));
1613
+ e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(G, Math.round(this.playingTotalMs)));
1591
1614
  } else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
1592
1615
  this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
1593
1616
  let a = {
1594
- fromState: Y[e] ?? "PLAYER_STATE_UNSPECIFIED",
1595
- toState: Y[t] ?? "PLAYER_STATE_UNSPECIFIED",
1596
- presentation: ct[this.presentation]
1617
+ fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
1618
+ toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
1619
+ presentation: dt[this.presentation]
1597
1620
  }, o = this.causeOf(e, t, i);
1598
1621
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
1599
1622
  }
1600
1623
  seekInduced(e) {
1601
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < st;
1624
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < ut;
1602
1625
  }
1603
1626
  causeOf(e, t, n) {
1604
1627
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -1635,19 +1658,19 @@ var pt = class {
1635
1658
  }
1636
1659
  this.muteChanges += 1;
1637
1660
  let r = this.now();
1638
- n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(J, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
1661
+ 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(G, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
1639
1662
  }
1640
1663
  notePresentation(e) {
1641
1664
  this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
1642
1665
  }
1643
1666
  notePlayIntent() {
1644
- this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = J), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = J));
1667
+ this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = G), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = G));
1645
1668
  }
1646
1669
  noteReady() {
1647
- this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(J, this.now() - this.startupAnchorMs));
1670
+ this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(G, this.now() - this.startupAnchorMs));
1648
1671
  }
1649
1672
  noteFirstBytes() {
1650
- this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(J, this.now() - this.startupAnchorMs));
1673
+ this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(G, this.now() - this.startupAnchorMs));
1651
1674
  }
1652
1675
  noteSeek() {
1653
1676
  this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
@@ -1666,7 +1689,7 @@ var pt = class {
1666
1689
  let r = n ?? "";
1667
1690
  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";
1668
1691
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
1669
- if (dt.has(e)) return "ERROR_STAGE_RESOLVE";
1692
+ if (pt.has(e)) return "ERROR_STAGE_RESOLVE";
1670
1693
  let i = t ?? "";
1671
1694
  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";
1672
1695
  }
@@ -1698,7 +1721,7 @@ var pt = class {
1698
1721
  let l = t.droppedFrames ?? 0;
1699
1722
  l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
1700
1723
  let u = t.renditionSwitches ?? 0;
1701
- u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = Y[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
1724
+ 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";
1702
1725
  let d = this.mutedTotalMs;
1703
1726
  this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
1704
1727
  let f = t.upshifts ?? 0;
@@ -1713,14 +1736,14 @@ var pt = class {
1713
1736
  if (this.lastRequestCount = g, _ > 0) {
1714
1737
  o.requestCountDelta = _;
1715
1738
  let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
1716
- n.length > 0 && (o.requestTimeP50Ms = ut(n, 50), o.requestTimeP95Ms = ut(n, 95));
1739
+ n.length > 0 && (o.requestTimeP50Ms = q(n, 50), o.requestTimeP95Ms = q(n, 95));
1717
1740
  }
1718
1741
  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();
1719
1742
  }
1720
1743
  maybeEmitMediaInfo(e) {
1721
1744
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
1722
1745
  let t = {};
1723
- e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = lt[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);
1746
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = ft[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);
1724
1747
  let n = JSON.stringify(t);
1725
1748
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
1726
1749
  }
@@ -1740,7 +1763,7 @@ var pt = class {
1740
1763
  let c = r?.positionMs ?? 0;
1741
1764
  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));
1742
1765
  let l = e !== "END_REASON_ENDED";
1743
- l && this.lastStallMs > 0 && n - this.lastStallMs <= ot && (i.abandonAfterStallMs = Math.max(J, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= ot && (i.abandonAfterErrorMs = Math.max(J, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
1766
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= K && (i.abandonAfterStallMs = Math.max(G, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= K && (i.abandonAfterErrorMs = Math.max(G, 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);
1744
1767
  let u = r?.decodedFrames ?? this.lastDecoded;
1745
1768
  u > 0 && (i.decodedFramesTotal = u), this.startupTimeMs === 0 && (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");
1746
1769
  }
@@ -1760,7 +1783,7 @@ var pt = class {
1760
1783
  };
1761
1784
  }
1762
1785
  enqueue(e) {
1763
- for (this.pending.push(this.wrap(e)); this.pending.length > it;) {
1786
+ for (this.pending.push(this.wrap(e)); this.pending.length > ct;) {
1764
1787
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
1765
1788
  this.pending.splice(e >= 0 ? e : 0, 1);
1766
1789
  }
@@ -1783,7 +1806,7 @@ var pt = class {
1783
1806
  };
1784
1807
  //#endregion
1785
1808
  //#region src/core/environment.ts
1786
- function mt() {
1809
+ function _t() {
1787
1810
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
1788
1811
  let e;
1789
1812
  try {
@@ -1808,14 +1831,14 @@ function mt() {
1808
1831
  integration: "INTEGRATION_KIND_IFRAME"
1809
1832
  };
1810
1833
  }
1811
- function ht() {
1834
+ function vt() {
1812
1835
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
1813
1836
  let e = navigator.userAgentData, t = e?.platform ?? "";
1814
1837
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
1815
1838
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
1816
1839
  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";
1817
1840
  }
1818
- function gt() {
1841
+ function yt() {
1819
1842
  let e = typeof navigator < "u" ? navigator.connection : void 0;
1820
1843
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
1821
1844
  let t = {
@@ -1834,17 +1857,17 @@ function gt() {
1834
1857
  }
1835
1858
  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;
1836
1859
  }
1837
- function _t(e) {
1838
- let t = mt(), n = {
1839
- deviceClass: ht(),
1860
+ function bt(e) {
1861
+ let t = _t(), n = {
1862
+ deviceClass: vt(),
1840
1863
  integration: t.integration,
1841
- ...gt()
1864
+ ...yt()
1842
1865
  };
1843
1866
  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);
1844
1867
  let r = e.getBoundingClientRect?.();
1845
1868
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
1846
1869
  }
1847
- async function vt() {
1870
+ async function xt() {
1848
1871
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
1849
1872
  if (!e?.getHighEntropyValues) return {};
1850
1873
  try {
@@ -1856,7 +1879,7 @@ async function vt() {
1856
1879
  }
1857
1880
  //#endregion
1858
1881
  //#region src/core/version.ts
1859
- var yt = "2.9.0", bt = {
1882
+ var St = "2.9.2", Ct = {
1860
1883
  accent: "#E1B600",
1861
1884
  accentText: "#1B1C23",
1862
1885
  background: "#0e0f13",
@@ -1867,7 +1890,7 @@ var yt = "2.9.0", bt = {
1867
1890
  border: "rgba(255, 255, 255, 0.1)",
1868
1891
  radius: "8px",
1869
1892
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
1870
- }, xt = {
1893
+ }, wt = {
1871
1894
  accent: "--havik-accent",
1872
1895
  accentText: "--havik-accent-text",
1873
1896
  background: "--havik-bg",
@@ -1879,25 +1902,25 @@ var yt = "2.9.0", bt = {
1879
1902
  radius: "--havik-radius",
1880
1903
  fontFamily: "--havik-font"
1881
1904
  };
1882
- function St(e, t) {
1905
+ function Tt(e, t) {
1883
1906
  let n = {
1884
- ...bt,
1907
+ ...Ct,
1885
1908
  ...t
1886
1909
  };
1887
- for (let t of Object.keys(xt)) e.style.setProperty(xt[t], n[t]);
1910
+ for (let t of Object.keys(wt)) e.style.setProperty(wt[t], n[t]);
1888
1911
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
1889
1912
  }
1890
1913
  //#endregion
1891
1914
  //#region src/ui/styles.ts
1892
- var Ct = "havik-player-styles", wt = "\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.havik-spinner{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";
1893
- function Tt(e = document) {
1894
- if (e.getElementById(Ct)) return;
1915
+ var Et = "havik-player-styles", Dt = "\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.havik-spinner{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";
1916
+ function Ot(e = document) {
1917
+ if (e.getElementById(Et)) return;
1895
1918
  let t = e.createElement("style");
1896
- t.id = Ct, t.textContent = wt, e.head.appendChild(t);
1919
+ t.id = Et, t.textContent = Dt, e.head.appendChild(t);
1897
1920
  }
1898
1921
  //#endregion
1899
1922
  //#region src/ui/icons.ts
1900
- var Et = {
1923
+ var kt = {
1901
1924
  play: "<path d=\"M8 5v14l11-7z\"/>",
1902
1925
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
1903
1926
  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\"/>",
@@ -1910,21 +1933,21 @@ var Et = {
1910
1933
  liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
1911
1934
  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\"/>"
1912
1935
  };
1913
- function X(e) {
1914
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Et[e]}</svg>`;
1936
+ function Z(e) {
1937
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${kt[e]}</svg>`;
1915
1938
  }
1916
1939
  //#endregion
1917
1940
  //#region src/ui/controls.ts
1918
- var Dt = 3e3, Ot = /* @__PURE__ */ new Set([
1941
+ var At = 3e3, jt = /* @__PURE__ */ new Set([
1919
1942
  "GONE",
1920
1943
  "NOT_FOUND",
1921
1944
  "INVALID_URN",
1922
1945
  "UNAUTHORIZED"
1923
1946
  ]);
1924
- function kt(e) {
1925
- return new At(e);
1947
+ function Mt(e) {
1948
+ return new Nt(e);
1926
1949
  }
1927
- var At = class {
1950
+ var Nt = class {
1928
1951
  root;
1929
1952
  video;
1930
1953
  player;
@@ -1966,7 +1989,7 @@ var At = class {
1966
1989
  scrubbing = !1;
1967
1990
  offFns = [];
1968
1991
  constructor(e) {
1969
- this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Dt, 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, Tt(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");
1992
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? At, 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, Ot(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");
1970
1993
  let t = (e, t, n) => {
1971
1994
  let r = this.doc.createElement(e);
1972
1995
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -1977,12 +2000,12 @@ var At = class {
1977
2000
  "aria-label": r,
1978
2001
  title: r
1979
2002
  });
1980
- return i.innerHTML = X(n), i;
2003
+ return i.innerHTML = Z(n), i;
1981
2004
  };
1982
2005
  this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
1983
2006
  type: "button",
1984
2007
  "aria-label": "Play"
1985
- }), this.center.innerHTML = X("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", {
2008
+ }), 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", {
1986
2009
  role: "slider",
1987
2010
  "aria-label": "Seek",
1988
2011
  "aria-valuemin": "0",
@@ -2000,7 +2023,7 @@ var At = class {
2000
2023
  "aria-label": "Volume"
2001
2024
  });
2002
2025
  let a = t("div", "havik-vol");
2003
- a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = X("liveDot");
2026
+ a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Z("liveDot");
2004
2027
  let o = this.doc.createElement("span");
2005
2028
  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";
2006
2029
  let s = t("div", "havik-spacer");
@@ -2054,12 +2077,12 @@ var At = class {
2054
2077
  }
2055
2078
  if (e === "preplay") {
2056
2079
  let e = this.doc.createElement("button");
2057
- e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = X("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
2080
+ 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);
2058
2081
  } else {
2059
2082
  let r = this.doc.createElement("div");
2060
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Ot.has(this.lastError.code)) {
2083
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !jt.has(this.lastError.code)) {
2061
2084
  let e = this.doc.createElement("button");
2062
- e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${X("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
2085
+ 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);
2063
2086
  }
2064
2087
  }
2065
2088
  this.root.append(n), this.statusBox = n, this.show();
@@ -2098,7 +2121,7 @@ var At = class {
2098
2121
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
2099
2122
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
2100
2123
  }
2101
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${jt(this.video.currentTime)} / ${jt(this.video.duration)}`);
2124
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Pt(this.video.currentTime)} / ${Pt(this.video.duration)}`);
2102
2125
  }
2103
2126
  syncLive() {
2104
2127
  let e = this.player.getStats(), t = e.isLive !== !1;
@@ -2148,17 +2171,17 @@ var At = class {
2148
2171
  renderQualityMenu() {
2149
2172
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
2150
2173
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
2151
- for (let n of e) this.menu.append(this.menuItem(Mt(n), t === n.index, () => this.player.setQuality(n.index)));
2174
+ for (let n of e) this.menu.append(this.menuItem(Ft(n), t === n.index, () => this.player.setQuality(n.index)));
2152
2175
  }
2153
2176
  renderAudioMenu() {
2154
2177
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
2155
2178
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
2156
- for (let t of e) this.menu.append(this.menuItem(Nt(t), t.default, () => this.player.setAudioTrack(t.id)));
2179
+ for (let t of e) this.menu.append(this.menuItem(It(t), t.default, () => this.player.setAudioTrack(t.id)));
2157
2180
  }
2158
2181
  renderCcMenu() {
2159
2182
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
2160
2183
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
2161
- for (let t of e) this.menu.append(this.menuItem(Pt(t), !1, () => this.player.setTextTrack(t.id)));
2184
+ for (let t of e) this.menu.append(this.menuItem(Lt(t), !1, () => this.player.setTextTrack(t.id)));
2162
2185
  }
2163
2186
  onTracksChanged() {
2164
2187
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2241,7 +2264,7 @@ var At = class {
2241
2264
  }
2242
2265
  }
2243
2266
  setIcon(e, t) {
2244
- e.innerHTML = X(t);
2267
+ e.innerHTML = Z(t);
2245
2268
  }
2246
2269
  destroy() {
2247
2270
  this.hideTimer && clearTimeout(this.hideTimer);
@@ -2258,41 +2281,41 @@ var At = class {
2258
2281
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
2259
2282
  }
2260
2283
  };
2261
- function jt(e) {
2284
+ function Pt(e) {
2262
2285
  (!Number.isFinite(e) || e < 0) && (e = 0);
2263
2286
  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");
2264
2287
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
2265
2288
  }
2266
- function Mt(e) {
2289
+ function Ft(e) {
2267
2290
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
2268
2291
  }
2269
- function Nt(e) {
2292
+ function It(e) {
2270
2293
  return e.name || e.lang || `Track ${e.id}`;
2271
2294
  }
2272
- function Pt(e) {
2295
+ function Lt(e) {
2273
2296
  return e.name || e.lang || `Track ${e.id}`;
2274
2297
  }
2275
2298
  //#endregion
2276
2299
  //#region src/managed/index.ts
2277
- var Ft = 6e3, Z = 45e3, It = 2e3, Lt = 3, Rt = 2e3, zt = 48e4;
2278
- function Bt(e) {
2300
+ var Rt = 6e3, Q = 45e3, zt = 2e3, Bt = 3, Vt = 2e3, Ht = 48e4;
2301
+ function Ut(e) {
2279
2302
  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)})`);
2280
- if (e.env !== void 0) return z(e.env);
2303
+ if (e.env !== void 0) return I(e.env);
2281
2304
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
2282
2305
  return e.baseUrl;
2283
2306
  }
2284
- async function Q(e) {
2307
+ async function Wt(e) {
2285
2308
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
2286
- let t = Bt(e);
2309
+ let t = Ut(e);
2287
2310
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
2288
2311
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
2289
- let r = new Vt({
2312
+ let r = new Gt({
2290
2313
  ...e,
2291
2314
  baseUrl: t
2292
2315
  });
2293
2316
  return await r.start(), r;
2294
2317
  }
2295
- var Vt = class {
2318
+ var Gt = class {
2296
2319
  opts;
2297
2320
  abort = new AbortController();
2298
2321
  listeners = {};
@@ -2380,7 +2403,7 @@ var Vt = class {
2380
2403
  setTimeout(() => {
2381
2404
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
2382
2405
  phase: i ? "unavailable" : "tooEarly",
2383
- retryInMs: Z,
2406
+ retryInMs: Q,
2384
2407
  attempt: 1,
2385
2408
  elapsedMs: 0,
2386
2409
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -2419,13 +2442,13 @@ var Vt = class {
2419
2442
  !a && !p() && h();
2420
2443
  }, e);
2421
2444
  };
2422
- _(Ft), this.armingSub = E({
2445
+ _(Rt), this.armingSub = E({
2423
2446
  eventsBaseUrl: t,
2424
2447
  matchUrn: this.opts.matchUrn,
2425
2448
  credential: this.opts.credential,
2426
- onAlive: () => _(Z),
2449
+ onAlive: () => _(Q),
2427
2450
  onState: (e) => {
2428
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * It);
2451
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * zt);
2429
2452
  },
2430
2453
  onError: () => h()
2431
2454
  });
@@ -2448,7 +2471,7 @@ var Vt = class {
2448
2471
  let n = await s(this.opts.credential);
2449
2472
  if (this.destroyed || t !== this.loadGen) return;
2450
2473
  this.setState("loading");
2451
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = je(this.opts.video, (e) => {
2474
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Fe(this.opts.video, (e) => {
2452
2475
  this._state !== "ended" && this._state !== "error" && this.setState(e);
2453
2476
  });
2454
2477
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -2459,43 +2482,48 @@ var Vt = class {
2459
2482
  a(), i.destroy();
2460
2483
  return;
2461
2484
  }
2462
- this.engine = i, this.detachMedia = a, this.opts.maxBitrate != null && i.setMaxBitrate(this.opts.maxBitrate), this.startStats(), this.scheduleLicenseRefresh(), this.startLiveState(t), this.startAnalytics(e, i), r && (this.pendingStartLoad = !0, this.setState("paused"), i.name === "native" && setTimeout(() => {
2485
+ this.engine = i, this.detachMedia = a, this.opts.maxBitrate != null && i.setMaxBitrate(this.opts.maxBitrate), this.startStats(), this.scheduleLicenseRefresh(), this.startLiveState(t), this.startAnalytics(e, i, t), r && (this.pendingStartLoad = !0, this.setState("paused"), i.name === "native" && setTimeout(() => {
2463
2486
  this.destroyed || t !== this.loadGen || this.engine !== i || (this.analyticsSession?.noteReady(), this.emit("ready"));
2464
2487
  }, 0));
2465
2488
  }
2466
2489
  onAnalyticsIdle(e) {
2467
2490
  this.destroyed || this.engine !== e || (this.idleClosed = !0, this.pendingStartLoad = !1, e.stop());
2468
2491
  }
2469
- startAnalytics(e, t) {
2492
+ startAnalytics(e, t, r) {
2470
2493
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
2471
- let n = e.analytics?.sid;
2472
- if (!n) return;
2473
- let r = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ?? ft(this.opts.baseUrl);
2474
- if (!r) return;
2475
- let i = this.opts.video, a = new pt({
2476
- endpoint: r,
2477
- sid: n,
2494
+ let i = e.analytics?.sid;
2495
+ if (!i) return;
2496
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = ht(this.opts.baseUrl, a);
2497
+ if (!o) {
2498
+ s && setTimeout(() => {
2499
+ this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
2500
+ }, 0);
2501
+ return;
2502
+ }
2503
+ let c = this.opts.video, l = new gt({
2504
+ endpoint: o,
2505
+ sid: i,
2478
2506
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
2479
- sdkVersion: yt,
2480
- environment: _t(i),
2507
+ sdkVersion: St,
2508
+ environment: bt(c),
2481
2509
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
2482
2510
  onIdle: () => this.onAnalyticsIdle(t),
2483
2511
  sample: () => {
2484
- let e = this.engine?.getStats() ?? B, t = i.buffered.length ? Math.max(0, i.buffered.end(i.buffered.length - 1) - i.currentTime) : 0;
2512
+ let e = this.engine?.getStats() ?? L, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
2485
2513
  return {
2486
2514
  ...e,
2487
2515
  bufferedMs: Math.round(t * 1e3),
2488
2516
  state: this._state,
2489
- positionMs: Math.round(i.currentTime * 1e3),
2490
- playbackRate: i.playbackRate
2517
+ positionMs: Math.round(c.currentTime * 1e3),
2518
+ playbackRate: c.playbackRate
2491
2519
  };
2492
2520
  }
2493
2521
  });
2494
- this.analyticsSession = a;
2495
- let o = () => a.noteSeek(), s = () => a.noteVolume(i.muted, i.volume);
2496
- i.addEventListener("seeking", o), i.addEventListener("volumechange", s), this.detachMediaListeners = () => {
2497
- i.removeEventListener("seeking", o), i.removeEventListener("volumechange", s);
2498
- }, a.start(), a.seedVolume(i.muted, i.volume), a.notePresentation(this.currentPresentation()), vt().then((e) => a.noteEnvironment(e)), this.opts.autoplay === !1 && a.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2522
+ this.analyticsSession = l;
2523
+ let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
2524
+ c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
2525
+ c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
2526
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), xt().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2499
2527
  }
2500
2528
  currentPresentation() {
2501
2529
  let e = this.opts.video;
@@ -2519,11 +2547,11 @@ var Vt = class {
2519
2547
  hlsConfig: i,
2520
2548
  emit: (e) => this.onEngineEvent(e)
2521
2549
  }, o = this.opts.engine ?? "auto";
2522
- if (o === "native") return new G(a);
2523
- if (o === "hls") return new q(a);
2524
- if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && U(this.opts.video) && W()) return new G(a);
2525
- if (Pe()) return new q(a);
2526
- if (U(this.opts.video)) return new G(a);
2550
+ if (o === "native") return new H(a);
2551
+ if (o === "hls") return new W(a);
2552
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && B(this.opts.video) && V()) return new H(a);
2553
+ if (Re()) return new W(a);
2554
+ if (B(this.opts.video)) return new H(a);
2527
2555
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
2528
2556
  }
2529
2557
  onEngineEvent(e) {
@@ -2566,7 +2594,7 @@ var Vt = class {
2566
2594
  r = 0, i = !1;
2567
2595
  },
2568
2596
  onError: () => {
2569
- this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Lt && (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.`))));
2597
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Bt && (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.`))));
2570
2598
  }
2571
2599
  });
2572
2600
  }
@@ -2588,7 +2616,7 @@ var Vt = class {
2588
2616
  scheduleRejoin(e) {
2589
2617
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
2590
2618
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
2591
- }, Math.random() * It));
2619
+ }, Math.random() * zt));
2592
2620
  }
2593
2621
  cancelRejoin() {
2594
2622
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -2612,7 +2640,7 @@ var Vt = class {
2612
2640
  }
2613
2641
  t.controls = !1;
2614
2642
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
2615
- r && r.insertBefore(n, t), n.appendChild(t), St(n, this.opts.theme), this.container = n, this.controlBar = kt({
2643
+ r && r.insertBefore(n, t), n.appendChild(t), Tt(n, this.opts.theme), this.container = n, this.controlBar = Mt({
2616
2644
  root: n,
2617
2645
  video: t,
2618
2646
  player: this,
@@ -2642,7 +2670,7 @@ var Vt = class {
2642
2670
  }
2643
2671
  startStats() {
2644
2672
  this.stopStats();
2645
- let e = Math.max(500, this.opts.statsIntervalMs ?? Rt);
2673
+ let e = Math.max(500, this.opts.statsIntervalMs ?? Vt);
2646
2674
  this.statsTimer = setInterval(() => {
2647
2675
  if (!this.engine) return;
2648
2676
  let e = this.engine.getStats();
@@ -2654,7 +2682,7 @@ var Vt = class {
2654
2682
  }
2655
2683
  scheduleLicenseRefresh() {
2656
2684
  this.stopRefresh();
2657
- let e = this.opts.licenseRefreshMs ?? zt;
2685
+ let e = this.opts.licenseRefreshMs ?? Ht;
2658
2686
  e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
2659
2687
  }
2660
2688
  stopRefresh() {
@@ -2699,7 +2727,7 @@ var Vt = class {
2699
2727
  this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
2700
2728
  }
2701
2729
  getStats() {
2702
- return this.engine?.getStats() ?? B;
2730
+ return this.engine?.getStats() ?? L;
2703
2731
  }
2704
2732
  getQualityLevels() {
2705
2733
  return this.engine?.getQualityLevels() ?? [];
@@ -2809,7 +2837,7 @@ function $(e) {
2809
2837
  }
2810
2838
  //#endregion
2811
2839
  //#region src/embed/host.ts
2812
- function Ht(e) {
2840
+ function Kt(e) {
2813
2841
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
2814
2842
  if (!e.src) throw Error("mountEmbed: opts.src is required");
2815
2843
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -2868,15 +2896,15 @@ function Ht(e) {
2868
2896
  }
2869
2897
  //#endregion
2870
2898
  //#region src/embed/page.ts
2871
- var Ut = /^[A-Za-z0-9:_.-]{1,128}$/;
2872
- function Wt(e) {
2899
+ var qt = /^[A-Za-z0-9:_.-]{1,128}$/;
2900
+ function Jt(e) {
2873
2901
  if (typeof e == "boolean") return e;
2874
2902
  if (typeof e == "object" && e) {
2875
2903
  let t = e.endpoint;
2876
2904
  return typeof t == "string" ? { endpoint: t } : {};
2877
2905
  }
2878
2906
  }
2879
- function Gt() {
2907
+ function Yt() {
2880
2908
  let e = window.HAVIK_EMBED_CONFIG;
2881
2909
  if (e) return {
2882
2910
  baseUrl: e.baseUrl ?? "",
@@ -2886,7 +2914,7 @@ function Gt() {
2886
2914
  autoplay: e.autoplay ?? !0,
2887
2915
  muted: e.muted ?? !0,
2888
2916
  waitForLive: e.waitForLive ?? !0,
2889
- analytics: Wt(e.analytics)
2917
+ analytics: Jt(e.analytics)
2890
2918
  };
2891
2919
  let t = new URLSearchParams(location.search);
2892
2920
  return {
@@ -2899,9 +2927,9 @@ function Gt() {
2899
2927
  waitForLive: !0
2900
2928
  };
2901
2929
  }
2902
- async function Kt() {
2903
- let e = Gt();
2904
- Jt();
2930
+ async function Xt() {
2931
+ let e = Yt();
2932
+ Qt();
2905
2933
  let t = document.createElement("video");
2906
2934
  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);
2907
2935
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -2956,12 +2984,12 @@ async function Kt() {
2956
2984
  code: e.code,
2957
2985
  message: e.message
2958
2986
  })), e.on("autoplayblocked", () => {
2959
- i({ type: "oddin:autoplayblocked" }), qt(t, e);
2987
+ i({ type: "oddin:autoplayblocked" }), Zt(t, e);
2960
2988
  });
2961
2989
  }, s = async (r) => {
2962
2990
  a?.destroy(), a = null;
2963
2991
  try {
2964
- let n = await Q({
2992
+ let n = await Wt({
2965
2993
  video: t,
2966
2994
  baseUrl: e.baseUrl,
2967
2995
  matchUrn: r,
@@ -3023,7 +3051,7 @@ async function Kt() {
3023
3051
  a?.retry();
3024
3052
  break;
3025
3053
  case "oddin:load":
3026
- typeof e.matchUrn == "string" && Ut.test(e.matchUrn) && s(e.matchUrn);
3054
+ typeof e.matchUrn == "string" && qt.test(e.matchUrn) && s(e.matchUrn);
3027
3055
  break;
3028
3056
  case "oddin:destroy": c();
3029
3057
  }
@@ -3035,18 +3063,18 @@ async function Kt() {
3035
3063
  protocol: 1
3036
3064
  });
3037
3065
  }
3038
- function qt(e, t) {
3066
+ function Zt(e, t) {
3039
3067
  if (document.getElementById("havik-tap")) return;
3040
3068
  let n = document.createElement("button");
3041
3069
  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", () => {
3042
3070
  n.remove(), t.play();
3043
3071
  }), document.body.appendChild(n);
3044
3072
  }
3045
- function Jt() {
3073
+ function Qt() {
3046
3074
  let e = document.createElement("style");
3047
3075
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
3048
3076
  }
3049
3077
  //#endregion
3050
- export { bt as ODDIN_THEME, n as PlaybackError, St as applyTheme, z as baseUrlForEnv, Kt as bootEmbed, _e as clearDeviceId, Q as createPlayer, D as deriveEventsBaseUrl, Ee as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ue as fetchCatalog, fe as fetchTournament, me as flattenMatches, A as getDeviceId, Oe as isLowLatencyManifest, $ as isOddinMessage, ye as licenseRequestHeaders, Ht as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, he as watchStatus };
3078
+ export { Ct as ODDIN_THEME, n as PlaybackError, Tt as applyTheme, I as baseUrlForEnv, Xt as bootEmbed, ve as clearDeviceId, Wt as createPlayer, D as deriveEventsBaseUrl, Ae as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, de as fetchCatalog, pe as fetchTournament, he as flattenMatches, A as getDeviceId, Me as isLowLatencyManifest, $ as isOddinMessage, be as licenseRequestHeaders, Kt as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, ge as watchStatus };
3051
3079
 
3052
3080
  //# sourceMappingURL=index.js.map