@oddin-gg/havik-player 2.10.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -46,9 +46,32 @@ async function s(e) {
46
46
  function c(e) {
47
47
  return e === "live" || e === "ended" || e === "upcoming" || e === "pending" ? e : "upcoming";
48
48
  }
49
+ function l(e) {
50
+ if (!Array.isArray(e)) return;
51
+ let t = [];
52
+ for (let n of e) {
53
+ if (!n || typeof n != "object") continue;
54
+ let e = typeof n.urn == "string" ? n.urn : "", r = typeof n.name == "string" ? n.name : "";
55
+ if (!e && !r) continue;
56
+ let i = {
57
+ urn: e,
58
+ name: r,
59
+ isHome: n.isHome === !0
60
+ };
61
+ typeof n.logoUrl == "string" && u(n.logoUrl) && (i.logoUrl = n.logoUrl), t.push(i);
62
+ }
63
+ return t.length > 0 ? t : void 0;
64
+ }
65
+ function u(e) {
66
+ try {
67
+ return new URL(e).protocol === "https:";
68
+ } catch {
69
+ return !1;
70
+ }
71
+ }
49
72
  //#endregion
50
73
  //#region src/core/http.ts
51
- function l(e, t) {
74
+ function d(e, t) {
52
75
  let r = e.replace(/\/+$/, ""), i;
53
76
  try {
54
77
  i = new URL(r + t);
@@ -58,14 +81,14 @@ function l(e, t) {
58
81
  if (i.protocol !== "https:" && i.protocol !== "http:") throw new n("INTERNAL", 0, `baseUrl must be http(s), got: ${JSON.stringify(e)}`);
59
82
  return i.toString();
60
83
  }
61
- function u(e) {
84
+ function f(e) {
62
85
  if (!e) return;
63
86
  let t = Number(e);
64
87
  if (Number.isFinite(t)) return Math.max(0, Math.round(t * 1e3));
65
88
  let n = Date.parse(e);
66
89
  if (!Number.isNaN(n)) return Math.max(0, n - Date.now());
67
90
  }
68
- async function d(e, t) {
91
+ async function p(e, t) {
69
92
  let r = await s(t.credential), i = t.headers ?? new Headers();
70
93
  if (t.apiHeaders) for (let [e, n] of Object.entries(t.apiHeaders)) i.has(e) || i.set(e, n);
71
94
  i.set("x-api-key", r.apiKey);
@@ -80,49 +103,49 @@ async function d(e, t) {
80
103
  mode: "cors"
81
104
  });
82
105
  } catch (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 });
106
+ throw t.signal?.aborted ? new n("ABORTED", 0, "request aborted", { cause: e }) : new n("NETWORK", 0, `network request failed: ${m(e)}`, { cause: e });
84
107
  }
85
108
  }
86
- function f(e) {
109
+ function m(e) {
87
110
  return e instanceof Error ? e.message : String(e);
88
111
  }
89
112
  //#endregion
90
113
  //#region src/core/waitForLive.ts
91
- var p = 1e3, m = 3e4, h = 6e5, g = 3e5, _ = 1e3, ee = {
114
+ var h = 1e3, g = 3e4, _ = 6e5, ee = 3e5, te = 1e3, ne = {
92
115
  TOO_EARLY: "tooEarly",
93
116
  UNAVAILABLE: "unavailable",
94
117
  RATE_LIMITED: "rateLimited",
95
118
  NETWORK: "network"
96
119
  };
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);
120
+ function re(e) {
121
+ let t = e === !0 || e === !1 ? {} : e, n = Math.max(te, t.floorMs ?? h), r = Math.max(n, t.ceilMs ?? g), i = Math.max(0, t.imminentMs ?? _), a = Math.max(r, t.sanityFloorMs ?? ee);
99
122
  return {
100
123
  timeoutMs: t.timeoutMs,
101
124
  floorMs: n,
102
125
  ceilMs: r,
103
126
  imminentMs: i,
104
127
  sanityFloorMs: a,
105
- kickoffMs: ne(t.kickoffAt),
128
+ kickoffMs: ie(t.kickoffAt),
106
129
  jitter: t.jitter ?? !0,
107
130
  onState: t.onState
108
131
  };
109
132
  }
110
- function ne(e) {
133
+ function ie(e) {
111
134
  if (e == null) return;
112
135
  if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
113
136
  let t = Date.parse(e);
114
137
  return Number.isFinite(t) ? t : void 0;
115
138
  }
116
- function re(e, t, n) {
139
+ function ae(e, t, n) {
117
140
  return Math.min(n, Math.max(t, e));
118
141
  }
119
- function ie(e) {
142
+ function oe(e) {
120
143
  return Math.round(e * (1 + .15 * Math.random()));
121
144
  }
122
- function ae(e, t, n, r) {
145
+ function se(e, t, n, r) {
123
146
  let i = r ?? n.kickoffMs, a = i == null ? void 0 : Math.max(0, i - t), o = Math.max(n.floorMs, e ?? 0);
124
147
  if (a == null || a <= n.imminentMs) return {
125
- delay: re(e ?? n.floorMs, o, n.ceilMs),
148
+ delay: ae(e ?? n.floorMs, o, n.ceilMs),
126
149
  ttkMs: a
127
150
  };
128
151
  let s = Math.min(Math.floor(a / 10), n.sanityFloorMs, a);
@@ -131,7 +154,7 @@ function ae(e, t, n, r) {
131
154
  ttkMs: a
132
155
  };
133
156
  }
134
- function oe(e, t) {
157
+ function ce(e, t) {
135
158
  return new Promise((r, i) => {
136
159
  if (t?.aborted) {
137
160
  i(new n("ABORTED", 0, "wait-for-live aborted"));
@@ -146,7 +169,7 @@ function oe(e, t) {
146
169
  });
147
170
  }
148
171
  async function v(e, t, r) {
149
- let i = te(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
172
+ let i = re(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
150
173
  for (;;) {
151
174
  if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
152
175
  try {
@@ -154,18 +177,18 @@ async function v(e, t, r) {
154
177
  } catch (e) {
155
178
  if (!(e instanceof n) || !o(e.code)) throw e;
156
179
  c += 1, e.liveStartsAtMs != null && Number.isFinite(e.liveStartsAtMs) && (l = e.liveStartsAtMs);
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`, {
180
+ let t = Date.now(), u = se(e.retryAfterMs, t, i, l), d = u.ttkMs, f = u.delay;
181
+ if (i.jitter && (f = oe(f)), t + f > s) throw new n("TIMEOUT", e.httpStatus, `timed out after ${i.timeoutMs}ms waiting for the stream to go live`, {
159
182
  retryAfterMs: e.retryAfterMs,
160
183
  cause: e
161
184
  });
162
185
  i.onState?.({
163
- phase: ee[e.code] ?? "unavailable",
186
+ phase: ne[e.code] ?? "unavailable",
164
187
  retryInMs: f,
165
188
  attempt: c,
166
189
  elapsedMs: t - a,
167
190
  ttkMs: d
168
- }), await oe(f, r);
191
+ }), await ce(f, r);
169
192
  }
170
193
  }
171
194
  }
@@ -173,20 +196,20 @@ async function v(e, t, r) {
173
196
  //#region src/core/resolve.ts
174
197
  async function y(e) {
175
198
  if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
176
- let t = await d(l(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
199
+ let t = await p(d(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
177
200
  credential: e.credential,
178
201
  signal: e.signal,
179
202
  apiHeaders: e.apiHeaders
180
203
  });
181
- if (!t.ok) throw await se(t);
182
- return le(await t.json(), e.matchUrn);
204
+ if (!t.ok) throw await le(t);
205
+ return de(await t.json(), e.matchUrn);
183
206
  }
184
207
  function b(e) {
185
208
  let t = () => y(e);
186
209
  return e.waitForLive ? v(t, e.waitForLive, e.signal) : t();
187
210
  }
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;
211
+ async function le(e) {
212
+ let t = f(e.headers.get("retry-after")), i = e.headers.get("x-request-id") ?? e.headers.get("x-amzn-requestid") ?? void 0, a = e.statusText || `HTTP ${e.status}`, o, s;
190
213
  try {
191
214
  let t = await e.json();
192
215
  if (t?.error?.message && (a = t.error.message), t?.error?.code && (o = t.error.code), typeof t?.liveStartsAt == "string") {
@@ -201,7 +224,7 @@ async function se(e) {
201
224
  liveStartsAtMs: s
202
225
  });
203
226
  }
204
- var ce = /* @__PURE__ */ new Set([
227
+ var ue = /* @__PURE__ */ new Set([
205
228
  "matchUrn",
206
229
  "protocol",
207
230
  "drmEnabled",
@@ -222,7 +245,7 @@ function x(e, t) {
222
245
  if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
223
246
  return t;
224
247
  }
225
- function le(e, t) {
248
+ function de(e, t) {
226
249
  if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
227
250
  let r = e.drmEnabled ?? !!e.drm, i = {
228
251
  matchUrn: e.matchUrn ?? t,
@@ -239,19 +262,19 @@ function le(e, t) {
239
262
  }), (t.widevine || t.fairplay) && (i.drm = t);
240
263
  }
241
264
  let a = {};
242
- for (let [t, n] of Object.entries(e)) ce.has(t) || (a[t] = n);
265
+ for (let [t, n] of Object.entries(e)) ue.has(t) || (a[t] = n);
243
266
  return Object.keys(a).length > 0 && (i.extensions = a), i;
244
267
  }
245
268
  //#endregion
246
269
  //#region src/core/fullscreen.ts
247
- function S(e) {
270
+ function fe(e) {
248
271
  return e.ownerDocument ?? document;
249
272
  }
250
- function ue(e) {
273
+ function S(e) {
251
274
  return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
252
275
  }
253
276
  function C(e, t) {
254
- let n = ue(S(e));
277
+ let n = S(fe(e));
255
278
  return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
256
279
  }
257
280
  async function w(e, t) {
@@ -267,17 +290,17 @@ async function T(e, t) {
267
290
  n.webkitExitFullscreen?.();
268
291
  return;
269
292
  }
270
- let r = S(e), i = ue(r);
293
+ let r = fe(e), i = S(r);
271
294
  i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
272
295
  }
273
296
  //#endregion
274
297
  //#region src/core/catalog.ts
275
- async function de(e) {
298
+ async function pe(e) {
276
299
  let t = new URLSearchParams();
277
300
  e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
278
- let i = t.toString(), a = l(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
301
+ let i = t.toString(), a = d(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
279
302
  e.etag && o.set("If-None-Match", e.etag);
280
- let s = await d(a, {
303
+ let s = await p(a, {
281
304
  credential: e.credential,
282
305
  signal: e.signal,
283
306
  headers: o,
@@ -290,12 +313,12 @@ async function de(e) {
290
313
  };
291
314
  if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
292
315
  return {
293
- tournaments: fe(await s.json()),
316
+ tournaments: me(await s.json()),
294
317
  etag: s.headers.get("etag") ?? void 0,
295
318
  notModified: !1
296
319
  };
297
320
  }
298
- function fe(e) {
321
+ function me(e) {
299
322
  return (e.tournaments ?? []).map((e) => {
300
323
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
301
324
  return {
@@ -311,15 +334,16 @@ function fe(e) {
311
334
  datePlannedStart: e.datePlannedStart,
312
335
  tournamentUrn: t,
313
336
  tournamentName: n,
314
- sport: r
337
+ sport: r,
338
+ teams: l(e.teams)
315
339
  }))
316
340
  };
317
341
  });
318
342
  }
319
- async function pe(e) {
320
- let t = l(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
343
+ async function he(e) {
344
+ let t = d(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
321
345
  e.etag && i.set("If-None-Match", e.etag);
322
- let a = await d(t, {
346
+ let a = await p(t, {
323
347
  credential: e.credential,
324
348
  signal: e.signal,
325
349
  headers: i,
@@ -336,13 +360,13 @@ async function pe(e) {
336
360
  };
337
361
  if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
338
362
  return {
339
- tournament: me(await a.json()),
363
+ tournament: ge(await a.json()),
340
364
  etag: a.headers.get("etag") ?? void 0,
341
365
  notModified: !1,
342
366
  notFound: !1
343
367
  };
344
368
  }
345
- function me(e) {
369
+ function ge(e) {
346
370
  let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
347
371
  return {
348
372
  urn: t,
@@ -357,23 +381,24 @@ function me(e) {
357
381
  datePlannedStart: e.datePlannedStart,
358
382
  tournamentUrn: t,
359
383
  tournamentName: n,
360
- sport: r
384
+ sport: r,
385
+ teams: l(e.teams)
361
386
  }))
362
387
  };
363
388
  }
364
- function he(e) {
389
+ function _e(e) {
365
390
  return e.tournaments.flatMap((e) => e.matches);
366
391
  }
367
392
  //#endregion
368
393
  //#region src/core/poll.ts
369
- function ge(e) {
394
+ function ve(e) {
370
395
  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 () => {
396
+ u || (a = setTimeout(m, t));
397
+ }, m = async () => {
373
398
  try {
374
- let t = l(e.baseUrl, `/v1/matches/${encodeURIComponent(e.matchUrn)}`), a = new Headers();
399
+ let t = d(e.baseUrl, `/v1/matches/${encodeURIComponent(e.matchUrn)}`), a = new Headers();
375
400
  o && a.set("If-None-Match", o);
376
- let u = await d(t, {
401
+ let u = await p(t, {
377
402
  credential: e.credential,
378
403
  signal: i.signal,
379
404
  headers: a,
@@ -382,13 +407,18 @@ function ge(e) {
382
407
  if (u.status !== 304) {
383
408
  if (!u.ok) throw new n(r(u.status), u.status, `match status request failed (HTTP ${u.status})`);
384
409
  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({
410
+ let t = await u.json(), i = c(t.status), a = typeof t.status == "string" ? t.status : i, d = l(t.teams), f = JSON.stringify([
411
+ a,
412
+ t.datePlannedStart ?? null,
413
+ d ?? null
414
+ ]);
415
+ f !== s && (s = f, e.onChange({
387
416
  matchUrn: t.matchUrn ?? e.matchUrn,
388
417
  matchName: t.matchName,
389
418
  status: i,
390
419
  statusRaw: t.status,
391
- datePlannedStart: t.datePlannedStart
420
+ datePlannedStart: t.datePlannedStart,
421
+ teams: d
392
422
  }));
393
423
  }
394
424
  } catch (t) {
@@ -397,21 +427,21 @@ function ge(e) {
397
427
  f();
398
428
  }
399
429
  };
400
- return p(), { stop() {
430
+ return m(), { stop() {
401
431
  u = !0, i.abort(), a && clearTimeout(a);
402
432
  } };
403
433
  }
404
434
  //#endregion
405
435
  //#region src/core/events.ts
406
- var _e = 45e3;
436
+ var ye = 45e3;
407
437
  function E(e) {
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) => {
438
+ let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? ye, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
409
439
  if (a.signal.aborted) return t();
410
440
  let n = setTimeout(t, e);
411
441
  a.signal.addEventListener("abort", () => {
412
442
  clearTimeout(n), t();
413
443
  }, { once: !0 });
414
- }), u = (t) => {
444
+ }), l = (t) => {
415
445
  e.onAlive?.();
416
446
  let n = "message", r = [];
417
447
  for (let e of t.split("\n")) {
@@ -424,9 +454,9 @@ function E(e) {
424
454
  let t = JSON.parse(r.join("\n"));
425
455
  t && typeof t.state == "string" && e.onState(t);
426
456
  } catch {}
427
- }, d = /\r\n\r\n|\n\n|\r\r/, f = async (e, t, n) => {
428
- let r = e.getReader(), a = new TextDecoder(), s = "", c = !1, l, f = () => {
429
- i && (clearTimeout(l), l = setTimeout(() => {
457
+ }, u = /\r\n\r\n|\n\n|\r\r/, f = async (e, t, n) => {
458
+ let r = e.getReader(), a = new TextDecoder(), s = "", c = !1, d, f = () => {
459
+ i && (clearTimeout(d), d = setTimeout(() => {
430
460
  n(), r.cancel().catch(() => {});
431
461
  }, i));
432
462
  };
@@ -436,27 +466,27 @@ function E(e) {
436
466
  if (n) return;
437
467
  e && e.length > 0 && (f(), c || (c = !0, t())), s += a.decode(e, { stream: !0 });
438
468
  let i;
439
- for (; (i = d.exec(s)) !== null;) u(s.slice(0, i.index)), s = s.slice(i.index + i[0].length);
469
+ for (; (i = u.exec(s)) !== null;) l(s.slice(0, i.index)), s = s.slice(i.index + i[0].length);
440
470
  if (o) return;
441
471
  }
442
472
  } finally {
443
- clearTimeout(l), await r.cancel().catch(() => {});
473
+ clearTimeout(d), await r.cancel().catch(() => {});
444
474
  }
445
475
  };
446
476
  return (async () => {
447
477
  let r = t;
448
478
  for (; !o;) {
449
- let u = new AbortController(), d = () => u.abort();
450
- a.signal.addEventListener("abort", d, { once: !0 });
479
+ let l = new AbortController(), u = () => l.abort();
480
+ a.signal.addEventListener("abort", u, { once: !0 });
451
481
  let p = null, m, h = () => {
452
- p = `no data for ${i}ms`, u.abort();
482
+ p = `no data for ${i}ms`, l.abort();
453
483
  };
454
484
  try {
455
485
  let n = await s(e.credential);
456
486
  if (o) return;
457
- let a = l(e.eventsBaseUrl, `/v1/events/${encodeURIComponent(e.matchUrn)}`);
487
+ let a = d(e.eventsBaseUrl, `/v1/events/${encodeURIComponent(e.matchUrn)}`);
458
488
  i && (m = setTimeout(() => {
459
- p = `no response headers within ${i}ms`, u.abort();
489
+ p = `no response headers within ${i}ms`, l.abort();
460
490
  }, i));
461
491
  let c = await fetch(a, {
462
492
  method: "GET",
@@ -464,7 +494,7 @@ function E(e) {
464
494
  "x-api-key": n.apiKey,
465
495
  accept: "text/event-stream"
466
496
  },
467
- signal: u.signal,
497
+ signal: l.signal,
468
498
  cache: "no-store",
469
499
  credentials: "omit",
470
500
  mode: "cors"
@@ -477,7 +507,7 @@ function E(e) {
477
507
  if (o || a.signal.aborted) return;
478
508
  p || e.onError?.(t);
479
509
  } finally {
480
- clearTimeout(m), a.signal.removeEventListener("abort", d), u.abort();
510
+ clearTimeout(m), a.signal.removeEventListener("abort", u), l.abort();
481
511
  }
482
512
  if (o) return;
483
513
  p && e.onError?.(/* @__PURE__ */ Error(`live-state subscribe idle: ${p} — reconnecting`)), await c(r), r = Math.min(n, r * 2);
@@ -503,20 +533,20 @@ function A() {
503
533
  let e = globalThis.localStorage?.getItem(O);
504
534
  if (e) return k = e, e;
505
535
  } catch {}
506
- let e = ye();
536
+ let e = xe();
507
537
  k = e;
508
538
  try {
509
539
  globalThis.localStorage?.setItem(O, e);
510
540
  } catch {}
511
541
  return e;
512
542
  }
513
- function ve() {
543
+ function be() {
514
544
  k = void 0;
515
545
  try {
516
546
  globalThis.localStorage?.removeItem(O);
517
547
  } catch {}
518
548
  }
519
- function ye() {
549
+ function xe() {
520
550
  let e = globalThis.crypto;
521
551
  if (e && typeof e.randomUUID == "function") return e.randomUUID();
522
552
  let t = /* @__PURE__ */ new Uint8Array(16);
@@ -528,7 +558,7 @@ function ye() {
528
558
  }
529
559
  //#endregion
530
560
  //#region src/core/drm/headers.ts
531
- function be(e, t, n = {}) {
561
+ function Se(e, t, n = {}) {
532
562
  let r = {
533
563
  "x-api-key": t.apiKey,
534
564
  "X-Match-Urn": e.matchUrn,
@@ -540,7 +570,7 @@ function be(e, t, n = {}) {
540
570
  //#endregion
541
571
  //#region src/core/drm/cdm.ts
542
572
  var j = /* @__PURE__ */ new WeakMap();
543
- function xe(e, t) {
573
+ function Ce(e, t) {
544
574
  let n = j.get(e);
545
575
  n || (n = /* @__PURE__ */ new Map(), j.set(e, n));
546
576
  let r = n.get(t.keySystem);
@@ -554,11 +584,11 @@ function M() {
554
584
  return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
555
585
  }
556
586
  var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
557
- function Se(e) {
587
+ function we(e) {
558
588
  return e.startsWith("com.widevine");
559
589
  }
560
- function Ce(e, t) {
561
- if (!Se(e)) return t;
590
+ function P(e, t) {
591
+ if (!we(e)) return t;
562
592
  let n = (e, t) => {
563
593
  let n = e.videoCapabilities;
564
594
  return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
@@ -574,20 +604,41 @@ function Ce(e, t) {
574
604
  })));
575
605
  return [...t, ...r];
576
606
  }
577
- function we(e) {
578
- return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, Ce(t, n)).then((t) => ({
607
+ function Te(e) {
608
+ return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, P(t, n)).then((t) => ({
579
609
  keySystem: t.keySystem,
580
610
  getConfiguration: () => t.getConfiguration(),
581
- createMediaKeys: () => xe(e, t)
611
+ createMediaKeys: () => Ce(e, t)
582
612
  })) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
583
613
  }
614
+ var F = {
615
+ video: "SW_SECURE_DECODE",
616
+ audio: "SW_SECURE_CRYPTO",
617
+ scheme: "cbcs"
618
+ };
619
+ function Ee(e) {
620
+ if (!M()) return;
621
+ let t = (e, t) => ({
622
+ contentType: e,
623
+ robustness: t,
624
+ encryptionScheme: F.scheme
625
+ });
626
+ Te(e)("com.widevine.alpha", [{
627
+ initDataTypes: ["cenc"],
628
+ distinctiveIdentifier: "optional",
629
+ persistentState: "optional",
630
+ sessionTypes: ["temporary"],
631
+ audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", F.audio)],
632
+ videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", F.video)]
633
+ }]).then((e) => e.createMediaKeys()).catch(() => {});
634
+ }
584
635
  //#endregion
585
636
  //#region src/core/drm/support.ts
586
- var Te = 5e3, Ee = "video/mp4; codecs=\"avc1.42E01E\"", De = "audio/mp4; codecs=\"mp4a.40.2\"", Oe = {
637
+ var De = 5e3, Oe = "video/mp4; codecs=\"avc1.42E01E\"", ke = "audio/mp4; codecs=\"mp4a.40.2\"", Ae = {
587
638
  widevine: ["com.widevine.alpha"],
588
639
  fairplay: ["com.apple.fps"]
589
640
  };
590
- function ke(e) {
641
+ function je(e) {
591
642
  return e === "fairplay" ? [{
592
643
  initDataTypes: [
593
644
  "sinf",
@@ -595,30 +646,30 @@ function ke(e) {
595
646
  "cenc"
596
647
  ],
597
648
  videoCapabilities: [{
598
- contentType: Ee,
649
+ contentType: Oe,
599
650
  robustness: "",
600
651
  encryptionScheme: "cbcs"
601
652
  }],
602
653
  audioCapabilities: [{
603
- contentType: De,
654
+ contentType: ke,
604
655
  robustness: "",
605
656
  encryptionScheme: "cbcs"
606
657
  }]
607
- }] : Ce("com.widevine.alpha", [{
658
+ }] : P("com.widevine.alpha", [{
608
659
  initDataTypes: ["cenc"],
609
660
  videoCapabilities: [{
610
- contentType: Ee,
611
- robustness: "SW_SECURE_DECODE",
612
- encryptionScheme: "cbcs"
661
+ contentType: Oe,
662
+ robustness: F.video,
663
+ encryptionScheme: F.scheme
613
664
  }],
614
665
  audioCapabilities: [{
615
- contentType: De,
616
- robustness: "SW_SECURE_CRYPTO",
617
- encryptionScheme: "cbcs"
666
+ contentType: ke,
667
+ robustness: F.audio,
668
+ encryptionScheme: F.scheme
618
669
  }]
619
670
  }]);
620
671
  }
621
- function P(e, t) {
672
+ function Me(e, t) {
622
673
  return new Promise((n, r) => {
623
674
  let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
624
675
  e.then((e) => {
@@ -628,8 +679,8 @@ function P(e, t) {
628
679
  });
629
680
  });
630
681
  }
631
- async function Ae(e = {}) {
632
- let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Te, r = {};
682
+ async function Ne(e = {}) {
683
+ let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? De, r = {};
633
684
  if (typeof window < "u" && window.isSecureContext === !1) return {
634
685
  verdict: "insecure-context",
635
686
  detail: r
@@ -641,7 +692,7 @@ async function Ae(e = {}) {
641
692
  };
642
693
  let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
643
694
  for (let e of t) {
644
- let t = Oe[e];
695
+ let t = Ae[e];
645
696
  if (!t) {
646
697
  r[e] = "unknown system";
647
698
  continue;
@@ -652,7 +703,7 @@ async function Ae(e = {}) {
652
703
  break;
653
704
  }
654
705
  try {
655
- return await P((await P(i(n, ke(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
706
+ return await Me((await Me(i(n, je(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
656
707
  verdict: "supported",
657
708
  system: e,
658
709
  detail: r
@@ -676,49 +727,49 @@ async function Ae(e = {}) {
676
727
  }
677
728
  //#endregion
678
729
  //#region src/core/manifest.ts
679
- var je = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
680
- function Me(e) {
681
- return je.test(e);
730
+ var Pe = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
731
+ function Fe(e) {
732
+ return Pe.test(e);
682
733
  }
683
734
  //#endregion
684
735
  //#region src/core/env.ts
685
- var F = {
736
+ var I = {
686
737
  integration: "https://feed-dev.oddin-video.gg",
687
738
  production: "https://feed.oddin-video.gg"
688
739
  };
689
- function I(e) {
690
- let t = Object.prototype.hasOwnProperty.call(F, e) ? F[e] : void 0;
740
+ function L(e) {
741
+ let t = Object.prototype.hasOwnProperty.call(I, e) ? I[e] : void 0;
691
742
  if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
692
743
  return t;
693
744
  }
694
745
  //#endregion
695
746
  //#region src/core/stats.ts
696
- var L = { droppedFrames: 0 };
697
- function R(e) {
747
+ var R = { droppedFrames: 0 };
748
+ function z(e) {
698
749
  try {
699
750
  return new URL(e).host;
700
751
  } catch {
701
752
  return "";
702
753
  }
703
754
  }
704
- var Ne = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
705
- function Pe(e) {
755
+ var Ie = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
756
+ function Le(e) {
706
757
  if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
707
758
  let t = "", n = -1, r = performance.getEntriesByType("resource");
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);
759
+ for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Ie.test(i.name)) && i.startTime >= n) {
760
+ let e = z(i.name);
710
761
  e && (t = e, n = i.startTime);
711
762
  }
712
763
  return t;
713
764
  }
714
- function z(e) {
765
+ function B(e) {
715
766
  let t = e.getVideoPlaybackQuality?.();
716
767
  return {
717
768
  dropped: t?.droppedVideoFrames ?? 0,
718
769
  totalFrames: t?.totalVideoFrames ?? 0
719
770
  };
720
771
  }
721
- function Fe(e, t) {
772
+ function Re(e, t) {
722
773
  let n = [
723
774
  ["playing", () => t("playing")],
724
775
  ["waiting", () => t("buffering")],
@@ -735,7 +786,7 @@ function Fe(e, t) {
735
786
  }
736
787
  //#endregion
737
788
  //#region src/core/engine/native.ts
738
- function Ie(e) {
789
+ function ze(e) {
739
790
  try {
740
791
  let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
741
792
  return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
@@ -743,15 +794,15 @@ function Ie(e) {
743
794
  return;
744
795
  }
745
796
  }
746
- function B(e) {
797
+ function V(e) {
747
798
  return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
748
799
  }
749
- function V() {
800
+ function H() {
750
801
  if (typeof window > "u") return !1;
751
802
  let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
752
803
  return e || t;
753
804
  }
754
- var H = class {
805
+ var U = class {
755
806
  name = "native";
756
807
  deps;
757
808
  onLoaded;
@@ -787,7 +838,7 @@ var H = class {
787
838
  type: "error",
788
839
  error: new n("INTERNAL", 0, "native HLS playback error"),
789
840
  fatal: !0
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();
841
+ }), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Be(t.manifestUrl, t.analytics?.sid), e.load();
791
842
  }
792
843
  startLoad() {
793
844
  this.loadStarted || (this.loadStarted = !0, this.restorePreload());
@@ -809,7 +860,7 @@ var H = class {
809
860
  });
810
861
  this.onEncrypted = (n) => {
811
862
  let i = n;
812
- i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Ie(i.initData), (async () => {
863
+ i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = ze(i.initData), (async () => {
813
864
  try {
814
865
  let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
815
866
  initDataTypes: [i.initDataType],
@@ -904,11 +955,11 @@ var H = class {
904
955
  e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
905
956
  }
906
957
  getStats() {
907
- let e = this.deps.video, t = z(e), n = {
958
+ let e = this.deps.video, t = B(e), n = {
908
959
  droppedFrames: t.dropped,
909
960
  decodedFrames: t.totalFrames
910
961
  };
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;
962
+ return this.cdnHost ||= Le(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity ? (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)) : Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1), n;
912
963
  }
913
964
  stop() {
914
965
  try {
@@ -927,35 +978,198 @@ var H = class {
927
978
  } catch {}
928
979
  }
929
980
  };
930
- function Le(e, t) {
981
+ function Be(e, t) {
931
982
  return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
932
983
  }
933
984
  //#endregion
985
+ //#region src/core/engine/prefetch.ts
986
+ var Ve = 15e3, He = 5e3, Ue = 6;
987
+ function W(e) {
988
+ try {
989
+ let t = new URL(e);
990
+ return t.searchParams.delete("CMCD"), t.toString();
991
+ } catch {
992
+ return e;
993
+ }
994
+ }
995
+ var We = class {
996
+ cmcd;
997
+ entries = /* @__PURE__ */ new Map();
998
+ keyed = /* @__PURE__ */ new Set();
999
+ perTrack = /* @__PURE__ */ new Map();
1000
+ stats = {
1001
+ started: 0,
1002
+ served: 0,
1003
+ missed: 0,
1004
+ failed: 0,
1005
+ expired: 0
1006
+ };
1007
+ constructor(e = {}) {
1008
+ this.cmcd = e;
1009
+ }
1010
+ keyUsable(e) {
1011
+ this.keyed.add(e);
1012
+ }
1013
+ isActive(e) {
1014
+ return !this.keyed.has(e);
1015
+ }
1016
+ prefetch(e, t, n) {
1017
+ if (!this.isActive(t)) return;
1018
+ let r = W(e);
1019
+ if (this.entries.has(r)) return;
1020
+ let i = this.perTrack.get(t) ?? 0;
1021
+ if (i >= Ue) return;
1022
+ this.perTrack.set(t, i + 1);
1023
+ let a = new AbortController(), o = {
1024
+ started: performance.now(),
1025
+ first: 0,
1026
+ bytes: Promise.resolve(null),
1027
+ abort: a
1028
+ };
1029
+ o.bytes = fetch(this.withCmcd(e, t, n), {
1030
+ credentials: "omit",
1031
+ mode: "cors",
1032
+ signal: a.signal
1033
+ }).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
1034
+ this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
1035
+ }, Ve);
1036
+ }
1037
+ take(e) {
1038
+ let t = W(e), n = this.entries.get(t);
1039
+ return n && this.entries.delete(t), n;
1040
+ }
1041
+ destroy() {
1042
+ for (let e of this.entries.values()) e.abort.abort();
1043
+ this.entries.clear();
1044
+ }
1045
+ withCmcd(e, t, n) {
1046
+ let { sessionId: r, contentId: i } = this.cmcd;
1047
+ if (!r && !i) return e;
1048
+ let a = [];
1049
+ i && a.push(`cid="${i}"`), a.push(`ot=${n === "init" ? "i" : t === "audio" ? "a" : "v"}`), a.push("sf=h"), r && a.push(`sid="${r}"`), a.push("st=ll");
1050
+ try {
1051
+ let t = new URL(e);
1052
+ return t.searchParams.set("CMCD", a.join(",")), t.toString();
1053
+ } catch {
1054
+ return e;
1055
+ }
1056
+ }
1057
+ };
1058
+ function Ge(t) {
1059
+ let n = e.DefaultConfig?.loader;
1060
+ if (typeof n != "function") return;
1061
+ class r extends n {
1062
+ served = !1;
1063
+ cancelled = !1;
1064
+ stats = Ke();
1065
+ load(e, n, r) {
1066
+ let i = e.rangeEnd ? void 0 : t.take(e.url);
1067
+ if (!i) {
1068
+ super.load(e, n, r);
1069
+ return;
1070
+ }
1071
+ this.served = !0;
1072
+ let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || He, s = setTimeout(() => {
1073
+ !this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
1074
+ }, o);
1075
+ i.bytes.then((o) => {
1076
+ if (clearTimeout(s), this.cancelled || !this.served) return;
1077
+ if (!o) {
1078
+ t.stats.failed += 1, this.served = !1, super.load(e, n, r);
1079
+ return;
1080
+ }
1081
+ t.stats.served += 1;
1082
+ let c = this.stats;
1083
+ c.loading.start = a, c.loading.first = Math.max(a, i.first || a), c.loading.end = performance.now(), c.loaded = c.total = o.byteLength, r.onSuccess({
1084
+ url: e.url,
1085
+ data: o
1086
+ }, c, e, null);
1087
+ });
1088
+ }
1089
+ abort() {
1090
+ if (this.served) {
1091
+ this.cancelled = !0, this.stats.aborted = !0;
1092
+ return;
1093
+ }
1094
+ super.abort();
1095
+ }
1096
+ }
1097
+ return r;
1098
+ }
1099
+ function Ke() {
1100
+ return {
1101
+ aborted: !1,
1102
+ loaded: 0,
1103
+ retry: 0,
1104
+ total: 0,
1105
+ chunkCount: 0,
1106
+ bwEstimate: 0,
1107
+ loading: {
1108
+ start: 0,
1109
+ first: 0,
1110
+ end: 0
1111
+ },
1112
+ parsing: {
1113
+ start: 0,
1114
+ end: 0
1115
+ },
1116
+ buffering: {
1117
+ start: 0,
1118
+ first: 0,
1119
+ end: 0
1120
+ }
1121
+ };
1122
+ }
1123
+ function G(e) {
1124
+ return e === "audio" ? "audio" : "main";
1125
+ }
1126
+ function qe(e, t) {
1127
+ let n = [];
1128
+ t.initSegment?.url && !t.initSegment.data && n.push({
1129
+ url: t.initSegment.url,
1130
+ kind: "init"
1131
+ });
1132
+ let r = ((t.type === "audio" ? e.audioTracks?.[e.audioTrack]?.details : typeof t.level == "number" ? e.levels?.[t.level]?.details : void 0)?.partList ?? []).filter((e) => e.fragment.sn === t.sn);
1133
+ if (r.length) for (let e of r) e.url && n.push({
1134
+ url: e.url,
1135
+ kind: "media"
1136
+ });
1137
+ else t.url && n.push({
1138
+ url: t.url,
1139
+ kind: "media"
1140
+ });
1141
+ return n;
1142
+ }
1143
+ //#endregion
934
1144
  //#region src/core/engine/hls.ts
935
- function Re() {
1145
+ function Je() {
936
1146
  return e.isSupported();
937
1147
  }
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) {
1148
+ var Ye = 3, Xe = 5, Ze = 3, Qe = 3e4, $e = 12e3, et = 3e3, K = 6e3, tt = 5e3, nt = 4e3, rt = 2, it = 5, at = 2, ot = 2, q = 4, st = 4, ct = 2e3, lt = 3e4, ut = 2, dt = 9, ft = .5, pt = 64;
1149
+ function mt(e) {
940
1150
  if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
941
1151
  delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
942
1152
  return;
943
1153
  }
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);
1154
+ e.liveSyncDuration ??= ut;
1155
+ let t = Math.max(12, e.liveSyncDuration + dt);
1156
+ (e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), ht(e, e.liveSyncDuration);
947
1157
  }
948
- function it(e, t) {
1158
+ function ht(e, t) {
949
1159
  let n = (e, t, n) => Math.min(n, Math.max(t, e));
950
1160
  e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
951
1161
  }
952
- var W = class {
1162
+ var J = class {
953
1163
  name = "hls";
954
1164
  hls = null;
955
1165
  deps;
956
1166
  licenseUrl;
957
1167
  detectedLowLatency = !1;
958
1168
  bytesLoaded = 0;
1169
+ prefetch = null;
1170
+ reportedFirstPlaylist = !1;
1171
+ reportedFirstBytes = !1;
1172
+ reportedDrmReady = !1;
959
1173
  playlistBytesLoaded = 0;
960
1174
  renditionSwitches = 0;
961
1175
  licenseTimeMs = 0;
@@ -993,6 +1207,11 @@ var W = class {
993
1207
  kickPending = !1;
994
1208
  kickTicks = 0;
995
1209
  starvationRebuilds = 0;
1210
+ kickKind = null;
1211
+ starvedFrames = 0;
1212
+ deadTicks = 0;
1213
+ mainFragsSinceTick = 0;
1214
+ recentMainFrags = [];
996
1215
  chaseSuspended = !1;
997
1216
  savedLiveMaxLatency;
998
1217
  savedMaxSyncRate;
@@ -1008,7 +1227,7 @@ var W = class {
1008
1227
  this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
1009
1228
  }
1010
1229
  async load() {
1011
- let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = B(r) && V(), o = !!e.drm?.widevine?.licenseUrl && !a;
1230
+ let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = V(r) && H(), o = !!e.drm?.widevine?.licenseUrl && !a;
1012
1231
  if (e.drmEnabled && !o) {
1013
1232
  i({
1014
1233
  type: "error",
@@ -1017,7 +1236,7 @@ var W = class {
1017
1236
  });
1018
1237
  return;
1019
1238
  }
1020
- this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1239
+ e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && Ee(r), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
1021
1240
  let e = this.hls;
1022
1241
  if (document.visibilityState !== "visible" || !e) return;
1023
1242
  let t = e.liveSyncPosition;
@@ -1040,11 +1259,11 @@ var W = class {
1040
1259
  }
1041
1260
  this.loadSuspended = !0;
1042
1261
  }
1043
- }, Ge));
1262
+ }, tt));
1044
1263
  }
1045
1264
  resumeLoading() {
1046
1265
  if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
1047
- this.lastAdvanceMs = Date.now(), this.lastFragLoadingMs = 0, this.starvedTicks = 0, this.kickPending = !1, this.kickTicks = 0;
1266
+ this.lastAdvanceMs = Date.now(), this.lastFragLoadingMs = 0, this.resetStarvationWindow(), this.clearKick();
1048
1267
  try {
1049
1268
  this.hls.startLoad(-1);
1050
1269
  } catch {}
@@ -1072,11 +1291,11 @@ var W = class {
1072
1291
  let t = e.liveSyncPosition;
1073
1292
  if (typeof t != "number" || !Number.isFinite(t)) return;
1074
1293
  let { video: n } = this.deps;
1075
- n.currentTime <= t + tt || (n.currentTime = t);
1294
+ n.currentTime <= t + ft || (n.currentTime = t);
1076
1295
  }
1077
1296
  startHls() {
1078
1297
  let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
1079
- this.kickPending = !1, this.kickTicks = 0, this.starvedTicks = 0, this.lastFragLoadingMs = 0, this.lastEndSN = -1, this.lastAdvanceMs = 0;
1298
+ this.clearKick(), this.resetStarvationWindow(), this.lastFragLoadingMs = 0, this.lastEndSN = -1, this.lastAdvanceMs = 0;
1080
1299
  let u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d = {
1081
1300
  debug: s === !0,
1082
1301
  enableWorker: !o,
@@ -1091,17 +1310,17 @@ var W = class {
1091
1310
  emeEnabled: !0,
1092
1311
  drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
1093
1312
  drmSystemOptions: {
1094
- videoRobustness: "SW_SECURE_DECODE",
1095
- audioRobustness: "SW_SECURE_CRYPTO",
1096
- videoEncryptionScheme: "cbcs",
1097
- audioEncryptionScheme: "cbcs"
1313
+ videoRobustness: F.video,
1314
+ audioRobustness: F.audio,
1315
+ videoEncryptionScheme: F.scheme,
1316
+ audioEncryptionScheme: F.scheme
1098
1317
  },
1099
- ...M() ? { requestMediaKeySystemAccessFunc: we(t) } : {},
1318
+ ...M() ? { requestMediaKeySystemAccessFunc: Te(t) } : {},
1100
1319
  licenseXhrSetup: (e, t) => {
1101
1320
  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;
1102
1321
  let o = performance.now();
1103
1322
  e.addEventListener("loadend", () => {
1104
- this.licenseTimeMs = Math.max(1, Math.round(performance.now() - o));
1323
+ this.licenseTimeMs === 0 && (this.licenseTimeMs = Math.max(1, Math.round(performance.now() - o)));
1105
1324
  });
1106
1325
  }
1107
1326
  } : {},
@@ -1112,39 +1331,56 @@ var W = class {
1112
1331
  } } : {},
1113
1332
  ...c
1114
1333
  };
1115
- rt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1334
+ if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
1335
+ let e = new We({
1336
+ sessionId: n.analytics?.sid,
1337
+ contentId: n.matchUrn
1338
+ }), t = Ge(e);
1339
+ t && (this.prefetch = e, d.fLoader = t);
1340
+ }
1341
+ mt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
1116
1342
  let f = new e(d);
1117
- this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
1343
+ if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
1118
1344
  this.mediaRecoveries = 0, this.networkRecoveries = 0;
1119
1345
  let e = f.levels.map((e) => e.height).filter((e) => !!e);
1120
1346
  this.ladderHeights = e.length ? [...new Set(e)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = f.levels.length ? Math.round(Math.max(...f.levels.map((e) => e.bitrate)) / 1e3) : 0, this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
1121
1347
  }), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
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(() => {
1348
+ t?.frag?.type === "main" && (this.kickKind !== "dead" && this.clearKick(), (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
1123
1349
  this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
1124
- }, He)));
1350
+ }, Qe)));
1125
1351
  }), f.on(e.Events.FRAG_LOADING, (e, t) => {
1126
1352
  t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
1127
1353
  }), f.on(e.Events.FRAG_LOADED, (e, t) => {
1354
+ t?.frag?.type === "main" && (this.mainFragsSinceTick += 1);
1128
1355
  let n = t?.frag?.stats, r = n?.loaded;
1129
- typeof r == "number" && (this.bytesLoaded += r);
1356
+ typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
1130
1357
  let i = n?.loading;
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());
1358
+ 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 > pt && this.requestTimesMs.shift());
1132
1359
  let a = t?.frag?.url;
1133
1360
  if (a) {
1134
- let e = R(a);
1361
+ let e = z(a);
1135
1362
  e && (this.cdnHost = e);
1136
1363
  }
1137
1364
  }), f.on(e.Events.LEVEL_LOADED, (e, t) => {
1138
1365
  let n = t?.stats?.loaded;
1139
- if (typeof n == "number" && (this.playlistBytesLoaded += n), this.detectedLowLatency) return;
1366
+ if (typeof n == "number" && (this.playlistBytesLoaded += n), this.reportedFirstPlaylist || (this.reportedFirstPlaylist = !0, l({ type: "firstPlaylist" })), this.detectedLowLatency) return;
1140
1367
  let r = t.details;
1141
1368
  (r?.partList?.length || (r?.partTarget ?? 0) > 0) && (this.detectedLowLatency = !0, l({
1142
1369
  type: "lowLatencyDetected",
1143
1370
  value: !0
1144
1371
  }));
1145
- }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1372
+ }), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
1373
+ let t = this.prefetch;
1374
+ f.on(e.Events.KEY_LOADING, (e, n) => {
1375
+ let r = n?.frag, i = G(r?.type);
1376
+ if (r && t.isActive(i)) for (let e of qe(f, r)) t.prefetch(e.url, i, e.kind);
1377
+ }), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(G(n?.frag?.type)));
1378
+ }
1379
+ f.on(e.Events.KEY_LOADED, () => {
1380
+ u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
1381
+ }), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
1146
1382
  this.checkEndStale(), this.checkStarvation();
1147
- }, We), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1383
+ }, et), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
1148
1384
  this.renditionSwitches += 1;
1149
1385
  let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
1150
1386
  n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
@@ -1208,7 +1444,7 @@ var W = class {
1208
1444
  return;
1209
1445
  }
1210
1446
  this.capTimer && clearTimeout(this.capTimer);
1211
- let t = e > this.sizeCapLevel ? Ze : Qe;
1447
+ let t = e > this.sizeCapLevel ? ct : lt;
1212
1448
  this.capTimer = setTimeout(() => {
1213
1449
  this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
1214
1450
  }, t);
@@ -1255,7 +1491,7 @@ var W = class {
1255
1491
  e.widevine && (this.licenseUrl = e.widevine);
1256
1492
  }
1257
1493
  getStats() {
1258
- let e = this.hls, t = z(this.deps.video), n = {
1494
+ let e = this.hls, t = B(this.deps.video), n = {
1259
1495
  droppedFrames: t.dropped,
1260
1496
  decodedFrames: t.totalFrames,
1261
1497
  lowLatency: this.detectedLowLatency,
@@ -1301,32 +1537,41 @@ var W = class {
1301
1537
  return;
1302
1538
  }
1303
1539
  let e = Date.now() - this.lastAdvanceMs;
1304
- !this.chaseSuspended && e > U && this.suspendChasing(), e > Ue && this.emitEnded("stalled");
1540
+ !this.chaseSuspended && e > K && this.suspendChasing(), e > $e && this.emitEnded("stalled");
1541
+ }
1542
+ resetStarvationWindow() {
1543
+ this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
1544
+ }
1545
+ clearKick() {
1546
+ this.kickPending = !1, this.kickTicks = 0, this.kickKind = null;
1305
1547
  }
1306
1548
  checkStarvation() {
1307
1549
  let e = this.hls, { video: t } = this.deps;
1308
1550
  if (!e || this.endedEmitted || !this.sawLive || this.chaseSuspended) return;
1309
1551
  if (typeof document < "u" && document.hidden || this.loadSuspended) {
1310
- this.starvedTicks = 0;
1552
+ this.resetStarvationWindow();
1311
1553
  return;
1312
1554
  }
1313
- let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < U, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > Ke;
1314
- if (!(t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused && n && r)) {
1315
- this.starvedTicks = 0;
1555
+ let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < K, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > nt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
1556
+ if (this.starvedFrames = c, !a || l) {
1557
+ (t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
1316
1558
  return;
1317
1559
  }
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)) {
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");
1321
- return;
1322
- }
1323
- if (!(this.starvationKicks >= Je)) {
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");
1325
- try {
1326
- e.stopLoad(), e.startLoad(-1);
1327
- } catch (e) {
1328
- console.warn("havik-player: starvation kick failed", e);
1329
- }
1560
+ if (!r) {
1561
+ this.resetStarvationWindow();
1562
+ return;
1563
+ }
1564
+ if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > q && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= at && (this.clearKick(), this.starvationRebuilds < ot)) {
1565
+ this.starvationRebuilds += 1, this.resetStarvationWindow(), this.clearRecoveryReset(), console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
1566
+ return;
1567
+ }
1568
+ let u = i && this.starvedTicks >= rt, d = !i && this.deadTicks >= q && this.recentMainFrags.reduce((e, t) => e + t, 0) >= st;
1569
+ if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= it))) {
1570
+ this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, this.kickKind = d ? "dead" : "quiet", this.clearRecoveryReset(), console.warn(d ? "havik-player: video starved while hls.js keeps loading media it never plays (dead pipeline at the live edge) — restarting the load" : "havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
1571
+ try {
1572
+ e.stopLoad(), e.startLoad(-1);
1573
+ } catch (e) {
1574
+ console.warn("havik-player: starvation kick failed", e);
1330
1575
  }
1331
1576
  }
1332
1577
  }
@@ -1346,7 +1591,7 @@ var W = class {
1346
1591
  }));
1347
1592
  }
1348
1593
  stop() {
1349
- this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.kickPending = !1, this.kickTicks = 0, this.stopped = !0, this.loadSuspended = !1, this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null);
1594
+ this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.clearKick(), this.stopped = !0, this.loadSuspended = !1, this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null);
1350
1595
  try {
1351
1596
  this.hls?.stopLoad();
1352
1597
  } catch {}
@@ -1355,7 +1600,7 @@ var W = class {
1355
1600
  } catch {}
1356
1601
  }
1357
1602
  destroy() {
1358
- if (this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
1603
+ if (this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
1359
1604
  try {
1360
1605
  this.hls.destroy();
1361
1606
  } catch (e) {
@@ -1370,7 +1615,7 @@ var W = class {
1370
1615
  scheduleLicenseRetry(t) {
1371
1616
  if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
1372
1617
  let n = t.response?.code ?? 0;
1373
- if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Ve) return !1;
1618
+ if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Ze) return !1;
1374
1619
  this.licenseRecoveries += 1;
1375
1620
  let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
1376
1621
  return this.licenseRetryTimer = setTimeout(() => {
@@ -1402,7 +1647,7 @@ var W = class {
1402
1647
  return;
1403
1648
  }
1404
1649
  if (t.type === e.ErrorTypes.NETWORK_ERROR) {
1405
- if (this.networkRecoveries < Be) {
1650
+ if (this.networkRecoveries < Xe) {
1406
1651
  this.networkRecoveries += 1;
1407
1652
  let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
1408
1653
  this.networkRetryTimer = setTimeout(() => {
@@ -1419,7 +1664,7 @@ var W = class {
1419
1664
  return;
1420
1665
  }
1421
1666
  if (t.type === e.ErrorTypes.MEDIA_ERROR) {
1422
- if (this.mediaRecoveries < ze) {
1667
+ if (this.mediaRecoveries < Ye) {
1423
1668
  this.mediaRecoveries += 1, n.recoverMediaError();
1424
1669
  return;
1425
1670
  }
@@ -1443,19 +1688,19 @@ var W = class {
1443
1688
  let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
1444
1689
  return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
1445
1690
  }
1446
- }, at = 15e3, ot = 6e5, st = 3e5, ct = 100, G = 1, lt = 1e3, K = 3e4, ut = 1e3, dt = {
1691
+ }, gt = 15e3, _t = 6e5, vt = 3e5, yt = 100, Y = 1, bt = 1e3, xt = 3e4, St = 1e3, Ct = {
1447
1692
  inline: "PRESENTATION_INLINE",
1448
1693
  fullscreen: "PRESENTATION_FULLSCREEN",
1449
1694
  pip: "PRESENTATION_PIP"
1450
- }, ft = {
1695
+ }, wt = {
1451
1696
  widevine: "KEY_SYSTEM_WIDEVINE",
1452
1697
  fairplay: "KEY_SYSTEM_FAIRPLAY",
1453
1698
  none: "KEY_SYSTEM_NONE"
1454
1699
  };
1455
- function q(e, t) {
1700
+ function Tt(e, t) {
1456
1701
  return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
1457
1702
  }
1458
- var pt = /* @__PURE__ */ new Set([
1703
+ var Et = /* @__PURE__ */ new Set([
1459
1704
  "INVALID_URN",
1460
1705
  "NOT_FOUND",
1461
1706
  "GONE",
@@ -1465,7 +1710,7 @@ var pt = /* @__PURE__ */ new Set([
1465
1710
  "FORBIDDEN",
1466
1711
  "RATE_LIMITED",
1467
1712
  "TIMEOUT"
1468
- ]), J = {
1713
+ ]), X = {
1469
1714
  idle: "PLAYER_STATE_IDLE",
1470
1715
  waiting: "PLAYER_STATE_WAITING",
1471
1716
  loading: "PLAYER_STATE_LOADING",
@@ -1475,7 +1720,7 @@ var pt = /* @__PURE__ */ new Set([
1475
1720
  ended: "PLAYER_STATE_ENDED",
1476
1721
  error: "PLAYER_STATE_ERROR"
1477
1722
  };
1478
- function mt(e) {
1723
+ function Dt(e) {
1479
1724
  try {
1480
1725
  let t = new URL(e), [n, ...r] = t.hostname.split(".");
1481
1726
  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);
@@ -1483,14 +1728,14 @@ function mt(e) {
1483
1728
  return;
1484
1729
  }
1485
1730
  }
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 };
1731
+ var Ot = /* @__PURE__ */ new Set();
1732
+ function kt(e, t) {
1733
+ return Ot.has(e) || (Ot.add(e), console.warn(`havik-player: ${t}`)), { disabledReason: t };
1489
1734
  }
1490
- function ht(e, t) {
1735
+ function At(e, t) {
1491
1736
  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);
1737
+ if (t !== void 0) return kt("empty-endpoint", "analytics is disabled: no QoE beacons will be sent. analytics.endpoint was supplied but empty. Pass a real beacons origin, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, or omit the option to derive it from baseUrl (or analytics: false to opt out).");
1738
+ let n = Dt(e);
1494
1739
  if (n) return { endpoint: n };
1495
1740
  let r;
1496
1741
  try {
@@ -1498,9 +1743,9 @@ function ht(e, t) {
1498
1743
  } catch {
1499
1744
  r = e;
1500
1745
  }
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).`);
1746
+ return kt(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
1747
  }
1503
- var gt = class {
1748
+ var jt = class {
1504
1749
  opts;
1505
1750
  url;
1506
1751
  now;
@@ -1567,6 +1812,8 @@ var gt = class {
1567
1812
  startupTimeMs = 0;
1568
1813
  manifestLoadMs = 0;
1569
1814
  firstFragLoadMs = 0;
1815
+ firstPlaylistMs = 0;
1816
+ drmSetupMs = 0;
1570
1817
  onPagehide = () => this.end("END_REASON_PAGEHIDE");
1571
1818
  onFreeze = () => {
1572
1819
  this.endedFlag || this.flush(!0);
@@ -1578,8 +1825,8 @@ var gt = class {
1578
1825
  constructor(e) {
1579
1826
  this.opts = {
1580
1827
  ...e,
1581
- heartbeatMs: e.heartbeatMs ?? at,
1582
- idleMs: e.idleMs ?? ot
1828
+ heartbeatMs: e.heartbeatMs ?? gt,
1829
+ idleMs: e.idleMs ?? _t
1583
1830
  }, 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;
1584
1831
  }
1585
1832
  start() {
@@ -1589,11 +1836,11 @@ var gt = class {
1589
1836
  sdkVersion: this.opts.sdkVersion,
1590
1837
  ...this.opts.environment
1591
1838
  };
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());
1839
+ this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), bt), 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());
1593
1840
  }
1594
1841
  checkSuspension(e) {
1595
1842
  if (this.endedFlag || !this.opts.idleMs) return !1;
1596
- let t = Math.max(this.opts.idleMs, st);
1843
+ let t = Math.max(this.opts.idleMs, vt);
1597
1844
  return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
1598
1845
  }
1599
1846
  syncIdle(e) {
@@ -1607,21 +1854,21 @@ var gt = class {
1607
1854
  noteStateChange(e, t, n, r) {
1608
1855
  if (this.endedFlag || e === t) return;
1609
1856
  let i = this.now();
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") {
1857
+ if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(Y, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(Y, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
1611
1858
  this.stallIsSeekInduced = this.seekInduced(i);
1612
1859
  let e = !this.isHidden && !this.stallIsSeekInduced;
1613
- e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(G, Math.round(this.playingTotalMs)));
1860
+ e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(Y, Math.round(this.playingTotalMs)));
1614
1861
  } else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
1615
1862
  this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
1616
1863
  let a = {
1617
- fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
1618
- toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
1619
- presentation: dt[this.presentation]
1864
+ fromState: X[e] ?? "PLAYER_STATE_UNSPECIFIED",
1865
+ toState: X[t] ?? "PLAYER_STATE_UNSPECIFIED",
1866
+ presentation: Ct[this.presentation]
1620
1867
  }, o = this.causeOf(e, t, i);
1621
1868
  o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
1622
1869
  }
1623
1870
  seekInduced(e) {
1624
- return this.lastSeekMs >= 0 && e - this.lastSeekMs < ut;
1871
+ return this.lastSeekMs >= 0 && e - this.lastSeekMs < St;
1625
1872
  }
1626
1873
  causeOf(e, t, n) {
1627
1874
  if (t === "error") return "TRANSITION_CAUSE_ERROR";
@@ -1658,19 +1905,25 @@ var gt = class {
1658
1905
  }
1659
1906
  this.muteChanges += 1;
1660
1907
  let r = this.now();
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();
1908
+ n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(Y, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
1662
1909
  }
1663
1910
  notePresentation(e) {
1664
1911
  this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
1665
1912
  }
1666
1913
  notePlayIntent() {
1667
- this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = G), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = G));
1914
+ this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = Y), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = Y), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = Y), this.drmSetupMs > 0 && (this.drmSetupMs = Y));
1668
1915
  }
1669
1916
  noteReady() {
1670
- this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(G, this.now() - this.startupAnchorMs));
1917
+ this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(Y, this.now() - this.startupAnchorMs));
1918
+ }
1919
+ noteFirstPlaylist() {
1920
+ this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(Y, this.now() - this.startupAnchorMs));
1921
+ }
1922
+ noteDrmReady() {
1923
+ this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(Y, this.now() - this.startupAnchorMs));
1671
1924
  }
1672
1925
  noteFirstBytes() {
1673
- this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(G, this.now() - this.startupAnchorMs));
1926
+ this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(Y, this.now() - this.startupAnchorMs));
1674
1927
  }
1675
1928
  noteSeek() {
1676
1929
  this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
@@ -1689,7 +1942,7 @@ var gt = class {
1689
1942
  let r = n ?? "";
1690
1943
  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";
1691
1944
  if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
1692
- if (pt.has(e)) return "ERROR_STAGE_RESOLVE";
1945
+ if (Et.has(e)) return "ERROR_STAGE_RESOLVE";
1693
1946
  let i = t ?? "";
1694
1947
  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";
1695
1948
  }
@@ -1721,7 +1974,7 @@ var gt = class {
1721
1974
  let l = t.droppedFrames ?? 0;
1722
1975
  l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
1723
1976
  let u = t.renditionSwitches ?? 0;
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";
1977
+ u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = X[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
1725
1978
  let d = this.mutedTotalMs;
1726
1979
  this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
1727
1980
  let f = t.upshifts ?? 0;
@@ -1736,14 +1989,14 @@ var gt = class {
1736
1989
  if (this.lastRequestCount = g, _ > 0) {
1737
1990
  o.requestCountDelta = _;
1738
1991
  let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
1739
- n.length > 0 && (o.requestTimeP50Ms = q(n, 50), o.requestTimeP95Ms = q(n, 95));
1992
+ n.length > 0 && (o.requestTimeP50Ms = Tt(n, 50), o.requestTimeP95Ms = Tt(n, 95));
1740
1993
  }
1741
1994
  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();
1742
1995
  }
1743
1996
  maybeEmitMediaInfo(e) {
1744
1997
  if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
1745
1998
  let t = {};
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);
1999
+ e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = wt[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);
1747
2000
  let n = JSON.stringify(t);
1748
2001
  n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
1749
2002
  }
@@ -1755,7 +2008,7 @@ var gt = class {
1755
2008
  let r = this.safeSample();
1756
2009
  r && this.maybeEmitMediaInfo(r);
1757
2010
  let i = { reason: e }, a = r?.bytesLoaded ?? this.lastBytes;
1758
- a > 0 && (i.bytesDownloadedTotal = a), this.playingTotalMs > 0 && (i.watchTimeMs = Math.round(this.playingTotalMs)), this.rebufferCount > 0 && (i.rebufferCount = this.rebufferCount), this.rebufferTotalMs > 0 && (i.rebufferTimeMs = Math.round(this.rebufferTotalMs)), this.startupTimeMs > 0 && (i.startupTimeMs = Math.round(this.startupTimeMs)), this.manifestLoadMs > 0 && (i.manifestLoadMs = Math.round(this.manifestLoadMs)), this.firstFragLoadMs > 0 && (i.firstFragLoadMs = Math.round(this.firstFragLoadMs));
2011
+ a > 0 && (i.bytesDownloadedTotal = a), this.playingTotalMs > 0 && (i.watchTimeMs = Math.round(this.playingTotalMs)), this.rebufferCount > 0 && (i.rebufferCount = this.rebufferCount), this.rebufferTotalMs > 0 && (i.rebufferTimeMs = Math.round(this.rebufferTotalMs)), this.startupTimeMs > 0 && (i.startupTimeMs = Math.round(this.startupTimeMs)), this.manifestLoadMs > 0 && (i.manifestLoadMs = Math.round(this.manifestLoadMs)), this.firstPlaylistMs > 0 && (i.firstPlaylistMs = Math.round(this.firstPlaylistMs)), this.firstFragLoadMs > 0 && (i.firstFragLoadMs = Math.round(this.firstFragLoadMs)), this.drmSetupMs > 0 && (i.drmSetupMs = Math.round(this.drmSetupMs));
1759
2012
  let o = r?.licenseTimeMs ?? 0;
1760
2013
  o > 0 && (i.licenseTimeMs = Math.round(o));
1761
2014
  let s = r?.droppedFrames ?? this.lastDropped;
@@ -1763,9 +2016,9 @@ var gt = class {
1763
2016
  let c = r?.positionMs ?? 0;
1764
2017
  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));
1765
2018
  let l = e !== "END_REASON_ENDED";
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);
2019
+ l && this.lastStallMs > 0 && n - this.lastStallMs <= xt && (i.abandonAfterStallMs = Math.max(Y, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= xt && (i.abandonAfterErrorMs = Math.max(Y, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
1767
2020
  let u = r?.decodedFrames ?? this.lastDecoded;
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");
2021
+ u > 0 && (i.decodedFramesTotal = u), e === "END_REASON_STOPPED" && this.startupTimeMs === 0 && this.lastErrorStage === null && (e = "END_REASON_ABORTED", i.reason = e), this.startupTimeMs === 0 && e !== "END_REASON_ABORTED" && (i.failedStage = this.lastErrorStage ?? (this.manifestLoadMs === 0 ? "ERROR_STAGE_MANIFEST" : this.firstFragLoadMs === 0 ? "ERROR_STAGE_FIRST_SEGMENT" : "ERROR_STAGE_OTHER")), this.pending.push(this.wrap({ sessionEnd: i })), this.flush(e === "END_REASON_PAGEHIDE");
1769
2022
  }
1770
2023
  safeSample() {
1771
2024
  try {
@@ -1783,7 +2036,7 @@ var gt = class {
1783
2036
  };
1784
2037
  }
1785
2038
  enqueue(e) {
1786
- for (this.pending.push(this.wrap(e)); this.pending.length > ct;) {
2039
+ for (this.pending.push(this.wrap(e)); this.pending.length > yt;) {
1787
2040
  let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
1788
2041
  this.pending.splice(e >= 0 ? e : 0, 1);
1789
2042
  }
@@ -1806,7 +2059,7 @@ var gt = class {
1806
2059
  };
1807
2060
  //#endregion
1808
2061
  //#region src/core/environment.ts
1809
- function _t() {
2062
+ function Mt() {
1810
2063
  if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
1811
2064
  let e;
1812
2065
  try {
@@ -1831,14 +2084,14 @@ function _t() {
1831
2084
  integration: "INTEGRATION_KIND_IFRAME"
1832
2085
  };
1833
2086
  }
1834
- function vt() {
2087
+ function Nt() {
1835
2088
  if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
1836
2089
  let e = navigator.userAgentData, t = e?.platform ?? "";
1837
2090
  if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
1838
2091
  let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
1839
2092
  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";
1840
2093
  }
1841
- function yt() {
2094
+ function Pt() {
1842
2095
  let e = typeof navigator < "u" ? navigator.connection : void 0;
1843
2096
  if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
1844
2097
  let t = {
@@ -1857,17 +2110,17 @@ function yt() {
1857
2110
  }
1858
2111
  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;
1859
2112
  }
1860
- function bt(e) {
1861
- let t = _t(), n = {
1862
- deviceClass: vt(),
2113
+ function Ft(e) {
2114
+ let t = Mt(), n = {
2115
+ deviceClass: Nt(),
1863
2116
  integration: t.integration,
1864
- ...yt()
2117
+ ...Pt()
1865
2118
  };
1866
2119
  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);
1867
2120
  let r = e.getBoundingClientRect?.();
1868
2121
  return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
1869
2122
  }
1870
- async function xt() {
2123
+ async function It() {
1871
2124
  let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
1872
2125
  if (!e?.getHighEntropyValues) return {};
1873
2126
  try {
@@ -1879,7 +2132,7 @@ async function xt() {
1879
2132
  }
1880
2133
  //#endregion
1881
2134
  //#region src/core/version.ts
1882
- var St = "2.10.0", Ct = {
2135
+ var Lt = "2.11.0", Rt = {
1883
2136
  accent: "#E1B600",
1884
2137
  accentText: "#1B1C23",
1885
2138
  background: "#0e0f13",
@@ -1890,7 +2143,7 @@ var St = "2.10.0", Ct = {
1890
2143
  border: "rgba(255, 255, 255, 0.1)",
1891
2144
  radius: "8px",
1892
2145
  fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
1893
- }, wt = {
2146
+ }, zt = {
1894
2147
  accent: "--havik-accent",
1895
2148
  accentText: "--havik-accent-text",
1896
2149
  background: "--havik-bg",
@@ -1902,25 +2155,25 @@ var St = "2.10.0", Ct = {
1902
2155
  radius: "--havik-radius",
1903
2156
  fontFamily: "--havik-font"
1904
2157
  };
1905
- function Tt(e, t) {
2158
+ function Z(e, t) {
1906
2159
  let n = {
1907
- ...Ct,
2160
+ ...Rt,
1908
2161
  ...t
1909
2162
  };
1910
- for (let t of Object.keys(wt)) e.style.setProperty(wt[t], n[t]);
2163
+ for (let t of Object.keys(zt)) e.style.setProperty(zt[t], n[t]);
1911
2164
  n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
1912
2165
  }
1913
2166
  //#endregion
1914
2167
  //#region src/ui/styles.ts
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/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
1916
- function Ot(e = document) {
1917
- if (e.getElementById(Et)) return;
2168
+ var Bt = "havik-player-styles", Vt = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
2169
+ function Ht(e = document) {
2170
+ if (e.getElementById(Bt)) return;
1918
2171
  let t = e.createElement("style");
1919
- t.id = Et, t.textContent = Dt, e.head.appendChild(t);
2172
+ t.id = Bt, t.textContent = Vt, e.head.appendChild(t);
1920
2173
  }
1921
2174
  //#endregion
1922
2175
  //#region src/ui/icons.ts
1923
- var kt = {
2176
+ var Ut = {
1924
2177
  play: "<path d=\"M8 5v14l11-7z\"/>",
1925
2178
  pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
1926
2179
  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\"/>",
@@ -1933,21 +2186,21 @@ var kt = {
1933
2186
  liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
1934
2187
  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\"/>"
1935
2188
  };
1936
- function Z(e) {
1937
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${kt[e]}</svg>`;
2189
+ function Q(e) {
2190
+ return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Ut[e]}</svg>`;
1938
2191
  }
1939
2192
  //#endregion
1940
2193
  //#region src/ui/controls.ts
1941
- var At = 3e3, jt = /* @__PURE__ */ new Set([
2194
+ var Wt = 3e3, Gt = /* @__PURE__ */ new Set([
1942
2195
  "GONE",
1943
2196
  "NOT_FOUND",
1944
2197
  "INVALID_URN",
1945
2198
  "UNAUTHORIZED"
1946
2199
  ]);
1947
- function Mt(e) {
1948
- return new Nt(e);
2200
+ function Kt(e) {
2201
+ return new qt(e);
1949
2202
  }
1950
- var Nt = class {
2203
+ var qt = class {
1951
2204
  root;
1952
2205
  video;
1953
2206
  player;
@@ -1989,7 +2242,7 @@ var Nt = class {
1989
2242
  scrubbing = !1;
1990
2243
  offFns = [];
1991
2244
  constructor(e) {
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");
2245
+ this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Wt, 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, Ht(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");
1993
2246
  let t = (e, t, n) => {
1994
2247
  let r = this.doc.createElement(e);
1995
2248
  if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
@@ -2000,12 +2253,12 @@ var Nt = class {
2000
2253
  "aria-label": r,
2001
2254
  title: r
2002
2255
  });
2003
- return i.innerHTML = Z(n), i;
2256
+ return i.innerHTML = Q(n), i;
2004
2257
  };
2005
2258
  this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
2006
2259
  type: "button",
2007
2260
  "aria-label": "Play"
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", {
2261
+ }), this.center.innerHTML = Q("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
2009
2262
  role: "slider",
2010
2263
  "aria-label": "Seek",
2011
2264
  "aria-valuemin": "0",
@@ -2023,7 +2276,7 @@ var Nt = class {
2023
2276
  "aria-label": "Volume"
2024
2277
  });
2025
2278
  let a = t("div", "havik-vol");
2026
- a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Z("liveDot");
2279
+ a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Q("liveDot");
2027
2280
  let o = this.doc.createElement("span");
2028
2281
  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";
2029
2282
  let s = t("div", "havik-spacer");
@@ -2077,12 +2330,12 @@ var Nt = class {
2077
2330
  }
2078
2331
  if (e === "preplay") {
2079
2332
  let e = this.doc.createElement("button");
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);
2333
+ e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Q("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
2081
2334
  } else {
2082
2335
  let r = this.doc.createElement("div");
2083
- if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !jt.has(this.lastError.code)) {
2336
+ if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Gt.has(this.lastError.code)) {
2084
2337
  let e = this.doc.createElement("button");
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);
2338
+ e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Q("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
2086
2339
  }
2087
2340
  }
2088
2341
  this.root.append(n), this.statusBox = n, this.show();
@@ -2121,11 +2374,11 @@ var Nt = class {
2121
2374
  let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
2122
2375
  this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
2123
2376
  }
2124
- !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Pt(this.video.currentTime)} / ${Pt(this.video.duration)}`);
2377
+ !this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Jt(this.video.currentTime)} / ${Jt(this.video.duration)}`);
2125
2378
  }
2126
2379
  syncLive() {
2127
2380
  let e = this.player.getStats(), t = e.isLive !== !1;
2128
- this.live.style.display = t ? "" : "none", this.time.style.display = t ? "none" : "", this.live.classList.toggle("is-live", e.atLiveEdge !== !1 && t);
2381
+ this.live.style.display = t ? "" : "none", this.time.style.display = t ? "none" : "", this.seek.style.display = t ? "none" : "", this.live.classList.toggle("is-live", e.atLiveEdge !== !1 && t);
2129
2382
  }
2130
2383
  onSeekDown(e) {
2131
2384
  let t = this.seekableRange();
@@ -2171,17 +2424,17 @@ var Nt = class {
2171
2424
  renderQualityMenu() {
2172
2425
  let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
2173
2426
  n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
2174
- for (let n of e) this.menu.append(this.menuItem(Ft(n), t === n.index, () => this.player.setQuality(n.index)));
2427
+ for (let n of e) this.menu.append(this.menuItem(Yt(n), t === n.index, () => this.player.setQuality(n.index)));
2175
2428
  }
2176
2429
  renderAudioMenu() {
2177
2430
  let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
2178
2431
  t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
2179
- for (let t of e) this.menu.append(this.menuItem(It(t), t.default, () => this.player.setAudioTrack(t.id)));
2432
+ for (let t of e) this.menu.append(this.menuItem(Xt(t), t.default, () => this.player.setAudioTrack(t.id)));
2180
2433
  }
2181
2434
  renderCcMenu() {
2182
2435
  let e = this.player.getTextTracks(), t = this.doc.createElement("div");
2183
2436
  t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
2184
- for (let t of e) this.menu.append(this.menuItem(Lt(t), !1, () => this.player.setTextTrack(t.id)));
2437
+ for (let t of e) this.menu.append(this.menuItem(Zt(t), !1, () => this.player.setTextTrack(t.id)));
2185
2438
  }
2186
2439
  onTracksChanged() {
2187
2440
  this.openMenu && this.renderMenu(this.openMenu);
@@ -2264,7 +2517,7 @@ var Nt = class {
2264
2517
  }
2265
2518
  }
2266
2519
  setIcon(e, t) {
2267
- e.innerHTML = Z(t);
2520
+ e.innerHTML = Q(t);
2268
2521
  }
2269
2522
  destroy() {
2270
2523
  this.hideTimer && clearTimeout(this.hideTimer);
@@ -2281,41 +2534,41 @@ var Nt = class {
2281
2534
  this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
2282
2535
  }
2283
2536
  };
2284
- function Pt(e) {
2537
+ function Jt(e) {
2285
2538
  (!Number.isFinite(e) || e < 0) && (e = 0);
2286
2539
  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");
2287
2540
  return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
2288
2541
  }
2289
- function Ft(e) {
2542
+ function Yt(e) {
2290
2543
  return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
2291
2544
  }
2292
- function It(e) {
2545
+ function Xt(e) {
2293
2546
  return e.name || e.lang || `Track ${e.id}`;
2294
2547
  }
2295
- function Lt(e) {
2548
+ function Zt(e) {
2296
2549
  return e.name || e.lang || `Track ${e.id}`;
2297
2550
  }
2298
2551
  //#endregion
2299
2552
  //#region src/managed/index.ts
2300
- var Rt = 6e3, Q = 45e3, zt = 2e3, Bt = 3, Vt = 2e3, Ht = 48e4;
2301
- function Ut(e) {
2553
+ var Qt = 6e3, $t = 45e3, en = 2e3, tn = 3, nn = 2e3, rn = 48e4;
2554
+ function an(e) {
2302
2555
  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)})`);
2303
- if (e.env !== void 0) return I(e.env);
2556
+ if (e.env !== void 0) return L(e.env);
2304
2557
  if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
2305
2558
  return e.baseUrl;
2306
2559
  }
2307
- async function Wt(e) {
2560
+ async function on(e) {
2308
2561
  if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
2309
- let t = Ut(e);
2562
+ let t = an(e);
2310
2563
  if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
2311
2564
  if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
2312
- let r = new Gt({
2565
+ let r = new sn({
2313
2566
  ...e,
2314
2567
  baseUrl: t
2315
2568
  });
2316
2569
  return await r.start(), r;
2317
2570
  }
2318
- var Gt = class {
2571
+ var sn = class {
2319
2572
  opts;
2320
2573
  abort = new AbortController();
2321
2574
  listeners = {};
@@ -2403,7 +2656,7 @@ var Gt = class {
2403
2656
  setTimeout(() => {
2404
2657
  a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
2405
2658
  phase: i ? "unavailable" : "tooEarly",
2406
- retryInMs: Q,
2659
+ retryInMs: $t,
2407
2660
  attempt: 1,
2408
2661
  elapsedMs: 0,
2409
2662
  ...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
@@ -2442,13 +2695,13 @@ var Gt = class {
2442
2695
  !a && !p() && h();
2443
2696
  }, e);
2444
2697
  };
2445
- _(Rt), this.armingSub = E({
2698
+ _(Qt), this.armingSub = E({
2446
2699
  eventsBaseUrl: t,
2447
2700
  matchUrn: this.opts.matchUrn,
2448
2701
  credential: this.opts.credential,
2449
- onAlive: () => _(Q),
2702
+ onAlive: () => _($t),
2450
2703
  onState: (e) => {
2451
- a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * zt);
2704
+ a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * en);
2452
2705
  },
2453
2706
  onError: () => h()
2454
2707
  });
@@ -2471,7 +2724,7 @@ var Gt = class {
2471
2724
  let n = await s(this.opts.credential);
2472
2725
  if (this.destroyed || t !== this.loadGen) return;
2473
2726
  this.setState("loading");
2474
- let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Fe(this.opts.video, (e) => {
2727
+ let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Re(this.opts.video, (e) => {
2475
2728
  this._state !== "ended" && this._state !== "error" && this.setState(e);
2476
2729
  });
2477
2730
  if (await i.load(), this.destroyed || t !== this.loadGen) {
@@ -2493,23 +2746,23 @@ var Gt = class {
2493
2746
  if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
2494
2747
  let i = e.analytics?.sid;
2495
2748
  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);
2749
+ let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = At(this.opts.baseUrl, a);
2497
2750
  if (!o) {
2498
2751
  s && setTimeout(() => {
2499
2752
  this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
2500
2753
  }, 0);
2501
2754
  return;
2502
2755
  }
2503
- let c = this.opts.video, l = new gt({
2756
+ let c = this.opts.video, l = new jt({
2504
2757
  endpoint: o,
2505
2758
  sid: i,
2506
2759
  player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
2507
- sdkVersion: St,
2508
- environment: bt(c),
2760
+ sdkVersion: Lt,
2761
+ environment: Ft(c),
2509
2762
  idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
2510
2763
  onIdle: () => this.onAnalyticsIdle(t),
2511
2764
  sample: () => {
2512
- let e = this.engine?.getStats() ?? L, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
2765
+ let e = this.engine?.getStats() ?? R, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
2513
2766
  return {
2514
2767
  ...e,
2515
2768
  bufferedMs: Math.round(t * 1e3),
@@ -2523,7 +2776,7 @@ var Gt = class {
2523
2776
  let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
2524
2777
  c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
2525
2778
  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");
2779
+ }, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), It().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
2527
2780
  }
2528
2781
  currentPresentation() {
2529
2782
  let e = this.opts.video;
@@ -2542,20 +2795,30 @@ var Gt = class {
2542
2795
  userId: this.opts.userId,
2543
2796
  lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
2544
2797
  snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
2798
+ mediaDuringKey: this.opts.mediaDuringKey,
2545
2799
  debug: this.opts.debug,
2546
2800
  deferLoad: r,
2547
2801
  hlsConfig: i,
2548
2802
  emit: (e) => this.onEngineEvent(e)
2549
2803
  }, o = this.opts.engine ?? "auto";
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);
2804
+ if (o === "native") return new U(a);
2805
+ if (o === "hls") return new J(a);
2806
+ if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && V(this.opts.video) && H()) return new U(a);
2807
+ if (Je()) return new J(a);
2808
+ if (V(this.opts.video)) return new U(a);
2555
2809
  throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
2556
2810
  }
2557
2811
  onEngineEvent(e) {
2558
2812
  if (!this.destroyed) switch (e.type) {
2813
+ case "firstPlaylist":
2814
+ this.analyticsSession?.noteFirstPlaylist();
2815
+ break;
2816
+ case "firstBytes":
2817
+ this.analyticsSession?.noteFirstBytes();
2818
+ break;
2819
+ case "drmReady":
2820
+ this.analyticsSession?.noteDrmReady();
2821
+ break;
2559
2822
  case "ready":
2560
2823
  this.analyticsSession?.noteReady(), this.emit("ready"), (this.opts.autoplay !== !1 || this.playRequested) && this.play();
2561
2824
  break;
@@ -2594,7 +2857,7 @@ var Gt = class {
2594
2857
  r = 0, i = !1;
2595
2858
  },
2596
2859
  onError: () => {
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.`))));
2860
+ this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= tn && (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.`))));
2598
2861
  }
2599
2862
  });
2600
2863
  }
@@ -2616,7 +2879,7 @@ var Gt = class {
2616
2879
  scheduleRejoin(e) {
2617
2880
  this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
2618
2881
  this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
2619
- }, Math.random() * zt));
2882
+ }, Math.random() * en));
2620
2883
  }
2621
2884
  cancelRejoin() {
2622
2885
  this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
@@ -2640,7 +2903,7 @@ var Gt = class {
2640
2903
  }
2641
2904
  t.controls = !1;
2642
2905
  let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
2643
- r && r.insertBefore(n, t), n.appendChild(t), Tt(n, this.opts.theme), this.container = n, this.controlBar = Mt({
2906
+ r && r.insertBefore(n, t), n.appendChild(t), Z(n, this.opts.theme), this.container = n, this.controlBar = Kt({
2644
2907
  root: n,
2645
2908
  video: t,
2646
2909
  player: this,
@@ -2670,7 +2933,7 @@ var Gt = class {
2670
2933
  }
2671
2934
  startStats() {
2672
2935
  this.stopStats();
2673
- let e = Math.max(500, this.opts.statsIntervalMs ?? Vt);
2936
+ let e = Math.max(500, this.opts.statsIntervalMs ?? nn);
2674
2937
  this.statsTimer = setInterval(() => {
2675
2938
  if (!this.engine) return;
2676
2939
  let e = this.engine.getStats();
@@ -2682,7 +2945,7 @@ var Gt = class {
2682
2945
  }
2683
2946
  scheduleLicenseRefresh() {
2684
2947
  this.stopRefresh();
2685
- let e = this.opts.licenseRefreshMs ?? Ht;
2948
+ let e = this.opts.licenseRefreshMs ?? rn;
2686
2949
  e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
2687
2950
  }
2688
2951
  stopRefresh() {
@@ -2727,7 +2990,7 @@ var Gt = class {
2727
2990
  this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
2728
2991
  }
2729
2992
  getStats() {
2730
- return this.engine?.getStats() ?? L;
2993
+ return this.engine?.getStats() ?? R;
2731
2994
  }
2732
2995
  getQualityLevels() {
2733
2996
  return this.engine?.getQualityLevels() ?? [];
@@ -2837,7 +3100,7 @@ function $(e) {
2837
3100
  }
2838
3101
  //#endregion
2839
3102
  //#region src/embed/host.ts
2840
- function Kt(e) {
3103
+ function cn(e) {
2841
3104
  if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
2842
3105
  if (!e.src) throw Error("mountEmbed: opts.src is required");
2843
3106
  if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
@@ -2896,15 +3159,15 @@ function Kt(e) {
2896
3159
  }
2897
3160
  //#endregion
2898
3161
  //#region src/embed/page.ts
2899
- var qt = /^[A-Za-z0-9:_.-]{1,128}$/;
2900
- function Jt(e) {
3162
+ var ln = /^[A-Za-z0-9:_.-]{1,128}$/;
3163
+ function un(e) {
2901
3164
  if (typeof e == "boolean") return e;
2902
3165
  if (typeof e == "object" && e) {
2903
3166
  let t = e.endpoint;
2904
3167
  return typeof t == "string" ? { endpoint: t } : {};
2905
3168
  }
2906
3169
  }
2907
- function Yt() {
3170
+ function dn() {
2908
3171
  let e = window.HAVIK_EMBED_CONFIG;
2909
3172
  if (e) return {
2910
3173
  baseUrl: e.baseUrl ?? "",
@@ -2914,7 +3177,7 @@ function Yt() {
2914
3177
  autoplay: e.autoplay ?? !0,
2915
3178
  muted: e.muted ?? !0,
2916
3179
  waitForLive: e.waitForLive ?? !0,
2917
- analytics: Jt(e.analytics)
3180
+ analytics: un(e.analytics)
2918
3181
  };
2919
3182
  let t = new URLSearchParams(location.search);
2920
3183
  return {
@@ -2927,9 +3190,9 @@ function Yt() {
2927
3190
  waitForLive: !0
2928
3191
  };
2929
3192
  }
2930
- async function Xt() {
2931
- let e = Yt();
2932
- Qt();
3193
+ async function fn() {
3194
+ let e = dn();
3195
+ mn();
2933
3196
  let t = document.createElement("video");
2934
3197
  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);
2935
3198
  let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
@@ -2984,12 +3247,12 @@ async function Xt() {
2984
3247
  code: e.code,
2985
3248
  message: e.message
2986
3249
  })), e.on("autoplayblocked", () => {
2987
- i({ type: "oddin:autoplayblocked" }), Zt(t, e);
3250
+ i({ type: "oddin:autoplayblocked" }), pn(t, e);
2988
3251
  });
2989
3252
  }, s = async (r) => {
2990
3253
  a?.destroy(), a = null;
2991
3254
  try {
2992
- let n = await Wt({
3255
+ let n = await on({
2993
3256
  video: t,
2994
3257
  baseUrl: e.baseUrl,
2995
3258
  matchUrn: r,
@@ -3051,7 +3314,7 @@ async function Xt() {
3051
3314
  a?.retry();
3052
3315
  break;
3053
3316
  case "oddin:load":
3054
- typeof e.matchUrn == "string" && qt.test(e.matchUrn) && s(e.matchUrn);
3317
+ typeof e.matchUrn == "string" && ln.test(e.matchUrn) && s(e.matchUrn);
3055
3318
  break;
3056
3319
  case "oddin:destroy": c();
3057
3320
  }
@@ -3063,18 +3326,18 @@ async function Xt() {
3063
3326
  protocol: 1
3064
3327
  });
3065
3328
  }
3066
- function Zt(e, t) {
3329
+ function pn(e, t) {
3067
3330
  if (document.getElementById("havik-tap")) return;
3068
3331
  let n = document.createElement("button");
3069
3332
  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", () => {
3070
3333
  n.remove(), t.play();
3071
3334
  }), document.body.appendChild(n);
3072
3335
  }
3073
- function Qt() {
3336
+ function mn() {
3074
3337
  let e = document.createElement("style");
3075
3338
  e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
3076
3339
  }
3077
3340
  //#endregion
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 };
3341
+ export { Rt as ODDIN_THEME, n as PlaybackError, Z as applyTheme, L as baseUrlForEnv, fn as bootEmbed, be as clearDeviceId, on as createPlayer, D as deriveEventsBaseUrl, Ne as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, pe as fetchCatalog, he as fetchTournament, _e as flattenMatches, A as getDeviceId, Fe as isLowLatencyManifest, $ as isOddinMessage, Se as licenseRequestHeaders, cn as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, ve as watchStatus };
3079
3342
 
3080
3343
  //# sourceMappingURL=index.js.map