@oddin-gg/havik-player 2.9.0 → 2.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -0
- 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 +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +288 -260
- package/dist/index.js.map +1 -1
- package/docs/API.md +9 -1
- 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 P(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,30 +595,30 @@ function Te(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
|
}]
|
|
613
619
|
}]);
|
|
614
620
|
}
|
|
615
|
-
function
|
|
621
|
+
function P(e, t) {
|
|
616
622
|
return new Promise((n, r) => {
|
|
617
623
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
618
624
|
e.then((e) => {
|
|
@@ -622,8 +628,8 @@ function L(e, t) {
|
|
|
622
628
|
});
|
|
623
629
|
});
|
|
624
630
|
}
|
|
625
|
-
async function
|
|
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 Ee(e = {}) {
|
|
|
635
641
|
};
|
|
636
642
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
637
643
|
for (let e of t) {
|
|
638
|
-
let t =
|
|
644
|
+
let t = Oe[e];
|
|
639
645
|
if (!t) {
|
|
640
646
|
r[e] = "unknown system";
|
|
641
647
|
continue;
|
|
@@ -646,7 +652,7 @@ async function Ee(e = {}) {
|
|
|
646
652
|
break;
|
|
647
653
|
}
|
|
648
654
|
try {
|
|
649
|
-
return await
|
|
655
|
+
return await P((await P(i(n, ke(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
650
656
|
verdict: "supported",
|
|
651
657
|
system: e,
|
|
652
658
|
detail: r
|
|
@@ -670,49 +676,49 @@ async function Ee(e = {}) {
|
|
|
670
676
|
}
|
|
671
677
|
//#endregion
|
|
672
678
|
//#region src/core/manifest.ts
|
|
673
|
-
var
|
|
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
|
|
679
|
-
var
|
|
685
|
+
var F = {
|
|
680
686
|
integration: "https://feed-dev.oddin-video.gg",
|
|
681
687
|
production: "https://feed.oddin-video.gg"
|
|
682
688
|
};
|
|
683
|
-
function
|
|
684
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
689
|
+
function I(e) {
|
|
690
|
+
let t = Object.prototype.hasOwnProperty.call(F, e) ? F[e] : void 0;
|
|
685
691
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
686
692
|
return t;
|
|
687
693
|
}
|
|
688
694
|
//#endregion
|
|
689
695
|
//#region src/core/stats.ts
|
|
690
|
-
var
|
|
691
|
-
function
|
|
696
|
+
var L = { droppedFrames: 0 };
|
|
697
|
+
function R(e) {
|
|
692
698
|
try {
|
|
693
699
|
return new URL(e).host;
|
|
694
700
|
} catch {
|
|
695
701
|
return "";
|
|
696
702
|
}
|
|
697
703
|
}
|
|
698
|
-
var
|
|
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" ||
|
|
703
|
-
let e =
|
|
708
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Ne.test(i.name)) && i.startTime >= n) {
|
|
709
|
+
let e = R(i.name);
|
|
704
710
|
e && (t = e, n = i.startTime);
|
|
705
711
|
}
|
|
706
712
|
return t;
|
|
707
713
|
}
|
|
708
|
-
function
|
|
714
|
+
function z(e) {
|
|
709
715
|
let t = e.getVideoPlaybackQuality?.();
|
|
710
716
|
return {
|
|
711
717
|
dropped: t?.droppedVideoFrames ?? 0,
|
|
712
718
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
713
719
|
};
|
|
714
720
|
}
|
|
715
|
-
function
|
|
721
|
+
function Fe(e, t) {
|
|
716
722
|
let n = [
|
|
717
723
|
["playing", () => t("playing")],
|
|
718
724
|
["waiting", () => t("buffering")],
|
|
@@ -729,7 +735,7 @@ function je(e, t) {
|
|
|
729
735
|
}
|
|
730
736
|
//#endregion
|
|
731
737
|
//#region src/core/engine/native.ts
|
|
732
|
-
function
|
|
738
|
+
function Ie(e) {
|
|
733
739
|
try {
|
|
734
740
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
735
741
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -737,15 +743,15 @@ function Me(e) {
|
|
|
737
743
|
return;
|
|
738
744
|
}
|
|
739
745
|
}
|
|
740
|
-
function
|
|
746
|
+
function B(e) {
|
|
741
747
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
742
748
|
}
|
|
743
|
-
function
|
|
749
|
+
function V() {
|
|
744
750
|
if (typeof window > "u") return !1;
|
|
745
751
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
746
752
|
return e || t;
|
|
747
753
|
}
|
|
748
|
-
var
|
|
754
|
+
var H = class {
|
|
749
755
|
name = "native";
|
|
750
756
|
deps;
|
|
751
757
|
onLoaded;
|
|
@@ -781,7 +787,7 @@ var G = class {
|
|
|
781
787
|
type: "error",
|
|
782
788
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
783
789
|
fatal: !0
|
|
784
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
790
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Le(t.manifestUrl, t.analytics?.sid), e.load();
|
|
785
791
|
}
|
|
786
792
|
startLoad() {
|
|
787
793
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -803,7 +809,7 @@ var G = class {
|
|
|
803
809
|
});
|
|
804
810
|
this.onEncrypted = (n) => {
|
|
805
811
|
let i = n;
|
|
806
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
812
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Ie(i.initData), (async () => {
|
|
807
813
|
try {
|
|
808
814
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
809
815
|
initDataTypes: [i.initDataType],
|
|
@@ -898,11 +904,11 @@ var G = class {
|
|
|
898
904
|
e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
|
|
899
905
|
}
|
|
900
906
|
getStats() {
|
|
901
|
-
let e = this.deps.video, t =
|
|
907
|
+
let e = this.deps.video, t = z(e), n = {
|
|
902
908
|
droppedFrames: t.dropped,
|
|
903
909
|
decodedFrames: t.totalFrames
|
|
904
910
|
};
|
|
905
|
-
return this.cdnHost ||=
|
|
911
|
+
return this.cdnHost ||= Pe(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity && (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)), n;
|
|
906
912
|
}
|
|
907
913
|
stop() {
|
|
908
914
|
try {
|
|
@@ -921,29 +927,29 @@ var G = class {
|
|
|
921
927
|
} catch {}
|
|
922
928
|
}
|
|
923
929
|
};
|
|
924
|
-
function
|
|
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
|
}
|
|
946
|
-
var
|
|
952
|
+
var W = class {
|
|
947
953
|
name = "hls";
|
|
948
954
|
hls = null;
|
|
949
955
|
deps;
|
|
@@ -1002,7 +1008,7 @@ var q = class {
|
|
|
1002
1008
|
this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1003
1009
|
}
|
|
1004
1010
|
async load() {
|
|
1005
|
-
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a =
|
|
1011
|
+
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = B(r) && V(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
1006
1012
|
if (e.drmEnabled && !o) {
|
|
1007
1013
|
i({
|
|
1008
1014
|
type: "error",
|
|
@@ -1034,7 +1040,7 @@ var q = class {
|
|
|
1034
1040
|
}
|
|
1035
1041
|
this.loadSuspended = !0;
|
|
1036
1042
|
}
|
|
1037
|
-
},
|
|
1043
|
+
}, Ge));
|
|
1038
1044
|
}
|
|
1039
1045
|
resumeLoading() {
|
|
1040
1046
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1066,7 +1072,7 @@ var q = class {
|
|
|
1066
1072
|
let t = e.liveSyncPosition;
|
|
1067
1073
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1068
1074
|
let { video: n } = this.deps;
|
|
1069
|
-
n.currentTime <= t +
|
|
1075
|
+
n.currentTime <= t + tt || (n.currentTime = t);
|
|
1070
1076
|
}
|
|
1071
1077
|
startHls() {
|
|
1072
1078
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1090,7 +1096,7 @@ var q = class {
|
|
|
1090
1096
|
videoEncryptionScheme: "cbcs",
|
|
1091
1097
|
audioEncryptionScheme: "cbcs"
|
|
1092
1098
|
},
|
|
1093
|
-
...M() ? { requestMediaKeySystemAccessFunc:
|
|
1099
|
+
...M() ? { requestMediaKeySystemAccessFunc: we(t) } : {},
|
|
1094
1100
|
licenseXhrSetup: (e, t) => {
|
|
1095
1101
|
e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a), this.licenseRequested = !0;
|
|
1096
1102
|
let o = performance.now();
|
|
@@ -1106,7 +1112,7 @@ var q = class {
|
|
|
1106
1112
|
} } : {},
|
|
1107
1113
|
...c
|
|
1108
1114
|
};
|
|
1109
|
-
|
|
1115
|
+
rt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
|
|
1110
1116
|
let f = new e(d);
|
|
1111
1117
|
this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1112
1118
|
this.mediaRecoveries = 0, this.networkRecoveries = 0;
|
|
@@ -1115,17 +1121,17 @@ var q = class {
|
|
|
1115
1121
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1116
1122
|
t?.frag?.type === "main" && (this.kickPending = !1, this.kickTicks = 0, (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
1117
1123
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1118
|
-
},
|
|
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
|
-
let e =
|
|
1134
|
+
let e = R(a);
|
|
1129
1135
|
e && (this.cdnHost = e);
|
|
1130
1136
|
}
|
|
1131
1137
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1138,7 +1144,7 @@ var q = class {
|
|
|
1138
1144
|
}));
|
|
1139
1145
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1140
1146
|
this.checkEndStale(), this.checkStarvation();
|
|
1141
|
-
},
|
|
1147
|
+
}, We), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1142
1148
|
this.renditionSwitches += 1;
|
|
1143
1149
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1144
1150
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1202,7 +1208,7 @@ var q = class {
|
|
|
1202
1208
|
return;
|
|
1203
1209
|
}
|
|
1204
1210
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1205
|
-
let t = e > this.sizeCapLevel ?
|
|
1211
|
+
let t = e > this.sizeCapLevel ? Ze : Qe;
|
|
1206
1212
|
this.capTimer = setTimeout(() => {
|
|
1207
1213
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1208
1214
|
}, t);
|
|
@@ -1249,7 +1255,7 @@ var q = class {
|
|
|
1249
1255
|
e.widevine && (this.licenseUrl = e.widevine);
|
|
1250
1256
|
}
|
|
1251
1257
|
getStats() {
|
|
1252
|
-
let e = this.hls, t =
|
|
1258
|
+
let e = this.hls, t = z(this.deps.video), n = {
|
|
1253
1259
|
droppedFrames: t.dropped,
|
|
1254
1260
|
decodedFrames: t.totalFrames,
|
|
1255
1261
|
lowLatency: this.detectedLowLatency,
|
|
@@ -1295,7 +1301,7 @@ var q = class {
|
|
|
1295
1301
|
return;
|
|
1296
1302
|
}
|
|
1297
1303
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1298
|
-
!this.chaseSuspended && e >
|
|
1304
|
+
!this.chaseSuspended && e > U && this.suspendChasing(), e > Ue && this.emitEnded("stalled");
|
|
1299
1305
|
}
|
|
1300
1306
|
checkStarvation() {
|
|
1301
1307
|
let e = this.hls, { video: t } = this.deps;
|
|
@@ -1304,17 +1310,17 @@ var q = class {
|
|
|
1304
1310
|
this.starvedTicks = 0;
|
|
1305
1311
|
return;
|
|
1306
1312
|
}
|
|
1307
|
-
let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs <
|
|
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 q = class {
|
|
|
1364
1370
|
scheduleLicenseRetry(t) {
|
|
1365
1371
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1366
1372
|
let n = t.response?.code ?? 0;
|
|
1367
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1373
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Ve) return !1;
|
|
1368
1374
|
this.licenseRecoveries += 1;
|
|
1369
1375
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1370
1376
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1396,7 +1402,7 @@ var q = class {
|
|
|
1396
1402
|
return;
|
|
1397
1403
|
}
|
|
1398
1404
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1399
|
-
if (this.networkRecoveries <
|
|
1405
|
+
if (this.networkRecoveries < Be) {
|
|
1400
1406
|
this.networkRecoveries += 1;
|
|
1401
1407
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1402
1408
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1413,7 +1419,7 @@ var q = class {
|
|
|
1413
1419
|
return;
|
|
1414
1420
|
}
|
|
1415
1421
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1416
|
-
if (this.mediaRecoveries <
|
|
1422
|
+
if (this.mediaRecoveries < ze) {
|
|
1417
1423
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1418
1424
|
return;
|
|
1419
1425
|
}
|
|
@@ -1437,19 +1443,19 @@ var q = class {
|
|
|
1437
1443
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1438
1444
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1439
1445
|
}
|
|
1440
|
-
},
|
|
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"
|
|
1448
1454
|
};
|
|
1449
|
-
function
|
|
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",
|
|
@@ -1459,7 +1465,7 @@ var dt = /* @__PURE__ */ new Set([
|
|
|
1459
1465
|
"FORBIDDEN",
|
|
1460
1466
|
"RATE_LIMITED",
|
|
1461
1467
|
"TIMEOUT"
|
|
1462
|
-
]),
|
|
1468
|
+
]), J = {
|
|
1463
1469
|
idle: "PLAYER_STATE_IDLE",
|
|
1464
1470
|
waiting: "PLAYER_STATE_WAITING",
|
|
1465
1471
|
loading: "PLAYER_STATE_LOADING",
|
|
@@ -1469,7 +1475,7 @@ var dt = /* @__PURE__ */ new Set([
|
|
|
1469
1475
|
ended: "PLAYER_STATE_ENDED",
|
|
1470
1476
|
error: "PLAYER_STATE_ERROR"
|
|
1471
1477
|
};
|
|
1472
|
-
function
|
|
1478
|
+
function mt(e) {
|
|
1473
1479
|
try {
|
|
1474
1480
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1475
1481
|
return !n || r.length === 0 || n !== "feed" && !n.startsWith("feed-") ? void 0 : (t.hostname = [n.replace(/^feed/, "beacons"), ...r].join("."), t.pathname = "", t.search = "", t.origin);
|
|
@@ -1477,7 +1483,24 @@ function ft(e) {
|
|
|
1477
1483
|
return;
|
|
1478
1484
|
}
|
|
1479
1485
|
}
|
|
1480
|
-
var
|
|
1486
|
+
var Y = /* @__PURE__ */ new Set();
|
|
1487
|
+
function X(e, t) {
|
|
1488
|
+
return Y.has(e) || (Y.add(e), console.warn(`havik-player: ${t}`)), { disabledReason: t };
|
|
1489
|
+
}
|
|
1490
|
+
function ht(e, t) {
|
|
1491
|
+
if (t) return { endpoint: t };
|
|
1492
|
+
if (t !== void 0) return X("empty-endpoint", "analytics is disabled: no QoE beacons will be sent. analytics.endpoint was supplied but empty. Pass a real beacons origin, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, or omit the option to derive it from baseUrl (or analytics: false to opt out).");
|
|
1493
|
+
let n = mt(e);
|
|
1494
|
+
if (n) return { endpoint: n };
|
|
1495
|
+
let r;
|
|
1496
|
+
try {
|
|
1497
|
+
r = new URL(e).hostname || e;
|
|
1498
|
+
} catch {
|
|
1499
|
+
r = e;
|
|
1500
|
+
}
|
|
1501
|
+
return X(r, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${r}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
|
|
1502
|
+
}
|
|
1503
|
+
var gt = class {
|
|
1481
1504
|
opts;
|
|
1482
1505
|
url;
|
|
1483
1506
|
now;
|
|
@@ -1555,8 +1578,8 @@ var pt = class {
|
|
|
1555
1578
|
constructor(e) {
|
|
1556
1579
|
this.opts = {
|
|
1557
1580
|
...e,
|
|
1558
|
-
heartbeatMs: e.heartbeatMs ??
|
|
1559
|
-
idleMs: e.idleMs ??
|
|
1581
|
+
heartbeatMs: e.heartbeatMs ?? at,
|
|
1582
|
+
idleMs: e.idleMs ?? ot
|
|
1560
1583
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs, this.startupAnchorMs = this.bornMs;
|
|
1561
1584
|
}
|
|
1562
1585
|
start() {
|
|
@@ -1566,11 +1589,11 @@ var pt = class {
|
|
|
1566
1589
|
sdkVersion: this.opts.sdkVersion,
|
|
1567
1590
|
...this.opts.environment
|
|
1568
1591
|
};
|
|
1569
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
1592
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), lt), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.onVisibility());
|
|
1570
1593
|
}
|
|
1571
1594
|
checkSuspension(e) {
|
|
1572
1595
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
1573
|
-
let t = Math.max(this.opts.idleMs,
|
|
1596
|
+
let t = Math.max(this.opts.idleMs, st);
|
|
1574
1597
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
1575
1598
|
}
|
|
1576
1599
|
syncIdle(e) {
|
|
@@ -1584,21 +1607,21 @@ var pt = class {
|
|
|
1584
1607
|
noteStateChange(e, t, n, r) {
|
|
1585
1608
|
if (this.endedFlag || e === t) return;
|
|
1586
1609
|
let i = this.now();
|
|
1587
|
-
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(
|
|
1610
|
+
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(G, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(G, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
|
|
1588
1611
|
this.stallIsSeekInduced = this.seekInduced(i);
|
|
1589
1612
|
let e = !this.isHidden && !this.stallIsSeekInduced;
|
|
1590
|
-
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(
|
|
1613
|
+
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(G, Math.round(this.playingTotalMs)));
|
|
1591
1614
|
} else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
|
|
1592
1615
|
this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
|
|
1593
1616
|
let a = {
|
|
1594
|
-
fromState:
|
|
1595
|
-
toState:
|
|
1596
|
-
presentation:
|
|
1617
|
+
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1618
|
+
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1619
|
+
presentation: dt[this.presentation]
|
|
1597
1620
|
}, o = this.causeOf(e, t, i);
|
|
1598
1621
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
1599
1622
|
}
|
|
1600
1623
|
seekInduced(e) {
|
|
1601
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
1624
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < ut;
|
|
1602
1625
|
}
|
|
1603
1626
|
causeOf(e, t, n) {
|
|
1604
1627
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -1635,19 +1658,19 @@ var pt = class {
|
|
|
1635
1658
|
}
|
|
1636
1659
|
this.muteChanges += 1;
|
|
1637
1660
|
let r = this.now();
|
|
1638
|
-
n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(
|
|
1661
|
+
n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(G, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
|
|
1639
1662
|
}
|
|
1640
1663
|
notePresentation(e) {
|
|
1641
1664
|
this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
|
|
1642
1665
|
}
|
|
1643
1666
|
notePlayIntent() {
|
|
1644
|
-
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs =
|
|
1667
|
+
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = G), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = G));
|
|
1645
1668
|
}
|
|
1646
1669
|
noteReady() {
|
|
1647
|
-
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(
|
|
1670
|
+
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(G, this.now() - this.startupAnchorMs));
|
|
1648
1671
|
}
|
|
1649
1672
|
noteFirstBytes() {
|
|
1650
|
-
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(
|
|
1673
|
+
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(G, this.now() - this.startupAnchorMs));
|
|
1651
1674
|
}
|
|
1652
1675
|
noteSeek() {
|
|
1653
1676
|
this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
|
|
@@ -1666,7 +1689,7 @@ var pt = class {
|
|
|
1666
1689
|
let r = n ?? "";
|
|
1667
1690
|
if (r !== "") return /^fragLoad/i.test(r) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /^(manifest|level|audioTrack|subtitleTrack)/i.test(r) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(r) ? "ERROR_STAGE_DRM" : /parsing|append|buffer|remux|decrypt|media/i.test(r) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
|
|
1668
1691
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
1669
|
-
if (
|
|
1692
|
+
if (pt.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
1670
1693
|
let i = t ?? "";
|
|
1671
1694
|
return /frag|segment/i.test(i) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /manifest|level|playlist/i.test(i) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(i) ? "ERROR_STAGE_DRM" : /buffer|decode|media|append/i.test(i) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
|
|
1672
1695
|
}
|
|
@@ -1698,7 +1721,7 @@ var pt = class {
|
|
|
1698
1721
|
let l = t.droppedFrames ?? 0;
|
|
1699
1722
|
l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
|
|
1700
1723
|
let u = t.renditionSwitches ?? 0;
|
|
1701
|
-
u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState =
|
|
1724
|
+
u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = J[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
|
|
1702
1725
|
let d = this.mutedTotalMs;
|
|
1703
1726
|
this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
|
|
1704
1727
|
let f = t.upshifts ?? 0;
|
|
@@ -1713,14 +1736,14 @@ var pt = class {
|
|
|
1713
1736
|
if (this.lastRequestCount = g, _ > 0) {
|
|
1714
1737
|
o.requestCountDelta = _;
|
|
1715
1738
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
1716
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
1739
|
+
n.length > 0 && (o.requestTimeP50Ms = q(n, 50), o.requestTimeP95Ms = q(n, 95));
|
|
1717
1740
|
}
|
|
1718
1741
|
typeof t.latencySeconds == "number" && typeof t.targetLatencySeconds == "number" && (o.driftMs = Math.round((t.latencySeconds - t.targetLatencySeconds) * 1e3)), typeof t.playbackRate == "number" && t.playbackRate > 0 && (o.playbackRate = t.playbackRate), t.qualityPinned === !0 && (o.qualityPinned = !0), t.cdnHost && (o.cdnHost = t.cdnHost), this.maybeEmitMediaInfo(t), this.enqueue({ heartbeat: o }), this.flush(), s > 0 && this.noteFirstBytes();
|
|
1719
1742
|
}
|
|
1720
1743
|
maybeEmitMediaInfo(e) {
|
|
1721
1744
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
1722
1745
|
let t = {};
|
|
1723
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
1746
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = ft[e.keySystem]), e.drmSecurityLevel && (t.drmSecurityLevel = e.drmSecurityLevel), e.ladderHeights?.length && (t.ladderHeights = e.ladderHeights), e.ladderTopBitrateKbps && (t.ladderTopBitrateKbps = e.ladderTopBitrateKbps), e.lowLatency && (t.lowLatency = !0);
|
|
1724
1747
|
let n = JSON.stringify(t);
|
|
1725
1748
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
1726
1749
|
}
|
|
@@ -1740,7 +1763,7 @@ var pt = class {
|
|
|
1740
1763
|
let c = r?.positionMs ?? 0;
|
|
1741
1764
|
c > 0 && (i.exitPositionMs = Math.round(c)), this.activeTotalMs > 0 && (i.activeWatchTimeMs = Math.round(this.activeTotalMs)), this.mutedTotalMs > 0 && (i.mutedTimeMs = Math.round(this.mutedTotalMs));
|
|
1742
1765
|
let l = e !== "END_REASON_ENDED";
|
|
1743
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
1766
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= K && (i.abandonAfterStallMs = Math.max(G, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= K && (i.abandonAfterErrorMs = Math.max(G, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
|
|
1744
1767
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
1745
1768
|
u > 0 && (i.decodedFramesTotal = u), this.startupTimeMs === 0 && (i.failedStage = this.lastErrorStage ?? (this.manifestLoadMs === 0 ? "ERROR_STAGE_MANIFEST" : this.firstFragLoadMs === 0 ? "ERROR_STAGE_FIRST_SEGMENT" : "ERROR_STAGE_OTHER")), this.pending.push(this.wrap({ sessionEnd: i })), this.flush(e === "END_REASON_PAGEHIDE");
|
|
1746
1769
|
}
|
|
@@ -1760,7 +1783,7 @@ var pt = class {
|
|
|
1760
1783
|
};
|
|
1761
1784
|
}
|
|
1762
1785
|
enqueue(e) {
|
|
1763
|
-
for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
1786
|
+
for (this.pending.push(this.wrap(e)); this.pending.length > ct;) {
|
|
1764
1787
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
1765
1788
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
1766
1789
|
}
|
|
@@ -1783,7 +1806,7 @@ var pt = class {
|
|
|
1783
1806
|
};
|
|
1784
1807
|
//#endregion
|
|
1785
1808
|
//#region src/core/environment.ts
|
|
1786
|
-
function
|
|
1809
|
+
function _t() {
|
|
1787
1810
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
1788
1811
|
let e;
|
|
1789
1812
|
try {
|
|
@@ -1808,14 +1831,14 @@ function mt() {
|
|
|
1808
1831
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
1809
1832
|
};
|
|
1810
1833
|
}
|
|
1811
|
-
function
|
|
1834
|
+
function vt() {
|
|
1812
1835
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
1813
1836
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
1814
1837
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
1815
1838
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
1816
1839
|
return e?.mobile ?? (typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1 && n > 0 && n < 900) ? n >= 600 ? "DEVICE_CLASS_TABLET" : "DEVICE_CLASS_PHONE" : e || n >= 900 || /mac|win|linux|chrome os/i.test(t) ? "DEVICE_CLASS_DESKTOP" : "DEVICE_CLASS_OTHER";
|
|
1817
1840
|
}
|
|
1818
|
-
function
|
|
1841
|
+
function yt() {
|
|
1819
1842
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
1820
1843
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
1821
1844
|
let t = {
|
|
@@ -1834,17 +1857,17 @@ function gt() {
|
|
|
1834
1857
|
}
|
|
1835
1858
|
return typeof e.downlink == "number" && e.downlink > 0 && (i.downlinkKbps = Math.round(e.downlink * 1e3)), typeof e.rtt == "number" && e.rtt > 0 && (i.rttMs = Math.round(e.rtt)), e.saveData && (i.saveData = !0), i;
|
|
1836
1859
|
}
|
|
1837
|
-
function
|
|
1838
|
-
let t =
|
|
1839
|
-
deviceClass:
|
|
1860
|
+
function bt(e) {
|
|
1861
|
+
let t = _t(), n = {
|
|
1862
|
+
deviceClass: vt(),
|
|
1840
1863
|
integration: t.integration,
|
|
1841
|
-
...
|
|
1864
|
+
...yt()
|
|
1842
1865
|
};
|
|
1843
1866
|
t.host && (n.host = t.host), typeof screen < "u" && screen.width > 0 && (n.screenWidth = screen.width, n.screenHeight = screen.height), typeof window < "u" && window.devicePixelRatio > 0 && (n.devicePixelRatio = Math.round(window.devicePixelRatio * 100) / 100);
|
|
1844
1867
|
let r = e.getBoundingClientRect?.();
|
|
1845
1868
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
1846
1869
|
}
|
|
1847
|
-
async function
|
|
1870
|
+
async function xt() {
|
|
1848
1871
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
1849
1872
|
if (!e?.getHighEntropyValues) return {};
|
|
1850
1873
|
try {
|
|
@@ -1856,7 +1879,7 @@ async function vt() {
|
|
|
1856
1879
|
}
|
|
1857
1880
|
//#endregion
|
|
1858
1881
|
//#region src/core/version.ts
|
|
1859
|
-
var
|
|
1882
|
+
var St = "2.9.2", Ct = {
|
|
1860
1883
|
accent: "#E1B600",
|
|
1861
1884
|
accentText: "#1B1C23",
|
|
1862
1885
|
background: "#0e0f13",
|
|
@@ -1867,7 +1890,7 @@ var yt = "2.9.0", bt = {
|
|
|
1867
1890
|
border: "rgba(255, 255, 255, 0.1)",
|
|
1868
1891
|
radius: "8px",
|
|
1869
1892
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
1870
|
-
},
|
|
1893
|
+
}, wt = {
|
|
1871
1894
|
accent: "--havik-accent",
|
|
1872
1895
|
accentText: "--havik-accent-text",
|
|
1873
1896
|
background: "--havik-bg",
|
|
@@ -1879,25 +1902,25 @@ var yt = "2.9.0", bt = {
|
|
|
1879
1902
|
radius: "--havik-radius",
|
|
1880
1903
|
fontFamily: "--havik-font"
|
|
1881
1904
|
};
|
|
1882
|
-
function
|
|
1905
|
+
function Tt(e, t) {
|
|
1883
1906
|
let n = {
|
|
1884
|
-
...
|
|
1907
|
+
...Ct,
|
|
1885
1908
|
...t
|
|
1886
1909
|
};
|
|
1887
|
-
for (let t of Object.keys(
|
|
1910
|
+
for (let t of Object.keys(wt)) e.style.setProperty(wt[t], n[t]);
|
|
1888
1911
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
1889
1912
|
}
|
|
1890
1913
|
//#endregion
|
|
1891
1914
|
//#region src/ui/styles.ts
|
|
1892
|
-
var
|
|
1893
|
-
function
|
|
1894
|
-
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;
|
|
1895
1918
|
let t = e.createElement("style");
|
|
1896
|
-
t.id =
|
|
1919
|
+
t.id = Et, t.textContent = Dt, e.head.appendChild(t);
|
|
1897
1920
|
}
|
|
1898
1921
|
//#endregion
|
|
1899
1922
|
//#region src/ui/icons.ts
|
|
1900
|
-
var
|
|
1923
|
+
var kt = {
|
|
1901
1924
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
1902
1925
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
1903
1926
|
volumeHigh: "<path d=\"M3 10v4h4l5 5V5L7 10H3zm13.5 2a4.5 4.5 0 0 0-2.5-4v8a4.5 4.5 0 0 0 2.5-4zm-2.5-9v2.06A7 7 0 0 1 14 19v2a9 9 0 0 0 0-18z\"/>",
|
|
@@ -1910,21 +1933,21 @@ var Et = {
|
|
|
1910
1933
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
1911
1934
|
retry: "<path d=\"M17.65 6.35A8 8 0 1 0 19.73 13h-2.08A6 6 0 1 1 12 6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"/>"
|
|
1912
1935
|
};
|
|
1913
|
-
function
|
|
1914
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
1936
|
+
function Z(e) {
|
|
1937
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${kt[e]}</svg>`;
|
|
1915
1938
|
}
|
|
1916
1939
|
//#endregion
|
|
1917
1940
|
//#region src/ui/controls.ts
|
|
1918
|
-
var
|
|
1941
|
+
var At = 3e3, jt = /* @__PURE__ */ new Set([
|
|
1919
1942
|
"GONE",
|
|
1920
1943
|
"NOT_FOUND",
|
|
1921
1944
|
"INVALID_URN",
|
|
1922
1945
|
"UNAUTHORIZED"
|
|
1923
1946
|
]);
|
|
1924
|
-
function
|
|
1925
|
-
return new
|
|
1947
|
+
function Mt(e) {
|
|
1948
|
+
return new Nt(e);
|
|
1926
1949
|
}
|
|
1927
|
-
var
|
|
1950
|
+
var Nt = class {
|
|
1928
1951
|
root;
|
|
1929
1952
|
video;
|
|
1930
1953
|
player;
|
|
@@ -1966,7 +1989,7 @@ var At = class {
|
|
|
1966
1989
|
scrubbing = !1;
|
|
1967
1990
|
offFns = [];
|
|
1968
1991
|
constructor(e) {
|
|
1969
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
1992
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? At, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, Ot(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
|
|
1970
1993
|
let t = (e, t, n) => {
|
|
1971
1994
|
let r = this.doc.createElement(e);
|
|
1972
1995
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -1977,12 +2000,12 @@ var At = class {
|
|
|
1977
2000
|
"aria-label": r,
|
|
1978
2001
|
title: r
|
|
1979
2002
|
});
|
|
1980
|
-
return i.innerHTML =
|
|
2003
|
+
return i.innerHTML = Z(n), i;
|
|
1981
2004
|
};
|
|
1982
2005
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
1983
2006
|
type: "button",
|
|
1984
2007
|
"aria-label": "Play"
|
|
1985
|
-
}), this.center.innerHTML =
|
|
2008
|
+
}), this.center.innerHTML = Z("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
|
|
1986
2009
|
role: "slider",
|
|
1987
2010
|
"aria-label": "Seek",
|
|
1988
2011
|
"aria-valuemin": "0",
|
|
@@ -2000,7 +2023,7 @@ var At = class {
|
|
|
2000
2023
|
"aria-label": "Volume"
|
|
2001
2024
|
});
|
|
2002
2025
|
let a = t("div", "havik-vol");
|
|
2003
|
-
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML =
|
|
2026
|
+
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Z("liveDot");
|
|
2004
2027
|
let o = this.doc.createElement("span");
|
|
2005
2028
|
o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
|
|
2006
2029
|
let s = t("div", "havik-spacer");
|
|
@@ -2054,12 +2077,12 @@ var At = class {
|
|
|
2054
2077
|
}
|
|
2055
2078
|
if (e === "preplay") {
|
|
2056
2079
|
let e = this.doc.createElement("button");
|
|
2057
|
-
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML =
|
|
2080
|
+
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Z("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
|
|
2058
2081
|
} else {
|
|
2059
2082
|
let r = this.doc.createElement("div");
|
|
2060
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2083
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !jt.has(this.lastError.code)) {
|
|
2061
2084
|
let e = this.doc.createElement("button");
|
|
2062
|
-
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${
|
|
2085
|
+
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Z("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
2063
2086
|
}
|
|
2064
2087
|
}
|
|
2065
2088
|
this.root.append(n), this.statusBox = n, this.show();
|
|
@@ -2098,7 +2121,7 @@ var At = class {
|
|
|
2098
2121
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2099
2122
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2100
2123
|
}
|
|
2101
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2124
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Pt(this.video.currentTime)} / ${Pt(this.video.duration)}`);
|
|
2102
2125
|
}
|
|
2103
2126
|
syncLive() {
|
|
2104
2127
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2148,17 +2171,17 @@ var At = class {
|
|
|
2148
2171
|
renderQualityMenu() {
|
|
2149
2172
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2150
2173
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2151
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2174
|
+
for (let n of e) this.menu.append(this.menuItem(Ft(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2152
2175
|
}
|
|
2153
2176
|
renderAudioMenu() {
|
|
2154
2177
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2155
2178
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2156
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2179
|
+
for (let t of e) this.menu.append(this.menuItem(It(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2157
2180
|
}
|
|
2158
2181
|
renderCcMenu() {
|
|
2159
2182
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2160
2183
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2161
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2184
|
+
for (let t of e) this.menu.append(this.menuItem(Lt(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2162
2185
|
}
|
|
2163
2186
|
onTracksChanged() {
|
|
2164
2187
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2241,7 +2264,7 @@ var At = class {
|
|
|
2241
2264
|
}
|
|
2242
2265
|
}
|
|
2243
2266
|
setIcon(e, t) {
|
|
2244
|
-
e.innerHTML =
|
|
2267
|
+
e.innerHTML = Z(t);
|
|
2245
2268
|
}
|
|
2246
2269
|
destroy() {
|
|
2247
2270
|
this.hideTimer && clearTimeout(this.hideTimer);
|
|
@@ -2258,41 +2281,41 @@ var At = class {
|
|
|
2258
2281
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2259
2282
|
}
|
|
2260
2283
|
};
|
|
2261
|
-
function
|
|
2284
|
+
function Pt(e) {
|
|
2262
2285
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2263
2286
|
let t = Math.floor(e % 60), n = Math.floor(e / 60 % 60), r = Math.floor(e / 3600), i = r > 0 ? String(n).padStart(2, "0") : String(n), a = String(t).padStart(2, "0");
|
|
2264
2287
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2265
2288
|
}
|
|
2266
|
-
function
|
|
2289
|
+
function Ft(e) {
|
|
2267
2290
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2268
2291
|
}
|
|
2269
|
-
function
|
|
2292
|
+
function It(e) {
|
|
2270
2293
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2271
2294
|
}
|
|
2272
|
-
function
|
|
2295
|
+
function Lt(e) {
|
|
2273
2296
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2274
2297
|
}
|
|
2275
2298
|
//#endregion
|
|
2276
2299
|
//#region src/managed/index.ts
|
|
2277
|
-
var
|
|
2278
|
-
function
|
|
2300
|
+
var Rt = 6e3, Q = 45e3, zt = 2e3, Bt = 3, Vt = 2e3, Ht = 48e4;
|
|
2301
|
+
function Ut(e) {
|
|
2279
2302
|
if (e.env !== void 0 && e.baseUrl !== void 0) throw new n("INTERNAL", 0, `createPlayer: pass env OR baseUrl, not both (got env=${JSON.stringify(e.env)} and baseUrl=${JSON.stringify(e.baseUrl)})`);
|
|
2280
|
-
if (e.env !== void 0) return
|
|
2303
|
+
if (e.env !== void 0) return I(e.env);
|
|
2281
2304
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2282
2305
|
return e.baseUrl;
|
|
2283
2306
|
}
|
|
2284
|
-
async function
|
|
2307
|
+
async function Wt(e) {
|
|
2285
2308
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2286
|
-
let t =
|
|
2309
|
+
let t = Ut(e);
|
|
2287
2310
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2288
2311
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2289
|
-
let r = new
|
|
2312
|
+
let r = new Gt({
|
|
2290
2313
|
...e,
|
|
2291
2314
|
baseUrl: t
|
|
2292
2315
|
});
|
|
2293
2316
|
return await r.start(), r;
|
|
2294
2317
|
}
|
|
2295
|
-
var
|
|
2318
|
+
var Gt = class {
|
|
2296
2319
|
opts;
|
|
2297
2320
|
abort = new AbortController();
|
|
2298
2321
|
listeners = {};
|
|
@@ -2380,7 +2403,7 @@ var Vt = class {
|
|
|
2380
2403
|
setTimeout(() => {
|
|
2381
2404
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
2382
2405
|
phase: i ? "unavailable" : "tooEarly",
|
|
2383
|
-
retryInMs:
|
|
2406
|
+
retryInMs: Q,
|
|
2384
2407
|
attempt: 1,
|
|
2385
2408
|
elapsedMs: 0,
|
|
2386
2409
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -2419,13 +2442,13 @@ var Vt = class {
|
|
|
2419
2442
|
!a && !p() && h();
|
|
2420
2443
|
}, e);
|
|
2421
2444
|
};
|
|
2422
|
-
_(
|
|
2445
|
+
_(Rt), this.armingSub = E({
|
|
2423
2446
|
eventsBaseUrl: t,
|
|
2424
2447
|
matchUrn: this.opts.matchUrn,
|
|
2425
2448
|
credential: this.opts.credential,
|
|
2426
|
-
onAlive: () => _(
|
|
2449
|
+
onAlive: () => _(Q),
|
|
2427
2450
|
onState: (e) => {
|
|
2428
|
-
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);
|
|
2429
2452
|
},
|
|
2430
2453
|
onError: () => h()
|
|
2431
2454
|
});
|
|
@@ -2448,7 +2471,7 @@ var Vt = class {
|
|
|
2448
2471
|
let n = await s(this.opts.credential);
|
|
2449
2472
|
if (this.destroyed || t !== this.loadGen) return;
|
|
2450
2473
|
this.setState("loading");
|
|
2451
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
2474
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Fe(this.opts.video, (e) => {
|
|
2452
2475
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
2453
2476
|
});
|
|
2454
2477
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -2459,43 +2482,48 @@ var Vt = class {
|
|
|
2459
2482
|
a(), i.destroy();
|
|
2460
2483
|
return;
|
|
2461
2484
|
}
|
|
2462
|
-
this.engine = i, this.detachMedia = a, this.opts.maxBitrate != null && i.setMaxBitrate(this.opts.maxBitrate), this.startStats(), this.scheduleLicenseRefresh(), this.startLiveState(t), this.startAnalytics(e, i), r && (this.pendingStartLoad = !0, this.setState("paused"), i.name === "native" && setTimeout(() => {
|
|
2485
|
+
this.engine = i, this.detachMedia = a, this.opts.maxBitrate != null && i.setMaxBitrate(this.opts.maxBitrate), this.startStats(), this.scheduleLicenseRefresh(), this.startLiveState(t), this.startAnalytics(e, i, t), r && (this.pendingStartLoad = !0, this.setState("paused"), i.name === "native" && setTimeout(() => {
|
|
2463
2486
|
this.destroyed || t !== this.loadGen || this.engine !== i || (this.analyticsSession?.noteReady(), this.emit("ready"));
|
|
2464
2487
|
}, 0));
|
|
2465
2488
|
}
|
|
2466
2489
|
onAnalyticsIdle(e) {
|
|
2467
2490
|
this.destroyed || this.engine !== e || (this.idleClosed = !0, this.pendingStartLoad = !1, e.stop());
|
|
2468
2491
|
}
|
|
2469
|
-
startAnalytics(e, t) {
|
|
2492
|
+
startAnalytics(e, t, r) {
|
|
2470
2493
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
2471
|
-
let
|
|
2472
|
-
if (!
|
|
2473
|
-
let
|
|
2474
|
-
if (!
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2494
|
+
let i = e.analytics?.sid;
|
|
2495
|
+
if (!i) return;
|
|
2496
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = ht(this.opts.baseUrl, a);
|
|
2497
|
+
if (!o) {
|
|
2498
|
+
s && setTimeout(() => {
|
|
2499
|
+
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
2500
|
+
}, 0);
|
|
2501
|
+
return;
|
|
2502
|
+
}
|
|
2503
|
+
let c = this.opts.video, l = new gt({
|
|
2504
|
+
endpoint: o,
|
|
2505
|
+
sid: i,
|
|
2478
2506
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
2479
|
-
sdkVersion:
|
|
2480
|
-
environment:
|
|
2507
|
+
sdkVersion: St,
|
|
2508
|
+
environment: bt(c),
|
|
2481
2509
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
2482
2510
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
2483
2511
|
sample: () => {
|
|
2484
|
-
let e = this.engine?.getStats() ??
|
|
2512
|
+
let e = this.engine?.getStats() ?? L, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
2485
2513
|
return {
|
|
2486
2514
|
...e,
|
|
2487
2515
|
bufferedMs: Math.round(t * 1e3),
|
|
2488
2516
|
state: this._state,
|
|
2489
|
-
positionMs: Math.round(
|
|
2490
|
-
playbackRate:
|
|
2517
|
+
positionMs: Math.round(c.currentTime * 1e3),
|
|
2518
|
+
playbackRate: c.playbackRate
|
|
2491
2519
|
};
|
|
2492
2520
|
}
|
|
2493
2521
|
});
|
|
2494
|
-
this.analyticsSession =
|
|
2495
|
-
let
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
},
|
|
2522
|
+
this.analyticsSession = l;
|
|
2523
|
+
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
2524
|
+
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
2525
|
+
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
2526
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), xt().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
2499
2527
|
}
|
|
2500
2528
|
currentPresentation() {
|
|
2501
2529
|
let e = this.opts.video;
|
|
@@ -2519,11 +2547,11 @@ var Vt = class {
|
|
|
2519
2547
|
hlsConfig: i,
|
|
2520
2548
|
emit: (e) => this.onEngineEvent(e)
|
|
2521
2549
|
}, o = this.opts.engine ?? "auto";
|
|
2522
|
-
if (o === "native") return new
|
|
2523
|
-
if (o === "hls") return new
|
|
2524
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
2525
|
-
if (
|
|
2526
|
-
if (
|
|
2550
|
+
if (o === "native") return new H(a);
|
|
2551
|
+
if (o === "hls") return new W(a);
|
|
2552
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && B(this.opts.video) && V()) return new H(a);
|
|
2553
|
+
if (Re()) return new W(a);
|
|
2554
|
+
if (B(this.opts.video)) return new H(a);
|
|
2527
2555
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
2528
2556
|
}
|
|
2529
2557
|
onEngineEvent(e) {
|
|
@@ -2566,7 +2594,7 @@ var Vt = class {
|
|
|
2566
2594
|
r = 0, i = !1;
|
|
2567
2595
|
},
|
|
2568
2596
|
onError: () => {
|
|
2569
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
2597
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Bt && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
|
|
2570
2598
|
}
|
|
2571
2599
|
});
|
|
2572
2600
|
}
|
|
@@ -2588,7 +2616,7 @@ var Vt = class {
|
|
|
2588
2616
|
scheduleRejoin(e) {
|
|
2589
2617
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
2590
2618
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
2591
|
-
}, Math.random() *
|
|
2619
|
+
}, Math.random() * zt));
|
|
2592
2620
|
}
|
|
2593
2621
|
cancelRejoin() {
|
|
2594
2622
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -2612,7 +2640,7 @@ var Vt = class {
|
|
|
2612
2640
|
}
|
|
2613
2641
|
t.controls = !1;
|
|
2614
2642
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
2615
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
2643
|
+
r && r.insertBefore(n, t), n.appendChild(t), Tt(n, this.opts.theme), this.container = n, this.controlBar = Mt({
|
|
2616
2644
|
root: n,
|
|
2617
2645
|
video: t,
|
|
2618
2646
|
player: this,
|
|
@@ -2642,7 +2670,7 @@ var Vt = class {
|
|
|
2642
2670
|
}
|
|
2643
2671
|
startStats() {
|
|
2644
2672
|
this.stopStats();
|
|
2645
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
2673
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Vt);
|
|
2646
2674
|
this.statsTimer = setInterval(() => {
|
|
2647
2675
|
if (!this.engine) return;
|
|
2648
2676
|
let e = this.engine.getStats();
|
|
@@ -2654,7 +2682,7 @@ var Vt = class {
|
|
|
2654
2682
|
}
|
|
2655
2683
|
scheduleLicenseRefresh() {
|
|
2656
2684
|
this.stopRefresh();
|
|
2657
|
-
let e = this.opts.licenseRefreshMs ??
|
|
2685
|
+
let e = this.opts.licenseRefreshMs ?? Ht;
|
|
2658
2686
|
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
2659
2687
|
}
|
|
2660
2688
|
stopRefresh() {
|
|
@@ -2699,7 +2727,7 @@ var Vt = class {
|
|
|
2699
2727
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
2700
2728
|
}
|
|
2701
2729
|
getStats() {
|
|
2702
|
-
return this.engine?.getStats() ??
|
|
2730
|
+
return this.engine?.getStats() ?? L;
|
|
2703
2731
|
}
|
|
2704
2732
|
getQualityLevels() {
|
|
2705
2733
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -2809,7 +2837,7 @@ function $(e) {
|
|
|
2809
2837
|
}
|
|
2810
2838
|
//#endregion
|
|
2811
2839
|
//#region src/embed/host.ts
|
|
2812
|
-
function
|
|
2840
|
+
function Kt(e) {
|
|
2813
2841
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
2814
2842
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
2815
2843
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -2868,15 +2896,15 @@ function Ht(e) {
|
|
|
2868
2896
|
}
|
|
2869
2897
|
//#endregion
|
|
2870
2898
|
//#region src/embed/page.ts
|
|
2871
|
-
var
|
|
2872
|
-
function
|
|
2899
|
+
var qt = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
2900
|
+
function Jt(e) {
|
|
2873
2901
|
if (typeof e == "boolean") return e;
|
|
2874
2902
|
if (typeof e == "object" && e) {
|
|
2875
2903
|
let t = e.endpoint;
|
|
2876
2904
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
2877
2905
|
}
|
|
2878
2906
|
}
|
|
2879
|
-
function
|
|
2907
|
+
function Yt() {
|
|
2880
2908
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
2881
2909
|
if (e) return {
|
|
2882
2910
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -2886,7 +2914,7 @@ function Gt() {
|
|
|
2886
2914
|
autoplay: e.autoplay ?? !0,
|
|
2887
2915
|
muted: e.muted ?? !0,
|
|
2888
2916
|
waitForLive: e.waitForLive ?? !0,
|
|
2889
|
-
analytics:
|
|
2917
|
+
analytics: Jt(e.analytics)
|
|
2890
2918
|
};
|
|
2891
2919
|
let t = new URLSearchParams(location.search);
|
|
2892
2920
|
return {
|
|
@@ -2899,9 +2927,9 @@ function Gt() {
|
|
|
2899
2927
|
waitForLive: !0
|
|
2900
2928
|
};
|
|
2901
2929
|
}
|
|
2902
|
-
async function
|
|
2903
|
-
let e =
|
|
2904
|
-
|
|
2930
|
+
async function Xt() {
|
|
2931
|
+
let e = Yt();
|
|
2932
|
+
Qt();
|
|
2905
2933
|
let t = document.createElement("video");
|
|
2906
2934
|
t.setAttribute("playsinline", ""), t.muted = e.muted ?? !0, t.style.cssText = "width:100%;height:100%;object-fit:contain;background:#000;aspect-ratio:auto", document.body.appendChild(t);
|
|
2907
2935
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -2956,12 +2984,12 @@ async function Kt() {
|
|
|
2956
2984
|
code: e.code,
|
|
2957
2985
|
message: e.message
|
|
2958
2986
|
})), e.on("autoplayblocked", () => {
|
|
2959
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
2987
|
+
i({ type: "oddin:autoplayblocked" }), Zt(t, e);
|
|
2960
2988
|
});
|
|
2961
2989
|
}, s = async (r) => {
|
|
2962
2990
|
a?.destroy(), a = null;
|
|
2963
2991
|
try {
|
|
2964
|
-
let n = await
|
|
2992
|
+
let n = await Wt({
|
|
2965
2993
|
video: t,
|
|
2966
2994
|
baseUrl: e.baseUrl,
|
|
2967
2995
|
matchUrn: r,
|
|
@@ -3023,7 +3051,7 @@ async function Kt() {
|
|
|
3023
3051
|
a?.retry();
|
|
3024
3052
|
break;
|
|
3025
3053
|
case "oddin:load":
|
|
3026
|
-
typeof e.matchUrn == "string" &&
|
|
3054
|
+
typeof e.matchUrn == "string" && qt.test(e.matchUrn) && s(e.matchUrn);
|
|
3027
3055
|
break;
|
|
3028
3056
|
case "oddin:destroy": c();
|
|
3029
3057
|
}
|
|
@@ -3035,18 +3063,18 @@ async function Kt() {
|
|
|
3035
3063
|
protocol: 1
|
|
3036
3064
|
});
|
|
3037
3065
|
}
|
|
3038
|
-
function
|
|
3066
|
+
function Zt(e, t) {
|
|
3039
3067
|
if (document.getElementById("havik-tap")) return;
|
|
3040
3068
|
let n = document.createElement("button");
|
|
3041
3069
|
n.id = "havik-tap", n.textContent = "▶ Tap to play", n.style.cssText = "position:fixed;inset:0;width:100%;height:100%;border:0;background:rgba(0,0,0,.55);color:#fff;font:600 18px system-ui,sans-serif;cursor:pointer;z-index:9", n.addEventListener("click", () => {
|
|
3042
3070
|
n.remove(), t.play();
|
|
3043
3071
|
}), document.body.appendChild(n);
|
|
3044
3072
|
}
|
|
3045
|
-
function
|
|
3073
|
+
function Qt() {
|
|
3046
3074
|
let e = document.createElement("style");
|
|
3047
3075
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3048
3076
|
}
|
|
3049
3077
|
//#endregion
|
|
3050
|
-
export {
|
|
3078
|
+
export { Ct as ODDIN_THEME, n as PlaybackError, Tt as applyTheme, I as baseUrlForEnv, Xt as bootEmbed, ve as clearDeviceId, Wt as createPlayer, D as deriveEventsBaseUrl, Ae as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, de as fetchCatalog, pe as fetchTournament, he as flattenMatches, A as getDeviceId, Me as isLowLatencyManifest, $ as isOddinMessage, be as licenseRequestHeaders, Kt as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, ge as watchStatus };
|
|
3051
3079
|
|
|
3052
3080
|
//# sourceMappingURL=index.js.map
|