@oddin-gg/havik-player 2.19.0 → 2.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -10
- 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 +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +464 -410
- package/dist/index.js.map +1 -1
- package/docs/API.md +70 -39
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,8 +7,9 @@ var n = class extends Error {
|
|
|
7
7
|
requestId;
|
|
8
8
|
serverCode;
|
|
9
9
|
liveStartsAtMs;
|
|
10
|
+
country;
|
|
10
11
|
constructor(e, t, n, r) {
|
|
11
|
-
super(n), this.name = "PlaybackError", this.code = e, this.httpStatus = t, this.retryAfterMs = r?.retryAfterMs, this.requestId = r?.requestId, this.serverCode = r?.serverCode, this.liveStartsAtMs = r?.liveStartsAtMs, r?.cause !== void 0 && (this.cause = r.cause);
|
|
12
|
+
super(n), this.name = "PlaybackError", this.code = e, this.httpStatus = t, this.retryAfterMs = r?.retryAfterMs, this.requestId = r?.requestId, this.serverCode = r?.serverCode, this.liveStartsAtMs = r?.liveStartsAtMs, this.country = r?.country, r?.cause !== void 0 && (this.cause = r.cause);
|
|
12
13
|
}
|
|
13
14
|
};
|
|
14
15
|
function r(e) {
|
|
@@ -20,33 +21,52 @@ function r(e) {
|
|
|
20
21
|
case 410: return "GONE";
|
|
21
22
|
case 425: return "TOO_EARLY";
|
|
22
23
|
case 429: return "RATE_LIMITED";
|
|
24
|
+
case 451: return "GEO_DENIED";
|
|
23
25
|
case 503: return "UNAVAILABLE";
|
|
24
26
|
default: return "INTERNAL";
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
29
|
function i(e) {
|
|
28
|
-
|
|
30
|
+
let t = e;
|
|
31
|
+
if (typeof e == "string") {
|
|
32
|
+
if (e === "") return;
|
|
33
|
+
try {
|
|
34
|
+
t = JSON.parse(e);
|
|
35
|
+
} catch {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (!t || typeof t != "object") return;
|
|
40
|
+
let n = t.error;
|
|
41
|
+
if (typeof n == "string") return n === "" ? void 0 : n;
|
|
42
|
+
if (n && typeof n == "object") {
|
|
43
|
+
let e = n.code;
|
|
44
|
+
if (typeof e == "string" && e !== "") return e;
|
|
45
|
+
}
|
|
29
46
|
}
|
|
30
|
-
|
|
47
|
+
function a(e, t) {
|
|
48
|
+
return e === 401 ? "UNAUTHORIZED" : e === 403 ? t === "cdm_revoked" ? "DRM_DEVICE_REVOKED" : "FORBIDDEN" : "DRM_CLIENT";
|
|
49
|
+
}
|
|
50
|
+
var o = /* @__PURE__ */ new Set([
|
|
31
51
|
"TOO_EARLY",
|
|
32
52
|
"UNAVAILABLE",
|
|
33
53
|
"RATE_LIMITED",
|
|
34
54
|
"NETWORK"
|
|
35
55
|
]);
|
|
36
|
-
function
|
|
37
|
-
return
|
|
56
|
+
function s(e) {
|
|
57
|
+
return o.has(e);
|
|
38
58
|
}
|
|
39
59
|
//#endregion
|
|
40
60
|
//#region src/core/types.ts
|
|
41
|
-
async function
|
|
61
|
+
async function c(e) {
|
|
42
62
|
let t = typeof e == "function" ? await e() : e;
|
|
43
63
|
if (!t || !t.apiKey) throw Error("havik-player: credential is missing an apiKey");
|
|
44
64
|
return t;
|
|
45
65
|
}
|
|
46
|
-
function
|
|
66
|
+
function l(e) {
|
|
47
67
|
return e === "live" || e === "ended" || e === "upcoming" || e === "pending" ? e : "upcoming";
|
|
48
68
|
}
|
|
49
|
-
function
|
|
69
|
+
function u(e) {
|
|
50
70
|
if (!Array.isArray(e)) return;
|
|
51
71
|
let t = [];
|
|
52
72
|
for (let n of e) {
|
|
@@ -58,11 +78,11 @@ function l(e) {
|
|
|
58
78
|
name: r,
|
|
59
79
|
isHome: n.isHome === !0
|
|
60
80
|
};
|
|
61
|
-
typeof n.logoUrl == "string" &&
|
|
81
|
+
typeof n.logoUrl == "string" && d(n.logoUrl) && (i.logoUrl = n.logoUrl), t.push(i);
|
|
62
82
|
}
|
|
63
83
|
return t.length > 0 ? t : void 0;
|
|
64
84
|
}
|
|
65
|
-
function
|
|
85
|
+
function d(e) {
|
|
66
86
|
try {
|
|
67
87
|
return new URL(e).protocol === "https:";
|
|
68
88
|
} catch {
|
|
@@ -71,7 +91,7 @@ function u(e) {
|
|
|
71
91
|
}
|
|
72
92
|
//#endregion
|
|
73
93
|
//#region src/core/http.ts
|
|
74
|
-
function
|
|
94
|
+
function f(e, t) {
|
|
75
95
|
let r = e.replace(/\/+$/, ""), i;
|
|
76
96
|
try {
|
|
77
97
|
i = new URL(r + t);
|
|
@@ -81,15 +101,15 @@ function d(e, t) {
|
|
|
81
101
|
if (i.protocol !== "https:" && i.protocol !== "http:") throw new n("INTERNAL", 0, `baseUrl must be http(s), got: ${JSON.stringify(e)}`);
|
|
82
102
|
return i.toString();
|
|
83
103
|
}
|
|
84
|
-
function
|
|
104
|
+
function p(e) {
|
|
85
105
|
if (!e) return;
|
|
86
106
|
let t = Number(e);
|
|
87
107
|
if (Number.isFinite(t)) return Math.max(0, Math.round(t * 1e3));
|
|
88
108
|
let n = Date.parse(e);
|
|
89
109
|
if (!Number.isNaN(n)) return Math.max(0, n - Date.now());
|
|
90
110
|
}
|
|
91
|
-
async function
|
|
92
|
-
let r = await
|
|
111
|
+
async function m(e, t) {
|
|
112
|
+
let r = await c(t.credential), i = t.headers ?? new Headers();
|
|
93
113
|
if (t.apiHeaders) for (let [e, n] of Object.entries(t.apiHeaders)) i.has(e) || i.set(e, n);
|
|
94
114
|
i.set("x-api-key", r.apiKey);
|
|
95
115
|
try {
|
|
@@ -103,55 +123,55 @@ async function p(e, t) {
|
|
|
103
123
|
mode: "cors"
|
|
104
124
|
});
|
|
105
125
|
} catch (e) {
|
|
106
|
-
throw t.signal?.aborted ? new n("ABORTED", 0, "request aborted", { cause: e }) : new n("NETWORK", 0, `network request failed: ${
|
|
126
|
+
throw t.signal?.aborted ? new n("ABORTED", 0, "request aborted", { cause: e }) : new n("NETWORK", 0, `network request failed: ${h(e)}`, { cause: e });
|
|
107
127
|
}
|
|
108
128
|
}
|
|
109
|
-
function
|
|
129
|
+
function h(e) {
|
|
110
130
|
return e instanceof Error ? e.message : String(e);
|
|
111
131
|
}
|
|
112
132
|
//#endregion
|
|
113
133
|
//#region src/core/warnOnce.ts
|
|
114
|
-
var
|
|
115
|
-
function
|
|
116
|
-
|
|
134
|
+
var g = /* @__PURE__ */ new Set();
|
|
135
|
+
function _(e, t = e) {
|
|
136
|
+
g.has(t) || (g.add(t), console.warn(`havik-player: ${e}`));
|
|
117
137
|
}
|
|
118
138
|
//#endregion
|
|
119
139
|
//#region src/core/waitForLive.ts
|
|
120
|
-
var
|
|
140
|
+
var ee = 1e3, te = 3e4, ne = 6e5, re = 3e5, ie = 1e3, ae = {
|
|
121
141
|
TOO_EARLY: "tooEarly",
|
|
122
142
|
UNAVAILABLE: "unavailable",
|
|
123
143
|
RATE_LIMITED: "rateLimited",
|
|
124
144
|
NETWORK: "network"
|
|
125
145
|
};
|
|
126
|
-
function
|
|
127
|
-
let t = e === !0 || e === !1 ? {} : e, n = Math.max(
|
|
146
|
+
function oe(e) {
|
|
147
|
+
let t = e === !0 || e === !1 ? {} : e, n = Math.max(ie, t.floorMs ?? ee), r = Math.max(n, t.ceilMs ?? te), i = Math.max(0, t.imminentMs ?? ne), a = Math.max(r, t.sanityFloorMs ?? re);
|
|
128
148
|
return {
|
|
129
149
|
timeoutMs: t.timeoutMs,
|
|
130
150
|
floorMs: n,
|
|
131
151
|
ceilMs: r,
|
|
132
152
|
imminentMs: i,
|
|
133
153
|
sanityFloorMs: a,
|
|
134
|
-
kickoffMs:
|
|
154
|
+
kickoffMs: se(t.kickoffAt),
|
|
135
155
|
jitter: t.jitter ?? !0,
|
|
136
156
|
onState: t.onState
|
|
137
157
|
};
|
|
138
158
|
}
|
|
139
|
-
function
|
|
159
|
+
function se(e) {
|
|
140
160
|
if (e == null) return;
|
|
141
161
|
if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
|
|
142
162
|
let t = Date.parse(e);
|
|
143
163
|
return Number.isFinite(t) ? t : void 0;
|
|
144
164
|
}
|
|
145
|
-
function
|
|
165
|
+
function ce(e, t, n) {
|
|
146
166
|
return Math.min(n, Math.max(t, e));
|
|
147
167
|
}
|
|
148
|
-
function
|
|
168
|
+
function le(e) {
|
|
149
169
|
return Math.round(e * (1 + .15 * Math.random()));
|
|
150
170
|
}
|
|
151
|
-
function
|
|
171
|
+
function ue(e, t, n, r) {
|
|
152
172
|
let i = r ?? n.kickoffMs, a = i == null ? void 0 : Math.max(0, i - t), o = Math.max(n.floorMs, e ?? 0);
|
|
153
173
|
if (a == null || a <= n.imminentMs) return {
|
|
154
|
-
delay:
|
|
174
|
+
delay: ce(e ?? n.floorMs, o, n.ceilMs),
|
|
155
175
|
ttkMs: a
|
|
156
176
|
};
|
|
157
177
|
let s = Math.min(Math.floor(a / 10), n.sanityFloorMs, a);
|
|
@@ -160,7 +180,7 @@ function le(e, t, n, r) {
|
|
|
160
180
|
ttkMs: a
|
|
161
181
|
};
|
|
162
182
|
}
|
|
163
|
-
function
|
|
183
|
+
function de(e, t) {
|
|
164
184
|
return new Promise((r, i) => {
|
|
165
185
|
if (t?.aborted) {
|
|
166
186
|
i(new n("ABORTED", 0, "wait-for-live aborted"));
|
|
@@ -174,27 +194,27 @@ function ue(e, t) {
|
|
|
174
194
|
t?.addEventListener("abort", a, { once: !0 });
|
|
175
195
|
});
|
|
176
196
|
}
|
|
177
|
-
async function
|
|
178
|
-
let i =
|
|
197
|
+
async function fe(e, t, r) {
|
|
198
|
+
let i = oe(t), a = Date.now(), o = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
|
|
179
199
|
for (;;) {
|
|
180
200
|
if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
|
|
181
201
|
try {
|
|
182
202
|
return await e();
|
|
183
203
|
} catch (e) {
|
|
184
|
-
if (!(e instanceof n) || !
|
|
204
|
+
if (!(e instanceof n) || !s(e.code)) throw e;
|
|
185
205
|
c += 1, e.liveStartsAtMs != null && Number.isFinite(e.liveStartsAtMs) && (l = e.liveStartsAtMs);
|
|
186
|
-
let t = Date.now(), u =
|
|
187
|
-
if (i.jitter && (f =
|
|
206
|
+
let t = Date.now(), u = ue(e.retryAfterMs, t, i, l), d = u.ttkMs, f = u.delay;
|
|
207
|
+
if (i.jitter && (f = le(f)), t + f > o) throw new n("TIMEOUT", e.httpStatus, `timed out after ${i.timeoutMs}ms waiting for the stream to go live`, {
|
|
188
208
|
retryAfterMs: e.retryAfterMs,
|
|
189
209
|
cause: e
|
|
190
210
|
});
|
|
191
211
|
i.onState?.({
|
|
192
|
-
phase:
|
|
212
|
+
phase: ae[e.code] ?? "unavailable",
|
|
193
213
|
retryInMs: f,
|
|
194
214
|
attempt: c,
|
|
195
215
|
elapsedMs: t - a,
|
|
196
216
|
ttkMs: d
|
|
197
|
-
}), await
|
|
217
|
+
}), await de(f, r);
|
|
198
218
|
}
|
|
199
219
|
}
|
|
200
220
|
}
|
|
@@ -202,35 +222,37 @@ async function de(e, t, r) {
|
|
|
202
222
|
//#region src/core/resolve.ts
|
|
203
223
|
async function v(e) {
|
|
204
224
|
if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
|
|
205
|
-
let t = await
|
|
225
|
+
let t = await m(f(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
|
|
206
226
|
credential: e.credential,
|
|
207
227
|
signal: e.signal,
|
|
208
228
|
apiHeaders: e.apiHeaders
|
|
209
229
|
});
|
|
210
|
-
if (!t.ok) throw await
|
|
211
|
-
return
|
|
230
|
+
if (!t.ok) throw await pe(t);
|
|
231
|
+
return ge(await t.json(), e.matchUrn);
|
|
212
232
|
}
|
|
213
233
|
function y(e) {
|
|
214
234
|
let t = () => v(e);
|
|
215
|
-
return e.waitForLive ?
|
|
235
|
+
return e.waitForLive ? fe(t, e.waitForLive, e.signal) : t();
|
|
216
236
|
}
|
|
217
|
-
async function
|
|
218
|
-
let t =
|
|
237
|
+
async function pe(e) {
|
|
238
|
+
let t = p(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, c;
|
|
219
239
|
try {
|
|
220
240
|
let t = await e.json();
|
|
221
241
|
if (t?.error?.message && (a = t.error.message), t?.error?.code && (o = t.error.code), typeof t?.liveStartsAt == "string") {
|
|
222
242
|
let e = Date.parse(t.liveStartsAt);
|
|
223
243
|
Number.isFinite(e) && (s = e);
|
|
224
244
|
}
|
|
245
|
+
e.status === 451 && typeof t?.country == "string" && /^[A-Z]{2}$/.test(t.country) && (c = t.country);
|
|
225
246
|
} catch {}
|
|
226
247
|
return new n(r(e.status), e.status, a, {
|
|
227
248
|
retryAfterMs: t,
|
|
228
249
|
requestId: i,
|
|
229
250
|
serverCode: o,
|
|
230
|
-
liveStartsAtMs: s
|
|
251
|
+
liveStartsAtMs: s,
|
|
252
|
+
country: c
|
|
231
253
|
});
|
|
232
254
|
}
|
|
233
|
-
var
|
|
255
|
+
var me = /* @__PURE__ */ new Set([
|
|
234
256
|
"matchUrn",
|
|
235
257
|
"protocol",
|
|
236
258
|
"drmEnabled",
|
|
@@ -251,16 +273,16 @@ function b(e, t) {
|
|
|
251
273
|
if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
|
|
252
274
|
return t;
|
|
253
275
|
}
|
|
254
|
-
function
|
|
276
|
+
function he(e) {
|
|
255
277
|
if (e !== void 0) {
|
|
256
278
|
if (typeof e == "string" && !e.endsWith("/")) try {
|
|
257
279
|
let t = new URL(e);
|
|
258
280
|
if (t.protocol === "https:" && t.href === `${t.origin}/`) return t.origin;
|
|
259
281
|
} catch {}
|
|
260
|
-
|
|
282
|
+
_(`server analytics.endpoint ${JSON.stringify(e)} ignored: not a bare https origin.`);
|
|
261
283
|
}
|
|
262
284
|
}
|
|
263
|
-
function
|
|
285
|
+
function ge(e, t) {
|
|
264
286
|
if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
|
|
265
287
|
let r = e.drmEnabled ?? !!e.drm, i = {
|
|
266
288
|
matchUrn: e.matchUrn ?? t,
|
|
@@ -271,7 +293,7 @@ function he(e, t) {
|
|
|
271
293
|
};
|
|
272
294
|
if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid) {
|
|
273
295
|
i.analytics = { sid: e.analytics.sid };
|
|
274
|
-
let t =
|
|
296
|
+
let t = he(e.analytics.endpoint);
|
|
275
297
|
t && (i.analytics.endpoint = t);
|
|
276
298
|
}
|
|
277
299
|
if (r && e.drm) {
|
|
@@ -282,7 +304,7 @@ function he(e, t) {
|
|
|
282
304
|
}), (t.widevine || t.fairplay) && (i.drm = t);
|
|
283
305
|
}
|
|
284
306
|
let a = {};
|
|
285
|
-
for (let [t, n] of Object.entries(e))
|
|
307
|
+
for (let [t, n] of Object.entries(e)) me.has(t) || (a[t] = n);
|
|
286
308
|
return Object.keys(a).length > 0 && (i.extensions = a), i;
|
|
287
309
|
}
|
|
288
310
|
//#endregion
|
|
@@ -290,11 +312,11 @@ function he(e, t) {
|
|
|
290
312
|
function x(e) {
|
|
291
313
|
return e.ownerDocument ?? document;
|
|
292
314
|
}
|
|
293
|
-
function
|
|
315
|
+
function _e(e) {
|
|
294
316
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
295
317
|
}
|
|
296
318
|
function S(e, t) {
|
|
297
|
-
let n =
|
|
319
|
+
let n = _e(x(e));
|
|
298
320
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
299
321
|
}
|
|
300
322
|
function C(e, t) {
|
|
@@ -317,17 +339,17 @@ async function T(e, t) {
|
|
|
317
339
|
n.webkitExitFullscreen?.();
|
|
318
340
|
return;
|
|
319
341
|
}
|
|
320
|
-
let r = x(e), i =
|
|
342
|
+
let r = x(e), i = _e(r);
|
|
321
343
|
i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
|
|
322
344
|
}
|
|
323
345
|
//#endregion
|
|
324
346
|
//#region src/core/catalog.ts
|
|
325
|
-
async function
|
|
347
|
+
async function ve(e) {
|
|
326
348
|
let t = new URLSearchParams();
|
|
327
349
|
e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
|
|
328
|
-
let i = t.toString(), a =
|
|
350
|
+
let i = t.toString(), a = f(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
|
|
329
351
|
e.etag && o.set("If-None-Match", e.etag);
|
|
330
|
-
let s = await
|
|
352
|
+
let s = await m(a, {
|
|
331
353
|
credential: e.credential,
|
|
332
354
|
signal: e.signal,
|
|
333
355
|
headers: o,
|
|
@@ -340,12 +362,12 @@ async function _e(e) {
|
|
|
340
362
|
};
|
|
341
363
|
if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
|
|
342
364
|
return {
|
|
343
|
-
tournaments:
|
|
365
|
+
tournaments: ye(await s.json()),
|
|
344
366
|
etag: s.headers.get("etag") ?? void 0,
|
|
345
367
|
notModified: !1
|
|
346
368
|
};
|
|
347
369
|
}
|
|
348
|
-
function
|
|
370
|
+
function ye(e) {
|
|
349
371
|
return (e.tournaments ?? []).map((e) => {
|
|
350
372
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
351
373
|
return {
|
|
@@ -356,21 +378,21 @@ function ve(e) {
|
|
|
356
378
|
matches: (e.matches ?? []).map((e) => ({
|
|
357
379
|
matchUrn: e.matchUrn ?? "",
|
|
358
380
|
matchName: e.matchName ?? "",
|
|
359
|
-
status:
|
|
381
|
+
status: l(e.status),
|
|
360
382
|
statusRaw: e.status,
|
|
361
383
|
datePlannedStart: e.datePlannedStart,
|
|
362
384
|
tournamentUrn: t,
|
|
363
385
|
tournamentName: n,
|
|
364
386
|
sport: r,
|
|
365
|
-
teams:
|
|
387
|
+
teams: u(e.teams)
|
|
366
388
|
}))
|
|
367
389
|
};
|
|
368
390
|
});
|
|
369
391
|
}
|
|
370
|
-
async function
|
|
371
|
-
let t =
|
|
392
|
+
async function be(e) {
|
|
393
|
+
let t = f(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
372
394
|
e.etag && i.set("If-None-Match", e.etag);
|
|
373
|
-
let a = await
|
|
395
|
+
let a = await m(t, {
|
|
374
396
|
credential: e.credential,
|
|
375
397
|
signal: e.signal,
|
|
376
398
|
headers: i,
|
|
@@ -387,13 +409,13 @@ async function ye(e) {
|
|
|
387
409
|
};
|
|
388
410
|
if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
389
411
|
return {
|
|
390
|
-
tournament:
|
|
412
|
+
tournament: xe(await a.json()),
|
|
391
413
|
etag: a.headers.get("etag") ?? void 0,
|
|
392
414
|
notModified: !1,
|
|
393
415
|
notFound: !1
|
|
394
416
|
};
|
|
395
417
|
}
|
|
396
|
-
function
|
|
418
|
+
function xe(e) {
|
|
397
419
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
398
420
|
return {
|
|
399
421
|
urn: t,
|
|
@@ -403,43 +425,44 @@ function be(e) {
|
|
|
403
425
|
matches: (e.matches ?? []).map((e) => ({
|
|
404
426
|
matchUrn: e.matchUrn ?? "",
|
|
405
427
|
matchName: e.matchName ?? "",
|
|
406
|
-
status:
|
|
428
|
+
status: l(e.status),
|
|
407
429
|
statusRaw: e.status,
|
|
408
430
|
datePlannedStart: e.datePlannedStart,
|
|
409
431
|
tournamentUrn: t,
|
|
410
432
|
tournamentName: n,
|
|
411
433
|
sport: r,
|
|
412
|
-
teams:
|
|
434
|
+
teams: u(e.teams)
|
|
413
435
|
}))
|
|
414
436
|
};
|
|
415
437
|
}
|
|
416
|
-
function
|
|
438
|
+
function Se(e) {
|
|
417
439
|
return e.tournaments.flatMap((e) => e.matches);
|
|
418
440
|
}
|
|
419
441
|
//#endregion
|
|
420
442
|
//#region src/core/poll.ts
|
|
421
|
-
var
|
|
443
|
+
var Ce = /* @__PURE__ */ new Set([
|
|
422
444
|
"NOT_FOUND",
|
|
445
|
+
"GEO_DENIED",
|
|
423
446
|
"GONE",
|
|
424
447
|
"INVALID_URN"
|
|
425
448
|
]);
|
|
426
|
-
function
|
|
427
|
-
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s,
|
|
428
|
-
|
|
429
|
-
},
|
|
449
|
+
function we(e) {
|
|
450
|
+
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, c = !1, d = () => {
|
|
451
|
+
c || (a = setTimeout(p, t));
|
|
452
|
+
}, p = async () => {
|
|
430
453
|
try {
|
|
431
|
-
let t =
|
|
454
|
+
let t = f(e.baseUrl, `/v1/matches/${encodeURIComponent(e.matchUrn)}`), a = new Headers();
|
|
432
455
|
o && a.set("If-None-Match", o);
|
|
433
|
-
let
|
|
456
|
+
let c = await m(t, {
|
|
434
457
|
credential: e.credential,
|
|
435
458
|
signal: i.signal,
|
|
436
459
|
headers: a,
|
|
437
460
|
apiHeaders: e.apiHeaders
|
|
438
461
|
});
|
|
439
|
-
if (
|
|
440
|
-
if (!
|
|
441
|
-
o =
|
|
442
|
-
let t = await
|
|
462
|
+
if (c.status !== 304) {
|
|
463
|
+
if (!c.ok) throw new n(r(c.status), c.status, `match status request failed (HTTP ${c.status})`);
|
|
464
|
+
o = c.headers.get("etag") ?? o;
|
|
465
|
+
let t = await c.json(), i = l(t.status), a = typeof t.status == "string" ? t.status : i, d = u(t.teams), f = JSON.stringify([
|
|
443
466
|
a,
|
|
444
467
|
t.datePlannedStart ?? null,
|
|
445
468
|
d ?? null
|
|
@@ -456,21 +479,21 @@ function Ce(e) {
|
|
|
456
479
|
} catch (t) {
|
|
457
480
|
if (!i.signal.aborted) {
|
|
458
481
|
let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
|
|
459
|
-
|
|
482
|
+
Ce.has(r.code) && (c = !0), e.onError?.(r);
|
|
460
483
|
}
|
|
461
484
|
} finally {
|
|
462
|
-
|
|
485
|
+
d();
|
|
463
486
|
}
|
|
464
487
|
};
|
|
465
|
-
return
|
|
466
|
-
|
|
488
|
+
return p(), { stop() {
|
|
489
|
+
c = !0, i.abort(), a && clearTimeout(a);
|
|
467
490
|
} };
|
|
468
491
|
}
|
|
469
492
|
//#endregion
|
|
470
493
|
//#region src/core/events.ts
|
|
471
|
-
var
|
|
494
|
+
var Te = 45e3;
|
|
472
495
|
function E(e) {
|
|
473
|
-
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ??
|
|
496
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? Te, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, s = (e) => new Promise((t) => {
|
|
474
497
|
if (a.signal.aborted) return t();
|
|
475
498
|
let n = setTimeout(t, e);
|
|
476
499
|
a.signal.addEventListener("abort", () => {
|
|
@@ -490,7 +513,7 @@ function E(e) {
|
|
|
490
513
|
let t = JSON.parse(r.join("\n"));
|
|
491
514
|
t && typeof t.state == "string" && e.onState(t);
|
|
492
515
|
} catch {}
|
|
493
|
-
}, u = /\r\n\r\n|\n\n|\r\r/,
|
|
516
|
+
}, u = /\r\n\r\n|\n\n|\r\r/, d = async (e, t, n) => {
|
|
494
517
|
let r = e.getReader(), a = new TextDecoder(), s = "", c = !1, d, f = () => {
|
|
495
518
|
i && (clearTimeout(d), d = setTimeout(() => {
|
|
496
519
|
n(), r.cancel().catch(() => {});
|
|
@@ -518,13 +541,13 @@ function E(e) {
|
|
|
518
541
|
p = `no data for ${i}ms`, l.abort();
|
|
519
542
|
};
|
|
520
543
|
try {
|
|
521
|
-
let n = await
|
|
544
|
+
let n = await c(e.credential);
|
|
522
545
|
if (o) return;
|
|
523
|
-
let a =
|
|
546
|
+
let a = f(e.eventsBaseUrl, `/v1/events/${encodeURIComponent(e.matchUrn)}`);
|
|
524
547
|
i && (m = setTimeout(() => {
|
|
525
548
|
p = `no response headers within ${i}ms`, l.abort();
|
|
526
549
|
}, i));
|
|
527
|
-
let
|
|
550
|
+
let s = await fetch(a, {
|
|
528
551
|
method: "GET",
|
|
529
552
|
headers: {
|
|
530
553
|
"x-api-key": n.apiKey,
|
|
@@ -536,7 +559,7 @@ function E(e) {
|
|
|
536
559
|
mode: "cors"
|
|
537
560
|
});
|
|
538
561
|
if (clearTimeout(m), o) return;
|
|
539
|
-
!
|
|
562
|
+
!s.ok || !s.body ? e.onError?.(/* @__PURE__ */ Error(`live-state subscribe failed: HTTP ${s.status}`)) : await d(s.body, () => {
|
|
540
563
|
r = t;
|
|
541
564
|
}, h);
|
|
542
565
|
} catch (t) {
|
|
@@ -546,7 +569,7 @@ function E(e) {
|
|
|
546
569
|
clearTimeout(m), a.signal.removeEventListener("abort", u), l.abort();
|
|
547
570
|
}
|
|
548
571
|
if (o) return;
|
|
549
|
-
p && e.onError?.(/* @__PURE__ */ Error(`live-state subscribe idle: ${p} — reconnecting`)), await
|
|
572
|
+
p && e.onError?.(/* @__PURE__ */ Error(`live-state subscribe idle: ${p} — reconnecting`)), await s(r), r = Math.min(n, r * 2);
|
|
550
573
|
}
|
|
551
574
|
})(), { close() {
|
|
552
575
|
o || (o = !0, a.abort());
|
|
@@ -569,20 +592,20 @@ function A() {
|
|
|
569
592
|
let e = globalThis.localStorage?.getItem(O);
|
|
570
593
|
if (e) return k = e, e;
|
|
571
594
|
} catch {}
|
|
572
|
-
let e =
|
|
595
|
+
let e = De();
|
|
573
596
|
k = e;
|
|
574
597
|
try {
|
|
575
598
|
globalThis.localStorage?.setItem(O, e);
|
|
576
599
|
} catch {}
|
|
577
600
|
return e;
|
|
578
601
|
}
|
|
579
|
-
function
|
|
602
|
+
function Ee() {
|
|
580
603
|
k = void 0;
|
|
581
604
|
try {
|
|
582
605
|
globalThis.localStorage?.removeItem(O);
|
|
583
606
|
} catch {}
|
|
584
607
|
}
|
|
585
|
-
function
|
|
608
|
+
function De() {
|
|
586
609
|
let e = globalThis.crypto;
|
|
587
610
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
588
611
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -594,7 +617,7 @@ function Ee() {
|
|
|
594
617
|
}
|
|
595
618
|
//#endregion
|
|
596
619
|
//#region src/core/drm/headers.ts
|
|
597
|
-
function
|
|
620
|
+
function Oe(e, t, n = {}) {
|
|
598
621
|
let r = {
|
|
599
622
|
"x-api-key": t.apiKey,
|
|
600
623
|
"X-Match-Urn": e.matchUrn,
|
|
@@ -605,19 +628,19 @@ function De(e, t, n = {}) {
|
|
|
605
628
|
}
|
|
606
629
|
//#endregion
|
|
607
630
|
//#region src/core/bandwidthMemory.ts
|
|
608
|
-
var j = "havik.player.bandwidth",
|
|
609
|
-
function
|
|
631
|
+
var j = "havik.player.bandwidth", ke = .8, Ae = 2e7, je = 3e5;
|
|
632
|
+
function Me() {
|
|
610
633
|
return globalThis.navigator?.connection;
|
|
611
634
|
}
|
|
612
|
-
function
|
|
613
|
-
let e =
|
|
635
|
+
function Ne() {
|
|
636
|
+
let e = Me()?.type;
|
|
614
637
|
return typeof e == "string" && e !== "" && e !== "unknown" ? e : "any";
|
|
615
638
|
}
|
|
616
|
-
function
|
|
617
|
-
let e =
|
|
639
|
+
function Pe() {
|
|
640
|
+
let e = Me()?.downlink;
|
|
618
641
|
return typeof e == "number" && Number.isFinite(e) && e > 0 ? e * 1e6 : void 0;
|
|
619
642
|
}
|
|
620
|
-
function
|
|
643
|
+
function Fe() {
|
|
621
644
|
try {
|
|
622
645
|
let e = globalThis.localStorage?.getItem(j);
|
|
623
646
|
if (!e) return {};
|
|
@@ -627,18 +650,18 @@ function Ne() {
|
|
|
627
650
|
return {};
|
|
628
651
|
}
|
|
629
652
|
}
|
|
630
|
-
function
|
|
631
|
-
let t =
|
|
653
|
+
function Ie(e = Date.now()) {
|
|
654
|
+
let t = Fe()[Ne()];
|
|
632
655
|
if (!t || typeof t.bps != "number" || typeof t.at != "number" || !Number.isFinite(t.bps) || t.bps <= 0) return;
|
|
633
656
|
let n = e - t.at;
|
|
634
657
|
if (n < 0 || n > 2592e5) return;
|
|
635
|
-
let r =
|
|
636
|
-
return Math.round(Math.min(
|
|
658
|
+
let r = Pe(), i = r === void 0 ? t.bps : Math.min(t.bps, r);
|
|
659
|
+
return Math.round(Math.min(Ae, Math.max(je, i * ke)));
|
|
637
660
|
}
|
|
638
|
-
function
|
|
661
|
+
function Le(e, t = Date.now()) {
|
|
639
662
|
if (!Number.isFinite(e) || e <= 0) return;
|
|
640
|
-
let n =
|
|
641
|
-
n[
|
|
663
|
+
let n = Fe();
|
|
664
|
+
n[Ne()] = {
|
|
642
665
|
bps: Math.round(e),
|
|
643
666
|
at: t
|
|
644
667
|
};
|
|
@@ -646,17 +669,17 @@ function Fe(e, t = Date.now()) {
|
|
|
646
669
|
globalThis.localStorage?.setItem(j, JSON.stringify(n));
|
|
647
670
|
} catch {}
|
|
648
671
|
}
|
|
649
|
-
function
|
|
672
|
+
function Re() {
|
|
650
673
|
try {
|
|
651
674
|
globalThis.localStorage?.removeItem(j);
|
|
652
675
|
} catch {}
|
|
653
676
|
}
|
|
654
677
|
//#endregion
|
|
655
678
|
//#region src/core/drm/cdm.ts
|
|
656
|
-
var
|
|
657
|
-
function
|
|
658
|
-
let n =
|
|
659
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
679
|
+
var ze = /* @__PURE__ */ new WeakMap();
|
|
680
|
+
function Be(e, t) {
|
|
681
|
+
let n = ze.get(e);
|
|
682
|
+
n || (n = /* @__PURE__ */ new Map(), ze.set(e, n));
|
|
660
683
|
let r = n.get(t.keySystem);
|
|
661
684
|
if (r) return r;
|
|
662
685
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -664,22 +687,22 @@ function Re(e, t) {
|
|
|
664
687
|
});
|
|
665
688
|
return n.set(t.keySystem, i), i;
|
|
666
689
|
}
|
|
667
|
-
function
|
|
690
|
+
function M() {
|
|
668
691
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
669
692
|
}
|
|
670
|
-
var
|
|
671
|
-
function
|
|
693
|
+
var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
694
|
+
function Ve(e) {
|
|
672
695
|
return e.startsWith("com.widevine");
|
|
673
696
|
}
|
|
674
|
-
function
|
|
675
|
-
if (!
|
|
697
|
+
function P(e, t) {
|
|
698
|
+
if (!Ve(e)) return t;
|
|
676
699
|
let n = (e, t) => {
|
|
677
700
|
let n = e.videoCapabilities;
|
|
678
701
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
679
|
-
let n =
|
|
680
|
-
return n === -1 ||
|
|
702
|
+
let n = N.indexOf(e.robustness);
|
|
703
|
+
return n === -1 || N.indexOf(t) > n;
|
|
681
704
|
});
|
|
682
|
-
}, r =
|
|
705
|
+
}, r = N.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
683
706
|
...t,
|
|
684
707
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
685
708
|
...t,
|
|
@@ -688,53 +711,53 @@ function F(e, t) {
|
|
|
688
711
|
})));
|
|
689
712
|
return [...t, ...r];
|
|
690
713
|
}
|
|
691
|
-
function
|
|
692
|
-
return (t, n) =>
|
|
714
|
+
function He(e) {
|
|
715
|
+
return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, P(t, n)).then((t) => ({
|
|
693
716
|
keySystem: t.keySystem,
|
|
694
717
|
getConfiguration: () => t.getConfiguration(),
|
|
695
|
-
createMediaKeys: () =>
|
|
718
|
+
createMediaKeys: () => Be(e, t)
|
|
696
719
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
697
720
|
}
|
|
698
|
-
var
|
|
721
|
+
var F = {
|
|
699
722
|
video: "SW_SECURE_DECODE",
|
|
700
723
|
audio: "SW_SECURE_CRYPTO",
|
|
701
724
|
scheme: "cbcs"
|
|
702
725
|
};
|
|
703
|
-
function
|
|
704
|
-
if (!
|
|
726
|
+
function Ue(e) {
|
|
727
|
+
if (!M()) return;
|
|
705
728
|
let t = (e, t) => ({
|
|
706
729
|
contentType: e,
|
|
707
730
|
robustness: t,
|
|
708
|
-
encryptionScheme:
|
|
731
|
+
encryptionScheme: F.scheme
|
|
709
732
|
});
|
|
710
|
-
|
|
733
|
+
He(e)("com.widevine.alpha", [{
|
|
711
734
|
initDataTypes: ["cenc"],
|
|
712
735
|
distinctiveIdentifier: "optional",
|
|
713
736
|
persistentState: "optional",
|
|
714
737
|
sessionTypes: ["temporary"],
|
|
715
|
-
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"",
|
|
716
|
-
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"",
|
|
738
|
+
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", F.audio)],
|
|
739
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", F.video)]
|
|
717
740
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
718
741
|
}
|
|
719
|
-
function
|
|
720
|
-
let t =
|
|
742
|
+
function I(e) {
|
|
743
|
+
let t = L(e);
|
|
721
744
|
if (/^avc[13]/.test(t)) return "avc";
|
|
722
745
|
if (/^(hvc1|hev1)/.test(t)) return "hevc";
|
|
723
746
|
if (/^(dvh1|dvhe)/.test(t)) return "dv";
|
|
724
747
|
if (t.startsWith("av01")) return "av1";
|
|
725
748
|
if (/^vp0?9/.test(t)) return "vp9";
|
|
726
749
|
}
|
|
727
|
-
function
|
|
750
|
+
function L(e) {
|
|
728
751
|
return (e ?? "").trim().toLowerCase();
|
|
729
752
|
}
|
|
730
|
-
var
|
|
753
|
+
var We = {
|
|
731
754
|
hevc: "hvc1.1.6.L93.90",
|
|
732
755
|
dv: "dvh1.05.06",
|
|
733
756
|
av1: "av01.0.05M.08",
|
|
734
757
|
vp9: "vp09.00.10.08"
|
|
735
|
-
},
|
|
736
|
-
function
|
|
737
|
-
let t =
|
|
758
|
+
}, Ge = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
|
|
759
|
+
function Ke(e) {
|
|
760
|
+
let t = L(e), n = Ge.get(t);
|
|
738
761
|
if (n) return n;
|
|
739
762
|
let r = {
|
|
740
763
|
initDataTypes: ["cenc"],
|
|
@@ -743,32 +766,32 @@ function We(e) {
|
|
|
743
766
|
sessionTypes: ["temporary"],
|
|
744
767
|
videoCapabilities: [{
|
|
745
768
|
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
746
|
-
robustness:
|
|
747
|
-
encryptionScheme:
|
|
769
|
+
robustness: F.video,
|
|
770
|
+
encryptionScheme: F.scheme
|
|
748
771
|
}]
|
|
749
772
|
}, i = (async () => {
|
|
750
773
|
try {
|
|
751
|
-
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha",
|
|
774
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", P("com.widevine.alpha", [r])), !0;
|
|
752
775
|
} catch {
|
|
753
776
|
return !1;
|
|
754
777
|
}
|
|
755
|
-
})().then((e) => (
|
|
756
|
-
return
|
|
778
|
+
})().then((e) => (R.set(t, e), e));
|
|
779
|
+
return Ge.set(t, i), i;
|
|
757
780
|
}
|
|
758
|
-
function
|
|
759
|
-
if (
|
|
781
|
+
function qe() {
|
|
782
|
+
if (M()) for (let e of Object.values(We)) Ke(e);
|
|
760
783
|
}
|
|
761
|
-
function
|
|
762
|
-
let t =
|
|
763
|
-
if (t) return t === "avc" ? !0 :
|
|
784
|
+
function Je(e) {
|
|
785
|
+
let t = I(e);
|
|
786
|
+
if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(We[t]));
|
|
764
787
|
}
|
|
765
788
|
//#endregion
|
|
766
789
|
//#region src/core/drm/support.ts
|
|
767
|
-
var
|
|
790
|
+
var Ye = 5e3, Xe = "video/mp4; codecs=\"avc1.42E01E\"", Ze = "audio/mp4; codecs=\"mp4a.40.2\"", Qe = {
|
|
768
791
|
widevine: ["com.widevine.alpha"],
|
|
769
792
|
fairplay: ["com.apple.fps"]
|
|
770
793
|
};
|
|
771
|
-
function
|
|
794
|
+
function $e(e) {
|
|
772
795
|
return e === "fairplay" ? [{
|
|
773
796
|
initDataTypes: [
|
|
774
797
|
"sinf",
|
|
@@ -776,30 +799,30 @@ function Ze(e) {
|
|
|
776
799
|
"cenc"
|
|
777
800
|
],
|
|
778
801
|
videoCapabilities: [{
|
|
779
|
-
contentType:
|
|
802
|
+
contentType: Xe,
|
|
780
803
|
robustness: "",
|
|
781
804
|
encryptionScheme: "cbcs"
|
|
782
805
|
}],
|
|
783
806
|
audioCapabilities: [{
|
|
784
|
-
contentType:
|
|
807
|
+
contentType: Ze,
|
|
785
808
|
robustness: "",
|
|
786
809
|
encryptionScheme: "cbcs"
|
|
787
810
|
}]
|
|
788
|
-
}] :
|
|
811
|
+
}] : P("com.widevine.alpha", [{
|
|
789
812
|
initDataTypes: ["cenc"],
|
|
790
813
|
videoCapabilities: [{
|
|
791
|
-
contentType:
|
|
792
|
-
robustness:
|
|
793
|
-
encryptionScheme:
|
|
814
|
+
contentType: Xe,
|
|
815
|
+
robustness: F.video,
|
|
816
|
+
encryptionScheme: F.scheme
|
|
794
817
|
}],
|
|
795
818
|
audioCapabilities: [{
|
|
796
|
-
contentType:
|
|
797
|
-
robustness:
|
|
798
|
-
encryptionScheme:
|
|
819
|
+
contentType: Ze,
|
|
820
|
+
robustness: F.audio,
|
|
821
|
+
encryptionScheme: F.scheme
|
|
799
822
|
}]
|
|
800
823
|
}]);
|
|
801
824
|
}
|
|
802
|
-
function
|
|
825
|
+
function et(e, t) {
|
|
803
826
|
return new Promise((n, r) => {
|
|
804
827
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
805
828
|
e.then((e) => {
|
|
@@ -809,8 +832,8 @@ function Qe(e, t) {
|
|
|
809
832
|
});
|
|
810
833
|
});
|
|
811
834
|
}
|
|
812
|
-
async function
|
|
813
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
835
|
+
async function tt(e = {}) {
|
|
836
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ye, r = {};
|
|
814
837
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
815
838
|
verdict: "insecure-context",
|
|
816
839
|
detail: r
|
|
@@ -822,7 +845,7 @@ async function $e(e = {}) {
|
|
|
822
845
|
};
|
|
823
846
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
824
847
|
for (let e of t) {
|
|
825
|
-
let t =
|
|
848
|
+
let t = Qe[e];
|
|
826
849
|
if (!t) {
|
|
827
850
|
r[e] = "unknown system";
|
|
828
851
|
continue;
|
|
@@ -833,7 +856,7 @@ async function $e(e = {}) {
|
|
|
833
856
|
break;
|
|
834
857
|
}
|
|
835
858
|
try {
|
|
836
|
-
return await
|
|
859
|
+
return await et((await et(i(n, $e(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
837
860
|
verdict: "supported",
|
|
838
861
|
system: e,
|
|
839
862
|
detail: r
|
|
@@ -857,37 +880,37 @@ async function $e(e = {}) {
|
|
|
857
880
|
}
|
|
858
881
|
//#endregion
|
|
859
882
|
//#region src/core/manifest.ts
|
|
860
|
-
var
|
|
861
|
-
function
|
|
862
|
-
return
|
|
883
|
+
var nt = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
884
|
+
function rt(e) {
|
|
885
|
+
return nt.test(e);
|
|
863
886
|
}
|
|
864
887
|
//#endregion
|
|
865
888
|
//#region src/core/env.ts
|
|
866
|
-
var
|
|
889
|
+
var it = {
|
|
867
890
|
integration: "https://feed-dev.oddin-video.gg",
|
|
868
891
|
production: "https://feed.oddin-video.gg"
|
|
869
892
|
};
|
|
870
|
-
function
|
|
871
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
893
|
+
function at(e) {
|
|
894
|
+
let t = Object.prototype.hasOwnProperty.call(it, e) ? it[e] : void 0;
|
|
872
895
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
873
896
|
return t;
|
|
874
897
|
}
|
|
875
898
|
//#endregion
|
|
876
899
|
//#region src/core/stats.ts
|
|
877
|
-
var
|
|
878
|
-
function
|
|
900
|
+
var z = { droppedFrames: 0 };
|
|
901
|
+
function ot(e) {
|
|
879
902
|
try {
|
|
880
903
|
return new URL(e).host;
|
|
881
904
|
} catch {
|
|
882
905
|
return "";
|
|
883
906
|
}
|
|
884
907
|
}
|
|
885
|
-
var
|
|
886
|
-
function
|
|
908
|
+
var st = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
909
|
+
function ct(e) {
|
|
887
910
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
888
911
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
889
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
890
|
-
let e =
|
|
912
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || st.test(i.name)) && i.startTime >= n) {
|
|
913
|
+
let e = ot(i.name);
|
|
891
914
|
e && (t = e, n = i.startTime);
|
|
892
915
|
}
|
|
893
916
|
return t;
|
|
@@ -899,7 +922,7 @@ function B(e) {
|
|
|
899
922
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
900
923
|
};
|
|
901
924
|
}
|
|
902
|
-
var
|
|
925
|
+
var lt = class {
|
|
903
926
|
video;
|
|
904
927
|
baseFrames = 0;
|
|
905
928
|
baseDropped = 0;
|
|
@@ -922,7 +945,7 @@ var ct = class {
|
|
|
922
945
|
};
|
|
923
946
|
}
|
|
924
947
|
};
|
|
925
|
-
function
|
|
948
|
+
function ut(e, t) {
|
|
926
949
|
let n = [
|
|
927
950
|
["playing", () => t("playing")],
|
|
928
951
|
["waiting", () => t("buffering")],
|
|
@@ -939,8 +962,8 @@ function lt(e, t) {
|
|
|
939
962
|
}
|
|
940
963
|
//#endregion
|
|
941
964
|
//#region src/core/engine/native.ts
|
|
942
|
-
var
|
|
943
|
-
function
|
|
965
|
+
var dt = 2e3, ft = 3, V = 500, pt = 6e3, mt = .25, ht = 250, gt = .05, _t = 4, vt = 12e3, yt = .25, bt = 1e3;
|
|
966
|
+
function xt(e) {
|
|
944
967
|
try {
|
|
945
968
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
946
969
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -956,7 +979,7 @@ function U() {
|
|
|
956
979
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
957
980
|
return e || t;
|
|
958
981
|
}
|
|
959
|
-
function
|
|
982
|
+
function St() {
|
|
960
983
|
if (typeof navigator > "u" || !U()) return !1;
|
|
961
984
|
let e = navigator.userAgent ?? "";
|
|
962
985
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
@@ -991,7 +1014,7 @@ var W = class {
|
|
|
991
1014
|
frameCounter;
|
|
992
1015
|
detachFrames = null;
|
|
993
1016
|
constructor(e) {
|
|
994
|
-
this.deps = e, this.frameCounter = new
|
|
1017
|
+
this.deps = e, this.frameCounter = new lt(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
|
|
995
1018
|
}
|
|
996
1019
|
async load() {
|
|
997
1020
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1012,7 +1035,7 @@ var W = class {
|
|
|
1012
1035
|
type: "error",
|
|
1013
1036
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
1014
1037
|
fatal: !0
|
|
1015
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
1038
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = wt(t.manifestUrl, t.analytics?.sid), e.load();
|
|
1016
1039
|
}
|
|
1017
1040
|
startLoad() {
|
|
1018
1041
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -1024,20 +1047,26 @@ var W = class {
|
|
|
1024
1047
|
this.savedPreload === null ? e.removeAttribute("preload") : e.setAttribute("preload", this.savedPreload);
|
|
1025
1048
|
}
|
|
1026
1049
|
armFairPlay() {
|
|
1027
|
-
let { video: e, descriptor: t, credential: r, deviceId:
|
|
1028
|
-
if (!
|
|
1029
|
-
this.fairplayLicenseUrl =
|
|
1030
|
-
let
|
|
1050
|
+
let { video: e, descriptor: t, credential: r, deviceId: o, userId: s, emit: c } = this.deps, l = t.drm?.fairplay;
|
|
1051
|
+
if (!l) return;
|
|
1052
|
+
this.fairplayLicenseUrl = l.licenseUrl;
|
|
1053
|
+
let u = (e, t, r, i) => c({
|
|
1031
1054
|
type: "error",
|
|
1032
|
-
error: new n(
|
|
1055
|
+
error: new n(a(t, i), t, e, i ? { serverCode: i } : void 0),
|
|
1033
1056
|
fatal: r
|
|
1034
|
-
})
|
|
1057
|
+
}), d = async (e) => {
|
|
1058
|
+
try {
|
|
1059
|
+
return await e.text();
|
|
1060
|
+
} catch {
|
|
1061
|
+
return "";
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1035
1064
|
this.onEncrypted = (n) => {
|
|
1036
|
-
let
|
|
1037
|
-
|
|
1065
|
+
let a = n;
|
|
1066
|
+
a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = xt(a.initData), (async () => {
|
|
1038
1067
|
try {
|
|
1039
1068
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
1040
|
-
initDataTypes: [
|
|
1069
|
+
initDataTypes: [a.initDataType],
|
|
1041
1070
|
videoCapabilities: [{
|
|
1042
1071
|
contentType: "application/vnd.apple.mpegurl",
|
|
1043
1072
|
robustness: ""
|
|
@@ -1045,39 +1074,40 @@ var W = class {
|
|
|
1045
1074
|
distinctiveIdentifier: "not-allowed",
|
|
1046
1075
|
persistentState: "not-allowed",
|
|
1047
1076
|
sessionTypes: ["temporary"]
|
|
1048
|
-
}])).createMediaKeys(),
|
|
1049
|
-
if (!
|
|
1050
|
-
this.fairplayArmed = !1,
|
|
1077
|
+
}])).createMediaKeys(), c = await fetch(l.certificateUrl, { headers: { "x-api-key": r.apiKey } });
|
|
1078
|
+
if (!c.ok) {
|
|
1079
|
+
this.fairplayArmed = !1, u(`FairPlay certificate request failed: ${c.status}`, c.status, !0);
|
|
1051
1080
|
return;
|
|
1052
1081
|
}
|
|
1053
|
-
await n.setServerCertificate(await
|
|
1054
|
-
let
|
|
1055
|
-
this.keySession =
|
|
1082
|
+
await n.setServerCertificate(await c.arrayBuffer()), await e.setMediaKeys(n);
|
|
1083
|
+
let f = n.createSession();
|
|
1084
|
+
this.keySession = f, f.addEventListener("message", (e) => {
|
|
1056
1085
|
(async () => {
|
|
1057
1086
|
try {
|
|
1058
|
-
let n = await fetch(this.fairplayLicenseUrl ??
|
|
1087
|
+
let n = await fetch(this.fairplayLicenseUrl ?? l.licenseUrl, {
|
|
1059
1088
|
method: "POST",
|
|
1060
1089
|
body: e.message,
|
|
1061
1090
|
headers: {
|
|
1062
1091
|
"x-api-key": r.apiKey,
|
|
1063
1092
|
"X-Match-Urn": t.matchUrn,
|
|
1064
|
-
"X-Device-Id":
|
|
1065
|
-
...
|
|
1093
|
+
"X-Device-Id": o,
|
|
1094
|
+
...s ? { "X-User-Id": s } : {},
|
|
1066
1095
|
...this.fairplayKeyIV ? { "X-Key-Iv": this.fairplayKeyIV } : {}
|
|
1067
1096
|
}
|
|
1068
1097
|
});
|
|
1069
1098
|
if (!n.ok) {
|
|
1070
|
-
|
|
1099
|
+
let e = n.status === 403 ? i(await d(n)) : void 0;
|
|
1100
|
+
u(`FairPlay license request failed: ${n.status}`, n.status, !0, e);
|
|
1071
1101
|
return;
|
|
1072
1102
|
}
|
|
1073
|
-
await
|
|
1103
|
+
await f.update(new Uint8Array(await n.arrayBuffer()));
|
|
1074
1104
|
} catch (e) {
|
|
1075
|
-
|
|
1105
|
+
u(`FairPlay license request failed: ${String(e)}`, 0, !0);
|
|
1076
1106
|
}
|
|
1077
1107
|
})();
|
|
1078
|
-
}), await
|
|
1108
|
+
}), await f.generateRequest(a.initDataType, a.initData);
|
|
1079
1109
|
} catch (e) {
|
|
1080
|
-
this.fairplayArmed = !1,
|
|
1110
|
+
this.fairplayArmed = !1, u(`FairPlay key session failed: ${String(e)}`, 0, !0);
|
|
1081
1111
|
}
|
|
1082
1112
|
})());
|
|
1083
1113
|
}, e.addEventListener("encrypted", this.onEncrypted);
|
|
@@ -1133,10 +1163,10 @@ var W = class {
|
|
|
1133
1163
|
droppedFrames: t.dropped,
|
|
1134
1164
|
decodedFrames: t.totalFrames
|
|
1135
1165
|
};
|
|
1136
|
-
if (this.cdnHost ||=
|
|
1166
|
+
if (this.cdnHost ||= ct(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1137
1167
|
n.isLive = !0;
|
|
1138
1168
|
let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
|
|
1139
|
-
Number.isFinite(r) && (n.atLiveEdge = r <=
|
|
1169
|
+
Number.isFinite(r) && (n.atLiveEdge = r <= _t, !e.paused && r >= 0 && (n.latencySeconds = r));
|
|
1140
1170
|
} else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
|
|
1141
1171
|
return n;
|
|
1142
1172
|
}
|
|
@@ -1154,7 +1184,7 @@ var W = class {
|
|
|
1154
1184
|
return;
|
|
1155
1185
|
}
|
|
1156
1186
|
let t = this.hiddenSince;
|
|
1157
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1187
|
+
this.hiddenSince = null, t != null && e - t >= dt && this.armRefocus();
|
|
1158
1188
|
}, this.onPageShow = (e) => {
|
|
1159
1189
|
e.persisted && this.armRefocus();
|
|
1160
1190
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
@@ -1164,7 +1194,7 @@ var W = class {
|
|
|
1164
1194
|
let e = this.liveEnd(), t = G, n = t(), r = 0, i = () => {
|
|
1165
1195
|
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1166
1196
|
r += V;
|
|
1167
|
-
let a = this.liveEnd(), o = a != null && (e == null || a >= e +
|
|
1197
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + mt), s = Math.max(r, t() - n) >= pt;
|
|
1168
1198
|
if (o || s && a != null) {
|
|
1169
1199
|
this.snapToLive();
|
|
1170
1200
|
return;
|
|
@@ -1184,9 +1214,9 @@ var W = class {
|
|
|
1184
1214
|
}, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
|
|
1185
1215
|
if (e.duration !== Infinity) return;
|
|
1186
1216
|
this.checkEndStale();
|
|
1187
|
-
let t =
|
|
1188
|
-
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >=
|
|
1189
|
-
},
|
|
1217
|
+
let t = Ct(e, e.currentTime);
|
|
1218
|
+
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= gt) && (this.bufferedAdvancedAt = G()), this.lastBufferedEnd = t);
|
|
1219
|
+
}, ht);
|
|
1190
1220
|
}
|
|
1191
1221
|
checkEndStale() {
|
|
1192
1222
|
if (this.endedEmitted) return;
|
|
@@ -1194,14 +1224,14 @@ var W = class {
|
|
|
1194
1224
|
this.lastTickAt = e;
|
|
1195
1225
|
let n = this.liveEnd();
|
|
1196
1226
|
if (n == null) return;
|
|
1197
|
-
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >=
|
|
1227
|
+
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= yt;
|
|
1198
1228
|
this.lastSeekableEnd = n;
|
|
1199
1229
|
let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
|
|
1200
|
-
if (r || t >
|
|
1230
|
+
if (r || t > bt || a || i.paused) {
|
|
1201
1231
|
this.edgeStampedAt = e;
|
|
1202
1232
|
return;
|
|
1203
1233
|
}
|
|
1204
|
-
e - (this.edgeStampedAt ?? e) >
|
|
1234
|
+
e - (this.edgeStampedAt ?? e) > vt && (this.endedEmitted = !0, this.deps.emit({
|
|
1205
1235
|
type: "ended",
|
|
1206
1236
|
reason: "stalled"
|
|
1207
1237
|
}));
|
|
@@ -1215,7 +1245,7 @@ var W = class {
|
|
|
1215
1245
|
liveEdgeEstimate() {
|
|
1216
1246
|
let e = this.deps.video;
|
|
1217
1247
|
if (e.duration !== Infinity) return null;
|
|
1218
|
-
let t = this.liveEnd(), n =
|
|
1248
|
+
let t = this.liveEnd(), n = Ct(e, e.currentTime) ?? this.lastBufferedEnd;
|
|
1219
1249
|
if (n != null) {
|
|
1220
1250
|
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (G() - e) / 1e3));
|
|
1221
1251
|
(t == null || r > t) && (t = r);
|
|
@@ -1231,7 +1261,7 @@ var W = class {
|
|
|
1231
1261
|
snapToLive() {
|
|
1232
1262
|
let e = this.deps.video, t = this.liveEnd();
|
|
1233
1263
|
if (t == null) return;
|
|
1234
|
-
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t -
|
|
1264
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - ft, r);
|
|
1235
1265
|
try {
|
|
1236
1266
|
e.currentTime = i;
|
|
1237
1267
|
} catch {}
|
|
@@ -1252,7 +1282,7 @@ var W = class {
|
|
|
1252
1282
|
function G() {
|
|
1253
1283
|
return typeof performance < "u" ? performance.now() : Date.now();
|
|
1254
1284
|
}
|
|
1255
|
-
function
|
|
1285
|
+
function Ct(e, t) {
|
|
1256
1286
|
let n = e.buffered;
|
|
1257
1287
|
if (!n || !Number.isFinite(t)) return null;
|
|
1258
1288
|
for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
|
|
@@ -1261,7 +1291,7 @@ function St(e, t) {
|
|
|
1261
1291
|
}
|
|
1262
1292
|
return null;
|
|
1263
1293
|
}
|
|
1264
|
-
function
|
|
1294
|
+
function wt(e, t) {
|
|
1265
1295
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1266
1296
|
}
|
|
1267
1297
|
//#endregion
|
|
@@ -1277,9 +1307,23 @@ function K(e, t = Date.now()) {
|
|
|
1277
1307
|
return !n || !/^\d+$/.test(n) ? !1 : Number(n) * 1e3 <= t;
|
|
1278
1308
|
}
|
|
1279
1309
|
//#endregion
|
|
1310
|
+
//#region src/core/drm/xhrBody.ts
|
|
1311
|
+
var Tt = 4096;
|
|
1312
|
+
function Et(e) {
|
|
1313
|
+
if (!e || typeof e != "object") return;
|
|
1314
|
+
let { response: t } = e;
|
|
1315
|
+
if (typeof t == "string") return t;
|
|
1316
|
+
let n;
|
|
1317
|
+
if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength > Tt)) try {
|
|
1318
|
+
return new TextDecoder().decode(n);
|
|
1319
|
+
} catch {
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
//#endregion
|
|
1280
1324
|
//#region src/core/engine/prefetch.ts
|
|
1281
|
-
var
|
|
1282
|
-
function
|
|
1325
|
+
var Dt = 15e3, Ot = 5e3, kt = 6;
|
|
1326
|
+
function At(e) {
|
|
1283
1327
|
try {
|
|
1284
1328
|
let t = new URL(e);
|
|
1285
1329
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1287,7 +1331,7 @@ function Dt(e) {
|
|
|
1287
1331
|
return e;
|
|
1288
1332
|
}
|
|
1289
1333
|
}
|
|
1290
|
-
var
|
|
1334
|
+
var jt = class {
|
|
1291
1335
|
cmcd;
|
|
1292
1336
|
entries = /* @__PURE__ */ new Map();
|
|
1293
1337
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1310,10 +1354,10 @@ var Ot = class {
|
|
|
1310
1354
|
}
|
|
1311
1355
|
prefetch(e, t, n) {
|
|
1312
1356
|
if (!this.isActive(t)) return;
|
|
1313
|
-
let r =
|
|
1357
|
+
let r = At(e);
|
|
1314
1358
|
if (this.entries.has(r)) return;
|
|
1315
1359
|
let i = this.perTrack.get(t) ?? 0;
|
|
1316
|
-
if (i >=
|
|
1360
|
+
if (i >= kt) return;
|
|
1317
1361
|
this.perTrack.set(t, i + 1);
|
|
1318
1362
|
let a = new AbortController(), o = {
|
|
1319
1363
|
started: performance.now(),
|
|
@@ -1327,10 +1371,10 @@ var Ot = class {
|
|
|
1327
1371
|
signal: a.signal
|
|
1328
1372
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1329
1373
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1330
|
-
},
|
|
1374
|
+
}, Dt);
|
|
1331
1375
|
}
|
|
1332
1376
|
take(e) {
|
|
1333
|
-
let t =
|
|
1377
|
+
let t = At(e), n = this.entries.get(t);
|
|
1334
1378
|
return n && this.entries.delete(t), n;
|
|
1335
1379
|
}
|
|
1336
1380
|
destroy() {
|
|
@@ -1350,13 +1394,13 @@ var Ot = class {
|
|
|
1350
1394
|
}
|
|
1351
1395
|
}
|
|
1352
1396
|
};
|
|
1353
|
-
function
|
|
1397
|
+
function Mt(t) {
|
|
1354
1398
|
let n = e.DefaultConfig?.loader;
|
|
1355
1399
|
if (typeof n != "function") return;
|
|
1356
1400
|
class r extends n {
|
|
1357
1401
|
served = !1;
|
|
1358
1402
|
cancelled = !1;
|
|
1359
|
-
stats =
|
|
1403
|
+
stats = Nt();
|
|
1360
1404
|
load(e, n, r) {
|
|
1361
1405
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1362
1406
|
if (!i) {
|
|
@@ -1364,7 +1408,7 @@ function kt(t) {
|
|
|
1364
1408
|
return;
|
|
1365
1409
|
}
|
|
1366
1410
|
this.served = !0;
|
|
1367
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1411
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Ot, s = setTimeout(() => {
|
|
1368
1412
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1369
1413
|
}, o);
|
|
1370
1414
|
i.bytes.then((o) => {
|
|
@@ -1391,7 +1435,7 @@ function kt(t) {
|
|
|
1391
1435
|
}
|
|
1392
1436
|
return r;
|
|
1393
1437
|
}
|
|
1394
|
-
function
|
|
1438
|
+
function Nt() {
|
|
1395
1439
|
return {
|
|
1396
1440
|
aborted: !1,
|
|
1397
1441
|
loaded: 0,
|
|
@@ -1415,10 +1459,10 @@ function At() {
|
|
|
1415
1459
|
}
|
|
1416
1460
|
};
|
|
1417
1461
|
}
|
|
1418
|
-
function
|
|
1462
|
+
function Pt(e) {
|
|
1419
1463
|
return e === "audio" ? "audio" : "main";
|
|
1420
1464
|
}
|
|
1421
|
-
function
|
|
1465
|
+
function Ft(e, t) {
|
|
1422
1466
|
let n = [];
|
|
1423
1467
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1424
1468
|
url: t.initSegment.url,
|
|
@@ -1437,24 +1481,24 @@ function Mt(e, t) {
|
|
|
1437
1481
|
}
|
|
1438
1482
|
//#endregion
|
|
1439
1483
|
//#region src/core/engine/hls.ts
|
|
1440
|
-
function
|
|
1484
|
+
function It() {
|
|
1441
1485
|
return e.isSupported();
|
|
1442
1486
|
}
|
|
1443
|
-
var
|
|
1444
|
-
function
|
|
1487
|
+
var Lt = 1e6, Rt = 20, zt = 1e4, Bt = 3, Vt = 5, Ht = 3, Ut = 1e4, Wt = 3e4, Gt = 12e3, Kt = 3e3, qt = .02, Jt = 6e3, Yt = .5, Xt = 3, Zt = .5, Qt = 1.1, $t = .25, en = 5e3, tn = 4e3, nn = 2, rn = 5, an = 2, on = 2, sn = 4, cn = 4, ln = 2e3, un = 3e4, dn = .2, fn = 30, pn = 2, mn = 2, hn = 9, gn = .5, _n = 64;
|
|
1488
|
+
function vn(e) {
|
|
1445
1489
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1446
1490
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1447
1491
|
return;
|
|
1448
1492
|
}
|
|
1449
|
-
e.liveSyncDuration ??=
|
|
1450
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1451
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1493
|
+
e.liveSyncDuration ??= mn;
|
|
1494
|
+
let t = Math.max(12, e.liveSyncDuration + hn);
|
|
1495
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), yn(e, e.liveSyncDuration);
|
|
1452
1496
|
}
|
|
1453
|
-
function
|
|
1497
|
+
function yn(e, t) {
|
|
1454
1498
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1455
1499
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1456
1500
|
}
|
|
1457
|
-
var
|
|
1501
|
+
var bn = class {
|
|
1458
1502
|
name = "hls";
|
|
1459
1503
|
hls = null;
|
|
1460
1504
|
deps;
|
|
@@ -1538,7 +1582,7 @@ var _n = class {
|
|
|
1538
1582
|
frameCounter;
|
|
1539
1583
|
detachFrames = null;
|
|
1540
1584
|
constructor(e) {
|
|
1541
|
-
this.deps = e, this.frameCounter = new
|
|
1585
|
+
this.deps = e, this.frameCounter = new lt(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1542
1586
|
}
|
|
1543
1587
|
async load() {
|
|
1544
1588
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1551,7 +1595,7 @@ var _n = class {
|
|
|
1551
1595
|
});
|
|
1552
1596
|
return;
|
|
1553
1597
|
}
|
|
1554
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1598
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ue(r), qe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1555
1599
|
let e = this.hls;
|
|
1556
1600
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1557
1601
|
let t = e.liveSyncPosition;
|
|
@@ -1574,7 +1618,7 @@ var _n = class {
|
|
|
1574
1618
|
}
|
|
1575
1619
|
this.loadSuspended = !0;
|
|
1576
1620
|
}
|
|
1577
|
-
},
|
|
1621
|
+
}, en));
|
|
1578
1622
|
}
|
|
1579
1623
|
resumeLoading() {
|
|
1580
1624
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1606,7 +1650,7 @@ var _n = class {
|
|
|
1606
1650
|
let t = e.liveSyncPosition;
|
|
1607
1651
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1608
1652
|
let { video: n } = this.deps;
|
|
1609
|
-
n.currentTime <= t +
|
|
1653
|
+
n.currentTime <= t + gn || (n.currentTime = t);
|
|
1610
1654
|
}
|
|
1611
1655
|
reanchorPartTimeline(e, t) {
|
|
1612
1656
|
let { frag: n, part: r } = t;
|
|
@@ -1618,7 +1662,7 @@ var _n = class {
|
|
|
1618
1662
|
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1619
1663
|
if (!s) return;
|
|
1620
1664
|
let c = a.startPTS - s.start;
|
|
1621
|
-
if (!(!Number.isFinite(c) || Math.abs(c) <
|
|
1665
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < qt)) {
|
|
1622
1666
|
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1623
1667
|
i.fragmentHint?.setStart(i.fragmentHint.start + c), this.deps.debug === !0 && console.info(`havik-player: LL-HLS timeline re-anchored by ${c >= 0 ? "+" : ""}${c.toFixed(3)}s at sn ${n.sn} (level ${n.level})`);
|
|
1624
1668
|
}
|
|
@@ -1641,12 +1685,12 @@ var _n = class {
|
|
|
1641
1685
|
emeEnabled: !0,
|
|
1642
1686
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1643
1687
|
drmSystemOptions: {
|
|
1644
|
-
videoRobustness:
|
|
1645
|
-
audioRobustness:
|
|
1646
|
-
videoEncryptionScheme:
|
|
1647
|
-
audioEncryptionScheme:
|
|
1688
|
+
videoRobustness: F.video,
|
|
1689
|
+
audioRobustness: F.audio,
|
|
1690
|
+
videoEncryptionScheme: F.scheme,
|
|
1691
|
+
audioEncryptionScheme: F.scheme
|
|
1648
1692
|
},
|
|
1649
|
-
...
|
|
1693
|
+
...M() ? { requestMediaKeySystemAccessFunc: He(t) } : {},
|
|
1650
1694
|
licenseXhrSetup: (e, t) => {
|
|
1651
1695
|
let o = performance.now(), s = () => {
|
|
1652
1696
|
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, e.addEventListener("loadend", () => {
|
|
@@ -1658,7 +1702,7 @@ var _n = class {
|
|
|
1658
1702
|
return;
|
|
1659
1703
|
}
|
|
1660
1704
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1661
|
-
u = setTimeout(() => e(void 0),
|
|
1705
|
+
u = setTimeout(() => e(void 0), Ut);
|
|
1662
1706
|
});
|
|
1663
1707
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1664
1708
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1674,20 +1718,20 @@ var _n = class {
|
|
|
1674
1718
|
...c
|
|
1675
1719
|
};
|
|
1676
1720
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !f.fLoader) {
|
|
1677
|
-
let e = new
|
|
1721
|
+
let e = new jt({
|
|
1678
1722
|
sessionId: n.analytics?.sid,
|
|
1679
1723
|
contentId: n.matchUrn
|
|
1680
|
-
}), t =
|
|
1724
|
+
}), t = Mt(e);
|
|
1681
1725
|
t && (this.prefetch = e, f.fLoader = t);
|
|
1682
1726
|
}
|
|
1683
|
-
|
|
1727
|
+
vn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
|
|
1684
1728
|
let p = new e(f);
|
|
1685
1729
|
if (this.hls = p, p.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(p, t)), p.on(e.Events.MANIFEST_PARSED, () => {
|
|
1686
1730
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(p), this.measureLadder(p), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1687
1731
|
}), p.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1688
1732
|
t?.frag?.type === "main" && (this.kickKind !== "dead" && this.clearKick(), (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
1689
1733
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1690
|
-
},
|
|
1734
|
+
}, Wt)));
|
|
1691
1735
|
}), p.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1692
1736
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1693
1737
|
}), p.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1695,10 +1739,10 @@ var _n = class {
|
|
|
1695
1739
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1696
1740
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1697
1741
|
let i = n?.loading;
|
|
1698
|
-
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 >
|
|
1742
|
+
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 > _n && this.requestTimesMs.shift());
|
|
1699
1743
|
let a = t?.frag?.url;
|
|
1700
1744
|
if (a) {
|
|
1701
|
-
let e =
|
|
1745
|
+
let e = ot(a);
|
|
1702
1746
|
e && (this.cdnHost = e);
|
|
1703
1747
|
}
|
|
1704
1748
|
}), p.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1712,15 +1756,15 @@ var _n = class {
|
|
|
1712
1756
|
}), p.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1713
1757
|
let t = this.prefetch;
|
|
1714
1758
|
p.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1715
|
-
let r = n?.frag, i =
|
|
1716
|
-
if (r && t.isActive(i)) for (let e of
|
|
1717
|
-
}), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1759
|
+
let r = n?.frag, i = Pt(r?.type);
|
|
1760
|
+
if (r && t.isActive(i)) for (let e of Ft(p, r)) t.prefetch(e.url, i, e.kind);
|
|
1761
|
+
}), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Pt(n?.frag?.type)));
|
|
1718
1762
|
}
|
|
1719
1763
|
p.on(e.Events.KEY_LOADED, () => {
|
|
1720
1764
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1721
1765
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1722
1766
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1723
|
-
},
|
|
1767
|
+
}, Kt), p.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1724
1768
|
this.renditionSwitches += 1;
|
|
1725
1769
|
let n = this.lastLevelIndex >= 0 ? p.levels[this.lastLevelIndex] : void 0, r = p.levels[t.level];
|
|
1726
1770
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1784,7 +1828,7 @@ var _n = class {
|
|
|
1784
1828
|
return;
|
|
1785
1829
|
}
|
|
1786
1830
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1787
|
-
let t = e > this.sizeCapLevel ?
|
|
1831
|
+
let t = e > this.sizeCapLevel ? ln : un;
|
|
1788
1832
|
this.capTimer = setTimeout(() => {
|
|
1789
1833
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1790
1834
|
}, t);
|
|
@@ -1794,9 +1838,9 @@ var _n = class {
|
|
|
1794
1838
|
this.ladderHeights = t.length ? [...new Set(t)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = e.levels.length ? Math.round(Math.max(...e.levels.map((e) => e.bitrate)) / 1e3) : 0;
|
|
1795
1839
|
}
|
|
1796
1840
|
dropLevelsWidevineCannotPlay(e) {
|
|
1797
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1798
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1799
|
-
for (let n of t)
|
|
1841
|
+
this.removeLevelsWhere(e, (e) => Je(e) !== !0);
|
|
1842
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
|
|
1843
|
+
for (let n of t) Ke(n).then((t) => {
|
|
1800
1844
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1801
1845
|
});
|
|
1802
1846
|
}
|
|
@@ -1804,10 +1848,10 @@ var _n = class {
|
|
|
1804
1848
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1805
1849
|
if (n.forEach((e, n) => {
|
|
1806
1850
|
let a = e.videoCodec;
|
|
1807
|
-
a &&
|
|
1851
|
+
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1808
1852
|
}), !r.length) return !1;
|
|
1809
1853
|
let a = [...i].join(", ");
|
|
1810
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !
|
|
1854
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Je(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1811
1855
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1812
1856
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1813
1857
|
}
|
|
@@ -1913,7 +1957,7 @@ var _n = class {
|
|
|
1913
1957
|
return;
|
|
1914
1958
|
}
|
|
1915
1959
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1916
|
-
!this.chaseSuspended && e >
|
|
1960
|
+
!this.chaseSuspended && e > Jt && this.suspendChasing(), e > Gt && this.emitEnded("stalled");
|
|
1917
1961
|
}
|
|
1918
1962
|
resetStarvationWindow() {
|
|
1919
1963
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1928,7 +1972,7 @@ var _n = class {
|
|
|
1928
1972
|
this.resetStarvationWindow();
|
|
1929
1973
|
return;
|
|
1930
1974
|
}
|
|
1931
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1975
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < Jt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > tn, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
|
|
1932
1976
|
if (this.starvedFrames = c, !a || l) {
|
|
1933
1977
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1934
1978
|
return;
|
|
@@ -1937,12 +1981,12 @@ var _n = class {
|
|
|
1937
1981
|
this.resetStarvationWindow();
|
|
1938
1982
|
return;
|
|
1939
1983
|
}
|
|
1940
|
-
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length >
|
|
1984
|
+
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > sn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= an && (this.clearKick(), this.starvationRebuilds < on)) {
|
|
1941
1985
|
this.starvationRebuilds += 1, this.resetStarvationWindow(), this.clearRecoveryReset(), console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
|
|
1942
1986
|
return;
|
|
1943
1987
|
}
|
|
1944
|
-
let u = i && this.starvedTicks >=
|
|
1945
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1988
|
+
let u = i && this.starvedTicks >= nn, d = !i && this.deadTicks >= sn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= cn;
|
|
1989
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= rn))) {
|
|
1946
1990
|
this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, this.kickKind = d ? "dead" : "quiet", this.clearRecoveryReset(), console.warn(d ? "havik-player: video starved while hls.js keeps loading media it never plays (dead pipeline at the live edge) — restarting the load" : "havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
|
|
1947
1991
|
try {
|
|
1948
1992
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1957,7 +2001,7 @@ var _n = class {
|
|
|
1957
2001
|
let t = e.latency, n = e.targetLatency;
|
|
1958
2002
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1959
2003
|
let r = t - n;
|
|
1960
|
-
!this.catchUpEngaged && r >
|
|
2004
|
+
!this.catchUpEngaged && r > Yt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Yt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1961
2005
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1962
2006
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1963
2007
|
}
|
|
@@ -1979,15 +2023,15 @@ var _n = class {
|
|
|
1979
2023
|
return;
|
|
1980
2024
|
}
|
|
1981
2025
|
let { totalFrames: n, dropped: r } = B(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
1982
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
2026
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < fn || o < 0) {
|
|
1983
2027
|
this.fpsBadTicks = 0;
|
|
1984
2028
|
return;
|
|
1985
2029
|
}
|
|
1986
|
-
if (o <=
|
|
2030
|
+
if (o <= dn * a) {
|
|
1987
2031
|
this.fpsBadTicks = 0;
|
|
1988
2032
|
return;
|
|
1989
2033
|
}
|
|
1990
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
2034
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < pn) return;
|
|
1991
2035
|
this.fpsBadTicks = 0;
|
|
1992
2036
|
let s = e.levels, c = s[e.currentLevel];
|
|
1993
2037
|
if (!c) return;
|
|
@@ -2004,20 +2048,20 @@ var _n = class {
|
|
|
2004
2048
|
return;
|
|
2005
2049
|
}
|
|
2006
2050
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
2007
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
2051
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Qt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
2008
2052
|
this.resetChaseWindow();
|
|
2009
2053
|
return;
|
|
2010
2054
|
}
|
|
2011
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
2055
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= Zt) {
|
|
2012
2056
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
2013
2057
|
return;
|
|
2014
2058
|
}
|
|
2015
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
2059
|
+
if (this.chaseTicks += 1, this.chaseTicks < Xt) return;
|
|
2016
2060
|
this.resetChaseWindow();
|
|
2017
2061
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2018
2062
|
if (!(a > 1)) return;
|
|
2019
2063
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
2020
|
-
s < o +
|
|
2064
|
+
s < o + $t || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s);
|
|
2021
2065
|
}
|
|
2022
2066
|
suspendChasing() {
|
|
2023
2067
|
let e = this.hls;
|
|
@@ -2047,14 +2091,14 @@ var _n = class {
|
|
|
2047
2091
|
} catch {}
|
|
2048
2092
|
}
|
|
2049
2093
|
startEstimate() {
|
|
2050
|
-
return this.deps.rememberBandwidth === !1 ?
|
|
2094
|
+
return this.deps.rememberBandwidth === !1 ? Lt : Ie() ?? Lt;
|
|
2051
2095
|
}
|
|
2052
2096
|
maybeRememberBandwidth(e) {
|
|
2053
|
-
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded <
|
|
2097
|
+
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Rt) return;
|
|
2054
2098
|
let t = Date.now();
|
|
2055
|
-
if (!e && t - this.bwSavedAt <
|
|
2099
|
+
if (!e && t - this.bwSavedAt < zt) return;
|
|
2056
2100
|
let n = this.hls?.bandwidthEstimate;
|
|
2057
|
-
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t,
|
|
2101
|
+
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Le(n));
|
|
2058
2102
|
}
|
|
2059
2103
|
destroy() {
|
|
2060
2104
|
if (this.maybeRememberBandwidth(!0), this.detachFrames?.(), this.detachFrames = null, this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
|
|
@@ -2072,7 +2116,7 @@ var _n = class {
|
|
|
2072
2116
|
scheduleLicenseRetry(t) {
|
|
2073
2117
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
2074
2118
|
let n = t.response?.code ?? 0;
|
|
2075
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
2119
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Ht) return !1;
|
|
2076
2120
|
this.licenseRecoveries += 1;
|
|
2077
2121
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
2078
2122
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -2104,7 +2148,7 @@ var _n = class {
|
|
|
2104
2148
|
return;
|
|
2105
2149
|
}
|
|
2106
2150
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
2107
|
-
if (this.networkRecoveries <
|
|
2151
|
+
if (this.networkRecoveries < Vt) {
|
|
2108
2152
|
this.networkRecoveries += 1;
|
|
2109
2153
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
2110
2154
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -2121,7 +2165,7 @@ var _n = class {
|
|
|
2121
2165
|
return;
|
|
2122
2166
|
}
|
|
2123
2167
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
2124
|
-
if (this.mediaRecoveries <
|
|
2168
|
+
if (this.mediaRecoveries < Bt) {
|
|
2125
2169
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
2126
2170
|
return;
|
|
2127
2171
|
}
|
|
@@ -2141,25 +2185,26 @@ var _n = class {
|
|
|
2141
2185
|
});
|
|
2142
2186
|
}
|
|
2143
2187
|
}
|
|
2144
|
-
toError(
|
|
2145
|
-
let
|
|
2146
|
-
return new n(
|
|
2188
|
+
toError(t, r = "PLAYBACK") {
|
|
2189
|
+
let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(Et(t.networkDetails)) : void 0;
|
|
2190
|
+
return new n(r === "DRM" ? a(o, l) : o === 401 ? "UNAUTHORIZED" : o === 403 ? "FORBIDDEN" : "INTERNAL", o, `${r} error: ${s}${c ? ` (${c})` : ""}`, l ? { serverCode: l } : void 0);
|
|
2147
2191
|
}
|
|
2148
|
-
},
|
|
2192
|
+
}, xn = 15e3, Sn = 6e5, Cn = 3e5, wn = 100, q = 1, Tn = 1e3, En = 3e4, Dn = 1e3, On = {
|
|
2149
2193
|
inline: "PRESENTATION_INLINE",
|
|
2150
2194
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2151
2195
|
pip: "PRESENTATION_PIP"
|
|
2152
|
-
},
|
|
2196
|
+
}, kn = {
|
|
2153
2197
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2154
2198
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2155
2199
|
none: "KEY_SYSTEM_NONE"
|
|
2156
2200
|
};
|
|
2157
|
-
function
|
|
2201
|
+
function An(e, t) {
|
|
2158
2202
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
2159
2203
|
}
|
|
2160
|
-
var
|
|
2204
|
+
var jn = /* @__PURE__ */ new Set([
|
|
2161
2205
|
"INVALID_URN",
|
|
2162
2206
|
"NOT_FOUND",
|
|
2207
|
+
"GEO_DENIED",
|
|
2163
2208
|
"GONE",
|
|
2164
2209
|
"TOO_EARLY",
|
|
2165
2210
|
"UNAVAILABLE",
|
|
@@ -2177,7 +2222,7 @@ var On = /* @__PURE__ */ new Set([
|
|
|
2177
2222
|
ended: "PLAYER_STATE_ENDED",
|
|
2178
2223
|
error: "PLAYER_STATE_ERROR"
|
|
2179
2224
|
};
|
|
2180
|
-
function
|
|
2225
|
+
function Mn(e) {
|
|
2181
2226
|
try {
|
|
2182
2227
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2183
2228
|
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);
|
|
@@ -2185,8 +2230,8 @@ function kn(e) {
|
|
|
2185
2230
|
return;
|
|
2186
2231
|
}
|
|
2187
2232
|
}
|
|
2188
|
-
var
|
|
2189
|
-
function
|
|
2233
|
+
var Nn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Pn = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), Fn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2234
|
+
function In(e) {
|
|
2190
2235
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2191
2236
|
let t;
|
|
2192
2237
|
try {
|
|
@@ -2195,19 +2240,19 @@ function Nn(e) {
|
|
|
2195
2240
|
} catch {
|
|
2196
2241
|
return;
|
|
2197
2242
|
}
|
|
2198
|
-
if (
|
|
2199
|
-
Y.add(t),
|
|
2243
|
+
if (Pn.has(t) && !Y.has(t)) {
|
|
2244
|
+
Y.add(t), _(Fn(new URL(t).origin));
|
|
2200
2245
|
for (let e of X) e.noteCspBlocked();
|
|
2201
2246
|
}
|
|
2202
2247
|
}
|
|
2203
|
-
function
|
|
2204
|
-
return
|
|
2248
|
+
function Ln(e, t) {
|
|
2249
|
+
return _(t, e), { disabledReason: t };
|
|
2205
2250
|
}
|
|
2206
|
-
function
|
|
2207
|
-
if (n) return t && !
|
|
2251
|
+
function Rn(e, t, n) {
|
|
2252
|
+
if (n) return t && !Nn(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2208
2253
|
if (t) return { endpoint: t };
|
|
2209
|
-
if (t !== void 0) return
|
|
2210
|
-
let r =
|
|
2254
|
+
if (t !== void 0) return Ln("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).");
|
|
2255
|
+
let r = Mn(e);
|
|
2211
2256
|
if (r) return { endpoint: r };
|
|
2212
2257
|
let i;
|
|
2213
2258
|
try {
|
|
@@ -2215,9 +2260,9 @@ function Fn(e, t, n) {
|
|
|
2215
2260
|
} catch {
|
|
2216
2261
|
i = e;
|
|
2217
2262
|
}
|
|
2218
|
-
return
|
|
2263
|
+
return Ln(i, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${i}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
|
|
2219
2264
|
}
|
|
2220
|
-
var
|
|
2265
|
+
var zn = class {
|
|
2221
2266
|
opts;
|
|
2222
2267
|
url;
|
|
2223
2268
|
cspKey;
|
|
@@ -2299,8 +2344,8 @@ var In = class {
|
|
|
2299
2344
|
constructor(e) {
|
|
2300
2345
|
this.opts = {
|
|
2301
2346
|
...e,
|
|
2302
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2303
|
-
idleMs: e.idleMs ??
|
|
2347
|
+
heartbeatMs: e.heartbeatMs ?? xn,
|
|
2348
|
+
idleMs: e.idleMs ?? Sn
|
|
2304
2349
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2305
2350
|
try {
|
|
2306
2351
|
let e = new URL(this.url);
|
|
@@ -2317,11 +2362,11 @@ var In = class {
|
|
|
2317
2362
|
sdkVersion: this.opts.sdkVersion,
|
|
2318
2363
|
...this.opts.environment
|
|
2319
2364
|
};
|
|
2320
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2365
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Tn), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.cspKey && Pn.add(this.cspKey), document.addEventListener("securitypolicyviolation", In), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2321
2366
|
}
|
|
2322
2367
|
checkSuspension(e) {
|
|
2323
2368
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2324
|
-
let t = Math.max(this.opts.idleMs,
|
|
2369
|
+
let t = Math.max(this.opts.idleMs, Cn);
|
|
2325
2370
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2326
2371
|
}
|
|
2327
2372
|
syncIdle(e) {
|
|
@@ -2344,12 +2389,12 @@ var In = class {
|
|
|
2344
2389
|
let a = {
|
|
2345
2390
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2346
2391
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2347
|
-
presentation:
|
|
2392
|
+
presentation: On[this.presentation]
|
|
2348
2393
|
}, o = this.causeOf(e, t, i);
|
|
2349
2394
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2350
2395
|
}
|
|
2351
2396
|
seekInduced(e) {
|
|
2352
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2397
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < Dn;
|
|
2353
2398
|
}
|
|
2354
2399
|
causeOf(e, t, n) {
|
|
2355
2400
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2422,8 +2467,8 @@ var In = class {
|
|
|
2422
2467
|
stageOf(e, t, n) {
|
|
2423
2468
|
let r = n ?? "";
|
|
2424
2469
|
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";
|
|
2425
|
-
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2426
|
-
if (
|
|
2470
|
+
if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
|
|
2471
|
+
if (jn.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2427
2472
|
let i = t ?? "";
|
|
2428
2473
|
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";
|
|
2429
2474
|
}
|
|
@@ -2470,14 +2515,14 @@ var In = class {
|
|
|
2470
2515
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2471
2516
|
o.requestCountDelta = _;
|
|
2472
2517
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2473
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2518
|
+
n.length > 0 && (o.requestTimeP50Ms = An(n, 50), o.requestTimeP95Ms = An(n, 95));
|
|
2474
2519
|
}
|
|
2475
2520
|
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();
|
|
2476
2521
|
}
|
|
2477
2522
|
maybeEmitMediaInfo(e) {
|
|
2478
2523
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2479
2524
|
let t = {};
|
|
2480
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2525
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = kn[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);
|
|
2481
2526
|
let n = JSON.stringify(t);
|
|
2482
2527
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2483
2528
|
}
|
|
@@ -2497,7 +2542,7 @@ var In = class {
|
|
|
2497
2542
|
let c = r?.positionMs ?? 0;
|
|
2498
2543
|
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));
|
|
2499
2544
|
let l = e !== "END_REASON_ENDED";
|
|
2500
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2545
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= En && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= En && (i.abandonAfterErrorMs = Math.max(q, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
|
|
2501
2546
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2502
2547
|
u > 0 && (i.decodedFramesTotal = u), e === "END_REASON_STOPPED" && this.startupTimeMs === 0 && this.lastErrorStage === null && (e = "END_REASON_ABORTED", i.reason = e), this.startupTimeMs === 0 && e !== "END_REASON_ABORTED" && (i.failedStage = this.lastErrorStage ?? (this.manifestLoadMs === 0 ? "ERROR_STAGE_MANIFEST" : this.firstFragLoadMs === 0 ? "ERROR_STAGE_FIRST_SEGMENT" : "ERROR_STAGE_OTHER")), this.pending.push(this.wrap({ sessionEnd: i })), this.flush(e === "END_REASON_PAGEHIDE");
|
|
2503
2548
|
}
|
|
@@ -2517,13 +2562,13 @@ var In = class {
|
|
|
2517
2562
|
};
|
|
2518
2563
|
}
|
|
2519
2564
|
noteCspBlocked() {
|
|
2520
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2565
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(Fn(new URL(this.url).origin)));
|
|
2521
2566
|
}
|
|
2522
2567
|
cspBlocked() {
|
|
2523
2568
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2524
2569
|
}
|
|
2525
2570
|
enqueue(e) {
|
|
2526
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2571
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > wn;) {
|
|
2527
2572
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2528
2573
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2529
2574
|
}
|
|
@@ -2550,7 +2595,7 @@ var In = class {
|
|
|
2550
2595
|
};
|
|
2551
2596
|
//#endregion
|
|
2552
2597
|
//#region src/core/environment.ts
|
|
2553
|
-
function
|
|
2598
|
+
function Bn() {
|
|
2554
2599
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2555
2600
|
let e;
|
|
2556
2601
|
try {
|
|
@@ -2575,14 +2620,14 @@ function Ln() {
|
|
|
2575
2620
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2576
2621
|
};
|
|
2577
2622
|
}
|
|
2578
|
-
function
|
|
2623
|
+
function Vn() {
|
|
2579
2624
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2580
2625
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2581
2626
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2582
2627
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2583
2628
|
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";
|
|
2584
2629
|
}
|
|
2585
|
-
function
|
|
2630
|
+
function Hn() {
|
|
2586
2631
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2587
2632
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2588
2633
|
let t = {
|
|
@@ -2601,17 +2646,17 @@ function zn() {
|
|
|
2601
2646
|
}
|
|
2602
2647
|
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;
|
|
2603
2648
|
}
|
|
2604
|
-
function
|
|
2605
|
-
let t =
|
|
2606
|
-
deviceClass:
|
|
2649
|
+
function Un(e) {
|
|
2650
|
+
let t = Bn(), n = {
|
|
2651
|
+
deviceClass: Vn(),
|
|
2607
2652
|
integration: t.integration,
|
|
2608
|
-
...
|
|
2653
|
+
...Hn()
|
|
2609
2654
|
};
|
|
2610
2655
|
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);
|
|
2611
2656
|
let r = e.getBoundingClientRect?.();
|
|
2612
2657
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2613
2658
|
}
|
|
2614
|
-
async function
|
|
2659
|
+
async function Wn() {
|
|
2615
2660
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2616
2661
|
if (!e?.getHighEntropyValues) return {};
|
|
2617
2662
|
try {
|
|
@@ -2623,7 +2668,7 @@ async function Vn() {
|
|
|
2623
2668
|
}
|
|
2624
2669
|
//#endregion
|
|
2625
2670
|
//#region src/core/version.ts
|
|
2626
|
-
var
|
|
2671
|
+
var Gn = "2.21.0", Kn = {
|
|
2627
2672
|
accent: "#E1B600",
|
|
2628
2673
|
accentText: "#1B1C23",
|
|
2629
2674
|
background: "#0e0f13",
|
|
@@ -2634,7 +2679,7 @@ var Hn = "2.19.0", Un = {
|
|
|
2634
2679
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2635
2680
|
radius: "8px",
|
|
2636
2681
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2637
|
-
},
|
|
2682
|
+
}, qn = {
|
|
2638
2683
|
accent: "--havik-accent",
|
|
2639
2684
|
accentText: "--havik-accent-text",
|
|
2640
2685
|
background: "--havik-bg",
|
|
@@ -2646,26 +2691,26 @@ var Hn = "2.19.0", Un = {
|
|
|
2646
2691
|
radius: "--havik-radius",
|
|
2647
2692
|
fontFamily: "--havik-font"
|
|
2648
2693
|
};
|
|
2649
|
-
function
|
|
2694
|
+
function Jn(e, t) {
|
|
2650
2695
|
let n = {
|
|
2651
|
-
...
|
|
2696
|
+
...Kn,
|
|
2652
2697
|
...t
|
|
2653
2698
|
};
|
|
2654
|
-
for (let t of Object.keys(
|
|
2699
|
+
for (let t of Object.keys(qn)) e.style.setProperty(qn[t], n[t]);
|
|
2655
2700
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2656
2701
|
}
|
|
2657
2702
|
//#endregion
|
|
2658
2703
|
//#region src/ui/styles.ts
|
|
2659
|
-
var
|
|
2660
|
-
function
|
|
2661
|
-
let n = e.querySelector(`style#${
|
|
2662
|
-
if (n && (!t ||
|
|
2704
|
+
var Z = "havik-player-styles", Yn = "\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 touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", Xn = /* @__PURE__ */ new WeakMap();
|
|
2705
|
+
function Zn(e = document, t) {
|
|
2706
|
+
let n = e.querySelector(`style#${Z}`);
|
|
2707
|
+
if (n && (!t || Xn.get(n) === t)) return;
|
|
2663
2708
|
let r = e.createElement("style");
|
|
2664
|
-
r.id =
|
|
2709
|
+
r.id = Z, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Yn, Xn.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2665
2710
|
}
|
|
2666
2711
|
//#endregion
|
|
2667
2712
|
//#region src/ui/icons.ts
|
|
2668
|
-
var
|
|
2713
|
+
var Qn = {
|
|
2669
2714
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2670
2715
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2671
2716
|
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\"/>",
|
|
@@ -2679,20 +2724,27 @@ var Yn = {
|
|
|
2679
2724
|
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\"/>"
|
|
2680
2725
|
};
|
|
2681
2726
|
function Q(e) {
|
|
2682
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2727
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Qn[e]}</svg>`;
|
|
2683
2728
|
}
|
|
2684
2729
|
//#endregion
|
|
2685
2730
|
//#region src/ui/controls.ts
|
|
2686
|
-
var
|
|
2731
|
+
var $n = 3e3, er = 250, tr = /* @__PURE__ */ new Set([
|
|
2687
2732
|
"GONE",
|
|
2688
2733
|
"NOT_FOUND",
|
|
2734
|
+
"GEO_DENIED",
|
|
2689
2735
|
"INVALID_URN",
|
|
2690
|
-
"UNAUTHORIZED"
|
|
2736
|
+
"UNAUTHORIZED",
|
|
2737
|
+
"DRM_DEVICE_REVOKED"
|
|
2691
2738
|
]);
|
|
2692
|
-
function
|
|
2693
|
-
|
|
2739
|
+
function nr(e) {
|
|
2740
|
+
let t = "This match isn't available in your country";
|
|
2741
|
+
return e ? `${t} (${e})` : t;
|
|
2742
|
+
}
|
|
2743
|
+
var rr = "This device can't play protected video";
|
|
2744
|
+
function ir(e) {
|
|
2745
|
+
return new ar(e);
|
|
2694
2746
|
}
|
|
2695
|
-
var
|
|
2747
|
+
var ar = class {
|
|
2696
2748
|
root;
|
|
2697
2749
|
video;
|
|
2698
2750
|
player;
|
|
@@ -2740,7 +2792,7 @@ var er = class {
|
|
|
2740
2792
|
scrubbing = !1;
|
|
2741
2793
|
offFns = [];
|
|
2742
2794
|
constructor(e) {
|
|
2743
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2795
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? $n, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, Zn(this.doc, e.cspNonce), 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");
|
|
2744
2796
|
let t = (e, t, n) => {
|
|
2745
2797
|
let r = this.doc.createElement(e);
|
|
2746
2798
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2826,7 +2878,7 @@ var er = class {
|
|
|
2826
2878
|
let t = this.surfaceWasHidden;
|
|
2827
2879
|
this.tapTimer = setTimeout(() => {
|
|
2828
2880
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2829
|
-
},
|
|
2881
|
+
}, er);
|
|
2830
2882
|
}
|
|
2831
2883
|
toggleBar(e) {
|
|
2832
2884
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2846,7 +2898,7 @@ var er = class {
|
|
|
2846
2898
|
this.statusOverlays && (e === "ended" ? t = "ended" : e === "error" ? t = "error" : e === "waiting" ? t = "waiting" : !this.hasPlayed && (e === "idle" || e === "paused") && (t = "preplay")), this.renderStatus(t);
|
|
2847
2899
|
}
|
|
2848
2900
|
statusMessageFor(e) {
|
|
2849
|
-
return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage
|
|
2901
|
+
return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? nr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? rr : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
|
|
2850
2902
|
}
|
|
2851
2903
|
renderStatus(e) {
|
|
2852
2904
|
let t = this.statusMessageFor(e);
|
|
@@ -2861,7 +2913,7 @@ var er = class {
|
|
|
2861
2913
|
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Q("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
|
|
2862
2914
|
} else {
|
|
2863
2915
|
let r = this.doc.createElement("div");
|
|
2864
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2916
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !tr.has(this.lastError.code)) {
|
|
2865
2917
|
let e = this.doc.createElement("button");
|
|
2866
2918
|
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Q("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
2867
2919
|
}
|
|
@@ -2902,7 +2954,7 @@ var er = class {
|
|
|
2902
2954
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2903
2955
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2904
2956
|
}
|
|
2905
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2957
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${or(this.video.currentTime)} / ${or(this.video.duration)}`);
|
|
2906
2958
|
}
|
|
2907
2959
|
syncLive() {
|
|
2908
2960
|
let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
|
|
@@ -2952,17 +3004,17 @@ var er = class {
|
|
|
2952
3004
|
renderQualityMenu() {
|
|
2953
3005
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2954
3006
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2955
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
3007
|
+
for (let n of e) this.menu.append(this.menuItem(sr(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2956
3008
|
}
|
|
2957
3009
|
renderAudioMenu() {
|
|
2958
3010
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2959
3011
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2960
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3012
|
+
for (let t of e) this.menu.append(this.menuItem(cr(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2961
3013
|
}
|
|
2962
3014
|
renderCcMenu() {
|
|
2963
3015
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2964
3016
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2965
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3017
|
+
for (let t of e) this.menu.append(this.menuItem(lr(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2966
3018
|
}
|
|
2967
3019
|
onTracksChanged() {
|
|
2968
3020
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -3067,41 +3119,41 @@ var er = class {
|
|
|
3067
3119
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
3068
3120
|
}
|
|
3069
3121
|
};
|
|
3070
|
-
function
|
|
3122
|
+
function or(e) {
|
|
3071
3123
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
3072
3124
|
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");
|
|
3073
3125
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
3074
3126
|
}
|
|
3075
|
-
function
|
|
3127
|
+
function sr(e) {
|
|
3076
3128
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
3077
3129
|
}
|
|
3078
|
-
function
|
|
3130
|
+
function cr(e) {
|
|
3079
3131
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3080
3132
|
}
|
|
3081
|
-
function
|
|
3133
|
+
function lr(e) {
|
|
3082
3134
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3083
3135
|
}
|
|
3084
3136
|
//#endregion
|
|
3085
3137
|
//#region src/managed/index.ts
|
|
3086
|
-
var
|
|
3087
|
-
function
|
|
3138
|
+
var ur = 6e3, dr = 45e3, fr = 2e3, pr = 3, mr = 5e3, hr = 2e3, gr = 48e4, _r = "keySystemLicenseRequestFailed";
|
|
3139
|
+
function vr(e) {
|
|
3088
3140
|
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)})`);
|
|
3089
|
-
if (e.env !== void 0) return
|
|
3141
|
+
if (e.env !== void 0) return at(e.env);
|
|
3090
3142
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
3091
3143
|
return e.baseUrl;
|
|
3092
3144
|
}
|
|
3093
|
-
async function
|
|
3145
|
+
async function yr(e) {
|
|
3094
3146
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
3095
|
-
let t =
|
|
3147
|
+
let t = vr(e);
|
|
3096
3148
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
3097
3149
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
3098
|
-
let r = new
|
|
3150
|
+
let r = new br({
|
|
3099
3151
|
...e,
|
|
3100
3152
|
baseUrl: t
|
|
3101
3153
|
});
|
|
3102
3154
|
return await r.start(), r;
|
|
3103
3155
|
}
|
|
3104
|
-
var
|
|
3156
|
+
var br = class {
|
|
3105
3157
|
opts;
|
|
3106
3158
|
abort = new AbortController();
|
|
3107
3159
|
listeners = {};
|
|
@@ -3158,7 +3210,7 @@ var hr = class {
|
|
|
3158
3210
|
throw this.destroy(), e;
|
|
3159
3211
|
}
|
|
3160
3212
|
} catch (t) {
|
|
3161
|
-
if (this.opts.waitForLive && t instanceof n &&
|
|
3213
|
+
if (this.opts.waitForLive && t instanceof n && s(t.code)) {
|
|
3162
3214
|
this.setState("waiting"), this.beginArming(e, t.liveStartsAtMs);
|
|
3163
3215
|
return;
|
|
3164
3216
|
}
|
|
@@ -3190,13 +3242,13 @@ var hr = class {
|
|
|
3190
3242
|
});
|
|
3191
3243
|
}
|
|
3192
3244
|
armWithSse(e, t, r, i = !1) {
|
|
3193
|
-
let a = !1,
|
|
3245
|
+
let a = !1, o = !1, c = new AbortController();
|
|
3194
3246
|
this.armFallbackCtrl = c, this.setState("waiting");
|
|
3195
3247
|
let l = this.opts.waitForLive, u = l && l !== !0 ? l.kickoffAt : void 0, d = typeof u == "number" ? u : typeof u == "string" ? Date.parse(u) : NaN, f = r ?? (Number.isFinite(d) ? d : void 0);
|
|
3196
3248
|
setTimeout(() => {
|
|
3197
3249
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3198
3250
|
phase: i ? "unavailable" : "tooEarly",
|
|
3199
|
-
retryInMs:
|
|
3251
|
+
retryInMs: dr,
|
|
3200
3252
|
attempt: 1,
|
|
3201
3253
|
elapsedMs: 0,
|
|
3202
3254
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3213,7 +3265,7 @@ var hr = class {
|
|
|
3213
3265
|
}
|
|
3214
3266
|
}
|
|
3215
3267
|
}, h = () => {
|
|
3216
|
-
a ||
|
|
3268
|
+
a || o || p() || (o = !0, y({
|
|
3217
3269
|
...this.resolveOptions(),
|
|
3218
3270
|
signal: c.signal,
|
|
3219
3271
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -3223,7 +3275,7 @@ var hr = class {
|
|
|
3223
3275
|
}, g = () => {
|
|
3224
3276
|
a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
|
|
3225
3277
|
if (!(a || p())) {
|
|
3226
|
-
if (e instanceof n &&
|
|
3278
|
+
if (e instanceof n && s(e.code)) {
|
|
3227
3279
|
h();
|
|
3228
3280
|
return;
|
|
3229
3281
|
}
|
|
@@ -3235,13 +3287,13 @@ var hr = class {
|
|
|
3235
3287
|
!a && !p() && h();
|
|
3236
3288
|
}, e);
|
|
3237
3289
|
};
|
|
3238
|
-
_(
|
|
3290
|
+
_(ur), this.armingSub = E({
|
|
3239
3291
|
eventsBaseUrl: t,
|
|
3240
3292
|
matchUrn: this.opts.matchUrn,
|
|
3241
3293
|
credential: this.opts.credential,
|
|
3242
|
-
onAlive: () => _(
|
|
3294
|
+
onAlive: () => _(dr),
|
|
3243
3295
|
onState: (e) => {
|
|
3244
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3296
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * fr);
|
|
3245
3297
|
},
|
|
3246
3298
|
onError: () => h()
|
|
3247
3299
|
});
|
|
@@ -3261,10 +3313,10 @@ var hr = class {
|
|
|
3261
3313
|
async onResolved(e, t) {
|
|
3262
3314
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3263
3315
|
this._descriptor = e, this.endedHandled = !1, this._endedReason = null;
|
|
3264
|
-
let n = await
|
|
3316
|
+
let n = await c(this.opts.credential);
|
|
3265
3317
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3266
3318
|
this.setState("loading");
|
|
3267
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3319
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = ut(this.opts.video, (e) => {
|
|
3268
3320
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3269
3321
|
});
|
|
3270
3322
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3286,26 +3338,26 @@ var hr = class {
|
|
|
3286
3338
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3287
3339
|
let i = e.analytics?.sid;
|
|
3288
3340
|
if (!i) return;
|
|
3289
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3341
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Rn(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3290
3342
|
if (!o) {
|
|
3291
3343
|
s && setTimeout(() => {
|
|
3292
3344
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3293
3345
|
}, 0);
|
|
3294
3346
|
return;
|
|
3295
3347
|
}
|
|
3296
|
-
let c = this.opts.video, l = new
|
|
3348
|
+
let c = this.opts.video, l = new zn({
|
|
3297
3349
|
endpoint: o,
|
|
3298
3350
|
sid: i,
|
|
3299
3351
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3300
|
-
sdkVersion:
|
|
3301
|
-
environment:
|
|
3352
|
+
sdkVersion: Gn,
|
|
3353
|
+
environment: Un(c),
|
|
3302
3354
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3303
3355
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3304
3356
|
onBlocked: (e) => setTimeout(() => {
|
|
3305
3357
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3306
3358
|
}, 0),
|
|
3307
3359
|
sample: () => {
|
|
3308
|
-
let e = this.engine?.getStats() ??
|
|
3360
|
+
let e = this.engine?.getStats() ?? z, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3309
3361
|
return {
|
|
3310
3362
|
...e,
|
|
3311
3363
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3319,7 +3371,7 @@ var hr = class {
|
|
|
3319
3371
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3320
3372
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3321
3373
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3322
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3374
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Wn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3323
3375
|
}
|
|
3324
3376
|
currentPresentation() {
|
|
3325
3377
|
let e = this.opts.video;
|
|
@@ -3347,9 +3399,9 @@ var hr = class {
|
|
|
3347
3399
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3348
3400
|
}, o = this.opts.engine ?? "auto";
|
|
3349
3401
|
if (o === "native") return new W(a);
|
|
3350
|
-
if (o === "hls") return new
|
|
3351
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled &&
|
|
3352
|
-
if (
|
|
3402
|
+
if (o === "hls") return new bn(a);
|
|
3403
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled && St() && H(this.opts.video)) return new W(a);
|
|
3404
|
+
if (It()) return new bn(a);
|
|
3353
3405
|
if (H(this.opts.video)) return new W(a);
|
|
3354
3406
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3355
3407
|
}
|
|
@@ -3412,7 +3464,7 @@ var hr = class {
|
|
|
3412
3464
|
r = 0, i = !1;
|
|
3413
3465
|
},
|
|
3414
3466
|
onError: () => {
|
|
3415
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
3467
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= pr && (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.`))));
|
|
3416
3468
|
}
|
|
3417
3469
|
});
|
|
3418
3470
|
}
|
|
@@ -3426,7 +3478,7 @@ var hr = class {
|
|
|
3426
3478
|
return;
|
|
3427
3479
|
}
|
|
3428
3480
|
let e = this.hiddenAtMs;
|
|
3429
|
-
this.hiddenAtMs = null, e != null && Date.now() - e >=
|
|
3481
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= mr && this.resyncLiveState();
|
|
3430
3482
|
}, this.onReturnPageShow = (e) => {
|
|
3431
3483
|
e.persisted && this.resyncLiveState();
|
|
3432
3484
|
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
@@ -3458,7 +3510,7 @@ var hr = class {
|
|
|
3458
3510
|
scheduleRejoin(e) {
|
|
3459
3511
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3460
3512
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3461
|
-
}, Math.random() *
|
|
3513
|
+
}, Math.random() * fr));
|
|
3462
3514
|
}
|
|
3463
3515
|
cancelRejoin() {
|
|
3464
3516
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3482,7 +3534,7 @@ var hr = class {
|
|
|
3482
3534
|
}
|
|
3483
3535
|
t.controls = !1;
|
|
3484
3536
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3485
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3537
|
+
r && r.insertBefore(n, t), n.appendChild(t), Jn(n, this.opts.theme), this.container = n, this.controlBar = ir({
|
|
3486
3538
|
root: n,
|
|
3487
3539
|
video: t,
|
|
3488
3540
|
player: this,
|
|
@@ -3520,7 +3572,7 @@ var hr = class {
|
|
|
3520
3572
|
}
|
|
3521
3573
|
startStats() {
|
|
3522
3574
|
this.stopStats();
|
|
3523
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3575
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? hr);
|
|
3524
3576
|
this.statsTimer = setInterval(() => {
|
|
3525
3577
|
if (!this.engine) return;
|
|
3526
3578
|
let e = this.engine.getStats();
|
|
@@ -3531,14 +3583,14 @@ var hr = class {
|
|
|
3531
3583
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3532
3584
|
}
|
|
3533
3585
|
isStaleLicenseDenial(e) {
|
|
3534
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3586
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== _r || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3535
3587
|
}
|
|
3536
3588
|
scheduleLicenseRefresh() {
|
|
3537
3589
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3538
3590
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3539
3591
|
document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3540
3592
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3541
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3593
|
+
let e = this.opts.licenseRefreshMs ?? gr;
|
|
3542
3594
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3543
3595
|
}
|
|
3544
3596
|
stopRefresh() {
|
|
@@ -3558,7 +3610,7 @@ var hr = class {
|
|
|
3558
3610
|
fairplay: r
|
|
3559
3611
|
}), this._descriptor = t), n;
|
|
3560
3612
|
} catch (e) {
|
|
3561
|
-
e instanceof n && !
|
|
3613
|
+
e instanceof n && !s(e.code) && (this.stopRefresh(), this.destroyed || this.emit("warning", e));
|
|
3562
3614
|
return;
|
|
3563
3615
|
} finally {
|
|
3564
3616
|
this.refreshInFlight?.promise === t && (this.refreshInFlight = void 0);
|
|
@@ -3595,7 +3647,7 @@ var hr = class {
|
|
|
3595
3647
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3596
3648
|
}
|
|
3597
3649
|
getStats() {
|
|
3598
|
-
return this.engine?.getStats() ??
|
|
3650
|
+
return this.engine?.getStats() ?? z;
|
|
3599
3651
|
}
|
|
3600
3652
|
getQualityLevels() {
|
|
3601
3653
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3708,7 +3760,7 @@ function $(e) {
|
|
|
3708
3760
|
}
|
|
3709
3761
|
//#endregion
|
|
3710
3762
|
//#region src/embed/host.ts
|
|
3711
|
-
function
|
|
3763
|
+
function xr(e) {
|
|
3712
3764
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3713
3765
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3714
3766
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3767,15 +3819,15 @@ function gr(e) {
|
|
|
3767
3819
|
}
|
|
3768
3820
|
//#endregion
|
|
3769
3821
|
//#region src/embed/page.ts
|
|
3770
|
-
var
|
|
3771
|
-
function
|
|
3822
|
+
var Sr = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3823
|
+
function Cr(e) {
|
|
3772
3824
|
if (typeof e == "boolean") return e;
|
|
3773
3825
|
if (typeof e == "object" && e) {
|
|
3774
3826
|
let t = e.endpoint;
|
|
3775
3827
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3776
3828
|
}
|
|
3777
3829
|
}
|
|
3778
|
-
function
|
|
3830
|
+
function wr() {
|
|
3779
3831
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3780
3832
|
if (e) return {
|
|
3781
3833
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3785,7 +3837,7 @@ function yr() {
|
|
|
3785
3837
|
autoplay: e.autoplay ?? !0,
|
|
3786
3838
|
muted: e.muted ?? !0,
|
|
3787
3839
|
waitForLive: e.waitForLive ?? !0,
|
|
3788
|
-
analytics:
|
|
3840
|
+
analytics: Cr(e.analytics)
|
|
3789
3841
|
};
|
|
3790
3842
|
let t = new URLSearchParams(location.search);
|
|
3791
3843
|
return {
|
|
@@ -3798,9 +3850,9 @@ function yr() {
|
|
|
3798
3850
|
waitForLive: !0
|
|
3799
3851
|
};
|
|
3800
3852
|
}
|
|
3801
|
-
async function
|
|
3802
|
-
let e =
|
|
3803
|
-
|
|
3853
|
+
async function Tr() {
|
|
3854
|
+
let e = wr();
|
|
3855
|
+
Dr();
|
|
3804
3856
|
let t = document.createElement("video");
|
|
3805
3857
|
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);
|
|
3806
3858
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3853,14 +3905,15 @@ async function br() {
|
|
|
3853
3905
|
})), e.on("error", (e) => i({
|
|
3854
3906
|
type: "oddin:error",
|
|
3855
3907
|
code: e.code,
|
|
3856
|
-
message: e.message
|
|
3908
|
+
message: e.message,
|
|
3909
|
+
...e.country === void 0 ? {} : { country: e.country }
|
|
3857
3910
|
})), e.on("autoplayblocked", () => {
|
|
3858
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3911
|
+
i({ type: "oddin:autoplayblocked" }), Er(t, e);
|
|
3859
3912
|
});
|
|
3860
3913
|
}, s = async (r) => {
|
|
3861
3914
|
a?.destroy(), a = null;
|
|
3862
3915
|
try {
|
|
3863
|
-
let n = await
|
|
3916
|
+
let n = await yr({
|
|
3864
3917
|
video: t,
|
|
3865
3918
|
baseUrl: e.baseUrl,
|
|
3866
3919
|
matchUrn: r,
|
|
@@ -3874,11 +3927,12 @@ async function br() {
|
|
|
3874
3927
|
let i = t.parentElement;
|
|
3875
3928
|
i?.classList.contains("havik-player") && (i.style.cssText = "position:absolute;inset:0;width:100%;height:100%;aspect-ratio:auto"), o(n);
|
|
3876
3929
|
} catch (e) {
|
|
3877
|
-
let t = e instanceof n ? e.code : "INTERNAL", r = e instanceof Error ? e.message : String(e);
|
|
3930
|
+
let t = e instanceof n ? e.code : "INTERNAL", r = e instanceof Error ? e.message : String(e), a = e instanceof n ? e.country : void 0;
|
|
3878
3931
|
i({
|
|
3879
3932
|
type: "oddin:error",
|
|
3880
3933
|
code: t,
|
|
3881
|
-
message: r
|
|
3934
|
+
message: r,
|
|
3935
|
+
...a === void 0 ? {} : { country: a }
|
|
3882
3936
|
});
|
|
3883
3937
|
}
|
|
3884
3938
|
}, c = () => {
|
|
@@ -3922,7 +3976,7 @@ async function br() {
|
|
|
3922
3976
|
a?.retry();
|
|
3923
3977
|
break;
|
|
3924
3978
|
case "oddin:load":
|
|
3925
|
-
typeof e.matchUrn == "string" &&
|
|
3979
|
+
typeof e.matchUrn == "string" && Sr.test(e.matchUrn) && s(e.matchUrn);
|
|
3926
3980
|
break;
|
|
3927
3981
|
case "oddin:destroy": c();
|
|
3928
3982
|
}
|
|
@@ -3934,18 +3988,18 @@ async function br() {
|
|
|
3934
3988
|
protocol: 1
|
|
3935
3989
|
});
|
|
3936
3990
|
}
|
|
3937
|
-
function
|
|
3991
|
+
function Er(e, t) {
|
|
3938
3992
|
if (document.getElementById("havik-tap")) return;
|
|
3939
3993
|
let n = document.createElement("button");
|
|
3940
3994
|
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", () => {
|
|
3941
3995
|
n.remove(), t.play();
|
|
3942
3996
|
}), document.body.appendChild(n);
|
|
3943
3997
|
}
|
|
3944
|
-
function
|
|
3998
|
+
function Dr() {
|
|
3945
3999
|
let e = document.createElement("style");
|
|
3946
4000
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3947
4001
|
}
|
|
3948
4002
|
//#endregion
|
|
3949
|
-
export {
|
|
4003
|
+
export { Kn as ODDIN_THEME, n as PlaybackError, Jn as applyTheme, at as baseUrlForEnv, Tr as bootEmbed, Ee as clearDeviceId, Re as clearRememberedBandwidth, yr as createPlayer, D as deriveEventsBaseUrl, tt as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, A as getDeviceId, rt as isLowLatencyManifest, $ as isOddinMessage, Oe as licenseRequestHeaders, xr as mountEmbed, fe as pollToLive, y as resolveStream, E as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
|
|
3950
4004
|
|
|
3951
4005
|
//# sourceMappingURL=index.js.map
|