@oddin-gg/havik-player 2.9.1 → 2.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/havik-player.global.js +18 -18
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +210 -204
- package/dist/index.js.map +1 -1
- package/docs/API.md +7 -0
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -43,9 +43,12 @@ async function s(e) {
|
|
|
43
43
|
if (!t || !t.apiKey) throw Error("havik-player: credential is missing an apiKey");
|
|
44
44
|
return t;
|
|
45
45
|
}
|
|
46
|
+
function c(e) {
|
|
47
|
+
return e === "live" || e === "ended" || e === "upcoming" ? e : "upcoming";
|
|
48
|
+
}
|
|
46
49
|
//#endregion
|
|
47
50
|
//#region src/core/http.ts
|
|
48
|
-
function
|
|
51
|
+
function l(e, t) {
|
|
49
52
|
let r = e.replace(/\/+$/, ""), i;
|
|
50
53
|
try {
|
|
51
54
|
i = new URL(r + t);
|
|
@@ -55,14 +58,14 @@ function c(e, t) {
|
|
|
55
58
|
if (i.protocol !== "https:" && i.protocol !== "http:") throw new n("INTERNAL", 0, `baseUrl must be http(s), got: ${JSON.stringify(e)}`);
|
|
56
59
|
return i.toString();
|
|
57
60
|
}
|
|
58
|
-
function
|
|
61
|
+
function u(e) {
|
|
59
62
|
if (!e) return;
|
|
60
63
|
let t = Number(e);
|
|
61
64
|
if (Number.isFinite(t)) return Math.max(0, Math.round(t * 1e3));
|
|
62
65
|
let n = Date.parse(e);
|
|
63
66
|
if (!Number.isNaN(n)) return Math.max(0, n - Date.now());
|
|
64
67
|
}
|
|
65
|
-
async function
|
|
68
|
+
async function d(e, t) {
|
|
66
69
|
let r = await s(t.credential), i = t.headers ?? new Headers();
|
|
67
70
|
if (t.apiHeaders) for (let [e, n] of Object.entries(t.apiHeaders)) i.has(e) || i.set(e, n);
|
|
68
71
|
i.set("x-api-key", r.apiKey);
|
|
@@ -77,49 +80,49 @@ async function u(e, t) {
|
|
|
77
80
|
mode: "cors"
|
|
78
81
|
});
|
|
79
82
|
} catch (e) {
|
|
80
|
-
throw t.signal?.aborted ? new n("ABORTED", 0, "request aborted", { cause: e }) : new n("NETWORK", 0, `network request failed: ${
|
|
83
|
+
throw t.signal?.aborted ? new n("ABORTED", 0, "request aborted", { cause: e }) : new n("NETWORK", 0, `network request failed: ${f(e)}`, { cause: e });
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
|
-
function
|
|
86
|
+
function f(e) {
|
|
84
87
|
return e instanceof Error ? e.message : String(e);
|
|
85
88
|
}
|
|
86
89
|
//#endregion
|
|
87
90
|
//#region src/core/waitForLive.ts
|
|
88
|
-
var
|
|
91
|
+
var p = 1e3, m = 3e4, h = 6e5, g = 3e5, _ = 1e3, ee = {
|
|
89
92
|
TOO_EARLY: "tooEarly",
|
|
90
93
|
UNAVAILABLE: "unavailable",
|
|
91
94
|
RATE_LIMITED: "rateLimited",
|
|
92
95
|
NETWORK: "network"
|
|
93
96
|
};
|
|
94
|
-
function
|
|
95
|
-
let t = e === !0 || e === !1 ? {} : e, n = Math.max(
|
|
97
|
+
function te(e) {
|
|
98
|
+
let t = e === !0 || e === !1 ? {} : e, n = Math.max(_, t.floorMs ?? p), r = Math.max(n, t.ceilMs ?? m), i = Math.max(0, t.imminentMs ?? h), a = Math.max(r, t.sanityFloorMs ?? g);
|
|
96
99
|
return {
|
|
97
100
|
timeoutMs: t.timeoutMs,
|
|
98
101
|
floorMs: n,
|
|
99
102
|
ceilMs: r,
|
|
100
103
|
imminentMs: i,
|
|
101
104
|
sanityFloorMs: a,
|
|
102
|
-
kickoffMs:
|
|
105
|
+
kickoffMs: ne(t.kickoffAt),
|
|
103
106
|
jitter: t.jitter ?? !0,
|
|
104
107
|
onState: t.onState
|
|
105
108
|
};
|
|
106
109
|
}
|
|
107
|
-
function
|
|
110
|
+
function ne(e) {
|
|
108
111
|
if (e == null) return;
|
|
109
112
|
if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
|
|
110
113
|
let t = Date.parse(e);
|
|
111
114
|
return Number.isFinite(t) ? t : void 0;
|
|
112
115
|
}
|
|
113
|
-
function
|
|
116
|
+
function re(e, t, n) {
|
|
114
117
|
return Math.min(n, Math.max(t, e));
|
|
115
118
|
}
|
|
116
|
-
function
|
|
119
|
+
function ie(e) {
|
|
117
120
|
return Math.round(e * (1 + .15 * Math.random()));
|
|
118
121
|
}
|
|
119
|
-
function
|
|
122
|
+
function ae(e, t, n, r) {
|
|
120
123
|
let i = r ?? n.kickoffMs, a = i == null ? void 0 : Math.max(0, i - t), o = Math.max(n.floorMs, e ?? 0);
|
|
121
124
|
if (a == null || a <= n.imminentMs) return {
|
|
122
|
-
delay:
|
|
125
|
+
delay: re(e ?? n.floorMs, o, n.ceilMs),
|
|
123
126
|
ttkMs: a
|
|
124
127
|
};
|
|
125
128
|
let s = Math.min(Math.floor(a / 10), n.sanityFloorMs, a);
|
|
@@ -128,7 +131,7 @@ function ie(e, t, n, r) {
|
|
|
128
131
|
ttkMs: a
|
|
129
132
|
};
|
|
130
133
|
}
|
|
131
|
-
function
|
|
134
|
+
function oe(e, t) {
|
|
132
135
|
return new Promise((r, i) => {
|
|
133
136
|
if (t?.aborted) {
|
|
134
137
|
i(new n("ABORTED", 0, "wait-for-live aborted"));
|
|
@@ -143,7 +146,7 @@ function ae(e, t) {
|
|
|
143
146
|
});
|
|
144
147
|
}
|
|
145
148
|
async function v(e, t, r) {
|
|
146
|
-
let i =
|
|
149
|
+
let i = te(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
|
|
147
150
|
for (;;) {
|
|
148
151
|
if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
|
|
149
152
|
try {
|
|
@@ -151,18 +154,18 @@ async function v(e, t, r) {
|
|
|
151
154
|
} catch (e) {
|
|
152
155
|
if (!(e instanceof n) || !o(e.code)) throw e;
|
|
153
156
|
c += 1, e.liveStartsAtMs != null && Number.isFinite(e.liveStartsAtMs) && (l = e.liveStartsAtMs);
|
|
154
|
-
let t = Date.now(), u =
|
|
155
|
-
if (i.jitter && (f =
|
|
157
|
+
let t = Date.now(), u = ae(e.retryAfterMs, t, i, l), d = u.ttkMs, f = u.delay;
|
|
158
|
+
if (i.jitter && (f = ie(f)), t + f > s) throw new n("TIMEOUT", e.httpStatus, `timed out after ${i.timeoutMs}ms waiting for the stream to go live`, {
|
|
156
159
|
retryAfterMs: e.retryAfterMs,
|
|
157
160
|
cause: e
|
|
158
161
|
});
|
|
159
162
|
i.onState?.({
|
|
160
|
-
phase:
|
|
163
|
+
phase: ee[e.code] ?? "unavailable",
|
|
161
164
|
retryInMs: f,
|
|
162
165
|
attempt: c,
|
|
163
166
|
elapsedMs: t - a,
|
|
164
167
|
ttkMs: d
|
|
165
|
-
}), await
|
|
168
|
+
}), await oe(f, r);
|
|
166
169
|
}
|
|
167
170
|
}
|
|
168
171
|
}
|
|
@@ -170,20 +173,20 @@ async function v(e, t, r) {
|
|
|
170
173
|
//#region src/core/resolve.ts
|
|
171
174
|
async function y(e) {
|
|
172
175
|
if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
|
|
173
|
-
let t = await
|
|
176
|
+
let t = await d(l(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
|
|
174
177
|
credential: e.credential,
|
|
175
178
|
signal: e.signal,
|
|
176
179
|
apiHeaders: e.apiHeaders
|
|
177
180
|
});
|
|
178
|
-
if (!t.ok) throw await
|
|
179
|
-
return
|
|
181
|
+
if (!t.ok) throw await se(t);
|
|
182
|
+
return le(await t.json(), e.matchUrn);
|
|
180
183
|
}
|
|
181
184
|
function b(e) {
|
|
182
185
|
let t = () => y(e);
|
|
183
186
|
return e.waitForLive ? v(t, e.waitForLive, e.signal) : t();
|
|
184
187
|
}
|
|
185
|
-
async function
|
|
186
|
-
let t =
|
|
188
|
+
async function se(e) {
|
|
189
|
+
let t = u(e.headers.get("retry-after")), i = e.headers.get("x-request-id") ?? e.headers.get("x-amzn-requestid") ?? void 0, a = e.statusText || `HTTP ${e.status}`, o, s;
|
|
187
190
|
try {
|
|
188
191
|
let t = await e.json();
|
|
189
192
|
if (t?.error?.message && (a = t.error.message), t?.error?.code && (o = t.error.code), typeof t?.liveStartsAt == "string") {
|
|
@@ -198,7 +201,7 @@ async function oe(e) {
|
|
|
198
201
|
liveStartsAtMs: s
|
|
199
202
|
});
|
|
200
203
|
}
|
|
201
|
-
var
|
|
204
|
+
var ce = /* @__PURE__ */ new Set([
|
|
202
205
|
"matchUrn",
|
|
203
206
|
"protocol",
|
|
204
207
|
"drmEnabled",
|
|
@@ -219,7 +222,7 @@ function x(e, t) {
|
|
|
219
222
|
if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
|
|
220
223
|
return t;
|
|
221
224
|
}
|
|
222
|
-
function
|
|
225
|
+
function le(e, t) {
|
|
223
226
|
if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
|
|
224
227
|
let r = e.drmEnabled ?? !!e.drm, i = {
|
|
225
228
|
matchUrn: e.matchUrn ?? t,
|
|
@@ -236,7 +239,7 @@ function ce(e, t) {
|
|
|
236
239
|
}), (t.widevine || t.fairplay) && (i.drm = t);
|
|
237
240
|
}
|
|
238
241
|
let a = {};
|
|
239
|
-
for (let [t, n] of Object.entries(e))
|
|
242
|
+
for (let [t, n] of Object.entries(e)) ce.has(t) || (a[t] = n);
|
|
240
243
|
return Object.keys(a).length > 0 && (i.extensions = a), i;
|
|
241
244
|
}
|
|
242
245
|
//#endregion
|
|
@@ -244,11 +247,11 @@ function ce(e, t) {
|
|
|
244
247
|
function S(e) {
|
|
245
248
|
return e.ownerDocument ?? document;
|
|
246
249
|
}
|
|
247
|
-
function
|
|
250
|
+
function ue(e) {
|
|
248
251
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
249
252
|
}
|
|
250
253
|
function C(e, t) {
|
|
251
|
-
let n =
|
|
254
|
+
let n = ue(S(e));
|
|
252
255
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
253
256
|
}
|
|
254
257
|
async function w(e, t) {
|
|
@@ -264,17 +267,17 @@ async function T(e, t) {
|
|
|
264
267
|
n.webkitExitFullscreen?.();
|
|
265
268
|
return;
|
|
266
269
|
}
|
|
267
|
-
let r = S(e), i =
|
|
270
|
+
let r = S(e), i = ue(r);
|
|
268
271
|
i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
|
|
269
272
|
}
|
|
270
273
|
//#endregion
|
|
271
274
|
//#region src/core/catalog.ts
|
|
272
|
-
async function
|
|
275
|
+
async function de(e) {
|
|
273
276
|
let t = new URLSearchParams();
|
|
274
277
|
e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
|
|
275
|
-
let i = t.toString(), a =
|
|
278
|
+
let i = t.toString(), a = l(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
|
|
276
279
|
e.etag && o.set("If-None-Match", e.etag);
|
|
277
|
-
let s = await
|
|
280
|
+
let s = await d(a, {
|
|
278
281
|
credential: e.credential,
|
|
279
282
|
signal: e.signal,
|
|
280
283
|
headers: o,
|
|
@@ -287,12 +290,12 @@ async function ue(e) {
|
|
|
287
290
|
};
|
|
288
291
|
if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
|
|
289
292
|
return {
|
|
290
|
-
tournaments:
|
|
293
|
+
tournaments: fe(await s.json()),
|
|
291
294
|
etag: s.headers.get("etag") ?? void 0,
|
|
292
295
|
notModified: !1
|
|
293
296
|
};
|
|
294
297
|
}
|
|
295
|
-
function
|
|
298
|
+
function fe(e) {
|
|
296
299
|
return (e.tournaments ?? []).map((e) => {
|
|
297
300
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
298
301
|
return {
|
|
@@ -303,7 +306,8 @@ function de(e) {
|
|
|
303
306
|
matches: (e.matches ?? []).map((e) => ({
|
|
304
307
|
matchUrn: e.matchUrn ?? "",
|
|
305
308
|
matchName: e.matchName ?? "",
|
|
306
|
-
status: e.status
|
|
309
|
+
status: c(e.status),
|
|
310
|
+
statusRaw: e.status,
|
|
307
311
|
datePlannedStart: e.datePlannedStart,
|
|
308
312
|
tournamentUrn: t,
|
|
309
313
|
tournamentName: n,
|
|
@@ -312,10 +316,10 @@ function de(e) {
|
|
|
312
316
|
};
|
|
313
317
|
});
|
|
314
318
|
}
|
|
315
|
-
async function
|
|
316
|
-
let t =
|
|
319
|
+
async function pe(e) {
|
|
320
|
+
let t = l(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
317
321
|
e.etag && i.set("If-None-Match", e.etag);
|
|
318
|
-
let a = await
|
|
322
|
+
let a = await d(t, {
|
|
319
323
|
credential: e.credential,
|
|
320
324
|
signal: e.signal,
|
|
321
325
|
headers: i,
|
|
@@ -332,13 +336,13 @@ async function fe(e) {
|
|
|
332
336
|
};
|
|
333
337
|
if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
334
338
|
return {
|
|
335
|
-
tournament:
|
|
339
|
+
tournament: me(await a.json()),
|
|
336
340
|
etag: a.headers.get("etag") ?? void 0,
|
|
337
341
|
notModified: !1,
|
|
338
342
|
notFound: !1
|
|
339
343
|
};
|
|
340
344
|
}
|
|
341
|
-
function
|
|
345
|
+
function me(e) {
|
|
342
346
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
343
347
|
return {
|
|
344
348
|
urn: t,
|
|
@@ -348,7 +352,8 @@ function pe(e) {
|
|
|
348
352
|
matches: (e.matches ?? []).map((e) => ({
|
|
349
353
|
matchUrn: e.matchUrn ?? "",
|
|
350
354
|
matchName: e.matchName ?? "",
|
|
351
|
-
status: e.status
|
|
355
|
+
status: c(e.status),
|
|
356
|
+
statusRaw: e.status,
|
|
352
357
|
datePlannedStart: e.datePlannedStart,
|
|
353
358
|
tournamentUrn: t,
|
|
354
359
|
tournamentName: n,
|
|
@@ -356,50 +361,51 @@ function pe(e) {
|
|
|
356
361
|
}))
|
|
357
362
|
};
|
|
358
363
|
}
|
|
359
|
-
function
|
|
364
|
+
function he(e) {
|
|
360
365
|
return e.tournaments.flatMap((e) => e.matches);
|
|
361
366
|
}
|
|
362
367
|
//#endregion
|
|
363
368
|
//#region src/core/poll.ts
|
|
364
|
-
function
|
|
365
|
-
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s,
|
|
366
|
-
|
|
367
|
-
},
|
|
369
|
+
function ge(e) {
|
|
370
|
+
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
|
|
371
|
+
u || (a = setTimeout(p, t));
|
|
372
|
+
}, p = async () => {
|
|
368
373
|
try {
|
|
369
|
-
let t =
|
|
374
|
+
let t = l(e.baseUrl, `/v1/matches/${encodeURIComponent(e.matchUrn)}`), a = new Headers();
|
|
370
375
|
o && a.set("If-None-Match", o);
|
|
371
|
-
let
|
|
376
|
+
let u = await d(t, {
|
|
372
377
|
credential: e.credential,
|
|
373
378
|
signal: i.signal,
|
|
374
379
|
headers: a,
|
|
375
380
|
apiHeaders: e.apiHeaders
|
|
376
381
|
});
|
|
377
|
-
if (
|
|
378
|
-
if (!
|
|
379
|
-
o =
|
|
380
|
-
let t = await
|
|
381
|
-
|
|
382
|
+
if (u.status !== 304) {
|
|
383
|
+
if (!u.ok) throw new n(r(u.status), u.status, `match status request failed (HTTP ${u.status})`);
|
|
384
|
+
o = u.headers.get("etag") ?? o;
|
|
385
|
+
let t = await u.json(), i = c(t.status), a = typeof t.status == "string" ? t.status : i;
|
|
386
|
+
a !== s && (s = a, e.onChange({
|
|
382
387
|
matchUrn: t.matchUrn ?? e.matchUrn,
|
|
383
388
|
matchName: t.matchName,
|
|
384
389
|
status: i,
|
|
390
|
+
statusRaw: t.status,
|
|
385
391
|
datePlannedStart: t.datePlannedStart
|
|
386
392
|
}));
|
|
387
393
|
}
|
|
388
394
|
} catch (t) {
|
|
389
395
|
i.signal.aborted || e.onError?.(t instanceof n ? t : new n("NETWORK", 0, String(t)));
|
|
390
396
|
} finally {
|
|
391
|
-
|
|
397
|
+
f();
|
|
392
398
|
}
|
|
393
399
|
};
|
|
394
|
-
return
|
|
395
|
-
|
|
400
|
+
return p(), { stop() {
|
|
401
|
+
u = !0, i.abort(), a && clearTimeout(a);
|
|
396
402
|
} };
|
|
397
403
|
}
|
|
398
404
|
//#endregion
|
|
399
405
|
//#region src/core/events.ts
|
|
400
|
-
var
|
|
406
|
+
var _e = 45e3;
|
|
401
407
|
function E(e) {
|
|
402
|
-
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ??
|
|
408
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? _e, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
|
|
403
409
|
if (a.signal.aborted) return t();
|
|
404
410
|
let n = setTimeout(t, e);
|
|
405
411
|
a.signal.addEventListener("abort", () => {
|
|
@@ -448,11 +454,11 @@ function E(e) {
|
|
|
448
454
|
try {
|
|
449
455
|
let n = await s(e.credential);
|
|
450
456
|
if (o) return;
|
|
451
|
-
let a =
|
|
457
|
+
let a = l(e.eventsBaseUrl, `/v1/events/${encodeURIComponent(e.matchUrn)}`);
|
|
452
458
|
i && (m = setTimeout(() => {
|
|
453
459
|
p = `no response headers within ${i}ms`, u.abort();
|
|
454
460
|
}, i));
|
|
455
|
-
let
|
|
461
|
+
let c = await fetch(a, {
|
|
456
462
|
method: "GET",
|
|
457
463
|
headers: {
|
|
458
464
|
"x-api-key": n.apiKey,
|
|
@@ -464,7 +470,7 @@ function E(e) {
|
|
|
464
470
|
mode: "cors"
|
|
465
471
|
});
|
|
466
472
|
if (clearTimeout(m), o) return;
|
|
467
|
-
!
|
|
473
|
+
!c.ok || !c.body ? e.onError?.(/* @__PURE__ */ Error(`live-state subscribe failed: HTTP ${c.status}`)) : await f(c.body, () => {
|
|
468
474
|
r = t;
|
|
469
475
|
}, h);
|
|
470
476
|
} catch (t) {
|
|
@@ -474,7 +480,7 @@ function E(e) {
|
|
|
474
480
|
clearTimeout(m), a.signal.removeEventListener("abort", d), u.abort();
|
|
475
481
|
}
|
|
476
482
|
if (o) return;
|
|
477
|
-
p && e.onError?.(/* @__PURE__ */ Error(`live-state subscribe idle: ${p} — reconnecting`)), await
|
|
483
|
+
p && e.onError?.(/* @__PURE__ */ Error(`live-state subscribe idle: ${p} — reconnecting`)), await c(r), r = Math.min(n, r * 2);
|
|
478
484
|
}
|
|
479
485
|
})(), { close() {
|
|
480
486
|
o || (o = !0, a.abort());
|
|
@@ -497,20 +503,20 @@ function A() {
|
|
|
497
503
|
let e = globalThis.localStorage?.getItem(O);
|
|
498
504
|
if (e) return k = e, e;
|
|
499
505
|
} catch {}
|
|
500
|
-
let e =
|
|
506
|
+
let e = ye();
|
|
501
507
|
k = e;
|
|
502
508
|
try {
|
|
503
509
|
globalThis.localStorage?.setItem(O, e);
|
|
504
510
|
} catch {}
|
|
505
511
|
return e;
|
|
506
512
|
}
|
|
507
|
-
function
|
|
513
|
+
function ve() {
|
|
508
514
|
k = void 0;
|
|
509
515
|
try {
|
|
510
516
|
globalThis.localStorage?.removeItem(O);
|
|
511
517
|
} catch {}
|
|
512
518
|
}
|
|
513
|
-
function
|
|
519
|
+
function ye() {
|
|
514
520
|
let e = globalThis.crypto;
|
|
515
521
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
516
522
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -522,7 +528,7 @@ function ve() {
|
|
|
522
528
|
}
|
|
523
529
|
//#endregion
|
|
524
530
|
//#region src/core/drm/headers.ts
|
|
525
|
-
function
|
|
531
|
+
function be(e, t, n = {}) {
|
|
526
532
|
let r = {
|
|
527
533
|
"x-api-key": t.apiKey,
|
|
528
534
|
"X-Match-Urn": e.matchUrn,
|
|
@@ -534,7 +540,7 @@ function ye(e, t, n = {}) {
|
|
|
534
540
|
//#endregion
|
|
535
541
|
//#region src/core/drm/cdm.ts
|
|
536
542
|
var j = /* @__PURE__ */ new WeakMap();
|
|
537
|
-
function
|
|
543
|
+
function xe(e, t) {
|
|
538
544
|
let n = j.get(e);
|
|
539
545
|
n || (n = /* @__PURE__ */ new Map(), j.set(e, n));
|
|
540
546
|
let r = n.get(t.keySystem);
|
|
@@ -548,11 +554,11 @@ function M() {
|
|
|
548
554
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
549
555
|
}
|
|
550
556
|
var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
551
|
-
function
|
|
557
|
+
function Se(e) {
|
|
552
558
|
return e.startsWith("com.widevine");
|
|
553
559
|
}
|
|
554
|
-
function
|
|
555
|
-
if (!
|
|
560
|
+
function Ce(e, t) {
|
|
561
|
+
if (!Se(e)) return t;
|
|
556
562
|
let n = (e, t) => {
|
|
557
563
|
let n = e.videoCapabilities;
|
|
558
564
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
@@ -568,20 +574,20 @@ function Se(e, t) {
|
|
|
568
574
|
})));
|
|
569
575
|
return [...t, ...r];
|
|
570
576
|
}
|
|
571
|
-
function
|
|
572
|
-
return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t,
|
|
577
|
+
function we(e) {
|
|
578
|
+
return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, Ce(t, n)).then((t) => ({
|
|
573
579
|
keySystem: t.keySystem,
|
|
574
580
|
getConfiguration: () => t.getConfiguration(),
|
|
575
|
-
createMediaKeys: () =>
|
|
581
|
+
createMediaKeys: () => xe(e, t)
|
|
576
582
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
577
583
|
}
|
|
578
584
|
//#endregion
|
|
579
585
|
//#region src/core/drm/support.ts
|
|
580
|
-
var
|
|
586
|
+
var Te = 5e3, Ee = "video/mp4; codecs=\"avc1.42E01E\"", De = "audio/mp4; codecs=\"mp4a.40.2\"", Oe = {
|
|
581
587
|
widevine: ["com.widevine.alpha"],
|
|
582
588
|
fairplay: ["com.apple.fps"]
|
|
583
589
|
};
|
|
584
|
-
function
|
|
590
|
+
function ke(e) {
|
|
585
591
|
return e === "fairplay" ? [{
|
|
586
592
|
initDataTypes: [
|
|
587
593
|
"sinf",
|
|
@@ -589,24 +595,24 @@ function Oe(e) {
|
|
|
589
595
|
"cenc"
|
|
590
596
|
],
|
|
591
597
|
videoCapabilities: [{
|
|
592
|
-
contentType:
|
|
598
|
+
contentType: Ee,
|
|
593
599
|
robustness: "",
|
|
594
600
|
encryptionScheme: "cbcs"
|
|
595
601
|
}],
|
|
596
602
|
audioCapabilities: [{
|
|
597
|
-
contentType:
|
|
603
|
+
contentType: De,
|
|
598
604
|
robustness: "",
|
|
599
605
|
encryptionScheme: "cbcs"
|
|
600
606
|
}]
|
|
601
|
-
}] :
|
|
607
|
+
}] : Ce("com.widevine.alpha", [{
|
|
602
608
|
initDataTypes: ["cenc"],
|
|
603
609
|
videoCapabilities: [{
|
|
604
|
-
contentType:
|
|
610
|
+
contentType: Ee,
|
|
605
611
|
robustness: "SW_SECURE_DECODE",
|
|
606
612
|
encryptionScheme: "cbcs"
|
|
607
613
|
}],
|
|
608
614
|
audioCapabilities: [{
|
|
609
|
-
contentType:
|
|
615
|
+
contentType: De,
|
|
610
616
|
robustness: "SW_SECURE_CRYPTO",
|
|
611
617
|
encryptionScheme: "cbcs"
|
|
612
618
|
}]
|
|
@@ -622,8 +628,8 @@ function P(e, t) {
|
|
|
622
628
|
});
|
|
623
629
|
});
|
|
624
630
|
}
|
|
625
|
-
async function
|
|
626
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
631
|
+
async function Ae(e = {}) {
|
|
632
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Te, r = {};
|
|
627
633
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
628
634
|
verdict: "insecure-context",
|
|
629
635
|
detail: r
|
|
@@ -635,7 +641,7 @@ async function ke(e = {}) {
|
|
|
635
641
|
};
|
|
636
642
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
637
643
|
for (let e of t) {
|
|
638
|
-
let t =
|
|
644
|
+
let t = Oe[e];
|
|
639
645
|
if (!t) {
|
|
640
646
|
r[e] = "unknown system";
|
|
641
647
|
continue;
|
|
@@ -646,7 +652,7 @@ async function ke(e = {}) {
|
|
|
646
652
|
break;
|
|
647
653
|
}
|
|
648
654
|
try {
|
|
649
|
-
return await P((await P(i(n,
|
|
655
|
+
return await P((await P(i(n, ke(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
650
656
|
verdict: "supported",
|
|
651
657
|
system: e,
|
|
652
658
|
detail: r
|
|
@@ -670,9 +676,9 @@ async function ke(e = {}) {
|
|
|
670
676
|
}
|
|
671
677
|
//#endregion
|
|
672
678
|
//#region src/core/manifest.ts
|
|
673
|
-
var
|
|
674
|
-
function
|
|
675
|
-
return
|
|
679
|
+
var je = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
680
|
+
function Me(e) {
|
|
681
|
+
return je.test(e);
|
|
676
682
|
}
|
|
677
683
|
//#endregion
|
|
678
684
|
//#region src/core/env.ts
|
|
@@ -695,11 +701,11 @@ function R(e) {
|
|
|
695
701
|
return "";
|
|
696
702
|
}
|
|
697
703
|
}
|
|
698
|
-
var
|
|
699
|
-
function
|
|
704
|
+
var Ne = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
705
|
+
function Pe(e) {
|
|
700
706
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
701
707
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
702
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
708
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Ne.test(i.name)) && i.startTime >= n) {
|
|
703
709
|
let e = R(i.name);
|
|
704
710
|
e && (t = e, n = i.startTime);
|
|
705
711
|
}
|
|
@@ -712,7 +718,7 @@ function z(e) {
|
|
|
712
718
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
713
719
|
};
|
|
714
720
|
}
|
|
715
|
-
function
|
|
721
|
+
function Fe(e, t) {
|
|
716
722
|
let n = [
|
|
717
723
|
["playing", () => t("playing")],
|
|
718
724
|
["waiting", () => t("buffering")],
|
|
@@ -729,7 +735,7 @@ function Pe(e, t) {
|
|
|
729
735
|
}
|
|
730
736
|
//#endregion
|
|
731
737
|
//#region src/core/engine/native.ts
|
|
732
|
-
function
|
|
738
|
+
function Ie(e) {
|
|
733
739
|
try {
|
|
734
740
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
735
741
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -781,7 +787,7 @@ var H = class {
|
|
|
781
787
|
type: "error",
|
|
782
788
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
783
789
|
fatal: !0
|
|
784
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
790
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Le(t.manifestUrl, t.analytics?.sid), e.load();
|
|
785
791
|
}
|
|
786
792
|
startLoad() {
|
|
787
793
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -803,7 +809,7 @@ var H = class {
|
|
|
803
809
|
});
|
|
804
810
|
this.onEncrypted = (n) => {
|
|
805
811
|
let i = n;
|
|
806
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
812
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Ie(i.initData), (async () => {
|
|
807
813
|
try {
|
|
808
814
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
809
815
|
initDataTypes: [i.initDataType],
|
|
@@ -902,7 +908,7 @@ var H = class {
|
|
|
902
908
|
droppedFrames: t.dropped,
|
|
903
909
|
decodedFrames: t.totalFrames
|
|
904
910
|
};
|
|
905
|
-
return this.cdnHost ||=
|
|
911
|
+
return this.cdnHost ||= Pe(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity && (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)), n;
|
|
906
912
|
}
|
|
907
913
|
stop() {
|
|
908
914
|
try {
|
|
@@ -921,25 +927,25 @@ var H = class {
|
|
|
921
927
|
} catch {}
|
|
922
928
|
}
|
|
923
929
|
};
|
|
924
|
-
function
|
|
930
|
+
function Le(e, t) {
|
|
925
931
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
926
932
|
}
|
|
927
933
|
//#endregion
|
|
928
934
|
//#region src/core/engine/hls.ts
|
|
929
|
-
function
|
|
935
|
+
function Re() {
|
|
930
936
|
return e.isSupported();
|
|
931
937
|
}
|
|
932
|
-
var
|
|
933
|
-
function
|
|
938
|
+
var ze = 3, Be = 5, Ve = 3, He = 3e4, Ue = 12e3, We = 3e3, U = 6e3, Ge = 5e3, Ke = 4e3, qe = 2, Je = 5, Ye = 2, Xe = 2, Ze = 2e3, Qe = 3e4, $e = 2, et = 9, tt = .5, nt = 64;
|
|
939
|
+
function rt(e) {
|
|
934
940
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
935
941
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
936
942
|
return;
|
|
937
943
|
}
|
|
938
|
-
e.liveSyncDuration ??=
|
|
939
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
940
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
944
|
+
e.liveSyncDuration ??= $e;
|
|
945
|
+
let t = Math.max(12, e.liveSyncDuration + et);
|
|
946
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), it(e, e.liveSyncDuration);
|
|
941
947
|
}
|
|
942
|
-
function
|
|
948
|
+
function it(e, t) {
|
|
943
949
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
944
950
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
945
951
|
}
|
|
@@ -1034,7 +1040,7 @@ var W = class {
|
|
|
1034
1040
|
}
|
|
1035
1041
|
this.loadSuspended = !0;
|
|
1036
1042
|
}
|
|
1037
|
-
},
|
|
1043
|
+
}, Ge));
|
|
1038
1044
|
}
|
|
1039
1045
|
resumeLoading() {
|
|
1040
1046
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1066,7 +1072,7 @@ var W = class {
|
|
|
1066
1072
|
let t = e.liveSyncPosition;
|
|
1067
1073
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1068
1074
|
let { video: n } = this.deps;
|
|
1069
|
-
n.currentTime <= t +
|
|
1075
|
+
n.currentTime <= t + tt || (n.currentTime = t);
|
|
1070
1076
|
}
|
|
1071
1077
|
startHls() {
|
|
1072
1078
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1090,7 +1096,7 @@ var W = class {
|
|
|
1090
1096
|
videoEncryptionScheme: "cbcs",
|
|
1091
1097
|
audioEncryptionScheme: "cbcs"
|
|
1092
1098
|
},
|
|
1093
|
-
...M() ? { requestMediaKeySystemAccessFunc:
|
|
1099
|
+
...M() ? { requestMediaKeySystemAccessFunc: we(t) } : {},
|
|
1094
1100
|
licenseXhrSetup: (e, t) => {
|
|
1095
1101
|
e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a), this.licenseRequested = !0;
|
|
1096
1102
|
let o = performance.now();
|
|
@@ -1106,7 +1112,7 @@ var W = class {
|
|
|
1106
1112
|
} } : {},
|
|
1107
1113
|
...c
|
|
1108
1114
|
};
|
|
1109
|
-
|
|
1115
|
+
rt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
|
|
1110
1116
|
let f = new e(d);
|
|
1111
1117
|
this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1112
1118
|
this.mediaRecoveries = 0, this.networkRecoveries = 0;
|
|
@@ -1115,14 +1121,14 @@ var W = class {
|
|
|
1115
1121
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1116
1122
|
t?.frag?.type === "main" && (this.kickPending = !1, this.kickTicks = 0, (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
1117
1123
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1118
|
-
},
|
|
1124
|
+
}, He)));
|
|
1119
1125
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1120
1126
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1121
1127
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
1122
1128
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1123
1129
|
typeof r == "number" && (this.bytesLoaded += r);
|
|
1124
1130
|
let i = n?.loading;
|
|
1125
|
-
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length >
|
|
1131
|
+
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > nt && this.requestTimesMs.shift());
|
|
1126
1132
|
let a = t?.frag?.url;
|
|
1127
1133
|
if (a) {
|
|
1128
1134
|
let e = R(a);
|
|
@@ -1138,7 +1144,7 @@ var W = class {
|
|
|
1138
1144
|
}));
|
|
1139
1145
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1140
1146
|
this.checkEndStale(), this.checkStarvation();
|
|
1141
|
-
},
|
|
1147
|
+
}, We), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1142
1148
|
this.renditionSwitches += 1;
|
|
1143
1149
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1144
1150
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1202,7 +1208,7 @@ var W = class {
|
|
|
1202
1208
|
return;
|
|
1203
1209
|
}
|
|
1204
1210
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1205
|
-
let t = e > this.sizeCapLevel ?
|
|
1211
|
+
let t = e > this.sizeCapLevel ? Ze : Qe;
|
|
1206
1212
|
this.capTimer = setTimeout(() => {
|
|
1207
1213
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1208
1214
|
}, t);
|
|
@@ -1295,7 +1301,7 @@ var W = class {
|
|
|
1295
1301
|
return;
|
|
1296
1302
|
}
|
|
1297
1303
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1298
|
-
!this.chaseSuspended && e > U && this.suspendChasing(), e >
|
|
1304
|
+
!this.chaseSuspended && e > U && this.suspendChasing(), e > Ue && this.emitEnded("stalled");
|
|
1299
1305
|
}
|
|
1300
1306
|
checkStarvation() {
|
|
1301
1307
|
let e = this.hls, { video: t } = this.deps;
|
|
@@ -1304,17 +1310,17 @@ var W = class {
|
|
|
1304
1310
|
this.starvedTicks = 0;
|
|
1305
1311
|
return;
|
|
1306
1312
|
}
|
|
1307
|
-
let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < U, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs >
|
|
1313
|
+
let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < U, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > Ke;
|
|
1308
1314
|
if (!(t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused && n && r)) {
|
|
1309
1315
|
this.starvedTicks = 0;
|
|
1310
1316
|
return;
|
|
1311
1317
|
}
|
|
1312
|
-
if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks <
|
|
1313
|
-
if (this.starvedTicks = 0, this.kickPending && this.kickTicks >=
|
|
1318
|
+
if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks < qe)) {
|
|
1319
|
+
if (this.starvedTicks = 0, this.kickPending && this.kickTicks >= Ye && (this.kickPending = !1, this.kickTicks = 0, this.starvationRebuilds < Xe)) {
|
|
1314
1320
|
this.starvationRebuilds += 1, console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
|
|
1315
1321
|
return;
|
|
1316
1322
|
}
|
|
1317
|
-
if (!(this.starvationKicks >=
|
|
1323
|
+
if (!(this.starvationKicks >= Je)) {
|
|
1318
1324
|
this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, console.warn("havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
|
|
1319
1325
|
try {
|
|
1320
1326
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1364,7 +1370,7 @@ var W = class {
|
|
|
1364
1370
|
scheduleLicenseRetry(t) {
|
|
1365
1371
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1366
1372
|
let n = t.response?.code ?? 0;
|
|
1367
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1373
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Ve) return !1;
|
|
1368
1374
|
this.licenseRecoveries += 1;
|
|
1369
1375
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1370
1376
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1396,7 +1402,7 @@ var W = class {
|
|
|
1396
1402
|
return;
|
|
1397
1403
|
}
|
|
1398
1404
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1399
|
-
if (this.networkRecoveries <
|
|
1405
|
+
if (this.networkRecoveries < Be) {
|
|
1400
1406
|
this.networkRecoveries += 1;
|
|
1401
1407
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1402
1408
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1413,7 +1419,7 @@ var W = class {
|
|
|
1413
1419
|
return;
|
|
1414
1420
|
}
|
|
1415
1421
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1416
|
-
if (this.mediaRecoveries <
|
|
1422
|
+
if (this.mediaRecoveries < ze) {
|
|
1417
1423
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1418
1424
|
return;
|
|
1419
1425
|
}
|
|
@@ -1437,11 +1443,11 @@ var W = class {
|
|
|
1437
1443
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1438
1444
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1439
1445
|
}
|
|
1440
|
-
},
|
|
1446
|
+
}, at = 15e3, ot = 6e5, st = 3e5, ct = 100, G = 1, lt = 1e3, K = 3e4, ut = 1e3, dt = {
|
|
1441
1447
|
inline: "PRESENTATION_INLINE",
|
|
1442
1448
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1443
1449
|
pip: "PRESENTATION_PIP"
|
|
1444
|
-
},
|
|
1450
|
+
}, ft = {
|
|
1445
1451
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1446
1452
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1447
1453
|
none: "KEY_SYSTEM_NONE"
|
|
@@ -1449,7 +1455,7 @@ var W = class {
|
|
|
1449
1455
|
function q(e, t) {
|
|
1450
1456
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1451
1457
|
}
|
|
1452
|
-
var
|
|
1458
|
+
var pt = /* @__PURE__ */ new Set([
|
|
1453
1459
|
"INVALID_URN",
|
|
1454
1460
|
"NOT_FOUND",
|
|
1455
1461
|
"GONE",
|
|
@@ -1469,7 +1475,7 @@ var ft = /* @__PURE__ */ new Set([
|
|
|
1469
1475
|
ended: "PLAYER_STATE_ENDED",
|
|
1470
1476
|
error: "PLAYER_STATE_ERROR"
|
|
1471
1477
|
};
|
|
1472
|
-
function
|
|
1478
|
+
function mt(e) {
|
|
1473
1479
|
try {
|
|
1474
1480
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1475
1481
|
return !n || r.length === 0 || n !== "feed" && !n.startsWith("feed-") ? void 0 : (t.hostname = [n.replace(/^feed/, "beacons"), ...r].join("."), t.pathname = "", t.search = "", t.origin);
|
|
@@ -1481,10 +1487,10 @@ var Y = /* @__PURE__ */ new Set();
|
|
|
1481
1487
|
function X(e, t) {
|
|
1482
1488
|
return Y.has(e) || (Y.add(e), console.warn(`havik-player: ${t}`)), { disabledReason: t };
|
|
1483
1489
|
}
|
|
1484
|
-
function
|
|
1490
|
+
function ht(e, t) {
|
|
1485
1491
|
if (t) return { endpoint: t };
|
|
1486
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).");
|
|
1487
|
-
let n =
|
|
1493
|
+
let n = mt(e);
|
|
1488
1494
|
if (n) return { endpoint: n };
|
|
1489
1495
|
let r;
|
|
1490
1496
|
try {
|
|
@@ -1494,7 +1500,7 @@ function mt(e, t) {
|
|
|
1494
1500
|
}
|
|
1495
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).`);
|
|
1496
1502
|
}
|
|
1497
|
-
var
|
|
1503
|
+
var gt = class {
|
|
1498
1504
|
opts;
|
|
1499
1505
|
url;
|
|
1500
1506
|
now;
|
|
@@ -1572,8 +1578,8 @@ var ht = class {
|
|
|
1572
1578
|
constructor(e) {
|
|
1573
1579
|
this.opts = {
|
|
1574
1580
|
...e,
|
|
1575
|
-
heartbeatMs: e.heartbeatMs ??
|
|
1576
|
-
idleMs: e.idleMs ??
|
|
1581
|
+
heartbeatMs: e.heartbeatMs ?? at,
|
|
1582
|
+
idleMs: e.idleMs ?? ot
|
|
1577
1583
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs, this.startupAnchorMs = this.bornMs;
|
|
1578
1584
|
}
|
|
1579
1585
|
start() {
|
|
@@ -1583,11 +1589,11 @@ var ht = class {
|
|
|
1583
1589
|
sdkVersion: this.opts.sdkVersion,
|
|
1584
1590
|
...this.opts.environment
|
|
1585
1591
|
};
|
|
1586
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
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());
|
|
1587
1593
|
}
|
|
1588
1594
|
checkSuspension(e) {
|
|
1589
1595
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
1590
|
-
let t = Math.max(this.opts.idleMs,
|
|
1596
|
+
let t = Math.max(this.opts.idleMs, st);
|
|
1591
1597
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
1592
1598
|
}
|
|
1593
1599
|
syncIdle(e) {
|
|
@@ -1610,12 +1616,12 @@ var ht = class {
|
|
|
1610
1616
|
let a = {
|
|
1611
1617
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1612
1618
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1613
|
-
presentation:
|
|
1619
|
+
presentation: dt[this.presentation]
|
|
1614
1620
|
}, o = this.causeOf(e, t, i);
|
|
1615
1621
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
1616
1622
|
}
|
|
1617
1623
|
seekInduced(e) {
|
|
1618
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
1624
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < ut;
|
|
1619
1625
|
}
|
|
1620
1626
|
causeOf(e, t, n) {
|
|
1621
1627
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -1683,7 +1689,7 @@ var ht = class {
|
|
|
1683
1689
|
let r = n ?? "";
|
|
1684
1690
|
if (r !== "") return /^fragLoad/i.test(r) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /^(manifest|level|audioTrack|subtitleTrack)/i.test(r) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(r) ? "ERROR_STAGE_DRM" : /parsing|append|buffer|remux|decrypt|media/i.test(r) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
|
|
1685
1691
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
1686
|
-
if (
|
|
1692
|
+
if (pt.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
1687
1693
|
let i = t ?? "";
|
|
1688
1694
|
return /frag|segment/i.test(i) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /manifest|level|playlist/i.test(i) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(i) ? "ERROR_STAGE_DRM" : /buffer|decode|media|append/i.test(i) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
|
|
1689
1695
|
}
|
|
@@ -1737,7 +1743,7 @@ var ht = class {
|
|
|
1737
1743
|
maybeEmitMediaInfo(e) {
|
|
1738
1744
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
1739
1745
|
let t = {};
|
|
1740
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
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);
|
|
1741
1747
|
let n = JSON.stringify(t);
|
|
1742
1748
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
1743
1749
|
}
|
|
@@ -1777,7 +1783,7 @@ var ht = class {
|
|
|
1777
1783
|
};
|
|
1778
1784
|
}
|
|
1779
1785
|
enqueue(e) {
|
|
1780
|
-
for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
1786
|
+
for (this.pending.push(this.wrap(e)); this.pending.length > ct;) {
|
|
1781
1787
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
1782
1788
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
1783
1789
|
}
|
|
@@ -1800,7 +1806,7 @@ var ht = class {
|
|
|
1800
1806
|
};
|
|
1801
1807
|
//#endregion
|
|
1802
1808
|
//#region src/core/environment.ts
|
|
1803
|
-
function
|
|
1809
|
+
function _t() {
|
|
1804
1810
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
1805
1811
|
let e;
|
|
1806
1812
|
try {
|
|
@@ -1825,14 +1831,14 @@ function gt() {
|
|
|
1825
1831
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
1826
1832
|
};
|
|
1827
1833
|
}
|
|
1828
|
-
function
|
|
1834
|
+
function vt() {
|
|
1829
1835
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
1830
1836
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
1831
1837
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
1832
1838
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
1833
1839
|
return e?.mobile ?? (typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1 && n > 0 && n < 900) ? n >= 600 ? "DEVICE_CLASS_TABLET" : "DEVICE_CLASS_PHONE" : e || n >= 900 || /mac|win|linux|chrome os/i.test(t) ? "DEVICE_CLASS_DESKTOP" : "DEVICE_CLASS_OTHER";
|
|
1834
1840
|
}
|
|
1835
|
-
function
|
|
1841
|
+
function yt() {
|
|
1836
1842
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
1837
1843
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
1838
1844
|
let t = {
|
|
@@ -1851,17 +1857,17 @@ function vt() {
|
|
|
1851
1857
|
}
|
|
1852
1858
|
return typeof e.downlink == "number" && e.downlink > 0 && (i.downlinkKbps = Math.round(e.downlink * 1e3)), typeof e.rtt == "number" && e.rtt > 0 && (i.rttMs = Math.round(e.rtt)), e.saveData && (i.saveData = !0), i;
|
|
1853
1859
|
}
|
|
1854
|
-
function
|
|
1855
|
-
let t =
|
|
1856
|
-
deviceClass:
|
|
1860
|
+
function bt(e) {
|
|
1861
|
+
let t = _t(), n = {
|
|
1862
|
+
deviceClass: vt(),
|
|
1857
1863
|
integration: t.integration,
|
|
1858
|
-
...
|
|
1864
|
+
...yt()
|
|
1859
1865
|
};
|
|
1860
1866
|
t.host && (n.host = t.host), typeof screen < "u" && screen.width > 0 && (n.screenWidth = screen.width, n.screenHeight = screen.height), typeof window < "u" && window.devicePixelRatio > 0 && (n.devicePixelRatio = Math.round(window.devicePixelRatio * 100) / 100);
|
|
1861
1867
|
let r = e.getBoundingClientRect?.();
|
|
1862
1868
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
1863
1869
|
}
|
|
1864
|
-
async function
|
|
1870
|
+
async function xt() {
|
|
1865
1871
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
1866
1872
|
if (!e?.getHighEntropyValues) return {};
|
|
1867
1873
|
try {
|
|
@@ -1873,7 +1879,7 @@ async function bt() {
|
|
|
1873
1879
|
}
|
|
1874
1880
|
//#endregion
|
|
1875
1881
|
//#region src/core/version.ts
|
|
1876
|
-
var
|
|
1882
|
+
var St = "2.9.2", Ct = {
|
|
1877
1883
|
accent: "#E1B600",
|
|
1878
1884
|
accentText: "#1B1C23",
|
|
1879
1885
|
background: "#0e0f13",
|
|
@@ -1884,7 +1890,7 @@ var xt = "2.9.1", St = {
|
|
|
1884
1890
|
border: "rgba(255, 255, 255, 0.1)",
|
|
1885
1891
|
radius: "8px",
|
|
1886
1892
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
1887
|
-
},
|
|
1893
|
+
}, wt = {
|
|
1888
1894
|
accent: "--havik-accent",
|
|
1889
1895
|
accentText: "--havik-accent-text",
|
|
1890
1896
|
background: "--havik-bg",
|
|
@@ -1896,25 +1902,25 @@ var xt = "2.9.1", St = {
|
|
|
1896
1902
|
radius: "--havik-radius",
|
|
1897
1903
|
fontFamily: "--havik-font"
|
|
1898
1904
|
};
|
|
1899
|
-
function
|
|
1905
|
+
function Tt(e, t) {
|
|
1900
1906
|
let n = {
|
|
1901
|
-
...
|
|
1907
|
+
...Ct,
|
|
1902
1908
|
...t
|
|
1903
1909
|
};
|
|
1904
|
-
for (let t of Object.keys(
|
|
1910
|
+
for (let t of Object.keys(wt)) e.style.setProperty(wt[t], n[t]);
|
|
1905
1911
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
1906
1912
|
}
|
|
1907
1913
|
//#endregion
|
|
1908
1914
|
//#region src/ui/styles.ts
|
|
1909
|
-
var
|
|
1910
|
-
function
|
|
1911
|
-
if (e.getElementById(
|
|
1915
|
+
var Et = "havik-player-styles", Dt = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n.havik-spinner{width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
|
|
1916
|
+
function Ot(e = document) {
|
|
1917
|
+
if (e.getElementById(Et)) return;
|
|
1912
1918
|
let t = e.createElement("style");
|
|
1913
|
-
t.id =
|
|
1919
|
+
t.id = Et, t.textContent = Dt, e.head.appendChild(t);
|
|
1914
1920
|
}
|
|
1915
1921
|
//#endregion
|
|
1916
1922
|
//#region src/ui/icons.ts
|
|
1917
|
-
var
|
|
1923
|
+
var kt = {
|
|
1918
1924
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
1919
1925
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
1920
1926
|
volumeHigh: "<path d=\"M3 10v4h4l5 5V5L7 10H3zm13.5 2a4.5 4.5 0 0 0-2.5-4v8a4.5 4.5 0 0 0 2.5-4zm-2.5-9v2.06A7 7 0 0 1 14 19v2a9 9 0 0 0 0-18z\"/>",
|
|
@@ -1928,20 +1934,20 @@ var Ot = {
|
|
|
1928
1934
|
retry: "<path d=\"M17.65 6.35A8 8 0 1 0 19.73 13h-2.08A6 6 0 1 1 12 6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"/>"
|
|
1929
1935
|
};
|
|
1930
1936
|
function Z(e) {
|
|
1931
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
1937
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${kt[e]}</svg>`;
|
|
1932
1938
|
}
|
|
1933
1939
|
//#endregion
|
|
1934
1940
|
//#region src/ui/controls.ts
|
|
1935
|
-
var
|
|
1941
|
+
var At = 3e3, jt = /* @__PURE__ */ new Set([
|
|
1936
1942
|
"GONE",
|
|
1937
1943
|
"NOT_FOUND",
|
|
1938
1944
|
"INVALID_URN",
|
|
1939
1945
|
"UNAUTHORIZED"
|
|
1940
1946
|
]);
|
|
1941
|
-
function
|
|
1942
|
-
return new
|
|
1947
|
+
function Mt(e) {
|
|
1948
|
+
return new Nt(e);
|
|
1943
1949
|
}
|
|
1944
|
-
var
|
|
1950
|
+
var Nt = class {
|
|
1945
1951
|
root;
|
|
1946
1952
|
video;
|
|
1947
1953
|
player;
|
|
@@ -1983,7 +1989,7 @@ var Mt = class {
|
|
|
1983
1989
|
scrubbing = !1;
|
|
1984
1990
|
offFns = [];
|
|
1985
1991
|
constructor(e) {
|
|
1986
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
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");
|
|
1987
1993
|
let t = (e, t, n) => {
|
|
1988
1994
|
let r = this.doc.createElement(e);
|
|
1989
1995
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2074,7 +2080,7 @@ var Mt = class {
|
|
|
2074
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);
|
|
2075
2081
|
} else {
|
|
2076
2082
|
let r = this.doc.createElement("div");
|
|
2077
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2083
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !jt.has(this.lastError.code)) {
|
|
2078
2084
|
let e = this.doc.createElement("button");
|
|
2079
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);
|
|
2080
2086
|
}
|
|
@@ -2115,7 +2121,7 @@ var Mt = class {
|
|
|
2115
2121
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2116
2122
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2117
2123
|
}
|
|
2118
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2124
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Pt(this.video.currentTime)} / ${Pt(this.video.duration)}`);
|
|
2119
2125
|
}
|
|
2120
2126
|
syncLive() {
|
|
2121
2127
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2165,17 +2171,17 @@ var Mt = class {
|
|
|
2165
2171
|
renderQualityMenu() {
|
|
2166
2172
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2167
2173
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2168
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2174
|
+
for (let n of e) this.menu.append(this.menuItem(Ft(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2169
2175
|
}
|
|
2170
2176
|
renderAudioMenu() {
|
|
2171
2177
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2172
2178
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2173
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2179
|
+
for (let t of e) this.menu.append(this.menuItem(It(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2174
2180
|
}
|
|
2175
2181
|
renderCcMenu() {
|
|
2176
2182
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2177
2183
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2178
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2184
|
+
for (let t of e) this.menu.append(this.menuItem(Lt(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2179
2185
|
}
|
|
2180
2186
|
onTracksChanged() {
|
|
2181
2187
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2275,41 +2281,41 @@ var Mt = class {
|
|
|
2275
2281
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2276
2282
|
}
|
|
2277
2283
|
};
|
|
2278
|
-
function
|
|
2284
|
+
function Pt(e) {
|
|
2279
2285
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2280
2286
|
let t = Math.floor(e % 60), n = Math.floor(e / 60 % 60), r = Math.floor(e / 3600), i = r > 0 ? String(n).padStart(2, "0") : String(n), a = String(t).padStart(2, "0");
|
|
2281
2287
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2282
2288
|
}
|
|
2283
|
-
function
|
|
2289
|
+
function Ft(e) {
|
|
2284
2290
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2285
2291
|
}
|
|
2286
|
-
function
|
|
2292
|
+
function It(e) {
|
|
2287
2293
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2288
2294
|
}
|
|
2289
|
-
function
|
|
2295
|
+
function Lt(e) {
|
|
2290
2296
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2291
2297
|
}
|
|
2292
2298
|
//#endregion
|
|
2293
2299
|
//#region src/managed/index.ts
|
|
2294
|
-
var
|
|
2295
|
-
function
|
|
2300
|
+
var Rt = 6e3, Q = 45e3, zt = 2e3, Bt = 3, Vt = 2e3, Ht = 48e4;
|
|
2301
|
+
function Ut(e) {
|
|
2296
2302
|
if (e.env !== void 0 && e.baseUrl !== void 0) throw new n("INTERNAL", 0, `createPlayer: pass env OR baseUrl, not both (got env=${JSON.stringify(e.env)} and baseUrl=${JSON.stringify(e.baseUrl)})`);
|
|
2297
2303
|
if (e.env !== void 0) return I(e.env);
|
|
2298
2304
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2299
2305
|
return e.baseUrl;
|
|
2300
2306
|
}
|
|
2301
|
-
async function
|
|
2307
|
+
async function Wt(e) {
|
|
2302
2308
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2303
|
-
let t =
|
|
2309
|
+
let t = Ut(e);
|
|
2304
2310
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2305
2311
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2306
|
-
let r = new
|
|
2312
|
+
let r = new Gt({
|
|
2307
2313
|
...e,
|
|
2308
2314
|
baseUrl: t
|
|
2309
2315
|
});
|
|
2310
2316
|
return await r.start(), r;
|
|
2311
2317
|
}
|
|
2312
|
-
var
|
|
2318
|
+
var Gt = class {
|
|
2313
2319
|
opts;
|
|
2314
2320
|
abort = new AbortController();
|
|
2315
2321
|
listeners = {};
|
|
@@ -2436,13 +2442,13 @@ var Wt = class {
|
|
|
2436
2442
|
!a && !p() && h();
|
|
2437
2443
|
}, e);
|
|
2438
2444
|
};
|
|
2439
|
-
_(
|
|
2445
|
+
_(Rt), this.armingSub = E({
|
|
2440
2446
|
eventsBaseUrl: t,
|
|
2441
2447
|
matchUrn: this.opts.matchUrn,
|
|
2442
2448
|
credential: this.opts.credential,
|
|
2443
2449
|
onAlive: () => _(Q),
|
|
2444
2450
|
onState: (e) => {
|
|
2445
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
2451
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * zt);
|
|
2446
2452
|
},
|
|
2447
2453
|
onError: () => h()
|
|
2448
2454
|
});
|
|
@@ -2465,7 +2471,7 @@ var Wt = class {
|
|
|
2465
2471
|
let n = await s(this.opts.credential);
|
|
2466
2472
|
if (this.destroyed || t !== this.loadGen) return;
|
|
2467
2473
|
this.setState("loading");
|
|
2468
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
2474
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Fe(this.opts.video, (e) => {
|
|
2469
2475
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
2470
2476
|
});
|
|
2471
2477
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -2487,19 +2493,19 @@ var Wt = class {
|
|
|
2487
2493
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
2488
2494
|
let i = e.analytics?.sid;
|
|
2489
2495
|
if (!i) return;
|
|
2490
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
2496
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = ht(this.opts.baseUrl, a);
|
|
2491
2497
|
if (!o) {
|
|
2492
2498
|
s && setTimeout(() => {
|
|
2493
2499
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
2494
2500
|
}, 0);
|
|
2495
2501
|
return;
|
|
2496
2502
|
}
|
|
2497
|
-
let c = this.opts.video, l = new
|
|
2503
|
+
let c = this.opts.video, l = new gt({
|
|
2498
2504
|
endpoint: o,
|
|
2499
2505
|
sid: i,
|
|
2500
2506
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
2501
|
-
sdkVersion:
|
|
2502
|
-
environment:
|
|
2507
|
+
sdkVersion: St,
|
|
2508
|
+
environment: bt(c),
|
|
2503
2509
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
2504
2510
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
2505
2511
|
sample: () => {
|
|
@@ -2517,7 +2523,7 @@ var Wt = class {
|
|
|
2517
2523
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
2518
2524
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
2519
2525
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
2520
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
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");
|
|
2521
2527
|
}
|
|
2522
2528
|
currentPresentation() {
|
|
2523
2529
|
let e = this.opts.video;
|
|
@@ -2544,7 +2550,7 @@ var Wt = class {
|
|
|
2544
2550
|
if (o === "native") return new H(a);
|
|
2545
2551
|
if (o === "hls") return new W(a);
|
|
2546
2552
|
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && B(this.opts.video) && V()) return new H(a);
|
|
2547
|
-
if (
|
|
2553
|
+
if (Re()) return new W(a);
|
|
2548
2554
|
if (B(this.opts.video)) return new H(a);
|
|
2549
2555
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
2550
2556
|
}
|
|
@@ -2588,7 +2594,7 @@ var Wt = class {
|
|
|
2588
2594
|
r = 0, i = !1;
|
|
2589
2595
|
},
|
|
2590
2596
|
onError: () => {
|
|
2591
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
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.`))));
|
|
2592
2598
|
}
|
|
2593
2599
|
});
|
|
2594
2600
|
}
|
|
@@ -2610,7 +2616,7 @@ var Wt = class {
|
|
|
2610
2616
|
scheduleRejoin(e) {
|
|
2611
2617
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
2612
2618
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
2613
|
-
}, Math.random() *
|
|
2619
|
+
}, Math.random() * zt));
|
|
2614
2620
|
}
|
|
2615
2621
|
cancelRejoin() {
|
|
2616
2622
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -2634,7 +2640,7 @@ var Wt = class {
|
|
|
2634
2640
|
}
|
|
2635
2641
|
t.controls = !1;
|
|
2636
2642
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
2637
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
2643
|
+
r && r.insertBefore(n, t), n.appendChild(t), Tt(n, this.opts.theme), this.container = n, this.controlBar = Mt({
|
|
2638
2644
|
root: n,
|
|
2639
2645
|
video: t,
|
|
2640
2646
|
player: this,
|
|
@@ -2664,7 +2670,7 @@ var Wt = class {
|
|
|
2664
2670
|
}
|
|
2665
2671
|
startStats() {
|
|
2666
2672
|
this.stopStats();
|
|
2667
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
2673
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Vt);
|
|
2668
2674
|
this.statsTimer = setInterval(() => {
|
|
2669
2675
|
if (!this.engine) return;
|
|
2670
2676
|
let e = this.engine.getStats();
|
|
@@ -2676,7 +2682,7 @@ var Wt = class {
|
|
|
2676
2682
|
}
|
|
2677
2683
|
scheduleLicenseRefresh() {
|
|
2678
2684
|
this.stopRefresh();
|
|
2679
|
-
let e = this.opts.licenseRefreshMs ??
|
|
2685
|
+
let e = this.opts.licenseRefreshMs ?? Ht;
|
|
2680
2686
|
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
2681
2687
|
}
|
|
2682
2688
|
stopRefresh() {
|
|
@@ -2831,7 +2837,7 @@ function $(e) {
|
|
|
2831
2837
|
}
|
|
2832
2838
|
//#endregion
|
|
2833
2839
|
//#region src/embed/host.ts
|
|
2834
|
-
function
|
|
2840
|
+
function Kt(e) {
|
|
2835
2841
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
2836
2842
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
2837
2843
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -2890,15 +2896,15 @@ function Gt(e) {
|
|
|
2890
2896
|
}
|
|
2891
2897
|
//#endregion
|
|
2892
2898
|
//#region src/embed/page.ts
|
|
2893
|
-
var
|
|
2894
|
-
function
|
|
2899
|
+
var qt = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
2900
|
+
function Jt(e) {
|
|
2895
2901
|
if (typeof e == "boolean") return e;
|
|
2896
2902
|
if (typeof e == "object" && e) {
|
|
2897
2903
|
let t = e.endpoint;
|
|
2898
2904
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
2899
2905
|
}
|
|
2900
2906
|
}
|
|
2901
|
-
function
|
|
2907
|
+
function Yt() {
|
|
2902
2908
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
2903
2909
|
if (e) return {
|
|
2904
2910
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -2908,7 +2914,7 @@ function Jt() {
|
|
|
2908
2914
|
autoplay: e.autoplay ?? !0,
|
|
2909
2915
|
muted: e.muted ?? !0,
|
|
2910
2916
|
waitForLive: e.waitForLive ?? !0,
|
|
2911
|
-
analytics:
|
|
2917
|
+
analytics: Jt(e.analytics)
|
|
2912
2918
|
};
|
|
2913
2919
|
let t = new URLSearchParams(location.search);
|
|
2914
2920
|
return {
|
|
@@ -2921,9 +2927,9 @@ function Jt() {
|
|
|
2921
2927
|
waitForLive: !0
|
|
2922
2928
|
};
|
|
2923
2929
|
}
|
|
2924
|
-
async function
|
|
2925
|
-
let e =
|
|
2926
|
-
|
|
2930
|
+
async function Xt() {
|
|
2931
|
+
let e = Yt();
|
|
2932
|
+
Qt();
|
|
2927
2933
|
let t = document.createElement("video");
|
|
2928
2934
|
t.setAttribute("playsinline", ""), t.muted = e.muted ?? !0, t.style.cssText = "width:100%;height:100%;object-fit:contain;background:#000;aspect-ratio:auto", document.body.appendChild(t);
|
|
2929
2935
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -2978,12 +2984,12 @@ async function Yt() {
|
|
|
2978
2984
|
code: e.code,
|
|
2979
2985
|
message: e.message
|
|
2980
2986
|
})), e.on("autoplayblocked", () => {
|
|
2981
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
2987
|
+
i({ type: "oddin:autoplayblocked" }), Zt(t, e);
|
|
2982
2988
|
});
|
|
2983
2989
|
}, s = async (r) => {
|
|
2984
2990
|
a?.destroy(), a = null;
|
|
2985
2991
|
try {
|
|
2986
|
-
let n = await
|
|
2992
|
+
let n = await Wt({
|
|
2987
2993
|
video: t,
|
|
2988
2994
|
baseUrl: e.baseUrl,
|
|
2989
2995
|
matchUrn: r,
|
|
@@ -3045,7 +3051,7 @@ async function Yt() {
|
|
|
3045
3051
|
a?.retry();
|
|
3046
3052
|
break;
|
|
3047
3053
|
case "oddin:load":
|
|
3048
|
-
typeof e.matchUrn == "string" &&
|
|
3054
|
+
typeof e.matchUrn == "string" && qt.test(e.matchUrn) && s(e.matchUrn);
|
|
3049
3055
|
break;
|
|
3050
3056
|
case "oddin:destroy": c();
|
|
3051
3057
|
}
|
|
@@ -3057,18 +3063,18 @@ async function Yt() {
|
|
|
3057
3063
|
protocol: 1
|
|
3058
3064
|
});
|
|
3059
3065
|
}
|
|
3060
|
-
function
|
|
3066
|
+
function Zt(e, t) {
|
|
3061
3067
|
if (document.getElementById("havik-tap")) return;
|
|
3062
3068
|
let n = document.createElement("button");
|
|
3063
3069
|
n.id = "havik-tap", n.textContent = "▶ Tap to play", n.style.cssText = "position:fixed;inset:0;width:100%;height:100%;border:0;background:rgba(0,0,0,.55);color:#fff;font:600 18px system-ui,sans-serif;cursor:pointer;z-index:9", n.addEventListener("click", () => {
|
|
3064
3070
|
n.remove(), t.play();
|
|
3065
3071
|
}), document.body.appendChild(n);
|
|
3066
3072
|
}
|
|
3067
|
-
function
|
|
3073
|
+
function Qt() {
|
|
3068
3074
|
let e = document.createElement("style");
|
|
3069
3075
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3070
3076
|
}
|
|
3071
3077
|
//#endregion
|
|
3072
|
-
export {
|
|
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 };
|
|
3073
3079
|
|
|
3074
3080
|
//# sourceMappingURL=index.js.map
|