@oddin-gg/havik-player 2.20.0 → 2.22.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 +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +430 -374
- package/dist/index.js.map +1 -1
- package/docs/API.md +65 -34
- 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,34 @@ 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 = 1, fn = 2;
|
|
1488
|
+
function pn(e, t, n) {
|
|
1489
|
+
if (n <= 0 || t < 0 || t >= e.length) return t;
|
|
1490
|
+
let r = (t, n) => e[t].width === e[n].width && e[t].height === e[n].height, i = (t) => {
|
|
1491
|
+
for (; t + 1 < e.length && r(t + 1, t);) t++;
|
|
1492
|
+
return t;
|
|
1493
|
+
}, a = i(t);
|
|
1494
|
+
for (let t = 0; t < n && a + 1 < e.length; t++) a = i(a + 1);
|
|
1495
|
+
return a;
|
|
1496
|
+
}
|
|
1497
|
+
var mn = .2, hn = 30, gn = 2, _n = 2, vn = 9, yn = .5, bn = 64;
|
|
1498
|
+
function xn(e) {
|
|
1450
1499
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1451
1500
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1452
1501
|
return;
|
|
1453
1502
|
}
|
|
1454
|
-
e.liveSyncDuration ??=
|
|
1455
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1456
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1503
|
+
e.liveSyncDuration ??= _n;
|
|
1504
|
+
let t = Math.max(12, e.liveSyncDuration + vn);
|
|
1505
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Sn(e, e.liveSyncDuration);
|
|
1457
1506
|
}
|
|
1458
|
-
function
|
|
1507
|
+
function Sn(e, t) {
|
|
1459
1508
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1460
1509
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1461
1510
|
}
|
|
1462
|
-
var
|
|
1511
|
+
var Cn = class {
|
|
1463
1512
|
name = "hls";
|
|
1464
1513
|
hls = null;
|
|
1465
1514
|
deps;
|
|
@@ -1543,7 +1592,7 @@ var _n = class {
|
|
|
1543
1592
|
frameCounter;
|
|
1544
1593
|
detachFrames = null;
|
|
1545
1594
|
constructor(e) {
|
|
1546
|
-
this.deps = e, this.frameCounter = new
|
|
1595
|
+
this.deps = e, this.frameCounter = new lt(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1547
1596
|
}
|
|
1548
1597
|
async load() {
|
|
1549
1598
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1556,7 +1605,7 @@ var _n = class {
|
|
|
1556
1605
|
});
|
|
1557
1606
|
return;
|
|
1558
1607
|
}
|
|
1559
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1608
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ue(r), qe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1560
1609
|
let e = this.hls;
|
|
1561
1610
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1562
1611
|
let t = e.liveSyncPosition;
|
|
@@ -1579,7 +1628,7 @@ var _n = class {
|
|
|
1579
1628
|
}
|
|
1580
1629
|
this.loadSuspended = !0;
|
|
1581
1630
|
}
|
|
1582
|
-
},
|
|
1631
|
+
}, en));
|
|
1583
1632
|
}
|
|
1584
1633
|
resumeLoading() {
|
|
1585
1634
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1611,7 +1660,7 @@ var _n = class {
|
|
|
1611
1660
|
let t = e.liveSyncPosition;
|
|
1612
1661
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1613
1662
|
let { video: n } = this.deps;
|
|
1614
|
-
n.currentTime <= t +
|
|
1663
|
+
n.currentTime <= t + yn || (n.currentTime = t);
|
|
1615
1664
|
}
|
|
1616
1665
|
reanchorPartTimeline(e, t) {
|
|
1617
1666
|
let { frag: n, part: r } = t;
|
|
@@ -1623,7 +1672,7 @@ var _n = class {
|
|
|
1623
1672
|
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1624
1673
|
if (!s) return;
|
|
1625
1674
|
let c = a.startPTS - s.start;
|
|
1626
|
-
if (!(!Number.isFinite(c) || Math.abs(c) <
|
|
1675
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < qt)) {
|
|
1627
1676
|
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1628
1677
|
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
1678
|
}
|
|
@@ -1651,7 +1700,7 @@ var _n = class {
|
|
|
1651
1700
|
videoEncryptionScheme: F.scheme,
|
|
1652
1701
|
audioEncryptionScheme: F.scheme
|
|
1653
1702
|
},
|
|
1654
|
-
...M() ? { requestMediaKeySystemAccessFunc:
|
|
1703
|
+
...M() ? { requestMediaKeySystemAccessFunc: He(t) } : {},
|
|
1655
1704
|
licenseXhrSetup: (e, t) => {
|
|
1656
1705
|
let o = performance.now(), s = () => {
|
|
1657
1706
|
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 +1712,7 @@ var _n = class {
|
|
|
1663
1712
|
return;
|
|
1664
1713
|
}
|
|
1665
1714
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1666
|
-
u = setTimeout(() => e(void 0),
|
|
1715
|
+
u = setTimeout(() => e(void 0), Ut);
|
|
1667
1716
|
});
|
|
1668
1717
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1669
1718
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1679,20 +1728,20 @@ var _n = class {
|
|
|
1679
1728
|
...c
|
|
1680
1729
|
};
|
|
1681
1730
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !f.fLoader) {
|
|
1682
|
-
let e = new
|
|
1731
|
+
let e = new jt({
|
|
1683
1732
|
sessionId: n.analytics?.sid,
|
|
1684
1733
|
contentId: n.matchUrn
|
|
1685
|
-
}), t =
|
|
1734
|
+
}), t = Mt(e);
|
|
1686
1735
|
t && (this.prefetch = e, f.fLoader = t);
|
|
1687
1736
|
}
|
|
1688
|
-
|
|
1737
|
+
xn(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
1738
|
let p = new e(f);
|
|
1690
1739
|
if (this.hls = p, p.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(p, t)), p.on(e.Events.MANIFEST_PARSED, () => {
|
|
1691
1740
|
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
1741
|
}), p.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1693
1742
|
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
1743
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1695
|
-
},
|
|
1744
|
+
}, Wt)));
|
|
1696
1745
|
}), p.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1697
1746
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1698
1747
|
}), p.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1700,10 +1749,10 @@ var _n = class {
|
|
|
1700
1749
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1701
1750
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1702
1751
|
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 >
|
|
1752
|
+
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 > bn && this.requestTimesMs.shift());
|
|
1704
1753
|
let a = t?.frag?.url;
|
|
1705
1754
|
if (a) {
|
|
1706
|
-
let e =
|
|
1755
|
+
let e = ot(a);
|
|
1707
1756
|
e && (this.cdnHost = e);
|
|
1708
1757
|
}
|
|
1709
1758
|
}), p.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1717,15 +1766,15 @@ var _n = class {
|
|
|
1717
1766
|
}), p.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1718
1767
|
let t = this.prefetch;
|
|
1719
1768
|
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(
|
|
1769
|
+
let r = n?.frag, i = Pt(r?.type);
|
|
1770
|
+
if (r && t.isActive(i)) for (let e of Ft(p, r)) t.prefetch(e.url, i, e.kind);
|
|
1771
|
+
}), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Pt(n?.frag?.type)));
|
|
1723
1772
|
}
|
|
1724
1773
|
p.on(e.Events.KEY_LOADED, () => {
|
|
1725
1774
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1726
1775
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1727
1776
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1728
|
-
},
|
|
1777
|
+
}, Kt), p.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1729
1778
|
this.renditionSwitches += 1;
|
|
1730
1779
|
let n = this.lastLevelIndex >= 0 ? p.levels[this.lastLevelIndex] : void 0, r = p.levels[t.level];
|
|
1731
1780
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1773,8 +1822,12 @@ var _n = class {
|
|
|
1773
1822
|
if (!e || e.levels.length === 0) return null;
|
|
1774
1823
|
let { video: n } = this.deps, r = n.getBoundingClientRect(), i = r.width, a = r.height;
|
|
1775
1824
|
if (!i && !a && (i = n.width || 0, a = n.height || 0), !(i > 0) || !(a > 0)) return null;
|
|
1776
|
-
let o = e.config ?? {}, s = 1;
|
|
1777
|
-
|
|
1825
|
+
let o = e.config ?? {}, s = typeof self < "u" && self.devicePixelRatio > 0 ? self.devicePixelRatio : 1, c = o.ignoreDevicePixelRatio ? 1 : s;
|
|
1826
|
+
c = Math.min(c, o.maxDevicePixelRatio ?? Infinity);
|
|
1827
|
+
let l = t.getMaxLevelByMediaSize(e.levels, i * c, a * c), u = this.deps.sizeCapHeadroom;
|
|
1828
|
+
if (u == null && s >= fn) return l;
|
|
1829
|
+
let d = u ?? dn, f = Number.isNaN(d) ? dn : d === Infinity ? e.levels.length : Math.max(0, Math.floor(d));
|
|
1830
|
+
return pn(e.levels, l, f);
|
|
1778
1831
|
}
|
|
1779
1832
|
onMediaResize() {
|
|
1780
1833
|
if (!this.sizeCapManaged) return;
|
|
@@ -1789,7 +1842,7 @@ var _n = class {
|
|
|
1789
1842
|
return;
|
|
1790
1843
|
}
|
|
1791
1844
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1792
|
-
let t = e > this.sizeCapLevel ?
|
|
1845
|
+
let t = e > this.sizeCapLevel ? ln : un;
|
|
1793
1846
|
this.capTimer = setTimeout(() => {
|
|
1794
1847
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1795
1848
|
}, t);
|
|
@@ -1799,9 +1852,9 @@ var _n = class {
|
|
|
1799
1852
|
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
1853
|
}
|
|
1801
1854
|
dropLevelsWidevineCannotPlay(e) {
|
|
1802
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1855
|
+
this.removeLevelsWhere(e, (e) => Je(e) !== !0);
|
|
1803
1856
|
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
|
|
1804
|
-
for (let n of t)
|
|
1857
|
+
for (let n of t) Ke(n).then((t) => {
|
|
1805
1858
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1806
1859
|
});
|
|
1807
1860
|
}
|
|
@@ -1812,7 +1865,7 @@ var _n = class {
|
|
|
1812
1865
|
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1813
1866
|
}), !r.length) return !1;
|
|
1814
1867
|
let a = [...i].join(", ");
|
|
1815
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) ||
|
|
1868
|
+
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
1869
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1817
1870
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1818
1871
|
}
|
|
@@ -1918,7 +1971,7 @@ var _n = class {
|
|
|
1918
1971
|
return;
|
|
1919
1972
|
}
|
|
1920
1973
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1921
|
-
!this.chaseSuspended && e >
|
|
1974
|
+
!this.chaseSuspended && e > Jt && this.suspendChasing(), e > Gt && this.emitEnded("stalled");
|
|
1922
1975
|
}
|
|
1923
1976
|
resetStarvationWindow() {
|
|
1924
1977
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1933,7 +1986,7 @@ var _n = class {
|
|
|
1933
1986
|
this.resetStarvationWindow();
|
|
1934
1987
|
return;
|
|
1935
1988
|
}
|
|
1936
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1989
|
+
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
1990
|
if (this.starvedFrames = c, !a || l) {
|
|
1938
1991
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1939
1992
|
return;
|
|
@@ -1942,12 +1995,12 @@ var _n = class {
|
|
|
1942
1995
|
this.resetStarvationWindow();
|
|
1943
1996
|
return;
|
|
1944
1997
|
}
|
|
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 >
|
|
1998
|
+
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
1999
|
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
2000
|
return;
|
|
1948
2001
|
}
|
|
1949
|
-
let u = i && this.starvedTicks >=
|
|
1950
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
2002
|
+
let u = i && this.starvedTicks >= nn, d = !i && this.deadTicks >= sn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= cn;
|
|
2003
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= rn))) {
|
|
1951
2004
|
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
2005
|
try {
|
|
1953
2006
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1962,7 +2015,7 @@ var _n = class {
|
|
|
1962
2015
|
let t = e.latency, n = e.targetLatency;
|
|
1963
2016
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1964
2017
|
let r = t - n;
|
|
1965
|
-
!this.catchUpEngaged && r >
|
|
2018
|
+
!this.catchUpEngaged && r > Yt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Yt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1966
2019
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1967
2020
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1968
2021
|
}
|
|
@@ -1984,15 +2037,15 @@ var _n = class {
|
|
|
1984
2037
|
return;
|
|
1985
2038
|
}
|
|
1986
2039
|
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 <
|
|
2040
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < hn || o < 0) {
|
|
1988
2041
|
this.fpsBadTicks = 0;
|
|
1989
2042
|
return;
|
|
1990
2043
|
}
|
|
1991
|
-
if (o <=
|
|
2044
|
+
if (o <= mn * a) {
|
|
1992
2045
|
this.fpsBadTicks = 0;
|
|
1993
2046
|
return;
|
|
1994
2047
|
}
|
|
1995
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
2048
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < gn) return;
|
|
1996
2049
|
this.fpsBadTicks = 0;
|
|
1997
2050
|
let s = e.levels, c = s[e.currentLevel];
|
|
1998
2051
|
if (!c) return;
|
|
@@ -2009,20 +2062,20 @@ var _n = class {
|
|
|
2009
2062
|
return;
|
|
2010
2063
|
}
|
|
2011
2064
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
2012
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
2065
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Qt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
2013
2066
|
this.resetChaseWindow();
|
|
2014
2067
|
return;
|
|
2015
2068
|
}
|
|
2016
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
2069
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= Zt) {
|
|
2017
2070
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
2018
2071
|
return;
|
|
2019
2072
|
}
|
|
2020
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
2073
|
+
if (this.chaseTicks += 1, this.chaseTicks < Xt) return;
|
|
2021
2074
|
this.resetChaseWindow();
|
|
2022
2075
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2023
2076
|
if (!(a > 1)) return;
|
|
2024
2077
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
2025
|
-
s < o +
|
|
2078
|
+
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
2079
|
}
|
|
2027
2080
|
suspendChasing() {
|
|
2028
2081
|
let e = this.hls;
|
|
@@ -2052,14 +2105,14 @@ var _n = class {
|
|
|
2052
2105
|
} catch {}
|
|
2053
2106
|
}
|
|
2054
2107
|
startEstimate() {
|
|
2055
|
-
return this.deps.rememberBandwidth === !1 ?
|
|
2108
|
+
return this.deps.rememberBandwidth === !1 ? Lt : Ie() ?? Lt;
|
|
2056
2109
|
}
|
|
2057
2110
|
maybeRememberBandwidth(e) {
|
|
2058
|
-
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded <
|
|
2111
|
+
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Rt) return;
|
|
2059
2112
|
let t = Date.now();
|
|
2060
|
-
if (!e && t - this.bwSavedAt <
|
|
2113
|
+
if (!e && t - this.bwSavedAt < zt) return;
|
|
2061
2114
|
let n = this.hls?.bandwidthEstimate;
|
|
2062
|
-
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t,
|
|
2115
|
+
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Le(n));
|
|
2063
2116
|
}
|
|
2064
2117
|
destroy() {
|
|
2065
2118
|
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 +2130,7 @@ var _n = class {
|
|
|
2077
2130
|
scheduleLicenseRetry(t) {
|
|
2078
2131
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
2079
2132
|
let n = t.response?.code ?? 0;
|
|
2080
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
2133
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Ht) return !1;
|
|
2081
2134
|
this.licenseRecoveries += 1;
|
|
2082
2135
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
2083
2136
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -2109,7 +2162,7 @@ var _n = class {
|
|
|
2109
2162
|
return;
|
|
2110
2163
|
}
|
|
2111
2164
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
2112
|
-
if (this.networkRecoveries <
|
|
2165
|
+
if (this.networkRecoveries < Vt) {
|
|
2113
2166
|
this.networkRecoveries += 1;
|
|
2114
2167
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
2115
2168
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -2126,7 +2179,7 @@ var _n = class {
|
|
|
2126
2179
|
return;
|
|
2127
2180
|
}
|
|
2128
2181
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
2129
|
-
if (this.mediaRecoveries <
|
|
2182
|
+
if (this.mediaRecoveries < Bt) {
|
|
2130
2183
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
2131
2184
|
return;
|
|
2132
2185
|
}
|
|
@@ -2146,23 +2199,23 @@ var _n = class {
|
|
|
2146
2199
|
});
|
|
2147
2200
|
}
|
|
2148
2201
|
}
|
|
2149
|
-
toError(
|
|
2150
|
-
let
|
|
2151
|
-
return new n(
|
|
2202
|
+
toError(t, r = "PLAYBACK") {
|
|
2203
|
+
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;
|
|
2204
|
+
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
2205
|
}
|
|
2153
|
-
},
|
|
2206
|
+
}, wn = 15e3, Tn = 6e5, En = 3e5, Dn = 100, q = 1, On = 1e3, kn = 3e4, An = 1e3, jn = {
|
|
2154
2207
|
inline: "PRESENTATION_INLINE",
|
|
2155
2208
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2156
2209
|
pip: "PRESENTATION_PIP"
|
|
2157
|
-
},
|
|
2210
|
+
}, Mn = {
|
|
2158
2211
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2159
2212
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2160
2213
|
none: "KEY_SYSTEM_NONE"
|
|
2161
2214
|
};
|
|
2162
|
-
function
|
|
2215
|
+
function Nn(e, t) {
|
|
2163
2216
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
2164
2217
|
}
|
|
2165
|
-
var
|
|
2218
|
+
var Pn = /* @__PURE__ */ new Set([
|
|
2166
2219
|
"INVALID_URN",
|
|
2167
2220
|
"NOT_FOUND",
|
|
2168
2221
|
"GEO_DENIED",
|
|
@@ -2183,7 +2236,7 @@ var On = /* @__PURE__ */ new Set([
|
|
|
2183
2236
|
ended: "PLAYER_STATE_ENDED",
|
|
2184
2237
|
error: "PLAYER_STATE_ERROR"
|
|
2185
2238
|
};
|
|
2186
|
-
function
|
|
2239
|
+
function Fn(e) {
|
|
2187
2240
|
try {
|
|
2188
2241
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2189
2242
|
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 +2244,8 @@ function kn(e) {
|
|
|
2191
2244
|
return;
|
|
2192
2245
|
}
|
|
2193
2246
|
}
|
|
2194
|
-
var
|
|
2195
|
-
function
|
|
2247
|
+
var In = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Ln = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), Rn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2248
|
+
function zn(e) {
|
|
2196
2249
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2197
2250
|
let t;
|
|
2198
2251
|
try {
|
|
@@ -2201,19 +2254,19 @@ function Nn(e) {
|
|
|
2201
2254
|
} catch {
|
|
2202
2255
|
return;
|
|
2203
2256
|
}
|
|
2204
|
-
if (
|
|
2205
|
-
Y.add(t),
|
|
2257
|
+
if (Ln.has(t) && !Y.has(t)) {
|
|
2258
|
+
Y.add(t), _(Rn(new URL(t).origin));
|
|
2206
2259
|
for (let e of X) e.noteCspBlocked();
|
|
2207
2260
|
}
|
|
2208
2261
|
}
|
|
2209
|
-
function
|
|
2210
|
-
return
|
|
2262
|
+
function Z(e, t) {
|
|
2263
|
+
return _(t, e), { disabledReason: t };
|
|
2211
2264
|
}
|
|
2212
|
-
function
|
|
2213
|
-
if (n) return t && !
|
|
2265
|
+
function Bn(e, t, n) {
|
|
2266
|
+
if (n) return t && !In(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2214
2267
|
if (t) return { endpoint: t };
|
|
2215
|
-
if (t !== void 0) return
|
|
2216
|
-
let r =
|
|
2268
|
+
if (t !== void 0) return Z("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).");
|
|
2269
|
+
let r = Fn(e);
|
|
2217
2270
|
if (r) return { endpoint: r };
|
|
2218
2271
|
let i;
|
|
2219
2272
|
try {
|
|
@@ -2221,9 +2274,9 @@ function Fn(e, t, n) {
|
|
|
2221
2274
|
} catch {
|
|
2222
2275
|
i = e;
|
|
2223
2276
|
}
|
|
2224
|
-
return
|
|
2277
|
+
return Z(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
2278
|
}
|
|
2226
|
-
var
|
|
2279
|
+
var Vn = class {
|
|
2227
2280
|
opts;
|
|
2228
2281
|
url;
|
|
2229
2282
|
cspKey;
|
|
@@ -2305,8 +2358,8 @@ var In = class {
|
|
|
2305
2358
|
constructor(e) {
|
|
2306
2359
|
this.opts = {
|
|
2307
2360
|
...e,
|
|
2308
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2309
|
-
idleMs: e.idleMs ??
|
|
2361
|
+
heartbeatMs: e.heartbeatMs ?? wn,
|
|
2362
|
+
idleMs: e.idleMs ?? Tn
|
|
2310
2363
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2311
2364
|
try {
|
|
2312
2365
|
let e = new URL(this.url);
|
|
@@ -2323,11 +2376,11 @@ var In = class {
|
|
|
2323
2376
|
sdkVersion: this.opts.sdkVersion,
|
|
2324
2377
|
...this.opts.environment
|
|
2325
2378
|
};
|
|
2326
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2379
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), On), 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 && Ln.add(this.cspKey), document.addEventListener("securitypolicyviolation", zn), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2327
2380
|
}
|
|
2328
2381
|
checkSuspension(e) {
|
|
2329
2382
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2330
|
-
let t = Math.max(this.opts.idleMs,
|
|
2383
|
+
let t = Math.max(this.opts.idleMs, En);
|
|
2331
2384
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2332
2385
|
}
|
|
2333
2386
|
syncIdle(e) {
|
|
@@ -2350,12 +2403,12 @@ var In = class {
|
|
|
2350
2403
|
let a = {
|
|
2351
2404
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2352
2405
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2353
|
-
presentation:
|
|
2406
|
+
presentation: jn[this.presentation]
|
|
2354
2407
|
}, o = this.causeOf(e, t, i);
|
|
2355
2408
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2356
2409
|
}
|
|
2357
2410
|
seekInduced(e) {
|
|
2358
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2411
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < An;
|
|
2359
2412
|
}
|
|
2360
2413
|
causeOf(e, t, n) {
|
|
2361
2414
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2428,8 +2481,8 @@ var In = class {
|
|
|
2428
2481
|
stageOf(e, t, n) {
|
|
2429
2482
|
let r = n ?? "";
|
|
2430
2483
|
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 (
|
|
2484
|
+
if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
|
|
2485
|
+
if (Pn.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2433
2486
|
let i = t ?? "";
|
|
2434
2487
|
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
2488
|
}
|
|
@@ -2476,14 +2529,14 @@ var In = class {
|
|
|
2476
2529
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2477
2530
|
o.requestCountDelta = _;
|
|
2478
2531
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2479
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2532
|
+
n.length > 0 && (o.requestTimeP50Ms = Nn(n, 50), o.requestTimeP95Ms = Nn(n, 95));
|
|
2480
2533
|
}
|
|
2481
2534
|
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
2535
|
}
|
|
2483
2536
|
maybeEmitMediaInfo(e) {
|
|
2484
2537
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2485
2538
|
let t = {};
|
|
2486
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2539
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Mn[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
2540
|
let n = JSON.stringify(t);
|
|
2488
2541
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2489
2542
|
}
|
|
@@ -2503,7 +2556,7 @@ var In = class {
|
|
|
2503
2556
|
let c = r?.positionMs ?? 0;
|
|
2504
2557
|
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
2558
|
let l = e !== "END_REASON_ENDED";
|
|
2506
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2559
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= kn && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= kn && (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
2560
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2508
2561
|
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
2562
|
}
|
|
@@ -2523,13 +2576,13 @@ var In = class {
|
|
|
2523
2576
|
};
|
|
2524
2577
|
}
|
|
2525
2578
|
noteCspBlocked() {
|
|
2526
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2579
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(Rn(new URL(this.url).origin)));
|
|
2527
2580
|
}
|
|
2528
2581
|
cspBlocked() {
|
|
2529
2582
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2530
2583
|
}
|
|
2531
2584
|
enqueue(e) {
|
|
2532
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2585
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Dn;) {
|
|
2533
2586
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2534
2587
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2535
2588
|
}
|
|
@@ -2556,7 +2609,7 @@ var In = class {
|
|
|
2556
2609
|
};
|
|
2557
2610
|
//#endregion
|
|
2558
2611
|
//#region src/core/environment.ts
|
|
2559
|
-
function
|
|
2612
|
+
function Hn() {
|
|
2560
2613
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2561
2614
|
let e;
|
|
2562
2615
|
try {
|
|
@@ -2581,14 +2634,14 @@ function Ln() {
|
|
|
2581
2634
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2582
2635
|
};
|
|
2583
2636
|
}
|
|
2584
|
-
function
|
|
2637
|
+
function Un() {
|
|
2585
2638
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2586
2639
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2587
2640
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2588
2641
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2589
2642
|
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
2643
|
}
|
|
2591
|
-
function
|
|
2644
|
+
function Wn() {
|
|
2592
2645
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2593
2646
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2594
2647
|
let t = {
|
|
@@ -2607,17 +2660,17 @@ function zn() {
|
|
|
2607
2660
|
}
|
|
2608
2661
|
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
2662
|
}
|
|
2610
|
-
function
|
|
2611
|
-
let t =
|
|
2612
|
-
deviceClass:
|
|
2663
|
+
function Gn(e) {
|
|
2664
|
+
let t = Hn(), n = {
|
|
2665
|
+
deviceClass: Un(),
|
|
2613
2666
|
integration: t.integration,
|
|
2614
|
-
...
|
|
2667
|
+
...Wn()
|
|
2615
2668
|
};
|
|
2616
2669
|
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
2670
|
let r = e.getBoundingClientRect?.();
|
|
2618
2671
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2619
2672
|
}
|
|
2620
|
-
async function
|
|
2673
|
+
async function Kn() {
|
|
2621
2674
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2622
2675
|
if (!e?.getHighEntropyValues) return {};
|
|
2623
2676
|
try {
|
|
@@ -2629,7 +2682,7 @@ async function Vn() {
|
|
|
2629
2682
|
}
|
|
2630
2683
|
//#endregion
|
|
2631
2684
|
//#region src/core/version.ts
|
|
2632
|
-
var
|
|
2685
|
+
var qn = "2.22.0", Jn = {
|
|
2633
2686
|
accent: "#E1B600",
|
|
2634
2687
|
accentText: "#1B1C23",
|
|
2635
2688
|
background: "#0e0f13",
|
|
@@ -2640,7 +2693,7 @@ var Hn = "2.20.0", Un = {
|
|
|
2640
2693
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2641
2694
|
radius: "8px",
|
|
2642
2695
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2643
|
-
},
|
|
2696
|
+
}, Yn = {
|
|
2644
2697
|
accent: "--havik-accent",
|
|
2645
2698
|
accentText: "--havik-accent-text",
|
|
2646
2699
|
background: "--havik-bg",
|
|
@@ -2652,26 +2705,26 @@ var Hn = "2.20.0", Un = {
|
|
|
2652
2705
|
radius: "--havik-radius",
|
|
2653
2706
|
fontFamily: "--havik-font"
|
|
2654
2707
|
};
|
|
2655
|
-
function
|
|
2708
|
+
function Xn(e, t) {
|
|
2656
2709
|
let n = {
|
|
2657
|
-
...
|
|
2710
|
+
...Jn,
|
|
2658
2711
|
...t
|
|
2659
2712
|
};
|
|
2660
|
-
for (let t of Object.keys(
|
|
2713
|
+
for (let t of Object.keys(Yn)) e.style.setProperty(Yn[t], n[t]);
|
|
2661
2714
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2662
2715
|
}
|
|
2663
2716
|
//#endregion
|
|
2664
2717
|
//#region src/ui/styles.ts
|
|
2665
|
-
var
|
|
2666
|
-
function
|
|
2667
|
-
let n = e.querySelector(`style#${
|
|
2668
|
-
if (n && (!t ||
|
|
2718
|
+
var Zn = "havik-player-styles", Qn = "\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", $n = /* @__PURE__ */ new WeakMap();
|
|
2719
|
+
function er(e = document, t) {
|
|
2720
|
+
let n = e.querySelector(`style#${Zn}`);
|
|
2721
|
+
if (n && (!t || $n.get(n) === t)) return;
|
|
2669
2722
|
let r = e.createElement("style");
|
|
2670
|
-
r.id =
|
|
2723
|
+
r.id = Zn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Qn, $n.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2671
2724
|
}
|
|
2672
2725
|
//#endregion
|
|
2673
2726
|
//#region src/ui/icons.ts
|
|
2674
|
-
var
|
|
2727
|
+
var tr = {
|
|
2675
2728
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2676
2729
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2677
2730
|
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 +2738,27 @@ var Yn = {
|
|
|
2685
2738
|
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
2739
|
};
|
|
2687
2740
|
function Q(e) {
|
|
2688
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2741
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${tr[e]}</svg>`;
|
|
2689
2742
|
}
|
|
2690
2743
|
//#endregion
|
|
2691
2744
|
//#region src/ui/controls.ts
|
|
2692
|
-
var
|
|
2745
|
+
var nr = 3e3, rr = 250, ir = /* @__PURE__ */ new Set([
|
|
2693
2746
|
"GONE",
|
|
2694
2747
|
"NOT_FOUND",
|
|
2695
2748
|
"GEO_DENIED",
|
|
2696
2749
|
"INVALID_URN",
|
|
2697
|
-
"UNAUTHORIZED"
|
|
2750
|
+
"UNAUTHORIZED",
|
|
2751
|
+
"DRM_DEVICE_REVOKED"
|
|
2698
2752
|
]);
|
|
2699
|
-
function
|
|
2753
|
+
function ar(e) {
|
|
2700
2754
|
let t = "This match isn't available in your country";
|
|
2701
2755
|
return e ? `${t} (${e})` : t;
|
|
2702
2756
|
}
|
|
2703
|
-
|
|
2704
|
-
|
|
2757
|
+
var or = "This device can't play protected video";
|
|
2758
|
+
function sr(e) {
|
|
2759
|
+
return new cr(e);
|
|
2705
2760
|
}
|
|
2706
|
-
var
|
|
2761
|
+
var cr = class {
|
|
2707
2762
|
root;
|
|
2708
2763
|
video;
|
|
2709
2764
|
player;
|
|
@@ -2751,7 +2806,7 @@ var tr = class {
|
|
|
2751
2806
|
scrubbing = !1;
|
|
2752
2807
|
offFns = [];
|
|
2753
2808
|
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 ??
|
|
2809
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? nr, 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, er(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
2810
|
let t = (e, t, n) => {
|
|
2756
2811
|
let r = this.doc.createElement(e);
|
|
2757
2812
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2837,7 +2892,7 @@ var tr = class {
|
|
|
2837
2892
|
let t = this.surfaceWasHidden;
|
|
2838
2893
|
this.tapTimer = setTimeout(() => {
|
|
2839
2894
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2840
|
-
},
|
|
2895
|
+
}, rr);
|
|
2841
2896
|
}
|
|
2842
2897
|
toggleBar(e) {
|
|
2843
2898
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2857,7 +2912,7 @@ var tr = class {
|
|
|
2857
2912
|
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
2913
|
}
|
|
2859
2914
|
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" ?
|
|
2915
|
+
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" ? ar(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? or : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
|
|
2861
2916
|
}
|
|
2862
2917
|
renderStatus(e) {
|
|
2863
2918
|
let t = this.statusMessageFor(e);
|
|
@@ -2872,7 +2927,7 @@ var tr = class {
|
|
|
2872
2927
|
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
2928
|
} else {
|
|
2874
2929
|
let r = this.doc.createElement("div");
|
|
2875
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2930
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !ir.has(this.lastError.code)) {
|
|
2876
2931
|
let e = this.doc.createElement("button");
|
|
2877
2932
|
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
2933
|
}
|
|
@@ -2913,7 +2968,7 @@ var tr = class {
|
|
|
2913
2968
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2914
2969
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2915
2970
|
}
|
|
2916
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2971
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${lr(this.video.currentTime)} / ${lr(this.video.duration)}`);
|
|
2917
2972
|
}
|
|
2918
2973
|
syncLive() {
|
|
2919
2974
|
let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
|
|
@@ -2963,17 +3018,17 @@ var tr = class {
|
|
|
2963
3018
|
renderQualityMenu() {
|
|
2964
3019
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2965
3020
|
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(
|
|
3021
|
+
for (let n of e) this.menu.append(this.menuItem(ur(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2967
3022
|
}
|
|
2968
3023
|
renderAudioMenu() {
|
|
2969
3024
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2970
3025
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2971
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3026
|
+
for (let t of e) this.menu.append(this.menuItem(dr(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2972
3027
|
}
|
|
2973
3028
|
renderCcMenu() {
|
|
2974
3029
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2975
3030
|
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(
|
|
3031
|
+
for (let t of e) this.menu.append(this.menuItem(fr(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2977
3032
|
}
|
|
2978
3033
|
onTracksChanged() {
|
|
2979
3034
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -3078,41 +3133,41 @@ var tr = class {
|
|
|
3078
3133
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
3079
3134
|
}
|
|
3080
3135
|
};
|
|
3081
|
-
function
|
|
3136
|
+
function lr(e) {
|
|
3082
3137
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
3083
3138
|
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
3139
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
3085
3140
|
}
|
|
3086
|
-
function
|
|
3141
|
+
function ur(e) {
|
|
3087
3142
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
3088
3143
|
}
|
|
3089
|
-
function
|
|
3144
|
+
function dr(e) {
|
|
3090
3145
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3091
3146
|
}
|
|
3092
|
-
function
|
|
3147
|
+
function fr(e) {
|
|
3093
3148
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3094
3149
|
}
|
|
3095
3150
|
//#endregion
|
|
3096
3151
|
//#region src/managed/index.ts
|
|
3097
|
-
var
|
|
3098
|
-
function
|
|
3152
|
+
var pr = 6e3, mr = 45e3, hr = 2e3, gr = 3, _r = 5e3, vr = 2e3, yr = 48e4, br = "keySystemLicenseRequestFailed";
|
|
3153
|
+
function xr(e) {
|
|
3099
3154
|
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
|
|
3155
|
+
if (e.env !== void 0) return at(e.env);
|
|
3101
3156
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
3102
3157
|
return e.baseUrl;
|
|
3103
3158
|
}
|
|
3104
|
-
async function
|
|
3159
|
+
async function Sr(e) {
|
|
3105
3160
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
3106
|
-
let t =
|
|
3161
|
+
let t = xr(e);
|
|
3107
3162
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
3108
3163
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
3109
|
-
let r = new
|
|
3164
|
+
let r = new Cr({
|
|
3110
3165
|
...e,
|
|
3111
3166
|
baseUrl: t
|
|
3112
3167
|
});
|
|
3113
3168
|
return await r.start(), r;
|
|
3114
3169
|
}
|
|
3115
|
-
var
|
|
3170
|
+
var Cr = class {
|
|
3116
3171
|
opts;
|
|
3117
3172
|
abort = new AbortController();
|
|
3118
3173
|
listeners = {};
|
|
@@ -3169,7 +3224,7 @@ var gr = class {
|
|
|
3169
3224
|
throw this.destroy(), e;
|
|
3170
3225
|
}
|
|
3171
3226
|
} catch (t) {
|
|
3172
|
-
if (this.opts.waitForLive && t instanceof n &&
|
|
3227
|
+
if (this.opts.waitForLive && t instanceof n && s(t.code)) {
|
|
3173
3228
|
this.setState("waiting"), this.beginArming(e, t.liveStartsAtMs);
|
|
3174
3229
|
return;
|
|
3175
3230
|
}
|
|
@@ -3201,13 +3256,13 @@ var gr = class {
|
|
|
3201
3256
|
});
|
|
3202
3257
|
}
|
|
3203
3258
|
armWithSse(e, t, r, i = !1) {
|
|
3204
|
-
let a = !1,
|
|
3259
|
+
let a = !1, o = !1, c = new AbortController();
|
|
3205
3260
|
this.armFallbackCtrl = c, this.setState("waiting");
|
|
3206
3261
|
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
3262
|
setTimeout(() => {
|
|
3208
3263
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3209
3264
|
phase: i ? "unavailable" : "tooEarly",
|
|
3210
|
-
retryInMs:
|
|
3265
|
+
retryInMs: mr,
|
|
3211
3266
|
attempt: 1,
|
|
3212
3267
|
elapsedMs: 0,
|
|
3213
3268
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3224,7 +3279,7 @@ var gr = class {
|
|
|
3224
3279
|
}
|
|
3225
3280
|
}
|
|
3226
3281
|
}, h = () => {
|
|
3227
|
-
a ||
|
|
3282
|
+
a || o || p() || (o = !0, y({
|
|
3228
3283
|
...this.resolveOptions(),
|
|
3229
3284
|
signal: c.signal,
|
|
3230
3285
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -3234,7 +3289,7 @@ var gr = class {
|
|
|
3234
3289
|
}, g = () => {
|
|
3235
3290
|
a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
|
|
3236
3291
|
if (!(a || p())) {
|
|
3237
|
-
if (e instanceof n &&
|
|
3292
|
+
if (e instanceof n && s(e.code)) {
|
|
3238
3293
|
h();
|
|
3239
3294
|
return;
|
|
3240
3295
|
}
|
|
@@ -3246,13 +3301,13 @@ var gr = class {
|
|
|
3246
3301
|
!a && !p() && h();
|
|
3247
3302
|
}, e);
|
|
3248
3303
|
};
|
|
3249
|
-
_(
|
|
3304
|
+
_(pr), this.armingSub = E({
|
|
3250
3305
|
eventsBaseUrl: t,
|
|
3251
3306
|
matchUrn: this.opts.matchUrn,
|
|
3252
3307
|
credential: this.opts.credential,
|
|
3253
|
-
onAlive: () => _(
|
|
3308
|
+
onAlive: () => _(mr),
|
|
3254
3309
|
onState: (e) => {
|
|
3255
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3310
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * hr);
|
|
3256
3311
|
},
|
|
3257
3312
|
onError: () => h()
|
|
3258
3313
|
});
|
|
@@ -3272,10 +3327,10 @@ var gr = class {
|
|
|
3272
3327
|
async onResolved(e, t) {
|
|
3273
3328
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3274
3329
|
this._descriptor = e, this.endedHandled = !1, this._endedReason = null;
|
|
3275
|
-
let n = await
|
|
3330
|
+
let n = await c(this.opts.credential);
|
|
3276
3331
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3277
3332
|
this.setState("loading");
|
|
3278
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3333
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = ut(this.opts.video, (e) => {
|
|
3279
3334
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3280
3335
|
});
|
|
3281
3336
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3297,19 +3352,19 @@ var gr = class {
|
|
|
3297
3352
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3298
3353
|
let i = e.analytics?.sid;
|
|
3299
3354
|
if (!i) return;
|
|
3300
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3355
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Bn(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3301
3356
|
if (!o) {
|
|
3302
3357
|
s && setTimeout(() => {
|
|
3303
3358
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3304
3359
|
}, 0);
|
|
3305
3360
|
return;
|
|
3306
3361
|
}
|
|
3307
|
-
let c = this.opts.video, l = new
|
|
3362
|
+
let c = this.opts.video, l = new Vn({
|
|
3308
3363
|
endpoint: o,
|
|
3309
3364
|
sid: i,
|
|
3310
3365
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3311
|
-
sdkVersion:
|
|
3312
|
-
environment:
|
|
3366
|
+
sdkVersion: qn,
|
|
3367
|
+
environment: Gn(c),
|
|
3313
3368
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3314
3369
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3315
3370
|
onBlocked: (e) => setTimeout(() => {
|
|
@@ -3330,7 +3385,7 @@ var gr = class {
|
|
|
3330
3385
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3331
3386
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3332
3387
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3333
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3388
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Kn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3334
3389
|
}
|
|
3335
3390
|
currentPresentation() {
|
|
3336
3391
|
let e = this.opts.video;
|
|
@@ -3350,6 +3405,7 @@ var gr = class {
|
|
|
3350
3405
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
3351
3406
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
3352
3407
|
rememberBandwidth: this.opts.rememberBandwidth,
|
|
3408
|
+
sizeCapHeadroom: this.opts.sizeCapHeadroom,
|
|
3353
3409
|
mediaDuringKey: this.opts.mediaDuringKey,
|
|
3354
3410
|
debug: this.opts.debug,
|
|
3355
3411
|
deferLoad: r,
|
|
@@ -3358,9 +3414,9 @@ var gr = class {
|
|
|
3358
3414
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3359
3415
|
}, o = this.opts.engine ?? "auto";
|
|
3360
3416
|
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 (
|
|
3417
|
+
if (o === "hls") return new Cn(a);
|
|
3418
|
+
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);
|
|
3419
|
+
if (It()) return new Cn(a);
|
|
3364
3420
|
if (H(this.opts.video)) return new W(a);
|
|
3365
3421
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3366
3422
|
}
|
|
@@ -3423,7 +3479,7 @@ var gr = class {
|
|
|
3423
3479
|
r = 0, i = !1;
|
|
3424
3480
|
},
|
|
3425
3481
|
onError: () => {
|
|
3426
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
3482
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= gr && (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
3483
|
}
|
|
3428
3484
|
});
|
|
3429
3485
|
}
|
|
@@ -3437,7 +3493,7 @@ var gr = class {
|
|
|
3437
3493
|
return;
|
|
3438
3494
|
}
|
|
3439
3495
|
let e = this.hiddenAtMs;
|
|
3440
|
-
this.hiddenAtMs = null, e != null && Date.now() - e >=
|
|
3496
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= _r && this.resyncLiveState();
|
|
3441
3497
|
}, this.onReturnPageShow = (e) => {
|
|
3442
3498
|
e.persisted && this.resyncLiveState();
|
|
3443
3499
|
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
@@ -3469,7 +3525,7 @@ var gr = class {
|
|
|
3469
3525
|
scheduleRejoin(e) {
|
|
3470
3526
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3471
3527
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3472
|
-
}, Math.random() *
|
|
3528
|
+
}, Math.random() * hr));
|
|
3473
3529
|
}
|
|
3474
3530
|
cancelRejoin() {
|
|
3475
3531
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3493,7 +3549,7 @@ var gr = class {
|
|
|
3493
3549
|
}
|
|
3494
3550
|
t.controls = !1;
|
|
3495
3551
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3496
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3552
|
+
r && r.insertBefore(n, t), n.appendChild(t), Xn(n, this.opts.theme), this.container = n, this.controlBar = sr({
|
|
3497
3553
|
root: n,
|
|
3498
3554
|
video: t,
|
|
3499
3555
|
player: this,
|
|
@@ -3531,7 +3587,7 @@ var gr = class {
|
|
|
3531
3587
|
}
|
|
3532
3588
|
startStats() {
|
|
3533
3589
|
this.stopStats();
|
|
3534
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3590
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? vr);
|
|
3535
3591
|
this.statsTimer = setInterval(() => {
|
|
3536
3592
|
if (!this.engine) return;
|
|
3537
3593
|
let e = this.engine.getStats();
|
|
@@ -3542,14 +3598,14 @@ var gr = class {
|
|
|
3542
3598
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3543
3599
|
}
|
|
3544
3600
|
isStaleLicenseDenial(e) {
|
|
3545
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3601
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== br || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3546
3602
|
}
|
|
3547
3603
|
scheduleLicenseRefresh() {
|
|
3548
3604
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3549
3605
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3550
3606
|
document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3551
3607
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3552
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3608
|
+
let e = this.opts.licenseRefreshMs ?? yr;
|
|
3553
3609
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3554
3610
|
}
|
|
3555
3611
|
stopRefresh() {
|
|
@@ -3569,7 +3625,7 @@ var gr = class {
|
|
|
3569
3625
|
fairplay: r
|
|
3570
3626
|
}), this._descriptor = t), n;
|
|
3571
3627
|
} catch (e) {
|
|
3572
|
-
e instanceof n && !
|
|
3628
|
+
e instanceof n && !s(e.code) && (this.stopRefresh(), this.destroyed || this.emit("warning", e));
|
|
3573
3629
|
return;
|
|
3574
3630
|
} finally {
|
|
3575
3631
|
this.refreshInFlight?.promise === t && (this.refreshInFlight = void 0);
|
|
@@ -3719,7 +3775,7 @@ function $(e) {
|
|
|
3719
3775
|
}
|
|
3720
3776
|
//#endregion
|
|
3721
3777
|
//#region src/embed/host.ts
|
|
3722
|
-
function
|
|
3778
|
+
function wr(e) {
|
|
3723
3779
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3724
3780
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3725
3781
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3778,15 +3834,15 @@ function _r(e) {
|
|
|
3778
3834
|
}
|
|
3779
3835
|
//#endregion
|
|
3780
3836
|
//#region src/embed/page.ts
|
|
3781
|
-
var
|
|
3782
|
-
function
|
|
3837
|
+
var Tr = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3838
|
+
function Er(e) {
|
|
3783
3839
|
if (typeof e == "boolean") return e;
|
|
3784
3840
|
if (typeof e == "object" && e) {
|
|
3785
3841
|
let t = e.endpoint;
|
|
3786
3842
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3787
3843
|
}
|
|
3788
3844
|
}
|
|
3789
|
-
function
|
|
3845
|
+
function Dr() {
|
|
3790
3846
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3791
3847
|
if (e) return {
|
|
3792
3848
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3796,7 +3852,7 @@ function br() {
|
|
|
3796
3852
|
autoplay: e.autoplay ?? !0,
|
|
3797
3853
|
muted: e.muted ?? !0,
|
|
3798
3854
|
waitForLive: e.waitForLive ?? !0,
|
|
3799
|
-
analytics:
|
|
3855
|
+
analytics: Er(e.analytics)
|
|
3800
3856
|
};
|
|
3801
3857
|
let t = new URLSearchParams(location.search);
|
|
3802
3858
|
return {
|
|
@@ -3809,9 +3865,9 @@ function br() {
|
|
|
3809
3865
|
waitForLive: !0
|
|
3810
3866
|
};
|
|
3811
3867
|
}
|
|
3812
|
-
async function
|
|
3813
|
-
let e =
|
|
3814
|
-
|
|
3868
|
+
async function Or() {
|
|
3869
|
+
let e = Dr();
|
|
3870
|
+
Ar();
|
|
3815
3871
|
let t = document.createElement("video");
|
|
3816
3872
|
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
3873
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3867,12 +3923,12 @@ async function xr() {
|
|
|
3867
3923
|
message: e.message,
|
|
3868
3924
|
...e.country === void 0 ? {} : { country: e.country }
|
|
3869
3925
|
})), e.on("autoplayblocked", () => {
|
|
3870
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3926
|
+
i({ type: "oddin:autoplayblocked" }), kr(t, e);
|
|
3871
3927
|
});
|
|
3872
3928
|
}, s = async (r) => {
|
|
3873
3929
|
a?.destroy(), a = null;
|
|
3874
3930
|
try {
|
|
3875
|
-
let n = await
|
|
3931
|
+
let n = await Sr({
|
|
3876
3932
|
video: t,
|
|
3877
3933
|
baseUrl: e.baseUrl,
|
|
3878
3934
|
matchUrn: r,
|
|
@@ -3935,7 +3991,7 @@ async function xr() {
|
|
|
3935
3991
|
a?.retry();
|
|
3936
3992
|
break;
|
|
3937
3993
|
case "oddin:load":
|
|
3938
|
-
typeof e.matchUrn == "string" &&
|
|
3994
|
+
typeof e.matchUrn == "string" && Tr.test(e.matchUrn) && s(e.matchUrn);
|
|
3939
3995
|
break;
|
|
3940
3996
|
case "oddin:destroy": c();
|
|
3941
3997
|
}
|
|
@@ -3947,18 +4003,18 @@ async function xr() {
|
|
|
3947
4003
|
protocol: 1
|
|
3948
4004
|
});
|
|
3949
4005
|
}
|
|
3950
|
-
function
|
|
4006
|
+
function kr(e, t) {
|
|
3951
4007
|
if (document.getElementById("havik-tap")) return;
|
|
3952
4008
|
let n = document.createElement("button");
|
|
3953
4009
|
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
4010
|
n.remove(), t.play();
|
|
3955
4011
|
}), document.body.appendChild(n);
|
|
3956
4012
|
}
|
|
3957
|
-
function
|
|
4013
|
+
function Ar() {
|
|
3958
4014
|
let e = document.createElement("style");
|
|
3959
4015
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3960
4016
|
}
|
|
3961
4017
|
//#endregion
|
|
3962
|
-
export {
|
|
4018
|
+
export { Jn as ODDIN_THEME, n as PlaybackError, Xn as applyTheme, at as baseUrlForEnv, Or as bootEmbed, Ee as clearDeviceId, Re as clearRememberedBandwidth, Sr 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, wr as mountEmbed, fe as pollToLive, y as resolveStream, E as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
|
|
3963
4019
|
|
|
3964
4020
|
//# sourceMappingURL=index.js.map
|