@oddin-gg/havik-player 2.20.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 -11
- 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 +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +412 -371
- package/dist/index.js.map +1 -1
- package/docs/API.md +54 -31
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -27,28 +27,46 @@ function r(e) {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
function i(e) {
|
|
30
|
-
|
|
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
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function a(e, t) {
|
|
48
|
+
return e === 401 ? "UNAUTHORIZED" : e === 403 ? t === "cdm_revoked" ? "DRM_DEVICE_REVOKED" : "FORBIDDEN" : "DRM_CLIENT";
|
|
31
49
|
}
|
|
32
|
-
var
|
|
50
|
+
var o = /* @__PURE__ */ new Set([
|
|
33
51
|
"TOO_EARLY",
|
|
34
52
|
"UNAVAILABLE",
|
|
35
53
|
"RATE_LIMITED",
|
|
36
54
|
"NETWORK"
|
|
37
55
|
]);
|
|
38
|
-
function
|
|
39
|
-
return
|
|
56
|
+
function s(e) {
|
|
57
|
+
return o.has(e);
|
|
40
58
|
}
|
|
41
59
|
//#endregion
|
|
42
60
|
//#region src/core/types.ts
|
|
43
|
-
async function
|
|
61
|
+
async function c(e) {
|
|
44
62
|
let t = typeof e == "function" ? await e() : e;
|
|
45
63
|
if (!t || !t.apiKey) throw Error("havik-player: credential is missing an apiKey");
|
|
46
64
|
return t;
|
|
47
65
|
}
|
|
48
|
-
function
|
|
66
|
+
function l(e) {
|
|
49
67
|
return e === "live" || e === "ended" || e === "upcoming" || e === "pending" ? e : "upcoming";
|
|
50
68
|
}
|
|
51
|
-
function
|
|
69
|
+
function u(e) {
|
|
52
70
|
if (!Array.isArray(e)) return;
|
|
53
71
|
let t = [];
|
|
54
72
|
for (let n of e) {
|
|
@@ -60,11 +78,11 @@ function l(e) {
|
|
|
60
78
|
name: r,
|
|
61
79
|
isHome: n.isHome === !0
|
|
62
80
|
};
|
|
63
|
-
typeof n.logoUrl == "string" &&
|
|
81
|
+
typeof n.logoUrl == "string" && d(n.logoUrl) && (i.logoUrl = n.logoUrl), t.push(i);
|
|
64
82
|
}
|
|
65
83
|
return t.length > 0 ? t : void 0;
|
|
66
84
|
}
|
|
67
|
-
function
|
|
85
|
+
function d(e) {
|
|
68
86
|
try {
|
|
69
87
|
return new URL(e).protocol === "https:";
|
|
70
88
|
} catch {
|
|
@@ -73,7 +91,7 @@ function u(e) {
|
|
|
73
91
|
}
|
|
74
92
|
//#endregion
|
|
75
93
|
//#region src/core/http.ts
|
|
76
|
-
function
|
|
94
|
+
function f(e, t) {
|
|
77
95
|
let r = e.replace(/\/+$/, ""), i;
|
|
78
96
|
try {
|
|
79
97
|
i = new URL(r + t);
|
|
@@ -83,15 +101,15 @@ function d(e, t) {
|
|
|
83
101
|
if (i.protocol !== "https:" && i.protocol !== "http:") throw new n("INTERNAL", 0, `baseUrl must be http(s), got: ${JSON.stringify(e)}`);
|
|
84
102
|
return i.toString();
|
|
85
103
|
}
|
|
86
|
-
function
|
|
104
|
+
function p(e) {
|
|
87
105
|
if (!e) return;
|
|
88
106
|
let t = Number(e);
|
|
89
107
|
if (Number.isFinite(t)) return Math.max(0, Math.round(t * 1e3));
|
|
90
108
|
let n = Date.parse(e);
|
|
91
109
|
if (!Number.isNaN(n)) return Math.max(0, n - Date.now());
|
|
92
110
|
}
|
|
93
|
-
async function
|
|
94
|
-
let r = await
|
|
111
|
+
async function m(e, t) {
|
|
112
|
+
let r = await c(t.credential), i = t.headers ?? new Headers();
|
|
95
113
|
if (t.apiHeaders) for (let [e, n] of Object.entries(t.apiHeaders)) i.has(e) || i.set(e, n);
|
|
96
114
|
i.set("x-api-key", r.apiKey);
|
|
97
115
|
try {
|
|
@@ -105,55 +123,55 @@ async function p(e, t) {
|
|
|
105
123
|
mode: "cors"
|
|
106
124
|
});
|
|
107
125
|
} catch (e) {
|
|
108
|
-
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 });
|
|
109
127
|
}
|
|
110
128
|
}
|
|
111
|
-
function
|
|
129
|
+
function h(e) {
|
|
112
130
|
return e instanceof Error ? e.message : String(e);
|
|
113
131
|
}
|
|
114
132
|
//#endregion
|
|
115
133
|
//#region src/core/warnOnce.ts
|
|
116
|
-
var
|
|
117
|
-
function
|
|
118
|
-
|
|
134
|
+
var g = /* @__PURE__ */ new Set();
|
|
135
|
+
function _(e, t = e) {
|
|
136
|
+
g.has(t) || (g.add(t), console.warn(`havik-player: ${e}`));
|
|
119
137
|
}
|
|
120
138
|
//#endregion
|
|
121
139
|
//#region src/core/waitForLive.ts
|
|
122
|
-
var
|
|
140
|
+
var ee = 1e3, te = 3e4, ne = 6e5, re = 3e5, ie = 1e3, ae = {
|
|
123
141
|
TOO_EARLY: "tooEarly",
|
|
124
142
|
UNAVAILABLE: "unavailable",
|
|
125
143
|
RATE_LIMITED: "rateLimited",
|
|
126
144
|
NETWORK: "network"
|
|
127
145
|
};
|
|
128
|
-
function
|
|
129
|
-
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);
|
|
130
148
|
return {
|
|
131
149
|
timeoutMs: t.timeoutMs,
|
|
132
150
|
floorMs: n,
|
|
133
151
|
ceilMs: r,
|
|
134
152
|
imminentMs: i,
|
|
135
153
|
sanityFloorMs: a,
|
|
136
|
-
kickoffMs:
|
|
154
|
+
kickoffMs: se(t.kickoffAt),
|
|
137
155
|
jitter: t.jitter ?? !0,
|
|
138
156
|
onState: t.onState
|
|
139
157
|
};
|
|
140
158
|
}
|
|
141
|
-
function
|
|
159
|
+
function se(e) {
|
|
142
160
|
if (e == null) return;
|
|
143
161
|
if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
|
|
144
162
|
let t = Date.parse(e);
|
|
145
163
|
return Number.isFinite(t) ? t : void 0;
|
|
146
164
|
}
|
|
147
|
-
function
|
|
165
|
+
function ce(e, t, n) {
|
|
148
166
|
return Math.min(n, Math.max(t, e));
|
|
149
167
|
}
|
|
150
|
-
function
|
|
168
|
+
function le(e) {
|
|
151
169
|
return Math.round(e * (1 + .15 * Math.random()));
|
|
152
170
|
}
|
|
153
|
-
function
|
|
171
|
+
function ue(e, t, n, r) {
|
|
154
172
|
let i = r ?? n.kickoffMs, a = i == null ? void 0 : Math.max(0, i - t), o = Math.max(n.floorMs, e ?? 0);
|
|
155
173
|
if (a == null || a <= n.imminentMs) return {
|
|
156
|
-
delay:
|
|
174
|
+
delay: ce(e ?? n.floorMs, o, n.ceilMs),
|
|
157
175
|
ttkMs: a
|
|
158
176
|
};
|
|
159
177
|
let s = Math.min(Math.floor(a / 10), n.sanityFloorMs, a);
|
|
@@ -162,7 +180,7 @@ function le(e, t, n, r) {
|
|
|
162
180
|
ttkMs: a
|
|
163
181
|
};
|
|
164
182
|
}
|
|
165
|
-
function
|
|
183
|
+
function de(e, t) {
|
|
166
184
|
return new Promise((r, i) => {
|
|
167
185
|
if (t?.aborted) {
|
|
168
186
|
i(new n("ABORTED", 0, "wait-for-live aborted"));
|
|
@@ -176,27 +194,27 @@ function ue(e, t) {
|
|
|
176
194
|
t?.addEventListener("abort", a, { once: !0 });
|
|
177
195
|
});
|
|
178
196
|
}
|
|
179
|
-
async function
|
|
180
|
-
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;
|
|
181
199
|
for (;;) {
|
|
182
200
|
if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
|
|
183
201
|
try {
|
|
184
202
|
return await e();
|
|
185
203
|
} catch (e) {
|
|
186
|
-
if (!(e instanceof n) || !
|
|
204
|
+
if (!(e instanceof n) || !s(e.code)) throw e;
|
|
187
205
|
c += 1, e.liveStartsAtMs != null && Number.isFinite(e.liveStartsAtMs) && (l = e.liveStartsAtMs);
|
|
188
|
-
let t = Date.now(), u =
|
|
189
|
-
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`, {
|
|
190
208
|
retryAfterMs: e.retryAfterMs,
|
|
191
209
|
cause: e
|
|
192
210
|
});
|
|
193
211
|
i.onState?.({
|
|
194
|
-
phase:
|
|
212
|
+
phase: ae[e.code] ?? "unavailable",
|
|
195
213
|
retryInMs: f,
|
|
196
214
|
attempt: c,
|
|
197
215
|
elapsedMs: t - a,
|
|
198
216
|
ttkMs: d
|
|
199
|
-
}), await
|
|
217
|
+
}), await de(f, r);
|
|
200
218
|
}
|
|
201
219
|
}
|
|
202
220
|
}
|
|
@@ -204,20 +222,20 @@ async function de(e, t, r) {
|
|
|
204
222
|
//#region src/core/resolve.ts
|
|
205
223
|
async function v(e) {
|
|
206
224
|
if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
|
|
207
|
-
let t = await
|
|
225
|
+
let t = await m(f(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
|
|
208
226
|
credential: e.credential,
|
|
209
227
|
signal: e.signal,
|
|
210
228
|
apiHeaders: e.apiHeaders
|
|
211
229
|
});
|
|
212
|
-
if (!t.ok) throw await
|
|
213
|
-
return
|
|
230
|
+
if (!t.ok) throw await pe(t);
|
|
231
|
+
return ge(await t.json(), e.matchUrn);
|
|
214
232
|
}
|
|
215
233
|
function y(e) {
|
|
216
234
|
let t = () => v(e);
|
|
217
|
-
return e.waitForLive ?
|
|
235
|
+
return e.waitForLive ? fe(t, e.waitForLive, e.signal) : t();
|
|
218
236
|
}
|
|
219
|
-
async function
|
|
220
|
-
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;
|
|
221
239
|
try {
|
|
222
240
|
let t = await e.json();
|
|
223
241
|
if (t?.error?.message && (a = t.error.message), t?.error?.code && (o = t.error.code), typeof t?.liveStartsAt == "string") {
|
|
@@ -234,7 +252,7 @@ async function fe(e) {
|
|
|
234
252
|
country: c
|
|
235
253
|
});
|
|
236
254
|
}
|
|
237
|
-
var
|
|
255
|
+
var me = /* @__PURE__ */ new Set([
|
|
238
256
|
"matchUrn",
|
|
239
257
|
"protocol",
|
|
240
258
|
"drmEnabled",
|
|
@@ -255,16 +273,16 @@ function b(e, t) {
|
|
|
255
273
|
if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
|
|
256
274
|
return t;
|
|
257
275
|
}
|
|
258
|
-
function
|
|
276
|
+
function he(e) {
|
|
259
277
|
if (e !== void 0) {
|
|
260
278
|
if (typeof e == "string" && !e.endsWith("/")) try {
|
|
261
279
|
let t = new URL(e);
|
|
262
280
|
if (t.protocol === "https:" && t.href === `${t.origin}/`) return t.origin;
|
|
263
281
|
} catch {}
|
|
264
|
-
|
|
282
|
+
_(`server analytics.endpoint ${JSON.stringify(e)} ignored: not a bare https origin.`);
|
|
265
283
|
}
|
|
266
284
|
}
|
|
267
|
-
function
|
|
285
|
+
function ge(e, t) {
|
|
268
286
|
if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
|
|
269
287
|
let r = e.drmEnabled ?? !!e.drm, i = {
|
|
270
288
|
matchUrn: e.matchUrn ?? t,
|
|
@@ -275,7 +293,7 @@ function he(e, t) {
|
|
|
275
293
|
};
|
|
276
294
|
if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid) {
|
|
277
295
|
i.analytics = { sid: e.analytics.sid };
|
|
278
|
-
let t =
|
|
296
|
+
let t = he(e.analytics.endpoint);
|
|
279
297
|
t && (i.analytics.endpoint = t);
|
|
280
298
|
}
|
|
281
299
|
if (r && e.drm) {
|
|
@@ -286,7 +304,7 @@ function he(e, t) {
|
|
|
286
304
|
}), (t.widevine || t.fairplay) && (i.drm = t);
|
|
287
305
|
}
|
|
288
306
|
let a = {};
|
|
289
|
-
for (let [t, n] of Object.entries(e))
|
|
307
|
+
for (let [t, n] of Object.entries(e)) me.has(t) || (a[t] = n);
|
|
290
308
|
return Object.keys(a).length > 0 && (i.extensions = a), i;
|
|
291
309
|
}
|
|
292
310
|
//#endregion
|
|
@@ -294,11 +312,11 @@ function he(e, t) {
|
|
|
294
312
|
function x(e) {
|
|
295
313
|
return e.ownerDocument ?? document;
|
|
296
314
|
}
|
|
297
|
-
function
|
|
315
|
+
function _e(e) {
|
|
298
316
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
299
317
|
}
|
|
300
318
|
function S(e, t) {
|
|
301
|
-
let n =
|
|
319
|
+
let n = _e(x(e));
|
|
302
320
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
303
321
|
}
|
|
304
322
|
function C(e, t) {
|
|
@@ -321,17 +339,17 @@ async function T(e, t) {
|
|
|
321
339
|
n.webkitExitFullscreen?.();
|
|
322
340
|
return;
|
|
323
341
|
}
|
|
324
|
-
let r = x(e), i =
|
|
342
|
+
let r = x(e), i = _e(r);
|
|
325
343
|
i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
|
|
326
344
|
}
|
|
327
345
|
//#endregion
|
|
328
346
|
//#region src/core/catalog.ts
|
|
329
|
-
async function
|
|
347
|
+
async function ve(e) {
|
|
330
348
|
let t = new URLSearchParams();
|
|
331
349
|
e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
|
|
332
|
-
let i = t.toString(), a =
|
|
350
|
+
let i = t.toString(), a = f(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
|
|
333
351
|
e.etag && o.set("If-None-Match", e.etag);
|
|
334
|
-
let s = await
|
|
352
|
+
let s = await m(a, {
|
|
335
353
|
credential: e.credential,
|
|
336
354
|
signal: e.signal,
|
|
337
355
|
headers: o,
|
|
@@ -344,12 +362,12 @@ async function _e(e) {
|
|
|
344
362
|
};
|
|
345
363
|
if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
|
|
346
364
|
return {
|
|
347
|
-
tournaments:
|
|
365
|
+
tournaments: ye(await s.json()),
|
|
348
366
|
etag: s.headers.get("etag") ?? void 0,
|
|
349
367
|
notModified: !1
|
|
350
368
|
};
|
|
351
369
|
}
|
|
352
|
-
function
|
|
370
|
+
function ye(e) {
|
|
353
371
|
return (e.tournaments ?? []).map((e) => {
|
|
354
372
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
355
373
|
return {
|
|
@@ -360,21 +378,21 @@ function ve(e) {
|
|
|
360
378
|
matches: (e.matches ?? []).map((e) => ({
|
|
361
379
|
matchUrn: e.matchUrn ?? "",
|
|
362
380
|
matchName: e.matchName ?? "",
|
|
363
|
-
status:
|
|
381
|
+
status: l(e.status),
|
|
364
382
|
statusRaw: e.status,
|
|
365
383
|
datePlannedStart: e.datePlannedStart,
|
|
366
384
|
tournamentUrn: t,
|
|
367
385
|
tournamentName: n,
|
|
368
386
|
sport: r,
|
|
369
|
-
teams:
|
|
387
|
+
teams: u(e.teams)
|
|
370
388
|
}))
|
|
371
389
|
};
|
|
372
390
|
});
|
|
373
391
|
}
|
|
374
|
-
async function
|
|
375
|
-
let t =
|
|
392
|
+
async function be(e) {
|
|
393
|
+
let t = f(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
376
394
|
e.etag && i.set("If-None-Match", e.etag);
|
|
377
|
-
let a = await
|
|
395
|
+
let a = await m(t, {
|
|
378
396
|
credential: e.credential,
|
|
379
397
|
signal: e.signal,
|
|
380
398
|
headers: i,
|
|
@@ -391,13 +409,13 @@ async function ye(e) {
|
|
|
391
409
|
};
|
|
392
410
|
if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
393
411
|
return {
|
|
394
|
-
tournament:
|
|
412
|
+
tournament: xe(await a.json()),
|
|
395
413
|
etag: a.headers.get("etag") ?? void 0,
|
|
396
414
|
notModified: !1,
|
|
397
415
|
notFound: !1
|
|
398
416
|
};
|
|
399
417
|
}
|
|
400
|
-
function
|
|
418
|
+
function xe(e) {
|
|
401
419
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
402
420
|
return {
|
|
403
421
|
urn: t,
|
|
@@ -407,44 +425,44 @@ function be(e) {
|
|
|
407
425
|
matches: (e.matches ?? []).map((e) => ({
|
|
408
426
|
matchUrn: e.matchUrn ?? "",
|
|
409
427
|
matchName: e.matchName ?? "",
|
|
410
|
-
status:
|
|
428
|
+
status: l(e.status),
|
|
411
429
|
statusRaw: e.status,
|
|
412
430
|
datePlannedStart: e.datePlannedStart,
|
|
413
431
|
tournamentUrn: t,
|
|
414
432
|
tournamentName: n,
|
|
415
433
|
sport: r,
|
|
416
|
-
teams:
|
|
434
|
+
teams: u(e.teams)
|
|
417
435
|
}))
|
|
418
436
|
};
|
|
419
437
|
}
|
|
420
|
-
function
|
|
438
|
+
function Se(e) {
|
|
421
439
|
return e.tournaments.flatMap((e) => e.matches);
|
|
422
440
|
}
|
|
423
441
|
//#endregion
|
|
424
442
|
//#region src/core/poll.ts
|
|
425
|
-
var
|
|
443
|
+
var Ce = /* @__PURE__ */ new Set([
|
|
426
444
|
"NOT_FOUND",
|
|
427
445
|
"GEO_DENIED",
|
|
428
446
|
"GONE",
|
|
429
447
|
"INVALID_URN"
|
|
430
448
|
]);
|
|
431
|
-
function
|
|
432
|
-
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s,
|
|
433
|
-
|
|
434
|
-
},
|
|
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 () => {
|
|
435
453
|
try {
|
|
436
|
-
let t =
|
|
454
|
+
let t = f(e.baseUrl, `/v1/matches/${encodeURIComponent(e.matchUrn)}`), a = new Headers();
|
|
437
455
|
o && a.set("If-None-Match", o);
|
|
438
|
-
let
|
|
456
|
+
let c = await m(t, {
|
|
439
457
|
credential: e.credential,
|
|
440
458
|
signal: i.signal,
|
|
441
459
|
headers: a,
|
|
442
460
|
apiHeaders: e.apiHeaders
|
|
443
461
|
});
|
|
444
|
-
if (
|
|
445
|
-
if (!
|
|
446
|
-
o =
|
|
447
|
-
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([
|
|
448
466
|
a,
|
|
449
467
|
t.datePlannedStart ?? null,
|
|
450
468
|
d ?? null
|
|
@@ -461,21 +479,21 @@ function Ce(e) {
|
|
|
461
479
|
} catch (t) {
|
|
462
480
|
if (!i.signal.aborted) {
|
|
463
481
|
let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
|
|
464
|
-
|
|
482
|
+
Ce.has(r.code) && (c = !0), e.onError?.(r);
|
|
465
483
|
}
|
|
466
484
|
} finally {
|
|
467
|
-
|
|
485
|
+
d();
|
|
468
486
|
}
|
|
469
487
|
};
|
|
470
|
-
return
|
|
471
|
-
|
|
488
|
+
return p(), { stop() {
|
|
489
|
+
c = !0, i.abort(), a && clearTimeout(a);
|
|
472
490
|
} };
|
|
473
491
|
}
|
|
474
492
|
//#endregion
|
|
475
493
|
//#region src/core/events.ts
|
|
476
|
-
var
|
|
494
|
+
var Te = 45e3;
|
|
477
495
|
function E(e) {
|
|
478
|
-
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) => {
|
|
479
497
|
if (a.signal.aborted) return t();
|
|
480
498
|
let n = setTimeout(t, e);
|
|
481
499
|
a.signal.addEventListener("abort", () => {
|
|
@@ -495,7 +513,7 @@ function E(e) {
|
|
|
495
513
|
let t = JSON.parse(r.join("\n"));
|
|
496
514
|
t && typeof t.state == "string" && e.onState(t);
|
|
497
515
|
} catch {}
|
|
498
|
-
}, u = /\r\n\r\n|\n\n|\r\r/,
|
|
516
|
+
}, u = /\r\n\r\n|\n\n|\r\r/, d = async (e, t, n) => {
|
|
499
517
|
let r = e.getReader(), a = new TextDecoder(), s = "", c = !1, d, f = () => {
|
|
500
518
|
i && (clearTimeout(d), d = setTimeout(() => {
|
|
501
519
|
n(), r.cancel().catch(() => {});
|
|
@@ -523,13 +541,13 @@ function E(e) {
|
|
|
523
541
|
p = `no data for ${i}ms`, l.abort();
|
|
524
542
|
};
|
|
525
543
|
try {
|
|
526
|
-
let n = await
|
|
544
|
+
let n = await c(e.credential);
|
|
527
545
|
if (o) return;
|
|
528
|
-
let a =
|
|
546
|
+
let a = f(e.eventsBaseUrl, `/v1/events/${encodeURIComponent(e.matchUrn)}`);
|
|
529
547
|
i && (m = setTimeout(() => {
|
|
530
548
|
p = `no response headers within ${i}ms`, l.abort();
|
|
531
549
|
}, i));
|
|
532
|
-
let
|
|
550
|
+
let s = await fetch(a, {
|
|
533
551
|
method: "GET",
|
|
534
552
|
headers: {
|
|
535
553
|
"x-api-key": n.apiKey,
|
|
@@ -541,7 +559,7 @@ function E(e) {
|
|
|
541
559
|
mode: "cors"
|
|
542
560
|
});
|
|
543
561
|
if (clearTimeout(m), o) return;
|
|
544
|
-
!
|
|
562
|
+
!s.ok || !s.body ? e.onError?.(/* @__PURE__ */ Error(`live-state subscribe failed: HTTP ${s.status}`)) : await d(s.body, () => {
|
|
545
563
|
r = t;
|
|
546
564
|
}, h);
|
|
547
565
|
} catch (t) {
|
|
@@ -551,7 +569,7 @@ function E(e) {
|
|
|
551
569
|
clearTimeout(m), a.signal.removeEventListener("abort", u), l.abort();
|
|
552
570
|
}
|
|
553
571
|
if (o) return;
|
|
554
|
-
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);
|
|
555
573
|
}
|
|
556
574
|
})(), { close() {
|
|
557
575
|
o || (o = !0, a.abort());
|
|
@@ -574,20 +592,20 @@ function A() {
|
|
|
574
592
|
let e = globalThis.localStorage?.getItem(O);
|
|
575
593
|
if (e) return k = e, e;
|
|
576
594
|
} catch {}
|
|
577
|
-
let e =
|
|
595
|
+
let e = De();
|
|
578
596
|
k = e;
|
|
579
597
|
try {
|
|
580
598
|
globalThis.localStorage?.setItem(O, e);
|
|
581
599
|
} catch {}
|
|
582
600
|
return e;
|
|
583
601
|
}
|
|
584
|
-
function
|
|
602
|
+
function Ee() {
|
|
585
603
|
k = void 0;
|
|
586
604
|
try {
|
|
587
605
|
globalThis.localStorage?.removeItem(O);
|
|
588
606
|
} catch {}
|
|
589
607
|
}
|
|
590
|
-
function
|
|
608
|
+
function De() {
|
|
591
609
|
let e = globalThis.crypto;
|
|
592
610
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
593
611
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -599,7 +617,7 @@ function Ee() {
|
|
|
599
617
|
}
|
|
600
618
|
//#endregion
|
|
601
619
|
//#region src/core/drm/headers.ts
|
|
602
|
-
function
|
|
620
|
+
function Oe(e, t, n = {}) {
|
|
603
621
|
let r = {
|
|
604
622
|
"x-api-key": t.apiKey,
|
|
605
623
|
"X-Match-Urn": e.matchUrn,
|
|
@@ -610,19 +628,19 @@ function De(e, t, n = {}) {
|
|
|
610
628
|
}
|
|
611
629
|
//#endregion
|
|
612
630
|
//#region src/core/bandwidthMemory.ts
|
|
613
|
-
var j = "havik.player.bandwidth",
|
|
614
|
-
function
|
|
631
|
+
var j = "havik.player.bandwidth", ke = .8, Ae = 2e7, je = 3e5;
|
|
632
|
+
function Me() {
|
|
615
633
|
return globalThis.navigator?.connection;
|
|
616
634
|
}
|
|
617
|
-
function
|
|
618
|
-
let e =
|
|
635
|
+
function Ne() {
|
|
636
|
+
let e = Me()?.type;
|
|
619
637
|
return typeof e == "string" && e !== "" && e !== "unknown" ? e : "any";
|
|
620
638
|
}
|
|
621
|
-
function
|
|
622
|
-
let e =
|
|
639
|
+
function Pe() {
|
|
640
|
+
let e = Me()?.downlink;
|
|
623
641
|
return typeof e == "number" && Number.isFinite(e) && e > 0 ? e * 1e6 : void 0;
|
|
624
642
|
}
|
|
625
|
-
function
|
|
643
|
+
function Fe() {
|
|
626
644
|
try {
|
|
627
645
|
let e = globalThis.localStorage?.getItem(j);
|
|
628
646
|
if (!e) return {};
|
|
@@ -632,18 +650,18 @@ function Pe() {
|
|
|
632
650
|
return {};
|
|
633
651
|
}
|
|
634
652
|
}
|
|
635
|
-
function
|
|
636
|
-
let t =
|
|
653
|
+
function Ie(e = Date.now()) {
|
|
654
|
+
let t = Fe()[Ne()];
|
|
637
655
|
if (!t || typeof t.bps != "number" || typeof t.at != "number" || !Number.isFinite(t.bps) || t.bps <= 0) return;
|
|
638
656
|
let n = e - t.at;
|
|
639
657
|
if (n < 0 || n > 2592e5) return;
|
|
640
|
-
let r =
|
|
641
|
-
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)));
|
|
642
660
|
}
|
|
643
|
-
function
|
|
661
|
+
function Le(e, t = Date.now()) {
|
|
644
662
|
if (!Number.isFinite(e) || e <= 0) return;
|
|
645
|
-
let n =
|
|
646
|
-
n[
|
|
663
|
+
let n = Fe();
|
|
664
|
+
n[Ne()] = {
|
|
647
665
|
bps: Math.round(e),
|
|
648
666
|
at: t
|
|
649
667
|
};
|
|
@@ -651,17 +669,17 @@ function Ie(e, t = Date.now()) {
|
|
|
651
669
|
globalThis.localStorage?.setItem(j, JSON.stringify(n));
|
|
652
670
|
} catch {}
|
|
653
671
|
}
|
|
654
|
-
function
|
|
672
|
+
function Re() {
|
|
655
673
|
try {
|
|
656
674
|
globalThis.localStorage?.removeItem(j);
|
|
657
675
|
} catch {}
|
|
658
676
|
}
|
|
659
677
|
//#endregion
|
|
660
678
|
//#region src/core/drm/cdm.ts
|
|
661
|
-
var
|
|
662
|
-
function
|
|
663
|
-
let n =
|
|
664
|
-
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));
|
|
665
683
|
let r = n.get(t.keySystem);
|
|
666
684
|
if (r) return r;
|
|
667
685
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -673,11 +691,11 @@ function M() {
|
|
|
673
691
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
674
692
|
}
|
|
675
693
|
var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
676
|
-
function
|
|
694
|
+
function Ve(e) {
|
|
677
695
|
return e.startsWith("com.widevine");
|
|
678
696
|
}
|
|
679
697
|
function P(e, t) {
|
|
680
|
-
if (!
|
|
698
|
+
if (!Ve(e)) return t;
|
|
681
699
|
let n = (e, t) => {
|
|
682
700
|
let n = e.videoCapabilities;
|
|
683
701
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
@@ -693,11 +711,11 @@ function P(e, t) {
|
|
|
693
711
|
})));
|
|
694
712
|
return [...t, ...r];
|
|
695
713
|
}
|
|
696
|
-
function
|
|
714
|
+
function He(e) {
|
|
697
715
|
return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, P(t, n)).then((t) => ({
|
|
698
716
|
keySystem: t.keySystem,
|
|
699
717
|
getConfiguration: () => t.getConfiguration(),
|
|
700
|
-
createMediaKeys: () =>
|
|
718
|
+
createMediaKeys: () => Be(e, t)
|
|
701
719
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
702
720
|
}
|
|
703
721
|
var F = {
|
|
@@ -705,14 +723,14 @@ var F = {
|
|
|
705
723
|
audio: "SW_SECURE_CRYPTO",
|
|
706
724
|
scheme: "cbcs"
|
|
707
725
|
};
|
|
708
|
-
function
|
|
726
|
+
function Ue(e) {
|
|
709
727
|
if (!M()) return;
|
|
710
728
|
let t = (e, t) => ({
|
|
711
729
|
contentType: e,
|
|
712
730
|
robustness: t,
|
|
713
731
|
encryptionScheme: F.scheme
|
|
714
732
|
});
|
|
715
|
-
|
|
733
|
+
He(e)("com.widevine.alpha", [{
|
|
716
734
|
initDataTypes: ["cenc"],
|
|
717
735
|
distinctiveIdentifier: "optional",
|
|
718
736
|
persistentState: "optional",
|
|
@@ -732,14 +750,14 @@ function I(e) {
|
|
|
732
750
|
function L(e) {
|
|
733
751
|
return (e ?? "").trim().toLowerCase();
|
|
734
752
|
}
|
|
735
|
-
var
|
|
753
|
+
var We = {
|
|
736
754
|
hevc: "hvc1.1.6.L93.90",
|
|
737
755
|
dv: "dvh1.05.06",
|
|
738
756
|
av1: "av01.0.05M.08",
|
|
739
757
|
vp9: "vp09.00.10.08"
|
|
740
|
-
},
|
|
741
|
-
function
|
|
742
|
-
let t = L(e), n =
|
|
758
|
+
}, Ge = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
|
|
759
|
+
function Ke(e) {
|
|
760
|
+
let t = L(e), n = Ge.get(t);
|
|
743
761
|
if (n) return n;
|
|
744
762
|
let r = {
|
|
745
763
|
initDataTypes: ["cenc"],
|
|
@@ -758,22 +776,22 @@ function Ge(e) {
|
|
|
758
776
|
return !1;
|
|
759
777
|
}
|
|
760
778
|
})().then((e) => (R.set(t, e), e));
|
|
761
|
-
return
|
|
779
|
+
return Ge.set(t, i), i;
|
|
762
780
|
}
|
|
763
|
-
function
|
|
764
|
-
if (M()) for (let e of Object.values(
|
|
781
|
+
function qe() {
|
|
782
|
+
if (M()) for (let e of Object.values(We)) Ke(e);
|
|
765
783
|
}
|
|
766
|
-
function
|
|
784
|
+
function Je(e) {
|
|
767
785
|
let t = I(e);
|
|
768
|
-
if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(
|
|
786
|
+
if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(We[t]));
|
|
769
787
|
}
|
|
770
788
|
//#endregion
|
|
771
789
|
//#region src/core/drm/support.ts
|
|
772
|
-
var
|
|
790
|
+
var Ye = 5e3, Xe = "video/mp4; codecs=\"avc1.42E01E\"", Ze = "audio/mp4; codecs=\"mp4a.40.2\"", Qe = {
|
|
773
791
|
widevine: ["com.widevine.alpha"],
|
|
774
792
|
fairplay: ["com.apple.fps"]
|
|
775
793
|
};
|
|
776
|
-
function
|
|
794
|
+
function $e(e) {
|
|
777
795
|
return e === "fairplay" ? [{
|
|
778
796
|
initDataTypes: [
|
|
779
797
|
"sinf",
|
|
@@ -781,30 +799,30 @@ function Qe(e) {
|
|
|
781
799
|
"cenc"
|
|
782
800
|
],
|
|
783
801
|
videoCapabilities: [{
|
|
784
|
-
contentType:
|
|
802
|
+
contentType: Xe,
|
|
785
803
|
robustness: "",
|
|
786
804
|
encryptionScheme: "cbcs"
|
|
787
805
|
}],
|
|
788
806
|
audioCapabilities: [{
|
|
789
|
-
contentType:
|
|
807
|
+
contentType: Ze,
|
|
790
808
|
robustness: "",
|
|
791
809
|
encryptionScheme: "cbcs"
|
|
792
810
|
}]
|
|
793
811
|
}] : P("com.widevine.alpha", [{
|
|
794
812
|
initDataTypes: ["cenc"],
|
|
795
813
|
videoCapabilities: [{
|
|
796
|
-
contentType:
|
|
814
|
+
contentType: Xe,
|
|
797
815
|
robustness: F.video,
|
|
798
816
|
encryptionScheme: F.scheme
|
|
799
817
|
}],
|
|
800
818
|
audioCapabilities: [{
|
|
801
|
-
contentType:
|
|
819
|
+
contentType: Ze,
|
|
802
820
|
robustness: F.audio,
|
|
803
821
|
encryptionScheme: F.scheme
|
|
804
822
|
}]
|
|
805
823
|
}]);
|
|
806
824
|
}
|
|
807
|
-
function
|
|
825
|
+
function et(e, t) {
|
|
808
826
|
return new Promise((n, r) => {
|
|
809
827
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
810
828
|
e.then((e) => {
|
|
@@ -814,8 +832,8 @@ function $e(e, t) {
|
|
|
814
832
|
});
|
|
815
833
|
});
|
|
816
834
|
}
|
|
817
|
-
async function
|
|
818
|
-
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 = {};
|
|
819
837
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
820
838
|
verdict: "insecure-context",
|
|
821
839
|
detail: r
|
|
@@ -827,7 +845,7 @@ async function et(e = {}) {
|
|
|
827
845
|
};
|
|
828
846
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
829
847
|
for (let e of t) {
|
|
830
|
-
let t =
|
|
848
|
+
let t = Qe[e];
|
|
831
849
|
if (!t) {
|
|
832
850
|
r[e] = "unknown system";
|
|
833
851
|
continue;
|
|
@@ -838,7 +856,7 @@ async function et(e = {}) {
|
|
|
838
856
|
break;
|
|
839
857
|
}
|
|
840
858
|
try {
|
|
841
|
-
return await
|
|
859
|
+
return await et((await et(i(n, $e(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
842
860
|
verdict: "supported",
|
|
843
861
|
system: e,
|
|
844
862
|
detail: r
|
|
@@ -862,37 +880,37 @@ async function et(e = {}) {
|
|
|
862
880
|
}
|
|
863
881
|
//#endregion
|
|
864
882
|
//#region src/core/manifest.ts
|
|
865
|
-
var
|
|
866
|
-
function
|
|
867
|
-
return
|
|
883
|
+
var nt = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
884
|
+
function rt(e) {
|
|
885
|
+
return nt.test(e);
|
|
868
886
|
}
|
|
869
887
|
//#endregion
|
|
870
888
|
//#region src/core/env.ts
|
|
871
|
-
var
|
|
889
|
+
var it = {
|
|
872
890
|
integration: "https://feed-dev.oddin-video.gg",
|
|
873
891
|
production: "https://feed.oddin-video.gg"
|
|
874
892
|
};
|
|
875
|
-
function
|
|
876
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
893
|
+
function at(e) {
|
|
894
|
+
let t = Object.prototype.hasOwnProperty.call(it, e) ? it[e] : void 0;
|
|
877
895
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
878
896
|
return t;
|
|
879
897
|
}
|
|
880
898
|
//#endregion
|
|
881
899
|
//#region src/core/stats.ts
|
|
882
900
|
var z = { droppedFrames: 0 };
|
|
883
|
-
function
|
|
901
|
+
function ot(e) {
|
|
884
902
|
try {
|
|
885
903
|
return new URL(e).host;
|
|
886
904
|
} catch {
|
|
887
905
|
return "";
|
|
888
906
|
}
|
|
889
907
|
}
|
|
890
|
-
var
|
|
891
|
-
function
|
|
908
|
+
var st = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
909
|
+
function ct(e) {
|
|
892
910
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
893
911
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
894
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
895
|
-
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);
|
|
896
914
|
e && (t = e, n = i.startTime);
|
|
897
915
|
}
|
|
898
916
|
return t;
|
|
@@ -904,7 +922,7 @@ function B(e) {
|
|
|
904
922
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
905
923
|
};
|
|
906
924
|
}
|
|
907
|
-
var
|
|
925
|
+
var lt = class {
|
|
908
926
|
video;
|
|
909
927
|
baseFrames = 0;
|
|
910
928
|
baseDropped = 0;
|
|
@@ -927,7 +945,7 @@ var ct = class {
|
|
|
927
945
|
};
|
|
928
946
|
}
|
|
929
947
|
};
|
|
930
|
-
function
|
|
948
|
+
function ut(e, t) {
|
|
931
949
|
let n = [
|
|
932
950
|
["playing", () => t("playing")],
|
|
933
951
|
["waiting", () => t("buffering")],
|
|
@@ -944,8 +962,8 @@ function lt(e, t) {
|
|
|
944
962
|
}
|
|
945
963
|
//#endregion
|
|
946
964
|
//#region src/core/engine/native.ts
|
|
947
|
-
var
|
|
948
|
-
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) {
|
|
949
967
|
try {
|
|
950
968
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
951
969
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -961,7 +979,7 @@ function U() {
|
|
|
961
979
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
962
980
|
return e || t;
|
|
963
981
|
}
|
|
964
|
-
function
|
|
982
|
+
function St() {
|
|
965
983
|
if (typeof navigator > "u" || !U()) return !1;
|
|
966
984
|
let e = navigator.userAgent ?? "";
|
|
967
985
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
@@ -996,7 +1014,7 @@ var W = class {
|
|
|
996
1014
|
frameCounter;
|
|
997
1015
|
detachFrames = null;
|
|
998
1016
|
constructor(e) {
|
|
999
|
-
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;
|
|
1000
1018
|
}
|
|
1001
1019
|
async load() {
|
|
1002
1020
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1017,7 +1035,7 @@ var W = class {
|
|
|
1017
1035
|
type: "error",
|
|
1018
1036
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
1019
1037
|
fatal: !0
|
|
1020
|
-
}), 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();
|
|
1021
1039
|
}
|
|
1022
1040
|
startLoad() {
|
|
1023
1041
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -1029,20 +1047,26 @@ var W = class {
|
|
|
1029
1047
|
this.savedPreload === null ? e.removeAttribute("preload") : e.setAttribute("preload", this.savedPreload);
|
|
1030
1048
|
}
|
|
1031
1049
|
armFairPlay() {
|
|
1032
|
-
let { video: e, descriptor: t, credential: r, deviceId:
|
|
1033
|
-
if (!
|
|
1034
|
-
this.fairplayLicenseUrl =
|
|
1035
|
-
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({
|
|
1036
1054
|
type: "error",
|
|
1037
|
-
error: new n(
|
|
1055
|
+
error: new n(a(t, i), t, e, i ? { serverCode: i } : void 0),
|
|
1038
1056
|
fatal: r
|
|
1039
|
-
})
|
|
1057
|
+
}), d = async (e) => {
|
|
1058
|
+
try {
|
|
1059
|
+
return await e.text();
|
|
1060
|
+
} catch {
|
|
1061
|
+
return "";
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1040
1064
|
this.onEncrypted = (n) => {
|
|
1041
|
-
let
|
|
1042
|
-
|
|
1065
|
+
let a = n;
|
|
1066
|
+
a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = xt(a.initData), (async () => {
|
|
1043
1067
|
try {
|
|
1044
1068
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
1045
|
-
initDataTypes: [
|
|
1069
|
+
initDataTypes: [a.initDataType],
|
|
1046
1070
|
videoCapabilities: [{
|
|
1047
1071
|
contentType: "application/vnd.apple.mpegurl",
|
|
1048
1072
|
robustness: ""
|
|
@@ -1050,39 +1074,40 @@ var W = class {
|
|
|
1050
1074
|
distinctiveIdentifier: "not-allowed",
|
|
1051
1075
|
persistentState: "not-allowed",
|
|
1052
1076
|
sessionTypes: ["temporary"]
|
|
1053
|
-
}])).createMediaKeys(),
|
|
1054
|
-
if (!
|
|
1055
|
-
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);
|
|
1056
1080
|
return;
|
|
1057
1081
|
}
|
|
1058
|
-
await n.setServerCertificate(await
|
|
1059
|
-
let
|
|
1060
|
-
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) => {
|
|
1061
1085
|
(async () => {
|
|
1062
1086
|
try {
|
|
1063
|
-
let n = await fetch(this.fairplayLicenseUrl ??
|
|
1087
|
+
let n = await fetch(this.fairplayLicenseUrl ?? l.licenseUrl, {
|
|
1064
1088
|
method: "POST",
|
|
1065
1089
|
body: e.message,
|
|
1066
1090
|
headers: {
|
|
1067
1091
|
"x-api-key": r.apiKey,
|
|
1068
1092
|
"X-Match-Urn": t.matchUrn,
|
|
1069
|
-
"X-Device-Id":
|
|
1070
|
-
...
|
|
1093
|
+
"X-Device-Id": o,
|
|
1094
|
+
...s ? { "X-User-Id": s } : {},
|
|
1071
1095
|
...this.fairplayKeyIV ? { "X-Key-Iv": this.fairplayKeyIV } : {}
|
|
1072
1096
|
}
|
|
1073
1097
|
});
|
|
1074
1098
|
if (!n.ok) {
|
|
1075
|
-
|
|
1099
|
+
let e = n.status === 403 ? i(await d(n)) : void 0;
|
|
1100
|
+
u(`FairPlay license request failed: ${n.status}`, n.status, !0, e);
|
|
1076
1101
|
return;
|
|
1077
1102
|
}
|
|
1078
|
-
await
|
|
1103
|
+
await f.update(new Uint8Array(await n.arrayBuffer()));
|
|
1079
1104
|
} catch (e) {
|
|
1080
|
-
|
|
1105
|
+
u(`FairPlay license request failed: ${String(e)}`, 0, !0);
|
|
1081
1106
|
}
|
|
1082
1107
|
})();
|
|
1083
|
-
}), await
|
|
1108
|
+
}), await f.generateRequest(a.initDataType, a.initData);
|
|
1084
1109
|
} catch (e) {
|
|
1085
|
-
this.fairplayArmed = !1,
|
|
1110
|
+
this.fairplayArmed = !1, u(`FairPlay key session failed: ${String(e)}`, 0, !0);
|
|
1086
1111
|
}
|
|
1087
1112
|
})());
|
|
1088
1113
|
}, e.addEventListener("encrypted", this.onEncrypted);
|
|
@@ -1138,10 +1163,10 @@ var W = class {
|
|
|
1138
1163
|
droppedFrames: t.dropped,
|
|
1139
1164
|
decodedFrames: t.totalFrames
|
|
1140
1165
|
};
|
|
1141
|
-
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) {
|
|
1142
1167
|
n.isLive = !0;
|
|
1143
1168
|
let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
|
|
1144
|
-
Number.isFinite(r) && (n.atLiveEdge = r <=
|
|
1169
|
+
Number.isFinite(r) && (n.atLiveEdge = r <= _t, !e.paused && r >= 0 && (n.latencySeconds = r));
|
|
1145
1170
|
} else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
|
|
1146
1171
|
return n;
|
|
1147
1172
|
}
|
|
@@ -1159,7 +1184,7 @@ var W = class {
|
|
|
1159
1184
|
return;
|
|
1160
1185
|
}
|
|
1161
1186
|
let t = this.hiddenSince;
|
|
1162
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1187
|
+
this.hiddenSince = null, t != null && e - t >= dt && this.armRefocus();
|
|
1163
1188
|
}, this.onPageShow = (e) => {
|
|
1164
1189
|
e.persisted && this.armRefocus();
|
|
1165
1190
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
@@ -1169,7 +1194,7 @@ var W = class {
|
|
|
1169
1194
|
let e = this.liveEnd(), t = G, n = t(), r = 0, i = () => {
|
|
1170
1195
|
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1171
1196
|
r += V;
|
|
1172
|
-
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;
|
|
1173
1198
|
if (o || s && a != null) {
|
|
1174
1199
|
this.snapToLive();
|
|
1175
1200
|
return;
|
|
@@ -1189,9 +1214,9 @@ var W = class {
|
|
|
1189
1214
|
}, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
|
|
1190
1215
|
if (e.duration !== Infinity) return;
|
|
1191
1216
|
this.checkEndStale();
|
|
1192
|
-
let t =
|
|
1193
|
-
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >=
|
|
1194
|
-
},
|
|
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);
|
|
1195
1220
|
}
|
|
1196
1221
|
checkEndStale() {
|
|
1197
1222
|
if (this.endedEmitted) return;
|
|
@@ -1199,14 +1224,14 @@ var W = class {
|
|
|
1199
1224
|
this.lastTickAt = e;
|
|
1200
1225
|
let n = this.liveEnd();
|
|
1201
1226
|
if (n == null) return;
|
|
1202
|
-
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >=
|
|
1227
|
+
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= yt;
|
|
1203
1228
|
this.lastSeekableEnd = n;
|
|
1204
1229
|
let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
|
|
1205
|
-
if (r || t >
|
|
1230
|
+
if (r || t > bt || a || i.paused) {
|
|
1206
1231
|
this.edgeStampedAt = e;
|
|
1207
1232
|
return;
|
|
1208
1233
|
}
|
|
1209
|
-
e - (this.edgeStampedAt ?? e) >
|
|
1234
|
+
e - (this.edgeStampedAt ?? e) > vt && (this.endedEmitted = !0, this.deps.emit({
|
|
1210
1235
|
type: "ended",
|
|
1211
1236
|
reason: "stalled"
|
|
1212
1237
|
}));
|
|
@@ -1220,7 +1245,7 @@ var W = class {
|
|
|
1220
1245
|
liveEdgeEstimate() {
|
|
1221
1246
|
let e = this.deps.video;
|
|
1222
1247
|
if (e.duration !== Infinity) return null;
|
|
1223
|
-
let t = this.liveEnd(), n =
|
|
1248
|
+
let t = this.liveEnd(), n = Ct(e, e.currentTime) ?? this.lastBufferedEnd;
|
|
1224
1249
|
if (n != null) {
|
|
1225
1250
|
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (G() - e) / 1e3));
|
|
1226
1251
|
(t == null || r > t) && (t = r);
|
|
@@ -1236,7 +1261,7 @@ var W = class {
|
|
|
1236
1261
|
snapToLive() {
|
|
1237
1262
|
let e = this.deps.video, t = this.liveEnd();
|
|
1238
1263
|
if (t == null) return;
|
|
1239
|
-
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);
|
|
1240
1265
|
try {
|
|
1241
1266
|
e.currentTime = i;
|
|
1242
1267
|
} catch {}
|
|
@@ -1257,7 +1282,7 @@ var W = class {
|
|
|
1257
1282
|
function G() {
|
|
1258
1283
|
return typeof performance < "u" ? performance.now() : Date.now();
|
|
1259
1284
|
}
|
|
1260
|
-
function
|
|
1285
|
+
function Ct(e, t) {
|
|
1261
1286
|
let n = e.buffered;
|
|
1262
1287
|
if (!n || !Number.isFinite(t)) return null;
|
|
1263
1288
|
for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
|
|
@@ -1266,7 +1291,7 @@ function St(e, t) {
|
|
|
1266
1291
|
}
|
|
1267
1292
|
return null;
|
|
1268
1293
|
}
|
|
1269
|
-
function
|
|
1294
|
+
function wt(e, t) {
|
|
1270
1295
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1271
1296
|
}
|
|
1272
1297
|
//#endregion
|
|
@@ -1282,9 +1307,23 @@ function K(e, t = Date.now()) {
|
|
|
1282
1307
|
return !n || !/^\d+$/.test(n) ? !1 : Number(n) * 1e3 <= t;
|
|
1283
1308
|
}
|
|
1284
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
|
|
1285
1324
|
//#region src/core/engine/prefetch.ts
|
|
1286
|
-
var
|
|
1287
|
-
function
|
|
1325
|
+
var Dt = 15e3, Ot = 5e3, kt = 6;
|
|
1326
|
+
function At(e) {
|
|
1288
1327
|
try {
|
|
1289
1328
|
let t = new URL(e);
|
|
1290
1329
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1292,7 +1331,7 @@ function Dt(e) {
|
|
|
1292
1331
|
return e;
|
|
1293
1332
|
}
|
|
1294
1333
|
}
|
|
1295
|
-
var
|
|
1334
|
+
var jt = class {
|
|
1296
1335
|
cmcd;
|
|
1297
1336
|
entries = /* @__PURE__ */ new Map();
|
|
1298
1337
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1315,10 +1354,10 @@ var Ot = class {
|
|
|
1315
1354
|
}
|
|
1316
1355
|
prefetch(e, t, n) {
|
|
1317
1356
|
if (!this.isActive(t)) return;
|
|
1318
|
-
let r =
|
|
1357
|
+
let r = At(e);
|
|
1319
1358
|
if (this.entries.has(r)) return;
|
|
1320
1359
|
let i = this.perTrack.get(t) ?? 0;
|
|
1321
|
-
if (i >=
|
|
1360
|
+
if (i >= kt) return;
|
|
1322
1361
|
this.perTrack.set(t, i + 1);
|
|
1323
1362
|
let a = new AbortController(), o = {
|
|
1324
1363
|
started: performance.now(),
|
|
@@ -1332,10 +1371,10 @@ var Ot = class {
|
|
|
1332
1371
|
signal: a.signal
|
|
1333
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(() => {
|
|
1334
1373
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1335
|
-
},
|
|
1374
|
+
}, Dt);
|
|
1336
1375
|
}
|
|
1337
1376
|
take(e) {
|
|
1338
|
-
let t =
|
|
1377
|
+
let t = At(e), n = this.entries.get(t);
|
|
1339
1378
|
return n && this.entries.delete(t), n;
|
|
1340
1379
|
}
|
|
1341
1380
|
destroy() {
|
|
@@ -1355,13 +1394,13 @@ var Ot = class {
|
|
|
1355
1394
|
}
|
|
1356
1395
|
}
|
|
1357
1396
|
};
|
|
1358
|
-
function
|
|
1397
|
+
function Mt(t) {
|
|
1359
1398
|
let n = e.DefaultConfig?.loader;
|
|
1360
1399
|
if (typeof n != "function") return;
|
|
1361
1400
|
class r extends n {
|
|
1362
1401
|
served = !1;
|
|
1363
1402
|
cancelled = !1;
|
|
1364
|
-
stats =
|
|
1403
|
+
stats = Nt();
|
|
1365
1404
|
load(e, n, r) {
|
|
1366
1405
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1367
1406
|
if (!i) {
|
|
@@ -1369,7 +1408,7 @@ function kt(t) {
|
|
|
1369
1408
|
return;
|
|
1370
1409
|
}
|
|
1371
1410
|
this.served = !0;
|
|
1372
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1411
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Ot, s = setTimeout(() => {
|
|
1373
1412
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1374
1413
|
}, o);
|
|
1375
1414
|
i.bytes.then((o) => {
|
|
@@ -1396,7 +1435,7 @@ function kt(t) {
|
|
|
1396
1435
|
}
|
|
1397
1436
|
return r;
|
|
1398
1437
|
}
|
|
1399
|
-
function
|
|
1438
|
+
function Nt() {
|
|
1400
1439
|
return {
|
|
1401
1440
|
aborted: !1,
|
|
1402
1441
|
loaded: 0,
|
|
@@ -1420,10 +1459,10 @@ function At() {
|
|
|
1420
1459
|
}
|
|
1421
1460
|
};
|
|
1422
1461
|
}
|
|
1423
|
-
function
|
|
1462
|
+
function Pt(e) {
|
|
1424
1463
|
return e === "audio" ? "audio" : "main";
|
|
1425
1464
|
}
|
|
1426
|
-
function
|
|
1465
|
+
function Ft(e, t) {
|
|
1427
1466
|
let n = [];
|
|
1428
1467
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1429
1468
|
url: t.initSegment.url,
|
|
@@ -1442,24 +1481,24 @@ function Mt(e, t) {
|
|
|
1442
1481
|
}
|
|
1443
1482
|
//#endregion
|
|
1444
1483
|
//#region src/core/engine/hls.ts
|
|
1445
|
-
function
|
|
1484
|
+
function It() {
|
|
1446
1485
|
return e.isSupported();
|
|
1447
1486
|
}
|
|
1448
|
-
var
|
|
1449
|
-
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) {
|
|
1450
1489
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1451
1490
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1452
1491
|
return;
|
|
1453
1492
|
}
|
|
1454
|
-
e.liveSyncDuration ??=
|
|
1455
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1456
|
-
(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);
|
|
1457
1496
|
}
|
|
1458
|
-
function
|
|
1497
|
+
function yn(e, t) {
|
|
1459
1498
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1460
1499
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1461
1500
|
}
|
|
1462
|
-
var
|
|
1501
|
+
var bn = class {
|
|
1463
1502
|
name = "hls";
|
|
1464
1503
|
hls = null;
|
|
1465
1504
|
deps;
|
|
@@ -1543,7 +1582,7 @@ var _n = class {
|
|
|
1543
1582
|
frameCounter;
|
|
1544
1583
|
detachFrames = null;
|
|
1545
1584
|
constructor(e) {
|
|
1546
|
-
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;
|
|
1547
1586
|
}
|
|
1548
1587
|
async load() {
|
|
1549
1588
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1556,7 +1595,7 @@ var _n = class {
|
|
|
1556
1595
|
});
|
|
1557
1596
|
return;
|
|
1558
1597
|
}
|
|
1559
|
-
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 = () => {
|
|
1560
1599
|
let e = this.hls;
|
|
1561
1600
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1562
1601
|
let t = e.liveSyncPosition;
|
|
@@ -1579,7 +1618,7 @@ var _n = class {
|
|
|
1579
1618
|
}
|
|
1580
1619
|
this.loadSuspended = !0;
|
|
1581
1620
|
}
|
|
1582
|
-
},
|
|
1621
|
+
}, en));
|
|
1583
1622
|
}
|
|
1584
1623
|
resumeLoading() {
|
|
1585
1624
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1611,7 +1650,7 @@ var _n = class {
|
|
|
1611
1650
|
let t = e.liveSyncPosition;
|
|
1612
1651
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1613
1652
|
let { video: n } = this.deps;
|
|
1614
|
-
n.currentTime <= t +
|
|
1653
|
+
n.currentTime <= t + gn || (n.currentTime = t);
|
|
1615
1654
|
}
|
|
1616
1655
|
reanchorPartTimeline(e, t) {
|
|
1617
1656
|
let { frag: n, part: r } = t;
|
|
@@ -1623,7 +1662,7 @@ var _n = class {
|
|
|
1623
1662
|
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1624
1663
|
if (!s) return;
|
|
1625
1664
|
let c = a.startPTS - s.start;
|
|
1626
|
-
if (!(!Number.isFinite(c) || Math.abs(c) <
|
|
1665
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < qt)) {
|
|
1627
1666
|
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1628
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})`);
|
|
1629
1668
|
}
|
|
@@ -1651,7 +1690,7 @@ var _n = class {
|
|
|
1651
1690
|
videoEncryptionScheme: F.scheme,
|
|
1652
1691
|
audioEncryptionScheme: F.scheme
|
|
1653
1692
|
},
|
|
1654
|
-
...M() ? { requestMediaKeySystemAccessFunc:
|
|
1693
|
+
...M() ? { requestMediaKeySystemAccessFunc: He(t) } : {},
|
|
1655
1694
|
licenseXhrSetup: (e, t) => {
|
|
1656
1695
|
let o = performance.now(), s = () => {
|
|
1657
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", () => {
|
|
@@ -1663,7 +1702,7 @@ var _n = class {
|
|
|
1663
1702
|
return;
|
|
1664
1703
|
}
|
|
1665
1704
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1666
|
-
u = setTimeout(() => e(void 0),
|
|
1705
|
+
u = setTimeout(() => e(void 0), Ut);
|
|
1667
1706
|
});
|
|
1668
1707
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1669
1708
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1679,20 +1718,20 @@ var _n = class {
|
|
|
1679
1718
|
...c
|
|
1680
1719
|
};
|
|
1681
1720
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !f.fLoader) {
|
|
1682
|
-
let e = new
|
|
1721
|
+
let e = new jt({
|
|
1683
1722
|
sessionId: n.analytics?.sid,
|
|
1684
1723
|
contentId: n.matchUrn
|
|
1685
|
-
}), t =
|
|
1724
|
+
}), t = Mt(e);
|
|
1686
1725
|
t && (this.prefetch = e, f.fLoader = t);
|
|
1687
1726
|
}
|
|
1688
|
-
|
|
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;
|
|
1689
1728
|
let p = new e(f);
|
|
1690
1729
|
if (this.hls = p, p.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(p, t)), p.on(e.Events.MANIFEST_PARSED, () => {
|
|
1691
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" });
|
|
1692
1731
|
}), p.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1693
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(() => {
|
|
1694
1733
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1695
|
-
},
|
|
1734
|
+
}, Wt)));
|
|
1696
1735
|
}), p.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1697
1736
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1698
1737
|
}), p.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1700,10 +1739,10 @@ var _n = class {
|
|
|
1700
1739
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1701
1740
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1702
1741
|
let i = n?.loading;
|
|
1703
|
-
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());
|
|
1704
1743
|
let a = t?.frag?.url;
|
|
1705
1744
|
if (a) {
|
|
1706
|
-
let e =
|
|
1745
|
+
let e = ot(a);
|
|
1707
1746
|
e && (this.cdnHost = e);
|
|
1708
1747
|
}
|
|
1709
1748
|
}), p.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1717,15 +1756,15 @@ var _n = class {
|
|
|
1717
1756
|
}), p.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1718
1757
|
let t = this.prefetch;
|
|
1719
1758
|
p.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1720
|
-
let r = n?.frag, i =
|
|
1721
|
-
if (r && t.isActive(i)) for (let e of
|
|
1722
|
-
}), 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)));
|
|
1723
1762
|
}
|
|
1724
1763
|
p.on(e.Events.KEY_LOADED, () => {
|
|
1725
1764
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1726
1765
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1727
1766
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1728
|
-
},
|
|
1767
|
+
}, Kt), p.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1729
1768
|
this.renditionSwitches += 1;
|
|
1730
1769
|
let n = this.lastLevelIndex >= 0 ? p.levels[this.lastLevelIndex] : void 0, r = p.levels[t.level];
|
|
1731
1770
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1789,7 +1828,7 @@ var _n = class {
|
|
|
1789
1828
|
return;
|
|
1790
1829
|
}
|
|
1791
1830
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1792
|
-
let t = e > this.sizeCapLevel ?
|
|
1831
|
+
let t = e > this.sizeCapLevel ? ln : un;
|
|
1793
1832
|
this.capTimer = setTimeout(() => {
|
|
1794
1833
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1795
1834
|
}, t);
|
|
@@ -1799,9 +1838,9 @@ var _n = class {
|
|
|
1799
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;
|
|
1800
1839
|
}
|
|
1801
1840
|
dropLevelsWidevineCannotPlay(e) {
|
|
1802
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1841
|
+
this.removeLevelsWhere(e, (e) => Je(e) !== !0);
|
|
1803
1842
|
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
|
|
1804
|
-
for (let n of t)
|
|
1843
|
+
for (let n of t) Ke(n).then((t) => {
|
|
1805
1844
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1806
1845
|
});
|
|
1807
1846
|
}
|
|
@@ -1812,7 +1851,7 @@ var _n = class {
|
|
|
1812
1851
|
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1813
1852
|
}), !r.length) return !1;
|
|
1814
1853
|
let a = [...i].join(", ");
|
|
1815
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) ||
|
|
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;
|
|
1816
1855
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1817
1856
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1818
1857
|
}
|
|
@@ -1918,7 +1957,7 @@ var _n = class {
|
|
|
1918
1957
|
return;
|
|
1919
1958
|
}
|
|
1920
1959
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1921
|
-
!this.chaseSuspended && e >
|
|
1960
|
+
!this.chaseSuspended && e > Jt && this.suspendChasing(), e > Gt && this.emitEnded("stalled");
|
|
1922
1961
|
}
|
|
1923
1962
|
resetStarvationWindow() {
|
|
1924
1963
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1933,7 +1972,7 @@ var _n = class {
|
|
|
1933
1972
|
this.resetStarvationWindow();
|
|
1934
1973
|
return;
|
|
1935
1974
|
}
|
|
1936
|
-
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;
|
|
1937
1976
|
if (this.starvedFrames = c, !a || l) {
|
|
1938
1977
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1939
1978
|
return;
|
|
@@ -1942,12 +1981,12 @@ var _n = class {
|
|
|
1942
1981
|
this.resetStarvationWindow();
|
|
1943
1982
|
return;
|
|
1944
1983
|
}
|
|
1945
|
-
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)) {
|
|
1946
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");
|
|
1947
1986
|
return;
|
|
1948
1987
|
}
|
|
1949
|
-
let u = i && this.starvedTicks >=
|
|
1950
|
-
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))) {
|
|
1951
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");
|
|
1952
1991
|
try {
|
|
1953
1992
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1962,7 +2001,7 @@ var _n = class {
|
|
|
1962
2001
|
let t = e.latency, n = e.targetLatency;
|
|
1963
2002
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1964
2003
|
let r = t - n;
|
|
1965
|
-
!this.catchUpEngaged && r >
|
|
2004
|
+
!this.catchUpEngaged && r > Yt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Yt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1966
2005
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1967
2006
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1968
2007
|
}
|
|
@@ -1984,15 +2023,15 @@ var _n = class {
|
|
|
1984
2023
|
return;
|
|
1985
2024
|
}
|
|
1986
2025
|
let { totalFrames: n, dropped: r } = B(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
1987
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
2026
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < fn || o < 0) {
|
|
1988
2027
|
this.fpsBadTicks = 0;
|
|
1989
2028
|
return;
|
|
1990
2029
|
}
|
|
1991
|
-
if (o <=
|
|
2030
|
+
if (o <= dn * a) {
|
|
1992
2031
|
this.fpsBadTicks = 0;
|
|
1993
2032
|
return;
|
|
1994
2033
|
}
|
|
1995
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
2034
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < pn) return;
|
|
1996
2035
|
this.fpsBadTicks = 0;
|
|
1997
2036
|
let s = e.levels, c = s[e.currentLevel];
|
|
1998
2037
|
if (!c) return;
|
|
@@ -2009,20 +2048,20 @@ var _n = class {
|
|
|
2009
2048
|
return;
|
|
2010
2049
|
}
|
|
2011
2050
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
2012
|
-
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))) {
|
|
2013
2052
|
this.resetChaseWindow();
|
|
2014
2053
|
return;
|
|
2015
2054
|
}
|
|
2016
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
2055
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= Zt) {
|
|
2017
2056
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
2018
2057
|
return;
|
|
2019
2058
|
}
|
|
2020
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
2059
|
+
if (this.chaseTicks += 1, this.chaseTicks < Xt) return;
|
|
2021
2060
|
this.resetChaseWindow();
|
|
2022
2061
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2023
2062
|
if (!(a > 1)) return;
|
|
2024
2063
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
2025
|
-
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);
|
|
2026
2065
|
}
|
|
2027
2066
|
suspendChasing() {
|
|
2028
2067
|
let e = this.hls;
|
|
@@ -2052,14 +2091,14 @@ var _n = class {
|
|
|
2052
2091
|
} catch {}
|
|
2053
2092
|
}
|
|
2054
2093
|
startEstimate() {
|
|
2055
|
-
return this.deps.rememberBandwidth === !1 ?
|
|
2094
|
+
return this.deps.rememberBandwidth === !1 ? Lt : Ie() ?? Lt;
|
|
2056
2095
|
}
|
|
2057
2096
|
maybeRememberBandwidth(e) {
|
|
2058
|
-
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded <
|
|
2097
|
+
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Rt) return;
|
|
2059
2098
|
let t = Date.now();
|
|
2060
|
-
if (!e && t - this.bwSavedAt <
|
|
2099
|
+
if (!e && t - this.bwSavedAt < zt) return;
|
|
2061
2100
|
let n = this.hls?.bandwidthEstimate;
|
|
2062
|
-
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));
|
|
2063
2102
|
}
|
|
2064
2103
|
destroy() {
|
|
2065
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) {
|
|
@@ -2077,7 +2116,7 @@ var _n = class {
|
|
|
2077
2116
|
scheduleLicenseRetry(t) {
|
|
2078
2117
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
2079
2118
|
let n = t.response?.code ?? 0;
|
|
2080
|
-
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;
|
|
2081
2120
|
this.licenseRecoveries += 1;
|
|
2082
2121
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
2083
2122
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -2109,7 +2148,7 @@ var _n = class {
|
|
|
2109
2148
|
return;
|
|
2110
2149
|
}
|
|
2111
2150
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
2112
|
-
if (this.networkRecoveries <
|
|
2151
|
+
if (this.networkRecoveries < Vt) {
|
|
2113
2152
|
this.networkRecoveries += 1;
|
|
2114
2153
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
2115
2154
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -2126,7 +2165,7 @@ var _n = class {
|
|
|
2126
2165
|
return;
|
|
2127
2166
|
}
|
|
2128
2167
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
2129
|
-
if (this.mediaRecoveries <
|
|
2168
|
+
if (this.mediaRecoveries < Bt) {
|
|
2130
2169
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
2131
2170
|
return;
|
|
2132
2171
|
}
|
|
@@ -2146,23 +2185,23 @@ var _n = class {
|
|
|
2146
2185
|
});
|
|
2147
2186
|
}
|
|
2148
2187
|
}
|
|
2149
|
-
toError(
|
|
2150
|
-
let
|
|
2151
|
-
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);
|
|
2152
2191
|
}
|
|
2153
|
-
},
|
|
2192
|
+
}, xn = 15e3, Sn = 6e5, Cn = 3e5, wn = 100, q = 1, Tn = 1e3, En = 3e4, Dn = 1e3, On = {
|
|
2154
2193
|
inline: "PRESENTATION_INLINE",
|
|
2155
2194
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2156
2195
|
pip: "PRESENTATION_PIP"
|
|
2157
|
-
},
|
|
2196
|
+
}, kn = {
|
|
2158
2197
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2159
2198
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2160
2199
|
none: "KEY_SYSTEM_NONE"
|
|
2161
2200
|
};
|
|
2162
|
-
function
|
|
2201
|
+
function An(e, t) {
|
|
2163
2202
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
2164
2203
|
}
|
|
2165
|
-
var
|
|
2204
|
+
var jn = /* @__PURE__ */ new Set([
|
|
2166
2205
|
"INVALID_URN",
|
|
2167
2206
|
"NOT_FOUND",
|
|
2168
2207
|
"GEO_DENIED",
|
|
@@ -2183,7 +2222,7 @@ var On = /* @__PURE__ */ new Set([
|
|
|
2183
2222
|
ended: "PLAYER_STATE_ENDED",
|
|
2184
2223
|
error: "PLAYER_STATE_ERROR"
|
|
2185
2224
|
};
|
|
2186
|
-
function
|
|
2225
|
+
function Mn(e) {
|
|
2187
2226
|
try {
|
|
2188
2227
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2189
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);
|
|
@@ -2191,8 +2230,8 @@ function kn(e) {
|
|
|
2191
2230
|
return;
|
|
2192
2231
|
}
|
|
2193
2232
|
}
|
|
2194
|
-
var
|
|
2195
|
-
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) {
|
|
2196
2235
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2197
2236
|
let t;
|
|
2198
2237
|
try {
|
|
@@ -2201,19 +2240,19 @@ function Nn(e) {
|
|
|
2201
2240
|
} catch {
|
|
2202
2241
|
return;
|
|
2203
2242
|
}
|
|
2204
|
-
if (
|
|
2205
|
-
Y.add(t),
|
|
2243
|
+
if (Pn.has(t) && !Y.has(t)) {
|
|
2244
|
+
Y.add(t), _(Fn(new URL(t).origin));
|
|
2206
2245
|
for (let e of X) e.noteCspBlocked();
|
|
2207
2246
|
}
|
|
2208
2247
|
}
|
|
2209
|
-
function
|
|
2210
|
-
return
|
|
2248
|
+
function Ln(e, t) {
|
|
2249
|
+
return _(t, e), { disabledReason: t };
|
|
2211
2250
|
}
|
|
2212
|
-
function
|
|
2213
|
-
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 };
|
|
2214
2253
|
if (t) return { endpoint: t };
|
|
2215
|
-
if (t !== void 0) return
|
|
2216
|
-
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);
|
|
2217
2256
|
if (r) return { endpoint: r };
|
|
2218
2257
|
let i;
|
|
2219
2258
|
try {
|
|
@@ -2221,9 +2260,9 @@ function Fn(e, t, n) {
|
|
|
2221
2260
|
} catch {
|
|
2222
2261
|
i = e;
|
|
2223
2262
|
}
|
|
2224
|
-
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).`);
|
|
2225
2264
|
}
|
|
2226
|
-
var
|
|
2265
|
+
var zn = class {
|
|
2227
2266
|
opts;
|
|
2228
2267
|
url;
|
|
2229
2268
|
cspKey;
|
|
@@ -2305,8 +2344,8 @@ var In = class {
|
|
|
2305
2344
|
constructor(e) {
|
|
2306
2345
|
this.opts = {
|
|
2307
2346
|
...e,
|
|
2308
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2309
|
-
idleMs: e.idleMs ??
|
|
2347
|
+
heartbeatMs: e.heartbeatMs ?? xn,
|
|
2348
|
+
idleMs: e.idleMs ?? Sn
|
|
2310
2349
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2311
2350
|
try {
|
|
2312
2351
|
let e = new URL(this.url);
|
|
@@ -2323,11 +2362,11 @@ var In = class {
|
|
|
2323
2362
|
sdkVersion: this.opts.sdkVersion,
|
|
2324
2363
|
...this.opts.environment
|
|
2325
2364
|
};
|
|
2326
|
-
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());
|
|
2327
2366
|
}
|
|
2328
2367
|
checkSuspension(e) {
|
|
2329
2368
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2330
|
-
let t = Math.max(this.opts.idleMs,
|
|
2369
|
+
let t = Math.max(this.opts.idleMs, Cn);
|
|
2331
2370
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2332
2371
|
}
|
|
2333
2372
|
syncIdle(e) {
|
|
@@ -2350,12 +2389,12 @@ var In = class {
|
|
|
2350
2389
|
let a = {
|
|
2351
2390
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2352
2391
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2353
|
-
presentation:
|
|
2392
|
+
presentation: On[this.presentation]
|
|
2354
2393
|
}, o = this.causeOf(e, t, i);
|
|
2355
2394
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2356
2395
|
}
|
|
2357
2396
|
seekInduced(e) {
|
|
2358
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2397
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < Dn;
|
|
2359
2398
|
}
|
|
2360
2399
|
causeOf(e, t, n) {
|
|
2361
2400
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2428,8 +2467,8 @@ var In = class {
|
|
|
2428
2467
|
stageOf(e, t, n) {
|
|
2429
2468
|
let r = n ?? "";
|
|
2430
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";
|
|
2431
|
-
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2432
|
-
if (
|
|
2470
|
+
if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
|
|
2471
|
+
if (jn.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2433
2472
|
let i = t ?? "";
|
|
2434
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";
|
|
2435
2474
|
}
|
|
@@ -2476,14 +2515,14 @@ var In = class {
|
|
|
2476
2515
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2477
2516
|
o.requestCountDelta = _;
|
|
2478
2517
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2479
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2518
|
+
n.length > 0 && (o.requestTimeP50Ms = An(n, 50), o.requestTimeP95Ms = An(n, 95));
|
|
2480
2519
|
}
|
|
2481
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();
|
|
2482
2521
|
}
|
|
2483
2522
|
maybeEmitMediaInfo(e) {
|
|
2484
2523
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2485
2524
|
let t = {};
|
|
2486
|
-
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);
|
|
2487
2526
|
let n = JSON.stringify(t);
|
|
2488
2527
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2489
2528
|
}
|
|
@@ -2503,7 +2542,7 @@ var In = class {
|
|
|
2503
2542
|
let c = r?.positionMs ?? 0;
|
|
2504
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));
|
|
2505
2544
|
let l = e !== "END_REASON_ENDED";
|
|
2506
|
-
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);
|
|
2507
2546
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2508
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");
|
|
2509
2548
|
}
|
|
@@ -2523,13 +2562,13 @@ var In = class {
|
|
|
2523
2562
|
};
|
|
2524
2563
|
}
|
|
2525
2564
|
noteCspBlocked() {
|
|
2526
|
-
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)));
|
|
2527
2566
|
}
|
|
2528
2567
|
cspBlocked() {
|
|
2529
2568
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2530
2569
|
}
|
|
2531
2570
|
enqueue(e) {
|
|
2532
|
-
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;) {
|
|
2533
2572
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2534
2573
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2535
2574
|
}
|
|
@@ -2556,7 +2595,7 @@ var In = class {
|
|
|
2556
2595
|
};
|
|
2557
2596
|
//#endregion
|
|
2558
2597
|
//#region src/core/environment.ts
|
|
2559
|
-
function
|
|
2598
|
+
function Bn() {
|
|
2560
2599
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2561
2600
|
let e;
|
|
2562
2601
|
try {
|
|
@@ -2581,14 +2620,14 @@ function Ln() {
|
|
|
2581
2620
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2582
2621
|
};
|
|
2583
2622
|
}
|
|
2584
|
-
function
|
|
2623
|
+
function Vn() {
|
|
2585
2624
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2586
2625
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2587
2626
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2588
2627
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2589
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";
|
|
2590
2629
|
}
|
|
2591
|
-
function
|
|
2630
|
+
function Hn() {
|
|
2592
2631
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2593
2632
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2594
2633
|
let t = {
|
|
@@ -2607,17 +2646,17 @@ function zn() {
|
|
|
2607
2646
|
}
|
|
2608
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;
|
|
2609
2648
|
}
|
|
2610
|
-
function
|
|
2611
|
-
let t =
|
|
2612
|
-
deviceClass:
|
|
2649
|
+
function Un(e) {
|
|
2650
|
+
let t = Bn(), n = {
|
|
2651
|
+
deviceClass: Vn(),
|
|
2613
2652
|
integration: t.integration,
|
|
2614
|
-
...
|
|
2653
|
+
...Hn()
|
|
2615
2654
|
};
|
|
2616
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);
|
|
2617
2656
|
let r = e.getBoundingClientRect?.();
|
|
2618
2657
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2619
2658
|
}
|
|
2620
|
-
async function
|
|
2659
|
+
async function Wn() {
|
|
2621
2660
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2622
2661
|
if (!e?.getHighEntropyValues) return {};
|
|
2623
2662
|
try {
|
|
@@ -2629,7 +2668,7 @@ async function Vn() {
|
|
|
2629
2668
|
}
|
|
2630
2669
|
//#endregion
|
|
2631
2670
|
//#region src/core/version.ts
|
|
2632
|
-
var
|
|
2671
|
+
var Gn = "2.21.0", Kn = {
|
|
2633
2672
|
accent: "#E1B600",
|
|
2634
2673
|
accentText: "#1B1C23",
|
|
2635
2674
|
background: "#0e0f13",
|
|
@@ -2640,7 +2679,7 @@ var Hn = "2.20.0", Un = {
|
|
|
2640
2679
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2641
2680
|
radius: "8px",
|
|
2642
2681
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2643
|
-
},
|
|
2682
|
+
}, qn = {
|
|
2644
2683
|
accent: "--havik-accent",
|
|
2645
2684
|
accentText: "--havik-accent-text",
|
|
2646
2685
|
background: "--havik-bg",
|
|
@@ -2652,26 +2691,26 @@ var Hn = "2.20.0", Un = {
|
|
|
2652
2691
|
radius: "--havik-radius",
|
|
2653
2692
|
fontFamily: "--havik-font"
|
|
2654
2693
|
};
|
|
2655
|
-
function
|
|
2694
|
+
function Jn(e, t) {
|
|
2656
2695
|
let n = {
|
|
2657
|
-
...
|
|
2696
|
+
...Kn,
|
|
2658
2697
|
...t
|
|
2659
2698
|
};
|
|
2660
|
-
for (let t of Object.keys(
|
|
2699
|
+
for (let t of Object.keys(qn)) e.style.setProperty(qn[t], n[t]);
|
|
2661
2700
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2662
2701
|
}
|
|
2663
2702
|
//#endregion
|
|
2664
2703
|
//#region src/ui/styles.ts
|
|
2665
|
-
var Z = "havik-player-styles",
|
|
2666
|
-
function
|
|
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) {
|
|
2667
2706
|
let n = e.querySelector(`style#${Z}`);
|
|
2668
|
-
if (n && (!t ||
|
|
2707
|
+
if (n && (!t || Xn.get(n) === t)) return;
|
|
2669
2708
|
let r = e.createElement("style");
|
|
2670
|
-
r.id = Z, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent =
|
|
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);
|
|
2671
2710
|
}
|
|
2672
2711
|
//#endregion
|
|
2673
2712
|
//#region src/ui/icons.ts
|
|
2674
|
-
var
|
|
2713
|
+
var Qn = {
|
|
2675
2714
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2676
2715
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2677
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\"/>",
|
|
@@ -2685,25 +2724,27 @@ var Yn = {
|
|
|
2685
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\"/>"
|
|
2686
2725
|
};
|
|
2687
2726
|
function Q(e) {
|
|
2688
|
-
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>`;
|
|
2689
2728
|
}
|
|
2690
2729
|
//#endregion
|
|
2691
2730
|
//#region src/ui/controls.ts
|
|
2692
|
-
var
|
|
2731
|
+
var $n = 3e3, er = 250, tr = /* @__PURE__ */ new Set([
|
|
2693
2732
|
"GONE",
|
|
2694
2733
|
"NOT_FOUND",
|
|
2695
2734
|
"GEO_DENIED",
|
|
2696
2735
|
"INVALID_URN",
|
|
2697
|
-
"UNAUTHORIZED"
|
|
2736
|
+
"UNAUTHORIZED",
|
|
2737
|
+
"DRM_DEVICE_REVOKED"
|
|
2698
2738
|
]);
|
|
2699
|
-
function
|
|
2739
|
+
function nr(e) {
|
|
2700
2740
|
let t = "This match isn't available in your country";
|
|
2701
2741
|
return e ? `${t} (${e})` : t;
|
|
2702
2742
|
}
|
|
2703
|
-
|
|
2704
|
-
|
|
2743
|
+
var rr = "This device can't play protected video";
|
|
2744
|
+
function ir(e) {
|
|
2745
|
+
return new ar(e);
|
|
2705
2746
|
}
|
|
2706
|
-
var
|
|
2747
|
+
var ar = class {
|
|
2707
2748
|
root;
|
|
2708
2749
|
video;
|
|
2709
2750
|
player;
|
|
@@ -2751,7 +2792,7 @@ var tr = class {
|
|
|
2751
2792
|
scrubbing = !1;
|
|
2752
2793
|
offFns = [];
|
|
2753
2794
|
constructor(e) {
|
|
2754
|
-
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");
|
|
2755
2796
|
let t = (e, t, n) => {
|
|
2756
2797
|
let r = this.doc.createElement(e);
|
|
2757
2798
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2837,7 +2878,7 @@ var tr = class {
|
|
|
2837
2878
|
let t = this.surfaceWasHidden;
|
|
2838
2879
|
this.tapTimer = setTimeout(() => {
|
|
2839
2880
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2840
|
-
},
|
|
2881
|
+
}, er);
|
|
2841
2882
|
}
|
|
2842
2883
|
toggleBar(e) {
|
|
2843
2884
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2857,7 +2898,7 @@ var tr = class {
|
|
|
2857
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);
|
|
2858
2899
|
}
|
|
2859
2900
|
statusMessageFor(e) {
|
|
2860
|
-
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" ?
|
|
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;
|
|
2861
2902
|
}
|
|
2862
2903
|
renderStatus(e) {
|
|
2863
2904
|
let t = this.statusMessageFor(e);
|
|
@@ -2872,7 +2913,7 @@ var tr = class {
|
|
|
2872
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);
|
|
2873
2914
|
} else {
|
|
2874
2915
|
let r = this.doc.createElement("div");
|
|
2875
|
-
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)) {
|
|
2876
2917
|
let e = this.doc.createElement("button");
|
|
2877
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);
|
|
2878
2919
|
}
|
|
@@ -2913,7 +2954,7 @@ var tr = class {
|
|
|
2913
2954
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2914
2955
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2915
2956
|
}
|
|
2916
|
-
!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)}`);
|
|
2917
2958
|
}
|
|
2918
2959
|
syncLive() {
|
|
2919
2960
|
let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
|
|
@@ -2963,17 +3004,17 @@ var tr = class {
|
|
|
2963
3004
|
renderQualityMenu() {
|
|
2964
3005
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2965
3006
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2966
|
-
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)));
|
|
2967
3008
|
}
|
|
2968
3009
|
renderAudioMenu() {
|
|
2969
3010
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2970
3011
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2971
|
-
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)));
|
|
2972
3013
|
}
|
|
2973
3014
|
renderCcMenu() {
|
|
2974
3015
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2975
3016
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2976
|
-
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)));
|
|
2977
3018
|
}
|
|
2978
3019
|
onTracksChanged() {
|
|
2979
3020
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -3078,41 +3119,41 @@ var tr = class {
|
|
|
3078
3119
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
3079
3120
|
}
|
|
3080
3121
|
};
|
|
3081
|
-
function
|
|
3122
|
+
function or(e) {
|
|
3082
3123
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
3083
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");
|
|
3084
3125
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
3085
3126
|
}
|
|
3086
|
-
function
|
|
3127
|
+
function sr(e) {
|
|
3087
3128
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
3088
3129
|
}
|
|
3089
|
-
function
|
|
3130
|
+
function cr(e) {
|
|
3090
3131
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3091
3132
|
}
|
|
3092
|
-
function
|
|
3133
|
+
function lr(e) {
|
|
3093
3134
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3094
3135
|
}
|
|
3095
3136
|
//#endregion
|
|
3096
3137
|
//#region src/managed/index.ts
|
|
3097
|
-
var
|
|
3098
|
-
function
|
|
3138
|
+
var ur = 6e3, dr = 45e3, fr = 2e3, pr = 3, mr = 5e3, hr = 2e3, gr = 48e4, _r = "keySystemLicenseRequestFailed";
|
|
3139
|
+
function vr(e) {
|
|
3099
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)})`);
|
|
3100
|
-
if (e.env !== void 0) return
|
|
3141
|
+
if (e.env !== void 0) return at(e.env);
|
|
3101
3142
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
3102
3143
|
return e.baseUrl;
|
|
3103
3144
|
}
|
|
3104
|
-
async function
|
|
3145
|
+
async function yr(e) {
|
|
3105
3146
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
3106
|
-
let t =
|
|
3147
|
+
let t = vr(e);
|
|
3107
3148
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
3108
3149
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
3109
|
-
let r = new
|
|
3150
|
+
let r = new br({
|
|
3110
3151
|
...e,
|
|
3111
3152
|
baseUrl: t
|
|
3112
3153
|
});
|
|
3113
3154
|
return await r.start(), r;
|
|
3114
3155
|
}
|
|
3115
|
-
var
|
|
3156
|
+
var br = class {
|
|
3116
3157
|
opts;
|
|
3117
3158
|
abort = new AbortController();
|
|
3118
3159
|
listeners = {};
|
|
@@ -3169,7 +3210,7 @@ var gr = class {
|
|
|
3169
3210
|
throw this.destroy(), e;
|
|
3170
3211
|
}
|
|
3171
3212
|
} catch (t) {
|
|
3172
|
-
if (this.opts.waitForLive && t instanceof n &&
|
|
3213
|
+
if (this.opts.waitForLive && t instanceof n && s(t.code)) {
|
|
3173
3214
|
this.setState("waiting"), this.beginArming(e, t.liveStartsAtMs);
|
|
3174
3215
|
return;
|
|
3175
3216
|
}
|
|
@@ -3201,13 +3242,13 @@ var gr = class {
|
|
|
3201
3242
|
});
|
|
3202
3243
|
}
|
|
3203
3244
|
armWithSse(e, t, r, i = !1) {
|
|
3204
|
-
let a = !1,
|
|
3245
|
+
let a = !1, o = !1, c = new AbortController();
|
|
3205
3246
|
this.armFallbackCtrl = c, this.setState("waiting");
|
|
3206
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);
|
|
3207
3248
|
setTimeout(() => {
|
|
3208
3249
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3209
3250
|
phase: i ? "unavailable" : "tooEarly",
|
|
3210
|
-
retryInMs:
|
|
3251
|
+
retryInMs: dr,
|
|
3211
3252
|
attempt: 1,
|
|
3212
3253
|
elapsedMs: 0,
|
|
3213
3254
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3224,7 +3265,7 @@ var gr = class {
|
|
|
3224
3265
|
}
|
|
3225
3266
|
}
|
|
3226
3267
|
}, h = () => {
|
|
3227
|
-
a ||
|
|
3268
|
+
a || o || p() || (o = !0, y({
|
|
3228
3269
|
...this.resolveOptions(),
|
|
3229
3270
|
signal: c.signal,
|
|
3230
3271
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -3234,7 +3275,7 @@ var gr = class {
|
|
|
3234
3275
|
}, g = () => {
|
|
3235
3276
|
a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
|
|
3236
3277
|
if (!(a || p())) {
|
|
3237
|
-
if (e instanceof n &&
|
|
3278
|
+
if (e instanceof n && s(e.code)) {
|
|
3238
3279
|
h();
|
|
3239
3280
|
return;
|
|
3240
3281
|
}
|
|
@@ -3246,13 +3287,13 @@ var gr = class {
|
|
|
3246
3287
|
!a && !p() && h();
|
|
3247
3288
|
}, e);
|
|
3248
3289
|
};
|
|
3249
|
-
_(
|
|
3290
|
+
_(ur), this.armingSub = E({
|
|
3250
3291
|
eventsBaseUrl: t,
|
|
3251
3292
|
matchUrn: this.opts.matchUrn,
|
|
3252
3293
|
credential: this.opts.credential,
|
|
3253
|
-
onAlive: () => _(
|
|
3294
|
+
onAlive: () => _(dr),
|
|
3254
3295
|
onState: (e) => {
|
|
3255
|
-
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);
|
|
3256
3297
|
},
|
|
3257
3298
|
onError: () => h()
|
|
3258
3299
|
});
|
|
@@ -3272,10 +3313,10 @@ var gr = class {
|
|
|
3272
3313
|
async onResolved(e, t) {
|
|
3273
3314
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3274
3315
|
this._descriptor = e, this.endedHandled = !1, this._endedReason = null;
|
|
3275
|
-
let n = await
|
|
3316
|
+
let n = await c(this.opts.credential);
|
|
3276
3317
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3277
3318
|
this.setState("loading");
|
|
3278
|
-
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) => {
|
|
3279
3320
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3280
3321
|
});
|
|
3281
3322
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3297,19 +3338,19 @@ var gr = class {
|
|
|
3297
3338
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3298
3339
|
let i = e.analytics?.sid;
|
|
3299
3340
|
if (!i) return;
|
|
3300
|
-
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);
|
|
3301
3342
|
if (!o) {
|
|
3302
3343
|
s && setTimeout(() => {
|
|
3303
3344
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3304
3345
|
}, 0);
|
|
3305
3346
|
return;
|
|
3306
3347
|
}
|
|
3307
|
-
let c = this.opts.video, l = new
|
|
3348
|
+
let c = this.opts.video, l = new zn({
|
|
3308
3349
|
endpoint: o,
|
|
3309
3350
|
sid: i,
|
|
3310
3351
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3311
|
-
sdkVersion:
|
|
3312
|
-
environment:
|
|
3352
|
+
sdkVersion: Gn,
|
|
3353
|
+
environment: Un(c),
|
|
3313
3354
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3314
3355
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3315
3356
|
onBlocked: (e) => setTimeout(() => {
|
|
@@ -3330,7 +3371,7 @@ var gr = class {
|
|
|
3330
3371
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3331
3372
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3332
3373
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3333
|
-
}, 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");
|
|
3334
3375
|
}
|
|
3335
3376
|
currentPresentation() {
|
|
3336
3377
|
let e = this.opts.video;
|
|
@@ -3358,9 +3399,9 @@ var gr = class {
|
|
|
3358
3399
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3359
3400
|
}, o = this.opts.engine ?? "auto";
|
|
3360
3401
|
if (o === "native") return new W(a);
|
|
3361
|
-
if (o === "hls") return new
|
|
3362
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled &&
|
|
3363
|
-
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);
|
|
3364
3405
|
if (H(this.opts.video)) return new W(a);
|
|
3365
3406
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3366
3407
|
}
|
|
@@ -3423,7 +3464,7 @@ var gr = class {
|
|
|
3423
3464
|
r = 0, i = !1;
|
|
3424
3465
|
},
|
|
3425
3466
|
onError: () => {
|
|
3426
|
-
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.`))));
|
|
3427
3468
|
}
|
|
3428
3469
|
});
|
|
3429
3470
|
}
|
|
@@ -3437,7 +3478,7 @@ var gr = class {
|
|
|
3437
3478
|
return;
|
|
3438
3479
|
}
|
|
3439
3480
|
let e = this.hiddenAtMs;
|
|
3440
|
-
this.hiddenAtMs = null, e != null && Date.now() - e >=
|
|
3481
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= mr && this.resyncLiveState();
|
|
3441
3482
|
}, this.onReturnPageShow = (e) => {
|
|
3442
3483
|
e.persisted && this.resyncLiveState();
|
|
3443
3484
|
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
@@ -3469,7 +3510,7 @@ var gr = class {
|
|
|
3469
3510
|
scheduleRejoin(e) {
|
|
3470
3511
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3471
3512
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3472
|
-
}, Math.random() *
|
|
3513
|
+
}, Math.random() * fr));
|
|
3473
3514
|
}
|
|
3474
3515
|
cancelRejoin() {
|
|
3475
3516
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3493,7 +3534,7 @@ var gr = class {
|
|
|
3493
3534
|
}
|
|
3494
3535
|
t.controls = !1;
|
|
3495
3536
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3496
|
-
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({
|
|
3497
3538
|
root: n,
|
|
3498
3539
|
video: t,
|
|
3499
3540
|
player: this,
|
|
@@ -3531,7 +3572,7 @@ var gr = class {
|
|
|
3531
3572
|
}
|
|
3532
3573
|
startStats() {
|
|
3533
3574
|
this.stopStats();
|
|
3534
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3575
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? hr);
|
|
3535
3576
|
this.statsTimer = setInterval(() => {
|
|
3536
3577
|
if (!this.engine) return;
|
|
3537
3578
|
let e = this.engine.getStats();
|
|
@@ -3542,14 +3583,14 @@ var gr = class {
|
|
|
3542
3583
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3543
3584
|
}
|
|
3544
3585
|
isStaleLicenseDenial(e) {
|
|
3545
|
-
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);
|
|
3546
3587
|
}
|
|
3547
3588
|
scheduleLicenseRefresh() {
|
|
3548
3589
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3549
3590
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3550
3591
|
document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3551
3592
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3552
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3593
|
+
let e = this.opts.licenseRefreshMs ?? gr;
|
|
3553
3594
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3554
3595
|
}
|
|
3555
3596
|
stopRefresh() {
|
|
@@ -3569,7 +3610,7 @@ var gr = class {
|
|
|
3569
3610
|
fairplay: r
|
|
3570
3611
|
}), this._descriptor = t), n;
|
|
3571
3612
|
} catch (e) {
|
|
3572
|
-
e instanceof n && !
|
|
3613
|
+
e instanceof n && !s(e.code) && (this.stopRefresh(), this.destroyed || this.emit("warning", e));
|
|
3573
3614
|
return;
|
|
3574
3615
|
} finally {
|
|
3575
3616
|
this.refreshInFlight?.promise === t && (this.refreshInFlight = void 0);
|
|
@@ -3719,7 +3760,7 @@ function $(e) {
|
|
|
3719
3760
|
}
|
|
3720
3761
|
//#endregion
|
|
3721
3762
|
//#region src/embed/host.ts
|
|
3722
|
-
function
|
|
3763
|
+
function xr(e) {
|
|
3723
3764
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3724
3765
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3725
3766
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3778,15 +3819,15 @@ function _r(e) {
|
|
|
3778
3819
|
}
|
|
3779
3820
|
//#endregion
|
|
3780
3821
|
//#region src/embed/page.ts
|
|
3781
|
-
var
|
|
3782
|
-
function
|
|
3822
|
+
var Sr = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3823
|
+
function Cr(e) {
|
|
3783
3824
|
if (typeof e == "boolean") return e;
|
|
3784
3825
|
if (typeof e == "object" && e) {
|
|
3785
3826
|
let t = e.endpoint;
|
|
3786
3827
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3787
3828
|
}
|
|
3788
3829
|
}
|
|
3789
|
-
function
|
|
3830
|
+
function wr() {
|
|
3790
3831
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3791
3832
|
if (e) return {
|
|
3792
3833
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3796,7 +3837,7 @@ function br() {
|
|
|
3796
3837
|
autoplay: e.autoplay ?? !0,
|
|
3797
3838
|
muted: e.muted ?? !0,
|
|
3798
3839
|
waitForLive: e.waitForLive ?? !0,
|
|
3799
|
-
analytics:
|
|
3840
|
+
analytics: Cr(e.analytics)
|
|
3800
3841
|
};
|
|
3801
3842
|
let t = new URLSearchParams(location.search);
|
|
3802
3843
|
return {
|
|
@@ -3809,9 +3850,9 @@ function br() {
|
|
|
3809
3850
|
waitForLive: !0
|
|
3810
3851
|
};
|
|
3811
3852
|
}
|
|
3812
|
-
async function
|
|
3813
|
-
let e =
|
|
3814
|
-
|
|
3853
|
+
async function Tr() {
|
|
3854
|
+
let e = wr();
|
|
3855
|
+
Dr();
|
|
3815
3856
|
let t = document.createElement("video");
|
|
3816
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);
|
|
3817
3858
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3867,12 +3908,12 @@ async function xr() {
|
|
|
3867
3908
|
message: e.message,
|
|
3868
3909
|
...e.country === void 0 ? {} : { country: e.country }
|
|
3869
3910
|
})), e.on("autoplayblocked", () => {
|
|
3870
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3911
|
+
i({ type: "oddin:autoplayblocked" }), Er(t, e);
|
|
3871
3912
|
});
|
|
3872
3913
|
}, s = async (r) => {
|
|
3873
3914
|
a?.destroy(), a = null;
|
|
3874
3915
|
try {
|
|
3875
|
-
let n = await
|
|
3916
|
+
let n = await yr({
|
|
3876
3917
|
video: t,
|
|
3877
3918
|
baseUrl: e.baseUrl,
|
|
3878
3919
|
matchUrn: r,
|
|
@@ -3935,7 +3976,7 @@ async function xr() {
|
|
|
3935
3976
|
a?.retry();
|
|
3936
3977
|
break;
|
|
3937
3978
|
case "oddin:load":
|
|
3938
|
-
typeof e.matchUrn == "string" &&
|
|
3979
|
+
typeof e.matchUrn == "string" && Sr.test(e.matchUrn) && s(e.matchUrn);
|
|
3939
3980
|
break;
|
|
3940
3981
|
case "oddin:destroy": c();
|
|
3941
3982
|
}
|
|
@@ -3947,18 +3988,18 @@ async function xr() {
|
|
|
3947
3988
|
protocol: 1
|
|
3948
3989
|
});
|
|
3949
3990
|
}
|
|
3950
|
-
function
|
|
3991
|
+
function Er(e, t) {
|
|
3951
3992
|
if (document.getElementById("havik-tap")) return;
|
|
3952
3993
|
let n = document.createElement("button");
|
|
3953
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", () => {
|
|
3954
3995
|
n.remove(), t.play();
|
|
3955
3996
|
}), document.body.appendChild(n);
|
|
3956
3997
|
}
|
|
3957
|
-
function
|
|
3998
|
+
function Dr() {
|
|
3958
3999
|
let e = document.createElement("style");
|
|
3959
4000
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3960
4001
|
}
|
|
3961
4002
|
//#endregion
|
|
3962
|
-
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 };
|
|
3963
4004
|
|
|
3964
4005
|
//# sourceMappingURL=index.js.map
|