@oddin-gg/havik-player 2.11.1 → 2.13.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 +29 -7
- 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 +38 -16
- package/dist/index.d.ts +38 -16
- package/dist/index.js +404 -339
- package/dist/index.js.map +1 -1
- package/docs/API.md +57 -52
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -110,42 +110,48 @@ function m(e) {
|
|
|
110
110
|
return e instanceof Error ? e.message : String(e);
|
|
111
111
|
}
|
|
112
112
|
//#endregion
|
|
113
|
+
//#region src/core/warnOnce.ts
|
|
114
|
+
var h = /* @__PURE__ */ new Set();
|
|
115
|
+
function g(e, t = e) {
|
|
116
|
+
h.has(t) || (h.add(t), console.warn(`havik-player: ${e}`));
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
113
119
|
//#region src/core/waitForLive.ts
|
|
114
|
-
var
|
|
120
|
+
var _ = 1e3, ee = 3e4, te = 6e5, ne = 3e5, re = 1e3, ie = {
|
|
115
121
|
TOO_EARLY: "tooEarly",
|
|
116
122
|
UNAVAILABLE: "unavailable",
|
|
117
123
|
RATE_LIMITED: "rateLimited",
|
|
118
124
|
NETWORK: "network"
|
|
119
125
|
};
|
|
120
|
-
function
|
|
121
|
-
let t = e === !0 || e === !1 ? {} : e, n = Math.max(
|
|
126
|
+
function ae(e) {
|
|
127
|
+
let t = e === !0 || e === !1 ? {} : e, n = Math.max(re, t.floorMs ?? _), r = Math.max(n, t.ceilMs ?? ee), i = Math.max(0, t.imminentMs ?? te), a = Math.max(r, t.sanityFloorMs ?? ne);
|
|
122
128
|
return {
|
|
123
129
|
timeoutMs: t.timeoutMs,
|
|
124
130
|
floorMs: n,
|
|
125
131
|
ceilMs: r,
|
|
126
132
|
imminentMs: i,
|
|
127
133
|
sanityFloorMs: a,
|
|
128
|
-
kickoffMs:
|
|
134
|
+
kickoffMs: oe(t.kickoffAt),
|
|
129
135
|
jitter: t.jitter ?? !0,
|
|
130
136
|
onState: t.onState
|
|
131
137
|
};
|
|
132
138
|
}
|
|
133
|
-
function
|
|
139
|
+
function oe(e) {
|
|
134
140
|
if (e == null) return;
|
|
135
141
|
if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
|
|
136
142
|
let t = Date.parse(e);
|
|
137
143
|
return Number.isFinite(t) ? t : void 0;
|
|
138
144
|
}
|
|
139
|
-
function
|
|
145
|
+
function se(e, t, n) {
|
|
140
146
|
return Math.min(n, Math.max(t, e));
|
|
141
147
|
}
|
|
142
|
-
function
|
|
148
|
+
function ce(e) {
|
|
143
149
|
return Math.round(e * (1 + .15 * Math.random()));
|
|
144
150
|
}
|
|
145
|
-
function
|
|
151
|
+
function le(e, t, n, r) {
|
|
146
152
|
let i = r ?? n.kickoffMs, a = i == null ? void 0 : Math.max(0, i - t), o = Math.max(n.floorMs, e ?? 0);
|
|
147
153
|
if (a == null || a <= n.imminentMs) return {
|
|
148
|
-
delay:
|
|
154
|
+
delay: se(e ?? n.floorMs, o, n.ceilMs),
|
|
149
155
|
ttkMs: a
|
|
150
156
|
};
|
|
151
157
|
let s = Math.min(Math.floor(a / 10), n.sanityFloorMs, a);
|
|
@@ -154,7 +160,7 @@ function se(e, t, n, r) {
|
|
|
154
160
|
ttkMs: a
|
|
155
161
|
};
|
|
156
162
|
}
|
|
157
|
-
function
|
|
163
|
+
function ue(e, t) {
|
|
158
164
|
return new Promise((r, i) => {
|
|
159
165
|
if (t?.aborted) {
|
|
160
166
|
i(new n("ABORTED", 0, "wait-for-live aborted"));
|
|
@@ -168,8 +174,8 @@ function ce(e, t) {
|
|
|
168
174
|
t?.addEventListener("abort", a, { once: !0 });
|
|
169
175
|
});
|
|
170
176
|
}
|
|
171
|
-
async function
|
|
172
|
-
let i =
|
|
177
|
+
async function de(e, t, r) {
|
|
178
|
+
let i = ae(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
|
|
173
179
|
for (;;) {
|
|
174
180
|
if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
|
|
175
181
|
try {
|
|
@@ -177,38 +183,38 @@ async function v(e, t, r) {
|
|
|
177
183
|
} catch (e) {
|
|
178
184
|
if (!(e instanceof n) || !o(e.code)) throw e;
|
|
179
185
|
c += 1, e.liveStartsAtMs != null && Number.isFinite(e.liveStartsAtMs) && (l = e.liveStartsAtMs);
|
|
180
|
-
let t = Date.now(), u =
|
|
181
|
-
if (i.jitter && (f =
|
|
186
|
+
let t = Date.now(), u = le(e.retryAfterMs, t, i, l), d = u.ttkMs, f = u.delay;
|
|
187
|
+
if (i.jitter && (f = ce(f)), t + f > s) throw new n("TIMEOUT", e.httpStatus, `timed out after ${i.timeoutMs}ms waiting for the stream to go live`, {
|
|
182
188
|
retryAfterMs: e.retryAfterMs,
|
|
183
189
|
cause: e
|
|
184
190
|
});
|
|
185
191
|
i.onState?.({
|
|
186
|
-
phase:
|
|
192
|
+
phase: ie[e.code] ?? "unavailable",
|
|
187
193
|
retryInMs: f,
|
|
188
194
|
attempt: c,
|
|
189
195
|
elapsedMs: t - a,
|
|
190
196
|
ttkMs: d
|
|
191
|
-
}), await
|
|
197
|
+
}), await ue(f, r);
|
|
192
198
|
}
|
|
193
199
|
}
|
|
194
200
|
}
|
|
195
201
|
//#endregion
|
|
196
202
|
//#region src/core/resolve.ts
|
|
197
|
-
async function
|
|
203
|
+
async function v(e) {
|
|
198
204
|
if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
|
|
199
205
|
let t = await p(d(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
|
|
200
206
|
credential: e.credential,
|
|
201
207
|
signal: e.signal,
|
|
202
208
|
apiHeaders: e.apiHeaders
|
|
203
209
|
});
|
|
204
|
-
if (!t.ok) throw await
|
|
205
|
-
return
|
|
210
|
+
if (!t.ok) throw await fe(t);
|
|
211
|
+
return he(await t.json(), e.matchUrn);
|
|
206
212
|
}
|
|
207
|
-
function
|
|
208
|
-
let t = () =>
|
|
209
|
-
return e.waitForLive ?
|
|
213
|
+
function y(e) {
|
|
214
|
+
let t = () => v(e);
|
|
215
|
+
return e.waitForLive ? de(t, e.waitForLive, e.signal) : t();
|
|
210
216
|
}
|
|
211
|
-
async function
|
|
217
|
+
async function fe(e) {
|
|
212
218
|
let t = f(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;
|
|
213
219
|
try {
|
|
214
220
|
let t = await e.json();
|
|
@@ -224,7 +230,7 @@ async function le(e) {
|
|
|
224
230
|
liveStartsAtMs: s
|
|
225
231
|
});
|
|
226
232
|
}
|
|
227
|
-
var
|
|
233
|
+
var pe = /* @__PURE__ */ new Set([
|
|
228
234
|
"matchUrn",
|
|
229
235
|
"protocol",
|
|
230
236
|
"drmEnabled",
|
|
@@ -235,7 +241,7 @@ var ue = /* @__PURE__ */ new Set([
|
|
|
235
241
|
"expiresAt",
|
|
236
242
|
"analytics"
|
|
237
243
|
]);
|
|
238
|
-
function
|
|
244
|
+
function b(e, t) {
|
|
239
245
|
let r;
|
|
240
246
|
try {
|
|
241
247
|
r = new URL(t);
|
|
@@ -245,57 +251,71 @@ function x(e, t) {
|
|
|
245
251
|
if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
|
|
246
252
|
return t;
|
|
247
253
|
}
|
|
248
|
-
function
|
|
254
|
+
function me(e) {
|
|
255
|
+
if (e !== void 0) {
|
|
256
|
+
if (typeof e == "string" && !e.endsWith("/")) try {
|
|
257
|
+
let t = new URL(e);
|
|
258
|
+
if (t.protocol === "https:" && t.href === `${t.origin}/`) return t.origin;
|
|
259
|
+
} catch {}
|
|
260
|
+
g(`server analytics.endpoint ${JSON.stringify(e)} ignored: not a bare https origin.`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function he(e, t) {
|
|
249
264
|
if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
|
|
250
265
|
let r = e.drmEnabled ?? !!e.drm, i = {
|
|
251
266
|
matchUrn: e.matchUrn ?? t,
|
|
252
267
|
protocol: "hls",
|
|
253
268
|
drmEnabled: r,
|
|
254
|
-
manifestUrl:
|
|
269
|
+
manifestUrl: b("manifestUrl", e.manifestUrl),
|
|
255
270
|
serverTime: e.serverTime ?? ""
|
|
256
271
|
};
|
|
257
|
-
if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid
|
|
272
|
+
if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid) {
|
|
273
|
+
i.analytics = { sid: e.analytics.sid };
|
|
274
|
+
let t = me(e.analytics.endpoint);
|
|
275
|
+
t && (i.analytics.endpoint = t);
|
|
276
|
+
}
|
|
277
|
+
if (r && e.drm) {
|
|
258
278
|
let t = {};
|
|
259
|
-
e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl:
|
|
260
|
-
licenseUrl:
|
|
261
|
-
certificateUrl:
|
|
279
|
+
e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: b("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
|
|
280
|
+
licenseUrl: b("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
|
|
281
|
+
certificateUrl: b("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
|
|
262
282
|
}), (t.widevine || t.fairplay) && (i.drm = t);
|
|
263
283
|
}
|
|
264
284
|
let a = {};
|
|
265
|
-
for (let [t, n] of Object.entries(e))
|
|
285
|
+
for (let [t, n] of Object.entries(e)) pe.has(t) || (a[t] = n);
|
|
266
286
|
return Object.keys(a).length > 0 && (i.extensions = a), i;
|
|
267
287
|
}
|
|
268
288
|
//#endregion
|
|
269
289
|
//#region src/core/fullscreen.ts
|
|
270
|
-
function
|
|
290
|
+
function ge(e) {
|
|
271
291
|
return e.ownerDocument ?? document;
|
|
272
292
|
}
|
|
273
|
-
function
|
|
293
|
+
function x(e) {
|
|
274
294
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
275
295
|
}
|
|
276
|
-
function
|
|
277
|
-
let n =
|
|
296
|
+
function S(e, t) {
|
|
297
|
+
let n = x(ge(e));
|
|
278
298
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
279
299
|
}
|
|
280
|
-
async function
|
|
300
|
+
async function C(e, t) {
|
|
281
301
|
let n = t ?? e;
|
|
282
302
|
if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
|
|
283
303
|
if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
|
|
284
304
|
let r = e;
|
|
285
305
|
return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
|
|
286
306
|
}
|
|
287
|
-
async function
|
|
307
|
+
async function w(e, t) {
|
|
288
308
|
let n = e;
|
|
289
309
|
if (n.webkitDisplayingFullscreen) {
|
|
290
310
|
n.webkitExitFullscreen?.();
|
|
291
311
|
return;
|
|
292
312
|
}
|
|
293
|
-
let r =
|
|
313
|
+
let r = ge(e), i = x(r);
|
|
294
314
|
i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
|
|
295
315
|
}
|
|
296
316
|
//#endregion
|
|
297
317
|
//#region src/core/catalog.ts
|
|
298
|
-
async function
|
|
318
|
+
async function _e(e) {
|
|
299
319
|
let t = new URLSearchParams();
|
|
300
320
|
e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
|
|
301
321
|
let i = t.toString(), a = d(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
|
|
@@ -313,12 +333,12 @@ async function fe(e) {
|
|
|
313
333
|
};
|
|
314
334
|
if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
|
|
315
335
|
return {
|
|
316
|
-
tournaments:
|
|
336
|
+
tournaments: ve(await s.json()),
|
|
317
337
|
etag: s.headers.get("etag") ?? void 0,
|
|
318
338
|
notModified: !1
|
|
319
339
|
};
|
|
320
340
|
}
|
|
321
|
-
function
|
|
341
|
+
function ve(e) {
|
|
322
342
|
return (e.tournaments ?? []).map((e) => {
|
|
323
343
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
324
344
|
return {
|
|
@@ -340,7 +360,7 @@ function pe(e) {
|
|
|
340
360
|
};
|
|
341
361
|
});
|
|
342
362
|
}
|
|
343
|
-
async function
|
|
363
|
+
async function ye(e) {
|
|
344
364
|
let t = d(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
345
365
|
e.etag && i.set("If-None-Match", e.etag);
|
|
346
366
|
let a = await p(t, {
|
|
@@ -360,13 +380,13 @@ async function me(e) {
|
|
|
360
380
|
};
|
|
361
381
|
if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
362
382
|
return {
|
|
363
|
-
tournament:
|
|
383
|
+
tournament: be(await a.json()),
|
|
364
384
|
etag: a.headers.get("etag") ?? void 0,
|
|
365
385
|
notModified: !1,
|
|
366
386
|
notFound: !1
|
|
367
387
|
};
|
|
368
388
|
}
|
|
369
|
-
function
|
|
389
|
+
function be(e) {
|
|
370
390
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
371
391
|
return {
|
|
372
392
|
urn: t,
|
|
@@ -386,12 +406,17 @@ function he(e) {
|
|
|
386
406
|
}))
|
|
387
407
|
};
|
|
388
408
|
}
|
|
389
|
-
function
|
|
409
|
+
function xe(e) {
|
|
390
410
|
return e.tournaments.flatMap((e) => e.matches);
|
|
391
411
|
}
|
|
392
412
|
//#endregion
|
|
393
413
|
//#region src/core/poll.ts
|
|
394
|
-
|
|
414
|
+
var Se = /* @__PURE__ */ new Set([
|
|
415
|
+
"NOT_FOUND",
|
|
416
|
+
"GONE",
|
|
417
|
+
"INVALID_URN"
|
|
418
|
+
]);
|
|
419
|
+
function Ce(e) {
|
|
395
420
|
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
|
|
396
421
|
u || (a = setTimeout(m, t));
|
|
397
422
|
}, m = async () => {
|
|
@@ -422,7 +447,10 @@ function _e(e) {
|
|
|
422
447
|
}));
|
|
423
448
|
}
|
|
424
449
|
} catch (t) {
|
|
425
|
-
i.signal.aborted
|
|
450
|
+
if (!i.signal.aborted) {
|
|
451
|
+
let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
|
|
452
|
+
Se.has(r.code) && (u = !0), e.onError?.(r);
|
|
453
|
+
}
|
|
426
454
|
} finally {
|
|
427
455
|
f();
|
|
428
456
|
}
|
|
@@ -433,9 +461,9 @@ function _e(e) {
|
|
|
433
461
|
}
|
|
434
462
|
//#endregion
|
|
435
463
|
//#region src/core/events.ts
|
|
436
|
-
var
|
|
437
|
-
function
|
|
438
|
-
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ??
|
|
464
|
+
var we = 45e3;
|
|
465
|
+
function T(e) {
|
|
466
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? we, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
|
|
439
467
|
if (a.signal.aborted) return t();
|
|
440
468
|
let n = setTimeout(t, e);
|
|
441
469
|
a.signal.addEventListener("abort", () => {
|
|
@@ -516,7 +544,7 @@ function D(e) {
|
|
|
516
544
|
o || (o = !0, a.abort());
|
|
517
545
|
} };
|
|
518
546
|
}
|
|
519
|
-
function
|
|
547
|
+
function E(e) {
|
|
520
548
|
try {
|
|
521
549
|
let t = new URL(e);
|
|
522
550
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -526,27 +554,27 @@ function O(e) {
|
|
|
526
554
|
}
|
|
527
555
|
//#endregion
|
|
528
556
|
//#region src/core/drm/deviceId.ts
|
|
529
|
-
var
|
|
530
|
-
function
|
|
531
|
-
if (
|
|
557
|
+
var D = "havik.player.deviceId", O;
|
|
558
|
+
function k() {
|
|
559
|
+
if (O) return O;
|
|
532
560
|
try {
|
|
533
|
-
let e = globalThis.localStorage?.getItem(
|
|
534
|
-
if (e) return
|
|
561
|
+
let e = globalThis.localStorage?.getItem(D);
|
|
562
|
+
if (e) return O = e, e;
|
|
535
563
|
} catch {}
|
|
536
|
-
let e =
|
|
537
|
-
|
|
564
|
+
let e = Ee();
|
|
565
|
+
O = e;
|
|
538
566
|
try {
|
|
539
|
-
globalThis.localStorage?.setItem(
|
|
567
|
+
globalThis.localStorage?.setItem(D, e);
|
|
540
568
|
} catch {}
|
|
541
569
|
return e;
|
|
542
570
|
}
|
|
543
|
-
function
|
|
544
|
-
|
|
571
|
+
function Te() {
|
|
572
|
+
O = void 0;
|
|
545
573
|
try {
|
|
546
|
-
globalThis.localStorage?.removeItem(
|
|
574
|
+
globalThis.localStorage?.removeItem(D);
|
|
547
575
|
} catch {}
|
|
548
576
|
}
|
|
549
|
-
function
|
|
577
|
+
function Ee() {
|
|
550
578
|
let e = globalThis.crypto;
|
|
551
579
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
552
580
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -558,21 +586,21 @@ function be() {
|
|
|
558
586
|
}
|
|
559
587
|
//#endregion
|
|
560
588
|
//#region src/core/drm/headers.ts
|
|
561
|
-
function
|
|
589
|
+
function De(e, t, n = {}) {
|
|
562
590
|
let r = {
|
|
563
591
|
"x-api-key": t.apiKey,
|
|
564
592
|
"X-Match-Urn": e.matchUrn,
|
|
565
|
-
"X-Device-Id": n.deviceId ??
|
|
593
|
+
"X-Device-Id": n.deviceId ?? k(),
|
|
566
594
|
"Content-Type": "application/octet-stream"
|
|
567
595
|
};
|
|
568
596
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
569
597
|
}
|
|
570
598
|
//#endregion
|
|
571
599
|
//#region src/core/drm/cdm.ts
|
|
572
|
-
var
|
|
573
|
-
function
|
|
574
|
-
let n =
|
|
575
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
600
|
+
var A = /* @__PURE__ */ new WeakMap();
|
|
601
|
+
function Oe(e, t) {
|
|
602
|
+
let n = A.get(e);
|
|
603
|
+
n || (n = /* @__PURE__ */ new Map(), A.set(e, n));
|
|
576
604
|
let r = n.get(t.keySystem);
|
|
577
605
|
if (r) return r;
|
|
578
606
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -580,22 +608,22 @@ function Se(e, t) {
|
|
|
580
608
|
});
|
|
581
609
|
return n.set(t.keySystem, i), i;
|
|
582
610
|
}
|
|
583
|
-
function
|
|
611
|
+
function j() {
|
|
584
612
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
585
613
|
}
|
|
586
|
-
var
|
|
587
|
-
function
|
|
614
|
+
var M = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
615
|
+
function ke(e) {
|
|
588
616
|
return e.startsWith("com.widevine");
|
|
589
617
|
}
|
|
590
|
-
function
|
|
591
|
-
if (!
|
|
618
|
+
function N(e, t) {
|
|
619
|
+
if (!ke(e)) return t;
|
|
592
620
|
let n = (e, t) => {
|
|
593
621
|
let n = e.videoCapabilities;
|
|
594
622
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
595
|
-
let n =
|
|
596
|
-
return n === -1 ||
|
|
623
|
+
let n = M.indexOf(e.robustness);
|
|
624
|
+
return n === -1 || M.indexOf(t) > n;
|
|
597
625
|
});
|
|
598
|
-
}, r =
|
|
626
|
+
}, r = M.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
599
627
|
...t,
|
|
600
628
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
601
629
|
...t,
|
|
@@ -604,53 +632,53 @@ function F(e, t) {
|
|
|
604
632
|
})));
|
|
605
633
|
return [...t, ...r];
|
|
606
634
|
}
|
|
607
|
-
function
|
|
608
|
-
return (t, n) =>
|
|
635
|
+
function P(e) {
|
|
636
|
+
return (t, n) => j() ? navigator.requestMediaKeySystemAccess(t, N(t, n)).then((t) => ({
|
|
609
637
|
keySystem: t.keySystem,
|
|
610
638
|
getConfiguration: () => t.getConfiguration(),
|
|
611
|
-
createMediaKeys: () =>
|
|
639
|
+
createMediaKeys: () => Oe(e, t)
|
|
612
640
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
613
641
|
}
|
|
614
|
-
var
|
|
642
|
+
var F = {
|
|
615
643
|
video: "SW_SECURE_DECODE",
|
|
616
644
|
audio: "SW_SECURE_CRYPTO",
|
|
617
645
|
scheme: "cbcs"
|
|
618
646
|
};
|
|
619
|
-
function
|
|
620
|
-
if (!
|
|
647
|
+
function Ae(e) {
|
|
648
|
+
if (!j()) return;
|
|
621
649
|
let t = (e, t) => ({
|
|
622
650
|
contentType: e,
|
|
623
651
|
robustness: t,
|
|
624
|
-
encryptionScheme:
|
|
652
|
+
encryptionScheme: F.scheme
|
|
625
653
|
});
|
|
626
|
-
|
|
654
|
+
P(e)("com.widevine.alpha", [{
|
|
627
655
|
initDataTypes: ["cenc"],
|
|
628
656
|
distinctiveIdentifier: "optional",
|
|
629
657
|
persistentState: "optional",
|
|
630
658
|
sessionTypes: ["temporary"],
|
|
631
|
-
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"",
|
|
632
|
-
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"",
|
|
659
|
+
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", F.audio)],
|
|
660
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", F.video)]
|
|
633
661
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
634
662
|
}
|
|
635
|
-
function
|
|
636
|
-
let t =
|
|
663
|
+
function I(e) {
|
|
664
|
+
let t = L(e);
|
|
637
665
|
if (/^avc[13]/.test(t)) return "avc";
|
|
638
666
|
if (/^(hvc1|hev1)/.test(t)) return "hevc";
|
|
639
667
|
if (/^(dvh1|dvhe)/.test(t)) return "dv";
|
|
640
668
|
if (t.startsWith("av01")) return "av1";
|
|
641
669
|
if (/^vp0?9/.test(t)) return "vp9";
|
|
642
670
|
}
|
|
643
|
-
function
|
|
671
|
+
function L(e) {
|
|
644
672
|
return (e ?? "").trim().toLowerCase();
|
|
645
673
|
}
|
|
646
|
-
var
|
|
674
|
+
var je = {
|
|
647
675
|
hevc: "hvc1.1.6.L93.90",
|
|
648
676
|
dv: "dvh1.05.06",
|
|
649
677
|
av1: "av01.0.05M.08",
|
|
650
678
|
vp9: "vp09.00.10.08"
|
|
651
|
-
},
|
|
652
|
-
function
|
|
653
|
-
let t =
|
|
679
|
+
}, Me = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
|
|
680
|
+
function Ne(e) {
|
|
681
|
+
let t = L(e), n = Me.get(t);
|
|
654
682
|
if (n) return n;
|
|
655
683
|
let r = {
|
|
656
684
|
initDataTypes: ["cenc"],
|
|
@@ -659,32 +687,32 @@ function Oe(e) {
|
|
|
659
687
|
sessionTypes: ["temporary"],
|
|
660
688
|
videoCapabilities: [{
|
|
661
689
|
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
662
|
-
robustness:
|
|
663
|
-
encryptionScheme:
|
|
690
|
+
robustness: F.video,
|
|
691
|
+
encryptionScheme: F.scheme
|
|
664
692
|
}]
|
|
665
693
|
}, i = (async () => {
|
|
666
694
|
try {
|
|
667
|
-
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha",
|
|
695
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", N("com.widevine.alpha", [r])), !0;
|
|
668
696
|
} catch {
|
|
669
697
|
return !1;
|
|
670
698
|
}
|
|
671
|
-
})().then((e) => (
|
|
672
|
-
return
|
|
699
|
+
})().then((e) => (R.set(t, e), e));
|
|
700
|
+
return Me.set(t, i), i;
|
|
673
701
|
}
|
|
674
|
-
function
|
|
675
|
-
if (
|
|
702
|
+
function Pe() {
|
|
703
|
+
if (j()) for (let e of Object.values(je)) Ne(e);
|
|
676
704
|
}
|
|
677
|
-
function
|
|
678
|
-
let t =
|
|
679
|
-
if (t) return t === "avc" ? !0 :
|
|
705
|
+
function Fe(e) {
|
|
706
|
+
let t = I(e);
|
|
707
|
+
if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(je[t]));
|
|
680
708
|
}
|
|
681
709
|
//#endregion
|
|
682
710
|
//#region src/core/drm/support.ts
|
|
683
|
-
var
|
|
711
|
+
var Ie = 5e3, Le = "video/mp4; codecs=\"avc1.42E01E\"", Re = "audio/mp4; codecs=\"mp4a.40.2\"", ze = {
|
|
684
712
|
widevine: ["com.widevine.alpha"],
|
|
685
713
|
fairplay: ["com.apple.fps"]
|
|
686
714
|
};
|
|
687
|
-
function
|
|
715
|
+
function Be(e) {
|
|
688
716
|
return e === "fairplay" ? [{
|
|
689
717
|
initDataTypes: [
|
|
690
718
|
"sinf",
|
|
@@ -692,30 +720,30 @@ function Pe(e) {
|
|
|
692
720
|
"cenc"
|
|
693
721
|
],
|
|
694
722
|
videoCapabilities: [{
|
|
695
|
-
contentType:
|
|
723
|
+
contentType: Le,
|
|
696
724
|
robustness: "",
|
|
697
725
|
encryptionScheme: "cbcs"
|
|
698
726
|
}],
|
|
699
727
|
audioCapabilities: [{
|
|
700
|
-
contentType:
|
|
728
|
+
contentType: Re,
|
|
701
729
|
robustness: "",
|
|
702
730
|
encryptionScheme: "cbcs"
|
|
703
731
|
}]
|
|
704
|
-
}] :
|
|
732
|
+
}] : N("com.widevine.alpha", [{
|
|
705
733
|
initDataTypes: ["cenc"],
|
|
706
734
|
videoCapabilities: [{
|
|
707
|
-
contentType:
|
|
708
|
-
robustness:
|
|
709
|
-
encryptionScheme:
|
|
735
|
+
contentType: Le,
|
|
736
|
+
robustness: F.video,
|
|
737
|
+
encryptionScheme: F.scheme
|
|
710
738
|
}],
|
|
711
739
|
audioCapabilities: [{
|
|
712
|
-
contentType:
|
|
713
|
-
robustness:
|
|
714
|
-
encryptionScheme:
|
|
740
|
+
contentType: Re,
|
|
741
|
+
robustness: F.audio,
|
|
742
|
+
encryptionScheme: F.scheme
|
|
715
743
|
}]
|
|
716
744
|
}]);
|
|
717
745
|
}
|
|
718
|
-
function
|
|
746
|
+
function Ve(e, t) {
|
|
719
747
|
return new Promise((n, r) => {
|
|
720
748
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
721
749
|
e.then((e) => {
|
|
@@ -725,8 +753,8 @@ function V(e, t) {
|
|
|
725
753
|
});
|
|
726
754
|
});
|
|
727
755
|
}
|
|
728
|
-
async function
|
|
729
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
756
|
+
async function He(e = {}) {
|
|
757
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ie, r = {};
|
|
730
758
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
731
759
|
verdict: "insecure-context",
|
|
732
760
|
detail: r
|
|
@@ -738,7 +766,7 @@ async function Fe(e = {}) {
|
|
|
738
766
|
};
|
|
739
767
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
740
768
|
for (let e of t) {
|
|
741
|
-
let t =
|
|
769
|
+
let t = ze[e];
|
|
742
770
|
if (!t) {
|
|
743
771
|
r[e] = "unknown system";
|
|
744
772
|
continue;
|
|
@@ -749,7 +777,7 @@ async function Fe(e = {}) {
|
|
|
749
777
|
break;
|
|
750
778
|
}
|
|
751
779
|
try {
|
|
752
|
-
return await
|
|
780
|
+
return await Ve((await Ve(i(n, Be(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
753
781
|
verdict: "supported",
|
|
754
782
|
system: e,
|
|
755
783
|
detail: r
|
|
@@ -773,49 +801,49 @@ async function Fe(e = {}) {
|
|
|
773
801
|
}
|
|
774
802
|
//#endregion
|
|
775
803
|
//#region src/core/manifest.ts
|
|
776
|
-
var
|
|
777
|
-
function
|
|
778
|
-
return
|
|
804
|
+
var Ue = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
805
|
+
function We(e) {
|
|
806
|
+
return Ue.test(e);
|
|
779
807
|
}
|
|
780
808
|
//#endregion
|
|
781
809
|
//#region src/core/env.ts
|
|
782
|
-
var
|
|
810
|
+
var z = {
|
|
783
811
|
integration: "https://feed-dev.oddin-video.gg",
|
|
784
812
|
production: "https://feed.oddin-video.gg"
|
|
785
813
|
};
|
|
786
|
-
function
|
|
787
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
814
|
+
function B(e) {
|
|
815
|
+
let t = Object.prototype.hasOwnProperty.call(z, e) ? z[e] : void 0;
|
|
788
816
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
789
817
|
return t;
|
|
790
818
|
}
|
|
791
819
|
//#endregion
|
|
792
820
|
//#region src/core/stats.ts
|
|
793
|
-
var
|
|
794
|
-
function
|
|
821
|
+
var V = { droppedFrames: 0 };
|
|
822
|
+
function H(e) {
|
|
795
823
|
try {
|
|
796
824
|
return new URL(e).host;
|
|
797
825
|
} catch {
|
|
798
826
|
return "";
|
|
799
827
|
}
|
|
800
828
|
}
|
|
801
|
-
var
|
|
802
|
-
function
|
|
829
|
+
var Ge = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
830
|
+
function Ke(e) {
|
|
803
831
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
804
832
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
805
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
806
|
-
let e =
|
|
833
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Ge.test(i.name)) && i.startTime >= n) {
|
|
834
|
+
let e = H(i.name);
|
|
807
835
|
e && (t = e, n = i.startTime);
|
|
808
836
|
}
|
|
809
837
|
return t;
|
|
810
838
|
}
|
|
811
|
-
function
|
|
839
|
+
function U(e) {
|
|
812
840
|
let t = e.getVideoPlaybackQuality?.();
|
|
813
841
|
return {
|
|
814
842
|
dropped: t?.droppedVideoFrames ?? 0,
|
|
815
843
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
816
844
|
};
|
|
817
845
|
}
|
|
818
|
-
function
|
|
846
|
+
function qe(e, t) {
|
|
819
847
|
let n = [
|
|
820
848
|
["playing", () => t("playing")],
|
|
821
849
|
["waiting", () => t("buffering")],
|
|
@@ -832,7 +860,7 @@ function Be(e, t) {
|
|
|
832
860
|
}
|
|
833
861
|
//#endregion
|
|
834
862
|
//#region src/core/engine/native.ts
|
|
835
|
-
function
|
|
863
|
+
function Je(e) {
|
|
836
864
|
try {
|
|
837
865
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
838
866
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -840,15 +868,15 @@ function Ve(e) {
|
|
|
840
868
|
return;
|
|
841
869
|
}
|
|
842
870
|
}
|
|
843
|
-
function
|
|
871
|
+
function W(e) {
|
|
844
872
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
845
873
|
}
|
|
846
|
-
function
|
|
874
|
+
function G() {
|
|
847
875
|
if (typeof window > "u") return !1;
|
|
848
876
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
849
877
|
return e || t;
|
|
850
878
|
}
|
|
851
|
-
var
|
|
879
|
+
var K = class {
|
|
852
880
|
name = "native";
|
|
853
881
|
deps;
|
|
854
882
|
onLoaded;
|
|
@@ -884,7 +912,7 @@ var Y = class {
|
|
|
884
912
|
type: "error",
|
|
885
913
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
886
914
|
fatal: !0
|
|
887
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
915
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Ye(t.manifestUrl, t.analytics?.sid), e.load();
|
|
888
916
|
}
|
|
889
917
|
startLoad() {
|
|
890
918
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -906,7 +934,7 @@ var Y = class {
|
|
|
906
934
|
});
|
|
907
935
|
this.onEncrypted = (n) => {
|
|
908
936
|
let i = n;
|
|
909
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
937
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Je(i.initData), (async () => {
|
|
910
938
|
try {
|
|
911
939
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
912
940
|
initDataTypes: [i.initDataType],
|
|
@@ -1001,11 +1029,11 @@ var Y = class {
|
|
|
1001
1029
|
e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
|
|
1002
1030
|
}
|
|
1003
1031
|
getStats() {
|
|
1004
|
-
let e = this.deps.video, t =
|
|
1032
|
+
let e = this.deps.video, t = U(e), n = {
|
|
1005
1033
|
droppedFrames: t.dropped,
|
|
1006
1034
|
decodedFrames: t.totalFrames
|
|
1007
1035
|
};
|
|
1008
|
-
return this.cdnHost ||=
|
|
1036
|
+
return this.cdnHost ||= Ke(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity ? (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)) : Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1), n;
|
|
1009
1037
|
}
|
|
1010
1038
|
stop() {
|
|
1011
1039
|
try {
|
|
@@ -1024,13 +1052,13 @@ var Y = class {
|
|
|
1024
1052
|
} catch {}
|
|
1025
1053
|
}
|
|
1026
1054
|
};
|
|
1027
|
-
function
|
|
1055
|
+
function Ye(e, t) {
|
|
1028
1056
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1029
1057
|
}
|
|
1030
1058
|
//#endregion
|
|
1031
1059
|
//#region src/core/engine/prefetch.ts
|
|
1032
|
-
var
|
|
1033
|
-
function
|
|
1060
|
+
var Xe = 15e3, Ze = 5e3, Qe = 6;
|
|
1061
|
+
function $e(e) {
|
|
1034
1062
|
try {
|
|
1035
1063
|
let t = new URL(e);
|
|
1036
1064
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1038,7 +1066,7 @@ function Ke(e) {
|
|
|
1038
1066
|
return e;
|
|
1039
1067
|
}
|
|
1040
1068
|
}
|
|
1041
|
-
var
|
|
1069
|
+
var et = class {
|
|
1042
1070
|
cmcd;
|
|
1043
1071
|
entries = /* @__PURE__ */ new Map();
|
|
1044
1072
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1061,10 +1089,10 @@ var qe = class {
|
|
|
1061
1089
|
}
|
|
1062
1090
|
prefetch(e, t, n) {
|
|
1063
1091
|
if (!this.isActive(t)) return;
|
|
1064
|
-
let r =
|
|
1092
|
+
let r = $e(e);
|
|
1065
1093
|
if (this.entries.has(r)) return;
|
|
1066
1094
|
let i = this.perTrack.get(t) ?? 0;
|
|
1067
|
-
if (i >=
|
|
1095
|
+
if (i >= Qe) return;
|
|
1068
1096
|
this.perTrack.set(t, i + 1);
|
|
1069
1097
|
let a = new AbortController(), o = {
|
|
1070
1098
|
started: performance.now(),
|
|
@@ -1078,10 +1106,10 @@ var qe = class {
|
|
|
1078
1106
|
signal: a.signal
|
|
1079
1107
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1080
1108
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1081
|
-
},
|
|
1109
|
+
}, Xe);
|
|
1082
1110
|
}
|
|
1083
1111
|
take(e) {
|
|
1084
|
-
let t =
|
|
1112
|
+
let t = $e(e), n = this.entries.get(t);
|
|
1085
1113
|
return n && this.entries.delete(t), n;
|
|
1086
1114
|
}
|
|
1087
1115
|
destroy() {
|
|
@@ -1101,13 +1129,13 @@ var qe = class {
|
|
|
1101
1129
|
}
|
|
1102
1130
|
}
|
|
1103
1131
|
};
|
|
1104
|
-
function
|
|
1132
|
+
function tt(t) {
|
|
1105
1133
|
let n = e.DefaultConfig?.loader;
|
|
1106
1134
|
if (typeof n != "function") return;
|
|
1107
1135
|
class r extends n {
|
|
1108
1136
|
served = !1;
|
|
1109
1137
|
cancelled = !1;
|
|
1110
|
-
stats =
|
|
1138
|
+
stats = nt();
|
|
1111
1139
|
load(e, n, r) {
|
|
1112
1140
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1113
1141
|
if (!i) {
|
|
@@ -1115,7 +1143,7 @@ function Je(t) {
|
|
|
1115
1143
|
return;
|
|
1116
1144
|
}
|
|
1117
1145
|
this.served = !0;
|
|
1118
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1146
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Ze, s = setTimeout(() => {
|
|
1119
1147
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1120
1148
|
}, o);
|
|
1121
1149
|
i.bytes.then((o) => {
|
|
@@ -1142,7 +1170,7 @@ function Je(t) {
|
|
|
1142
1170
|
}
|
|
1143
1171
|
return r;
|
|
1144
1172
|
}
|
|
1145
|
-
function
|
|
1173
|
+
function nt() {
|
|
1146
1174
|
return {
|
|
1147
1175
|
aborted: !1,
|
|
1148
1176
|
loaded: 0,
|
|
@@ -1166,10 +1194,10 @@ function Ye() {
|
|
|
1166
1194
|
}
|
|
1167
1195
|
};
|
|
1168
1196
|
}
|
|
1169
|
-
function
|
|
1197
|
+
function rt(e) {
|
|
1170
1198
|
return e === "audio" ? "audio" : "main";
|
|
1171
1199
|
}
|
|
1172
|
-
function
|
|
1200
|
+
function it(e, t) {
|
|
1173
1201
|
let n = [];
|
|
1174
1202
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1175
1203
|
url: t.initSegment.url,
|
|
@@ -1188,24 +1216,24 @@ function Ze(e, t) {
|
|
|
1188
1216
|
}
|
|
1189
1217
|
//#endregion
|
|
1190
1218
|
//#region src/core/engine/hls.ts
|
|
1191
|
-
function
|
|
1219
|
+
function at() {
|
|
1192
1220
|
return e.isSupported();
|
|
1193
1221
|
}
|
|
1194
|
-
var
|
|
1195
|
-
function
|
|
1222
|
+
var ot = 3, st = 5, ct = 3, lt = 3e4, ut = 12e3, dt = 3e3, ft = 6e3, pt = 5e3, mt = 4e3, ht = 2, gt = 5, _t = 2, vt = 2, yt = 4, bt = 4, xt = 2e3, St = 3e4, Ct = 2, wt = 9, Tt = .5, Et = 64;
|
|
1223
|
+
function Dt(e) {
|
|
1196
1224
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1197
1225
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1198
1226
|
return;
|
|
1199
1227
|
}
|
|
1200
|
-
e.liveSyncDuration ??=
|
|
1201
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1202
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1228
|
+
e.liveSyncDuration ??= Ct;
|
|
1229
|
+
let t = Math.max(12, e.liveSyncDuration + wt);
|
|
1230
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Ot(e, e.liveSyncDuration);
|
|
1203
1231
|
}
|
|
1204
|
-
function
|
|
1232
|
+
function Ot(e, t) {
|
|
1205
1233
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1206
1234
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1207
1235
|
}
|
|
1208
|
-
var
|
|
1236
|
+
var kt = class {
|
|
1209
1237
|
name = "hls";
|
|
1210
1238
|
hls = null;
|
|
1211
1239
|
deps;
|
|
@@ -1273,7 +1301,7 @@ var St = class {
|
|
|
1273
1301
|
this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1274
1302
|
}
|
|
1275
1303
|
async load() {
|
|
1276
|
-
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a =
|
|
1304
|
+
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = W(r) && G(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
1277
1305
|
if (e.drmEnabled && !o) {
|
|
1278
1306
|
i({
|
|
1279
1307
|
type: "error",
|
|
@@ -1282,7 +1310,7 @@ var St = class {
|
|
|
1282
1310
|
});
|
|
1283
1311
|
return;
|
|
1284
1312
|
}
|
|
1285
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1313
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Pe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1286
1314
|
let e = this.hls;
|
|
1287
1315
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1288
1316
|
let t = e.liveSyncPosition;
|
|
@@ -1305,7 +1333,7 @@ var St = class {
|
|
|
1305
1333
|
}
|
|
1306
1334
|
this.loadSuspended = !0;
|
|
1307
1335
|
}
|
|
1308
|
-
},
|
|
1336
|
+
}, pt));
|
|
1309
1337
|
}
|
|
1310
1338
|
resumeLoading() {
|
|
1311
1339
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1337,7 +1365,7 @@ var St = class {
|
|
|
1337
1365
|
let t = e.liveSyncPosition;
|
|
1338
1366
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1339
1367
|
let { video: n } = this.deps;
|
|
1340
|
-
n.currentTime <= t +
|
|
1368
|
+
n.currentTime <= t + Tt || (n.currentTime = t);
|
|
1341
1369
|
}
|
|
1342
1370
|
startHls() {
|
|
1343
1371
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1356,12 +1384,12 @@ var St = class {
|
|
|
1356
1384
|
emeEnabled: !0,
|
|
1357
1385
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1358
1386
|
drmSystemOptions: {
|
|
1359
|
-
videoRobustness:
|
|
1360
|
-
audioRobustness:
|
|
1361
|
-
videoEncryptionScheme:
|
|
1362
|
-
audioEncryptionScheme:
|
|
1387
|
+
videoRobustness: F.video,
|
|
1388
|
+
audioRobustness: F.audio,
|
|
1389
|
+
videoEncryptionScheme: F.scheme,
|
|
1390
|
+
audioEncryptionScheme: F.scheme
|
|
1363
1391
|
},
|
|
1364
|
-
...
|
|
1392
|
+
...j() ? { requestMediaKeySystemAccessFunc: P(t) } : {},
|
|
1365
1393
|
licenseXhrSetup: (e, t) => {
|
|
1366
1394
|
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;
|
|
1367
1395
|
let o = performance.now();
|
|
@@ -1378,20 +1406,20 @@ var St = class {
|
|
|
1378
1406
|
...c
|
|
1379
1407
|
};
|
|
1380
1408
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
|
|
1381
|
-
let e = new
|
|
1409
|
+
let e = new et({
|
|
1382
1410
|
sessionId: n.analytics?.sid,
|
|
1383
1411
|
contentId: n.matchUrn
|
|
1384
|
-
}), t =
|
|
1412
|
+
}), t = tt(e);
|
|
1385
1413
|
t && (this.prefetch = e, d.fLoader = t);
|
|
1386
1414
|
}
|
|
1387
|
-
|
|
1415
|
+
Dt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
|
|
1388
1416
|
let f = new e(d);
|
|
1389
1417
|
if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1390
1418
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(f), this.measureLadder(f), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1391
1419
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1392
1420
|
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(() => {
|
|
1393
1421
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1394
|
-
},
|
|
1422
|
+
}, lt)));
|
|
1395
1423
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1396
1424
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1397
1425
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1399,10 +1427,10 @@ var St = class {
|
|
|
1399
1427
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1400
1428
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1401
1429
|
let i = n?.loading;
|
|
1402
|
-
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 >
|
|
1430
|
+
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 > Et && this.requestTimesMs.shift());
|
|
1403
1431
|
let a = t?.frag?.url;
|
|
1404
1432
|
if (a) {
|
|
1405
|
-
let e =
|
|
1433
|
+
let e = H(a);
|
|
1406
1434
|
e && (this.cdnHost = e);
|
|
1407
1435
|
}
|
|
1408
1436
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1416,15 +1444,15 @@ var St = class {
|
|
|
1416
1444
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1417
1445
|
let t = this.prefetch;
|
|
1418
1446
|
f.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1419
|
-
let r = n?.frag, i =
|
|
1420
|
-
if (r && t.isActive(i)) for (let e of
|
|
1421
|
-
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1447
|
+
let r = n?.frag, i = rt(r?.type);
|
|
1448
|
+
if (r && t.isActive(i)) for (let e of it(f, r)) t.prefetch(e.url, i, e.kind);
|
|
1449
|
+
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(rt(n?.frag?.type)));
|
|
1422
1450
|
}
|
|
1423
1451
|
f.on(e.Events.KEY_LOADED, () => {
|
|
1424
1452
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1425
1453
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1426
1454
|
this.checkEndStale(), this.checkStarvation();
|
|
1427
|
-
},
|
|
1455
|
+
}, dt), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1428
1456
|
this.renditionSwitches += 1;
|
|
1429
1457
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1430
1458
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1488,7 +1516,7 @@ var St = class {
|
|
|
1488
1516
|
return;
|
|
1489
1517
|
}
|
|
1490
1518
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1491
|
-
let t = e > this.sizeCapLevel ?
|
|
1519
|
+
let t = e > this.sizeCapLevel ? xt : St;
|
|
1492
1520
|
this.capTimer = setTimeout(() => {
|
|
1493
1521
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1494
1522
|
}, t);
|
|
@@ -1498,9 +1526,9 @@ var St = class {
|
|
|
1498
1526
|
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;
|
|
1499
1527
|
}
|
|
1500
1528
|
dropLevelsWidevineCannotPlay(e) {
|
|
1501
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1502
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1503
|
-
for (let n of t)
|
|
1529
|
+
this.removeLevelsWhere(e, (e) => Fe(e) !== !0);
|
|
1530
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
|
|
1531
|
+
for (let n of t) Ne(n).then((t) => {
|
|
1504
1532
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1505
1533
|
});
|
|
1506
1534
|
}
|
|
@@ -1508,10 +1536,10 @@ var St = class {
|
|
|
1508
1536
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1509
1537
|
if (n.forEach((e, n) => {
|
|
1510
1538
|
let a = e.videoCodec;
|
|
1511
|
-
a &&
|
|
1539
|
+
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1512
1540
|
}), !r.length) return !1;
|
|
1513
1541
|
let a = [...i].join(", ");
|
|
1514
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !
|
|
1542
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Fe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1515
1543
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1516
1544
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1517
1545
|
}
|
|
@@ -1557,7 +1585,7 @@ var St = class {
|
|
|
1557
1585
|
e.widevine && (this.licenseUrl = e.widevine);
|
|
1558
1586
|
}
|
|
1559
1587
|
getStats() {
|
|
1560
|
-
let e = this.hls, t =
|
|
1588
|
+
let e = this.hls, t = U(this.deps.video), n = {
|
|
1561
1589
|
droppedFrames: t.dropped,
|
|
1562
1590
|
decodedFrames: t.totalFrames,
|
|
1563
1591
|
lowLatency: this.detectedLowLatency,
|
|
@@ -1603,7 +1631,7 @@ var St = class {
|
|
|
1603
1631
|
return;
|
|
1604
1632
|
}
|
|
1605
1633
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1606
|
-
!this.chaseSuspended && e >
|
|
1634
|
+
!this.chaseSuspended && e > ft && this.suspendChasing(), e > ut && this.emitEnded("stalled");
|
|
1607
1635
|
}
|
|
1608
1636
|
resetStarvationWindow() {
|
|
1609
1637
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1618,7 +1646,7 @@ var St = class {
|
|
|
1618
1646
|
this.resetStarvationWindow();
|
|
1619
1647
|
return;
|
|
1620
1648
|
}
|
|
1621
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1649
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < ft, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > mt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = U(t), c = o - s, l = c !== this.starvedFrames;
|
|
1622
1650
|
if (this.starvedFrames = c, !a || l) {
|
|
1623
1651
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1624
1652
|
return;
|
|
@@ -1627,12 +1655,12 @@ var St = class {
|
|
|
1627
1655
|
this.resetStarvationWindow();
|
|
1628
1656
|
return;
|
|
1629
1657
|
}
|
|
1630
|
-
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 >
|
|
1658
|
+
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 > yt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= _t && (this.clearKick(), this.starvationRebuilds < vt)) {
|
|
1631
1659
|
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");
|
|
1632
1660
|
return;
|
|
1633
1661
|
}
|
|
1634
|
-
let u = i && this.starvedTicks >=
|
|
1635
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1662
|
+
let u = i && this.starvedTicks >= ht, d = !i && this.deadTicks >= yt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= bt;
|
|
1663
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= gt))) {
|
|
1636
1664
|
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");
|
|
1637
1665
|
try {
|
|
1638
1666
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1681,7 +1709,7 @@ var St = class {
|
|
|
1681
1709
|
scheduleLicenseRetry(t) {
|
|
1682
1710
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1683
1711
|
let n = t.response?.code ?? 0;
|
|
1684
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1712
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= ct) return !1;
|
|
1685
1713
|
this.licenseRecoveries += 1;
|
|
1686
1714
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1687
1715
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1713,7 +1741,7 @@ var St = class {
|
|
|
1713
1741
|
return;
|
|
1714
1742
|
}
|
|
1715
1743
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1716
|
-
if (this.networkRecoveries <
|
|
1744
|
+
if (this.networkRecoveries < st) {
|
|
1717
1745
|
this.networkRecoveries += 1;
|
|
1718
1746
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1719
1747
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1730,7 +1758,7 @@ var St = class {
|
|
|
1730
1758
|
return;
|
|
1731
1759
|
}
|
|
1732
1760
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1733
|
-
if (this.mediaRecoveries <
|
|
1761
|
+
if (this.mediaRecoveries < ot) {
|
|
1734
1762
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1735
1763
|
return;
|
|
1736
1764
|
}
|
|
@@ -1754,19 +1782,19 @@ var St = class {
|
|
|
1754
1782
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1755
1783
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1756
1784
|
}
|
|
1757
|
-
},
|
|
1785
|
+
}, At = 15e3, jt = 6e5, Mt = 3e5, Nt = 100, q = 1, Pt = 1e3, Ft = 3e4, It = 1e3, Lt = {
|
|
1758
1786
|
inline: "PRESENTATION_INLINE",
|
|
1759
1787
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1760
1788
|
pip: "PRESENTATION_PIP"
|
|
1761
|
-
},
|
|
1789
|
+
}, Rt = {
|
|
1762
1790
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1763
1791
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1764
1792
|
none: "KEY_SYSTEM_NONE"
|
|
1765
1793
|
};
|
|
1766
|
-
function
|
|
1794
|
+
function zt(e, t) {
|
|
1767
1795
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1768
1796
|
}
|
|
1769
|
-
var
|
|
1797
|
+
var Bt = /* @__PURE__ */ new Set([
|
|
1770
1798
|
"INVALID_URN",
|
|
1771
1799
|
"NOT_FOUND",
|
|
1772
1800
|
"GONE",
|
|
@@ -1776,7 +1804,7 @@ var Nt = /* @__PURE__ */ new Set([
|
|
|
1776
1804
|
"FORBIDDEN",
|
|
1777
1805
|
"RATE_LIMITED",
|
|
1778
1806
|
"TIMEOUT"
|
|
1779
|
-
]),
|
|
1807
|
+
]), J = {
|
|
1780
1808
|
idle: "PLAYER_STATE_IDLE",
|
|
1781
1809
|
waiting: "PLAYER_STATE_WAITING",
|
|
1782
1810
|
loading: "PLAYER_STATE_LOADING",
|
|
@@ -1786,7 +1814,7 @@ var Nt = /* @__PURE__ */ new Set([
|
|
|
1786
1814
|
ended: "PLAYER_STATE_ENDED",
|
|
1787
1815
|
error: "PLAYER_STATE_ERROR"
|
|
1788
1816
|
};
|
|
1789
|
-
function
|
|
1817
|
+
function Vt(e) {
|
|
1790
1818
|
try {
|
|
1791
1819
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1792
1820
|
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);
|
|
@@ -1794,26 +1822,42 @@ function Pt(e) {
|
|
|
1794
1822
|
return;
|
|
1795
1823
|
}
|
|
1796
1824
|
}
|
|
1797
|
-
var
|
|
1798
|
-
function
|
|
1799
|
-
|
|
1825
|
+
var Ht = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Ut = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), Wt = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
1826
|
+
function Gt(e) {
|
|
1827
|
+
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
1828
|
+
let t;
|
|
1829
|
+
try {
|
|
1830
|
+
let n = new URL(e.blockedURI);
|
|
1831
|
+
t = n.origin + n.pathname;
|
|
1832
|
+
} catch {
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
if (Ut.has(t) && !Y.has(t)) {
|
|
1836
|
+
Y.add(t), g(Wt(new URL(t).origin));
|
|
1837
|
+
for (let e of X) e.noteCspBlocked();
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
function Kt(e, t) {
|
|
1841
|
+
return g(t, e), { disabledReason: t };
|
|
1800
1842
|
}
|
|
1801
|
-
function
|
|
1843
|
+
function qt(e, t, n) {
|
|
1844
|
+
if (n) return t && !Ht(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
1802
1845
|
if (t) return { endpoint: t };
|
|
1803
|
-
if (t !== void 0) return
|
|
1804
|
-
let
|
|
1805
|
-
if (
|
|
1806
|
-
let
|
|
1846
|
+
if (t !== void 0) return Kt("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).");
|
|
1847
|
+
let r = Vt(e);
|
|
1848
|
+
if (r) return { endpoint: r };
|
|
1849
|
+
let i;
|
|
1807
1850
|
try {
|
|
1808
|
-
|
|
1851
|
+
i = new URL(e).hostname || e;
|
|
1809
1852
|
} catch {
|
|
1810
|
-
|
|
1853
|
+
i = e;
|
|
1811
1854
|
}
|
|
1812
|
-
return
|
|
1855
|
+
return Kt(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).`);
|
|
1813
1856
|
}
|
|
1814
|
-
var
|
|
1857
|
+
var Jt = class {
|
|
1815
1858
|
opts;
|
|
1816
1859
|
url;
|
|
1860
|
+
cspKey;
|
|
1817
1861
|
now;
|
|
1818
1862
|
seq = 0;
|
|
1819
1863
|
pending = [];
|
|
@@ -1881,6 +1925,7 @@ var Rt = class {
|
|
|
1881
1925
|
firstPlaylistMs = 0;
|
|
1882
1926
|
drmSetupMs = 0;
|
|
1883
1927
|
onPagehide = () => this.end("END_REASON_PAGEHIDE");
|
|
1928
|
+
cspBlockedNoted = !1;
|
|
1884
1929
|
onFreeze = () => {
|
|
1885
1930
|
this.endedFlag || this.flush(!0);
|
|
1886
1931
|
};
|
|
@@ -1891,9 +1936,16 @@ var Rt = class {
|
|
|
1891
1936
|
constructor(e) {
|
|
1892
1937
|
this.opts = {
|
|
1893
1938
|
...e,
|
|
1894
|
-
heartbeatMs: e.heartbeatMs ??
|
|
1895
|
-
idleMs: e.idleMs ??
|
|
1896
|
-
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons
|
|
1939
|
+
heartbeatMs: e.heartbeatMs ?? At,
|
|
1940
|
+
idleMs: e.idleMs ?? jt
|
|
1941
|
+
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
1942
|
+
try {
|
|
1943
|
+
let e = new URL(this.url);
|
|
1944
|
+
this.cspKey = e.origin + e.pathname;
|
|
1945
|
+
} catch {
|
|
1946
|
+
this.cspKey = void 0;
|
|
1947
|
+
}
|
|
1948
|
+
this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs, this.startupAnchorMs = this.bornMs;
|
|
1897
1949
|
}
|
|
1898
1950
|
start() {
|
|
1899
1951
|
if (this.endedFlag) return;
|
|
@@ -1902,11 +1954,11 @@ var Rt = class {
|
|
|
1902
1954
|
sdkVersion: this.opts.sdkVersion,
|
|
1903
1955
|
...this.opts.environment
|
|
1904
1956
|
};
|
|
1905
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
1957
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Pt), 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 && Ut.add(this.cspKey), document.addEventListener("securitypolicyviolation", Gt), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
1906
1958
|
}
|
|
1907
1959
|
checkSuspension(e) {
|
|
1908
1960
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
1909
|
-
let t = Math.max(this.opts.idleMs,
|
|
1961
|
+
let t = Math.max(this.opts.idleMs, Mt);
|
|
1910
1962
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
1911
1963
|
}
|
|
1912
1964
|
syncIdle(e) {
|
|
@@ -1920,21 +1972,21 @@ var Rt = class {
|
|
|
1920
1972
|
noteStateChange(e, t, n, r) {
|
|
1921
1973
|
if (this.endedFlag || e === t) return;
|
|
1922
1974
|
let i = this.now();
|
|
1923
|
-
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(
|
|
1975
|
+
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(q, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(q, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
|
|
1924
1976
|
this.stallIsSeekInduced = this.seekInduced(i);
|
|
1925
1977
|
let e = !this.isHidden && !this.stallIsSeekInduced;
|
|
1926
|
-
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(
|
|
1978
|
+
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(q, Math.round(this.playingTotalMs)));
|
|
1927
1979
|
} else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
|
|
1928
1980
|
this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
|
|
1929
1981
|
let a = {
|
|
1930
|
-
fromState:
|
|
1931
|
-
toState:
|
|
1932
|
-
presentation:
|
|
1982
|
+
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1983
|
+
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1984
|
+
presentation: Lt[this.presentation]
|
|
1933
1985
|
}, o = this.causeOf(e, t, i);
|
|
1934
1986
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
1935
1987
|
}
|
|
1936
1988
|
seekInduced(e) {
|
|
1937
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
1989
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < It;
|
|
1938
1990
|
}
|
|
1939
1991
|
causeOf(e, t, n) {
|
|
1940
1992
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -1971,25 +2023,25 @@ var Rt = class {
|
|
|
1971
2023
|
}
|
|
1972
2024
|
this.muteChanges += 1;
|
|
1973
2025
|
let r = this.now();
|
|
1974
|
-
n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(
|
|
2026
|
+
n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(q, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
|
|
1975
2027
|
}
|
|
1976
2028
|
notePresentation(e) {
|
|
1977
2029
|
this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
|
|
1978
2030
|
}
|
|
1979
2031
|
notePlayIntent() {
|
|
1980
|
-
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs =
|
|
2032
|
+
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = q), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = q), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = q), this.drmSetupMs > 0 && (this.drmSetupMs = q));
|
|
1981
2033
|
}
|
|
1982
2034
|
noteReady() {
|
|
1983
|
-
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(
|
|
2035
|
+
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(q, this.now() - this.startupAnchorMs));
|
|
1984
2036
|
}
|
|
1985
2037
|
noteFirstPlaylist() {
|
|
1986
|
-
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(
|
|
2038
|
+
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(q, this.now() - this.startupAnchorMs));
|
|
1987
2039
|
}
|
|
1988
2040
|
noteDrmReady() {
|
|
1989
|
-
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(
|
|
2041
|
+
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(q, this.now() - this.startupAnchorMs));
|
|
1990
2042
|
}
|
|
1991
2043
|
noteFirstBytes() {
|
|
1992
|
-
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(
|
|
2044
|
+
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(q, this.now() - this.startupAnchorMs));
|
|
1993
2045
|
}
|
|
1994
2046
|
noteSeek() {
|
|
1995
2047
|
this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
|
|
@@ -2008,7 +2060,7 @@ var Rt = class {
|
|
|
2008
2060
|
let r = n ?? "";
|
|
2009
2061
|
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";
|
|
2010
2062
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2011
|
-
if (
|
|
2063
|
+
if (Bt.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2012
2064
|
let i = t ?? "";
|
|
2013
2065
|
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";
|
|
2014
2066
|
}
|
|
@@ -2024,7 +2076,7 @@ var Rt = class {
|
|
|
2024
2076
|
heartbeat() {
|
|
2025
2077
|
if (this.endedFlag) return;
|
|
2026
2078
|
let e = this.now();
|
|
2027
|
-
if (this.checkSuspension(e)) return;
|
|
2079
|
+
if (this.checkSuspension(e) || this.cspBlocked()) return;
|
|
2028
2080
|
let t = this.opts.sample(), n = this.playingTotalMs;
|
|
2029
2081
|
this.playingSinceMs !== null && (n += e - this.playingSinceMs);
|
|
2030
2082
|
let r = this.hiddenTotalMs;
|
|
@@ -2040,7 +2092,7 @@ var Rt = class {
|
|
|
2040
2092
|
let l = t.droppedFrames ?? 0;
|
|
2041
2093
|
l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
|
|
2042
2094
|
let u = t.renditionSwitches ?? 0;
|
|
2043
|
-
u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState =
|
|
2095
|
+
u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = J[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
|
|
2044
2096
|
let d = this.mutedTotalMs;
|
|
2045
2097
|
this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
|
|
2046
2098
|
let f = t.upshifts ?? 0;
|
|
@@ -2055,20 +2107,20 @@ var Rt = class {
|
|
|
2055
2107
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2056
2108
|
o.requestCountDelta = _;
|
|
2057
2109
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2058
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2110
|
+
n.length > 0 && (o.requestTimeP50Ms = zt(n, 50), o.requestTimeP95Ms = zt(n, 95));
|
|
2059
2111
|
}
|
|
2060
2112
|
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();
|
|
2061
2113
|
}
|
|
2062
2114
|
maybeEmitMediaInfo(e) {
|
|
2063
2115
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2064
2116
|
let t = {};
|
|
2065
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2117
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Rt[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);
|
|
2066
2118
|
let n = JSON.stringify(t);
|
|
2067
2119
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2068
2120
|
}
|
|
2069
2121
|
end(e, t) {
|
|
2070
2122
|
if (this.endedFlag) return;
|
|
2071
|
-
this.endedFlag = !0;
|
|
2123
|
+
this.endedFlag = !0, X.delete(this);
|
|
2072
2124
|
let n = t ?? this.now();
|
|
2073
2125
|
this.playingSinceMs !== null && (this.playingTotalMs += n - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += n - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += n - this.bufferingSinceMs, this.bufferingSinceMs = null), this.mutedSinceMs !== null && (this.mutedTotalMs += n - this.mutedSinceMs, this.mutedSinceMs = null), this.waitingSinceMs !== null && (this.waitingTotalMs += n - this.waitingSinceMs, this.waitingSinceMs = null), this.isPlaying = !1, this.syncActive(n), this.closePresentation(n), this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.timer &&= (clearInterval(this.timer), null), this.idleTimer &&= (clearTimeout(this.idleTimer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), document.removeEventListener("freeze", this.onFreeze), document.removeEventListener("resume", this.onResume));
|
|
2074
2126
|
let r = this.safeSample();
|
|
@@ -2082,7 +2134,7 @@ var Rt = class {
|
|
|
2082
2134
|
let c = r?.positionMs ?? 0;
|
|
2083
2135
|
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));
|
|
2084
2136
|
let l = e !== "END_REASON_ENDED";
|
|
2085
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2137
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= Ft && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Ft && (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);
|
|
2086
2138
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2087
2139
|
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");
|
|
2088
2140
|
}
|
|
@@ -2101,14 +2153,24 @@ var Rt = class {
|
|
|
2101
2153
|
...e
|
|
2102
2154
|
};
|
|
2103
2155
|
}
|
|
2156
|
+
noteCspBlocked() {
|
|
2157
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(Wt(new URL(this.url).origin)));
|
|
2158
|
+
}
|
|
2159
|
+
cspBlocked() {
|
|
2160
|
+
return !!this.cspKey && Y.has(this.cspKey);
|
|
2161
|
+
}
|
|
2104
2162
|
enqueue(e) {
|
|
2105
|
-
for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2163
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Nt;) {
|
|
2106
2164
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2107
2165
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2108
2166
|
}
|
|
2109
2167
|
}
|
|
2110
2168
|
flush(e = !1) {
|
|
2111
2169
|
if (this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.pendingStart = null, this.pending.length === 0) return;
|
|
2170
|
+
if (this.cspBlocked()) {
|
|
2171
|
+
this.pending = [];
|
|
2172
|
+
return;
|
|
2173
|
+
}
|
|
2112
2174
|
let t = JSON.stringify({ beacons: this.pending });
|
|
2113
2175
|
if (this.pending = [], e) {
|
|
2114
2176
|
let e = this.opts.sendBeacon ?? (typeof navigator < "u" && navigator.sendBeacon ? navigator.sendBeacon.bind(navigator) : void 0);
|
|
@@ -2125,7 +2187,7 @@ var Rt = class {
|
|
|
2125
2187
|
};
|
|
2126
2188
|
//#endregion
|
|
2127
2189
|
//#region src/core/environment.ts
|
|
2128
|
-
function
|
|
2190
|
+
function Yt() {
|
|
2129
2191
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2130
2192
|
let e;
|
|
2131
2193
|
try {
|
|
@@ -2150,14 +2212,14 @@ function zt() {
|
|
|
2150
2212
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2151
2213
|
};
|
|
2152
2214
|
}
|
|
2153
|
-
function
|
|
2215
|
+
function Xt() {
|
|
2154
2216
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2155
2217
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2156
2218
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2157
2219
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2158
2220
|
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";
|
|
2159
2221
|
}
|
|
2160
|
-
function
|
|
2222
|
+
function Zt() {
|
|
2161
2223
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2162
2224
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2163
2225
|
let t = {
|
|
@@ -2176,17 +2238,17 @@ function Vt() {
|
|
|
2176
2238
|
}
|
|
2177
2239
|
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;
|
|
2178
2240
|
}
|
|
2179
|
-
function
|
|
2180
|
-
let t =
|
|
2181
|
-
deviceClass:
|
|
2241
|
+
function Qt(e) {
|
|
2242
|
+
let t = Yt(), n = {
|
|
2243
|
+
deviceClass: Xt(),
|
|
2182
2244
|
integration: t.integration,
|
|
2183
|
-
...
|
|
2245
|
+
...Zt()
|
|
2184
2246
|
};
|
|
2185
2247
|
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);
|
|
2186
2248
|
let r = e.getBoundingClientRect?.();
|
|
2187
2249
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2188
2250
|
}
|
|
2189
|
-
async function
|
|
2251
|
+
async function $t() {
|
|
2190
2252
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2191
2253
|
if (!e?.getHighEntropyValues) return {};
|
|
2192
2254
|
try {
|
|
@@ -2198,7 +2260,7 @@ async function Ut() {
|
|
|
2198
2260
|
}
|
|
2199
2261
|
//#endregion
|
|
2200
2262
|
//#region src/core/version.ts
|
|
2201
|
-
var
|
|
2263
|
+
var en = "2.13.0", tn = {
|
|
2202
2264
|
accent: "#E1B600",
|
|
2203
2265
|
accentText: "#1B1C23",
|
|
2204
2266
|
background: "#0e0f13",
|
|
@@ -2209,7 +2271,7 @@ var Wt = "2.11.1", Gt = {
|
|
|
2209
2271
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2210
2272
|
radius: "8px",
|
|
2211
2273
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2212
|
-
},
|
|
2274
|
+
}, nn = {
|
|
2213
2275
|
accent: "--havik-accent",
|
|
2214
2276
|
accentText: "--havik-accent-text",
|
|
2215
2277
|
background: "--havik-bg",
|
|
@@ -2221,25 +2283,25 @@ var Wt = "2.11.1", Gt = {
|
|
|
2221
2283
|
radius: "--havik-radius",
|
|
2222
2284
|
fontFamily: "--havik-font"
|
|
2223
2285
|
};
|
|
2224
|
-
function
|
|
2286
|
+
function rn(e, t) {
|
|
2225
2287
|
let n = {
|
|
2226
|
-
...
|
|
2288
|
+
...tn,
|
|
2227
2289
|
...t
|
|
2228
2290
|
};
|
|
2229
|
-
for (let t of Object.keys(
|
|
2291
|
+
for (let t of Object.keys(nn)) e.style.setProperty(nn[t], n[t]);
|
|
2230
2292
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2231
2293
|
}
|
|
2232
2294
|
//#endregion
|
|
2233
2295
|
//#region src/ui/styles.ts
|
|
2234
|
-
var
|
|
2235
|
-
function
|
|
2236
|
-
if (e.getElementById(
|
|
2296
|
+
var an = "havik-player-styles", on = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* 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";
|
|
2297
|
+
function sn(e = document) {
|
|
2298
|
+
if (e.getElementById(an)) return;
|
|
2237
2299
|
let t = e.createElement("style");
|
|
2238
|
-
t.id =
|
|
2300
|
+
t.id = an, t.textContent = on, e.head.appendChild(t);
|
|
2239
2301
|
}
|
|
2240
2302
|
//#endregion
|
|
2241
2303
|
//#region src/ui/icons.ts
|
|
2242
|
-
var
|
|
2304
|
+
var cn = {
|
|
2243
2305
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2244
2306
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2245
2307
|
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\"/>",
|
|
@@ -2252,21 +2314,21 @@ var Zt = {
|
|
|
2252
2314
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
2253
2315
|
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\"/>"
|
|
2254
2316
|
};
|
|
2255
|
-
function
|
|
2256
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2317
|
+
function Z(e) {
|
|
2318
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${cn[e]}</svg>`;
|
|
2257
2319
|
}
|
|
2258
2320
|
//#endregion
|
|
2259
2321
|
//#region src/ui/controls.ts
|
|
2260
|
-
var
|
|
2322
|
+
var ln = 3e3, un = /* @__PURE__ */ new Set([
|
|
2261
2323
|
"GONE",
|
|
2262
2324
|
"NOT_FOUND",
|
|
2263
2325
|
"INVALID_URN",
|
|
2264
2326
|
"UNAUTHORIZED"
|
|
2265
2327
|
]);
|
|
2266
|
-
function
|
|
2267
|
-
return new
|
|
2328
|
+
function dn(e) {
|
|
2329
|
+
return new fn(e);
|
|
2268
2330
|
}
|
|
2269
|
-
var
|
|
2331
|
+
var fn = class {
|
|
2270
2332
|
root;
|
|
2271
2333
|
video;
|
|
2272
2334
|
player;
|
|
@@ -2308,7 +2370,7 @@ var tn = class {
|
|
|
2308
2370
|
scrubbing = !1;
|
|
2309
2371
|
offFns = [];
|
|
2310
2372
|
constructor(e) {
|
|
2311
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2373
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? ln, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, sn(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
|
|
2312
2374
|
let t = (e, t, n) => {
|
|
2313
2375
|
let r = this.doc.createElement(e);
|
|
2314
2376
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2319,12 +2381,12 @@ var tn = class {
|
|
|
2319
2381
|
"aria-label": r,
|
|
2320
2382
|
title: r
|
|
2321
2383
|
});
|
|
2322
|
-
return i.innerHTML =
|
|
2384
|
+
return i.innerHTML = Z(n), i;
|
|
2323
2385
|
};
|
|
2324
2386
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
2325
2387
|
type: "button",
|
|
2326
2388
|
"aria-label": "Play"
|
|
2327
|
-
}), this.center.innerHTML =
|
|
2389
|
+
}), this.center.innerHTML = Z("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
|
|
2328
2390
|
role: "slider",
|
|
2329
2391
|
"aria-label": "Seek",
|
|
2330
2392
|
"aria-valuemin": "0",
|
|
@@ -2342,7 +2404,7 @@ var tn = class {
|
|
|
2342
2404
|
"aria-label": "Volume"
|
|
2343
2405
|
});
|
|
2344
2406
|
let a = t("div", "havik-vol");
|
|
2345
|
-
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML =
|
|
2407
|
+
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Z("liveDot");
|
|
2346
2408
|
let o = this.doc.createElement("span");
|
|
2347
2409
|
o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
|
|
2348
2410
|
let s = t("div", "havik-spacer");
|
|
@@ -2396,12 +2458,12 @@ var tn = class {
|
|
|
2396
2458
|
}
|
|
2397
2459
|
if (e === "preplay") {
|
|
2398
2460
|
let e = this.doc.createElement("button");
|
|
2399
|
-
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML =
|
|
2461
|
+
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Z("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
|
|
2400
2462
|
} else {
|
|
2401
2463
|
let r = this.doc.createElement("div");
|
|
2402
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError &&
|
|
2464
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !un.has(this.lastError.code)) {
|
|
2403
2465
|
let e = this.doc.createElement("button");
|
|
2404
|
-
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${
|
|
2466
|
+
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Z("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
2405
2467
|
}
|
|
2406
2468
|
}
|
|
2407
2469
|
this.root.append(n), this.statusBox = n, this.show();
|
|
@@ -2440,7 +2502,7 @@ var tn = class {
|
|
|
2440
2502
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2441
2503
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2442
2504
|
}
|
|
2443
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2505
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Q(this.video.currentTime)} / ${Q(this.video.duration)}`);
|
|
2444
2506
|
}
|
|
2445
2507
|
syncLive() {
|
|
2446
2508
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2490,17 +2552,17 @@ var tn = class {
|
|
|
2490
2552
|
renderQualityMenu() {
|
|
2491
2553
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2492
2554
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2493
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2555
|
+
for (let n of e) this.menu.append(this.menuItem(pn(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2494
2556
|
}
|
|
2495
2557
|
renderAudioMenu() {
|
|
2496
2558
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2497
2559
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2498
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2560
|
+
for (let t of e) this.menu.append(this.menuItem(mn(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2499
2561
|
}
|
|
2500
2562
|
renderCcMenu() {
|
|
2501
2563
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2502
2564
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2503
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2565
|
+
for (let t of e) this.menu.append(this.menuItem(hn(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2504
2566
|
}
|
|
2505
2567
|
onTracksChanged() {
|
|
2506
2568
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2520,11 +2582,11 @@ var tn = class {
|
|
|
2520
2582
|
}
|
|
2521
2583
|
async toggleFullscreen() {
|
|
2522
2584
|
try {
|
|
2523
|
-
|
|
2585
|
+
S(this.video, this.root) ? await w(this.video, this.root) : await C(this.video, this.root);
|
|
2524
2586
|
} catch {}
|
|
2525
2587
|
}
|
|
2526
2588
|
syncFullscreen() {
|
|
2527
|
-
let e =
|
|
2589
|
+
let e = S(this.video, this.root);
|
|
2528
2590
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
2529
2591
|
}
|
|
2530
2592
|
poke() {
|
|
@@ -2583,7 +2645,7 @@ var tn = class {
|
|
|
2583
2645
|
}
|
|
2584
2646
|
}
|
|
2585
2647
|
setIcon(e, t) {
|
|
2586
|
-
e.innerHTML =
|
|
2648
|
+
e.innerHTML = Z(t);
|
|
2587
2649
|
}
|
|
2588
2650
|
destroy() {
|
|
2589
2651
|
this.hideTimer && clearTimeout(this.hideTimer);
|
|
@@ -2600,41 +2662,41 @@ var tn = class {
|
|
|
2600
2662
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2601
2663
|
}
|
|
2602
2664
|
};
|
|
2603
|
-
function
|
|
2665
|
+
function Q(e) {
|
|
2604
2666
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2605
2667
|
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");
|
|
2606
2668
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2607
2669
|
}
|
|
2608
|
-
function
|
|
2670
|
+
function pn(e) {
|
|
2609
2671
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2610
2672
|
}
|
|
2611
|
-
function
|
|
2673
|
+
function mn(e) {
|
|
2612
2674
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2613
2675
|
}
|
|
2614
|
-
function
|
|
2676
|
+
function hn(e) {
|
|
2615
2677
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2616
2678
|
}
|
|
2617
2679
|
//#endregion
|
|
2618
2680
|
//#region src/managed/index.ts
|
|
2619
|
-
var
|
|
2620
|
-
function
|
|
2681
|
+
var gn = 6e3, _n = 45e3, vn = 2e3, yn = 3, bn = 2e3, xn = 48e4;
|
|
2682
|
+
function Sn(e) {
|
|
2621
2683
|
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)})`);
|
|
2622
|
-
if (e.env !== void 0) return
|
|
2684
|
+
if (e.env !== void 0) return B(e.env);
|
|
2623
2685
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2624
2686
|
return e.baseUrl;
|
|
2625
2687
|
}
|
|
2626
|
-
async function
|
|
2688
|
+
async function Cn(e) {
|
|
2627
2689
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2628
|
-
let t =
|
|
2690
|
+
let t = Sn(e);
|
|
2629
2691
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2630
2692
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2631
|
-
let r = new
|
|
2693
|
+
let r = new wn({
|
|
2632
2694
|
...e,
|
|
2633
2695
|
baseUrl: t
|
|
2634
2696
|
});
|
|
2635
2697
|
return await r.start(), r;
|
|
2636
2698
|
}
|
|
2637
|
-
var
|
|
2699
|
+
var wn = class {
|
|
2638
2700
|
opts;
|
|
2639
2701
|
abort = new AbortController();
|
|
2640
2702
|
listeners = {};
|
|
@@ -2678,7 +2740,7 @@ var hn = class {
|
|
|
2678
2740
|
this.opts.muted && (this.opts.video.muted = !0), this.opts.poster && (this.opts.video.poster = this.opts.poster), this.mountControls(), this.attachPipListeners(), this.setState("loading");
|
|
2679
2741
|
let e = ++this.loadGen, t = this.resolveOptions();
|
|
2680
2742
|
try {
|
|
2681
|
-
let n = await
|
|
2743
|
+
let n = await v(t);
|
|
2682
2744
|
if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
|
|
2683
2745
|
let e = this._lastError;
|
|
2684
2746
|
throw this.destroy(), e;
|
|
@@ -2701,11 +2763,11 @@ var hn = class {
|
|
|
2701
2763
|
};
|
|
2702
2764
|
}
|
|
2703
2765
|
beginArming(e, t, n = !1) {
|
|
2704
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
2766
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
|
|
2705
2767
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
2706
2768
|
}
|
|
2707
2769
|
beginArmingByPolling(e) {
|
|
2708
|
-
|
|
2770
|
+
y({
|
|
2709
2771
|
...this.resolveOptions(),
|
|
2710
2772
|
signal: this.abort.signal,
|
|
2711
2773
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -2722,7 +2784,7 @@ var hn = class {
|
|
|
2722
2784
|
setTimeout(() => {
|
|
2723
2785
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
2724
2786
|
phase: i ? "unavailable" : "tooEarly",
|
|
2725
|
-
retryInMs:
|
|
2787
|
+
retryInMs: _n,
|
|
2726
2788
|
attempt: 1,
|
|
2727
2789
|
elapsedMs: 0,
|
|
2728
2790
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -2739,7 +2801,7 @@ var hn = class {
|
|
|
2739
2801
|
}
|
|
2740
2802
|
}
|
|
2741
2803
|
}, h = () => {
|
|
2742
|
-
a || s || p() || (s = !0,
|
|
2804
|
+
a || s || p() || (s = !0, y({
|
|
2743
2805
|
...this.resolveOptions(),
|
|
2744
2806
|
signal: c.signal,
|
|
2745
2807
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -2747,7 +2809,7 @@ var hn = class {
|
|
|
2747
2809
|
a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
|
|
2748
2810
|
}));
|
|
2749
2811
|
}, g = () => {
|
|
2750
|
-
a || p() ||
|
|
2812
|
+
a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
|
|
2751
2813
|
if (!(a || p())) {
|
|
2752
2814
|
if (e instanceof n && o(e.code)) {
|
|
2753
2815
|
h();
|
|
@@ -2761,13 +2823,13 @@ var hn = class {
|
|
|
2761
2823
|
!a && !p() && h();
|
|
2762
2824
|
}, e);
|
|
2763
2825
|
};
|
|
2764
|
-
_(
|
|
2826
|
+
_(gn), this.armingSub = T({
|
|
2765
2827
|
eventsBaseUrl: t,
|
|
2766
2828
|
matchUrn: this.opts.matchUrn,
|
|
2767
2829
|
credential: this.opts.credential,
|
|
2768
|
-
onAlive: () => _(
|
|
2830
|
+
onAlive: () => _(_n),
|
|
2769
2831
|
onState: (e) => {
|
|
2770
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
2832
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * vn);
|
|
2771
2833
|
},
|
|
2772
2834
|
onError: () => h()
|
|
2773
2835
|
});
|
|
@@ -2790,7 +2852,7 @@ var hn = class {
|
|
|
2790
2852
|
let n = await s(this.opts.credential);
|
|
2791
2853
|
if (this.destroyed || t !== this.loadGen) return;
|
|
2792
2854
|
this.setState("loading");
|
|
2793
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
2855
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = qe(this.opts.video, (e) => {
|
|
2794
2856
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
2795
2857
|
});
|
|
2796
2858
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -2812,23 +2874,26 @@ var hn = class {
|
|
|
2812
2874
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
2813
2875
|
let i = e.analytics?.sid;
|
|
2814
2876
|
if (!i) return;
|
|
2815
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
2877
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = qt(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
2816
2878
|
if (!o) {
|
|
2817
2879
|
s && setTimeout(() => {
|
|
2818
2880
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
2819
2881
|
}, 0);
|
|
2820
2882
|
return;
|
|
2821
2883
|
}
|
|
2822
|
-
let c = this.opts.video, l = new
|
|
2884
|
+
let c = this.opts.video, l = new Jt({
|
|
2823
2885
|
endpoint: o,
|
|
2824
2886
|
sid: i,
|
|
2825
2887
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
2826
|
-
sdkVersion:
|
|
2827
|
-
environment:
|
|
2888
|
+
sdkVersion: en,
|
|
2889
|
+
environment: Qt(c),
|
|
2828
2890
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
2829
2891
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
2892
|
+
onBlocked: (e) => setTimeout(() => {
|
|
2893
|
+
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
2894
|
+
}, 0),
|
|
2830
2895
|
sample: () => {
|
|
2831
|
-
let e = this.engine?.getStats() ??
|
|
2896
|
+
let e = this.engine?.getStats() ?? V, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
2832
2897
|
return {
|
|
2833
2898
|
...e,
|
|
2834
2899
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -2842,7 +2907,7 @@ var hn = class {
|
|
|
2842
2907
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
2843
2908
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
2844
2909
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
2845
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
2910
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), $t().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
2846
2911
|
}
|
|
2847
2912
|
currentPresentation() {
|
|
2848
2913
|
let e = this.opts.video;
|
|
@@ -2857,7 +2922,7 @@ var hn = class {
|
|
|
2857
2922
|
video: this.opts.video,
|
|
2858
2923
|
descriptor: e,
|
|
2859
2924
|
credential: t,
|
|
2860
|
-
deviceId:
|
|
2925
|
+
deviceId: k(),
|
|
2861
2926
|
userId: this.opts.userId,
|
|
2862
2927
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
2863
2928
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -2867,11 +2932,11 @@ var hn = class {
|
|
|
2867
2932
|
hlsConfig: i,
|
|
2868
2933
|
emit: (e) => this.onEngineEvent(e)
|
|
2869
2934
|
}, o = this.opts.engine ?? "auto";
|
|
2870
|
-
if (o === "native") return new
|
|
2871
|
-
if (o === "hls") return new
|
|
2872
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
2873
|
-
if (
|
|
2874
|
-
if (
|
|
2935
|
+
if (o === "native") return new K(a);
|
|
2936
|
+
if (o === "hls") return new kt(a);
|
|
2937
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G()) return new K(a);
|
|
2938
|
+
if (at()) return new kt(a);
|
|
2939
|
+
if (W(this.opts.video)) return new K(a);
|
|
2875
2940
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
2876
2941
|
}
|
|
2877
2942
|
onEngineEvent(e) {
|
|
@@ -2908,11 +2973,11 @@ var hn = class {
|
|
|
2908
2973
|
}
|
|
2909
2974
|
startLiveState(e) {
|
|
2910
2975
|
if (this.opts.liveStateEvents === !1) return;
|
|
2911
|
-
let t = this.opts.eventsBaseUrl ??
|
|
2976
|
+
let t = this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
|
|
2912
2977
|
if (!t) return;
|
|
2913
2978
|
this.closeLiveState();
|
|
2914
2979
|
let r = 0, i = !1;
|
|
2915
|
-
this.liveStateSub =
|
|
2980
|
+
this.liveStateSub = T({
|
|
2916
2981
|
eventsBaseUrl: t,
|
|
2917
2982
|
matchUrn: this.opts.matchUrn,
|
|
2918
2983
|
credential: this.opts.credential,
|
|
@@ -2923,7 +2988,7 @@ var hn = class {
|
|
|
2923
2988
|
r = 0, i = !1;
|
|
2924
2989
|
},
|
|
2925
2990
|
onError: () => {
|
|
2926
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
2991
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= yn && (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.`))));
|
|
2927
2992
|
}
|
|
2928
2993
|
});
|
|
2929
2994
|
}
|
|
@@ -2945,7 +3010,7 @@ var hn = class {
|
|
|
2945
3010
|
scheduleRejoin(e) {
|
|
2946
3011
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
2947
3012
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
2948
|
-
}, Math.random() *
|
|
3013
|
+
}, Math.random() * vn));
|
|
2949
3014
|
}
|
|
2950
3015
|
cancelRejoin() {
|
|
2951
3016
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -2969,7 +3034,7 @@ var hn = class {
|
|
|
2969
3034
|
}
|
|
2970
3035
|
t.controls = !1;
|
|
2971
3036
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
2972
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3037
|
+
r && r.insertBefore(n, t), n.appendChild(t), rn(n, this.opts.theme), this.container = n, this.controlBar = dn({
|
|
2973
3038
|
root: n,
|
|
2974
3039
|
video: t,
|
|
2975
3040
|
player: this,
|
|
@@ -2999,7 +3064,7 @@ var hn = class {
|
|
|
2999
3064
|
}
|
|
3000
3065
|
startStats() {
|
|
3001
3066
|
this.stopStats();
|
|
3002
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3067
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? bn);
|
|
3003
3068
|
this.statsTimer = setInterval(() => {
|
|
3004
3069
|
if (!this.engine) return;
|
|
3005
3070
|
let e = this.engine.getStats();
|
|
@@ -3011,7 +3076,7 @@ var hn = class {
|
|
|
3011
3076
|
}
|
|
3012
3077
|
scheduleLicenseRefresh() {
|
|
3013
3078
|
this.stopRefresh();
|
|
3014
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3079
|
+
let e = this.opts.licenseRefreshMs ?? xn;
|
|
3015
3080
|
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3016
3081
|
}
|
|
3017
3082
|
stopRefresh() {
|
|
@@ -3020,7 +3085,7 @@ var hn = class {
|
|
|
3020
3085
|
async refreshLicense() {
|
|
3021
3086
|
let e = this.engine;
|
|
3022
3087
|
if (!this.destroyed && e) try {
|
|
3023
|
-
let t = await
|
|
3088
|
+
let t = await v(this.resolveOptions());
|
|
3024
3089
|
if (this.destroyed || this.engine !== e) return;
|
|
3025
3090
|
let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
|
|
3026
3091
|
(n || r) && (e.setLicenseUrls({
|
|
@@ -3056,7 +3121,7 @@ var hn = class {
|
|
|
3056
3121
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3057
3122
|
}
|
|
3058
3123
|
getStats() {
|
|
3059
|
-
return this.engine?.getStats() ??
|
|
3124
|
+
return this.engine?.getStats() ?? V;
|
|
3060
3125
|
}
|
|
3061
3126
|
getQualityLevels() {
|
|
3062
3127
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3095,10 +3160,10 @@ var hn = class {
|
|
|
3095
3160
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
3096
3161
|
}
|
|
3097
3162
|
async enterFullscreen() {
|
|
3098
|
-
return !this.destroyed &&
|
|
3163
|
+
return !this.destroyed && C(this.opts.video, this.container ?? void 0);
|
|
3099
3164
|
}
|
|
3100
3165
|
async exitFullscreen() {
|
|
3101
|
-
await
|
|
3166
|
+
await w(this.opts.video, this.container ?? void 0);
|
|
3102
3167
|
}
|
|
3103
3168
|
retry() {
|
|
3104
3169
|
return this.reload();
|
|
@@ -3108,7 +3173,7 @@ var hn = class {
|
|
|
3108
3173
|
let e = ++this.loadGen;
|
|
3109
3174
|
this.teardownPlayback();
|
|
3110
3175
|
try {
|
|
3111
|
-
let t = await
|
|
3176
|
+
let t = await y({
|
|
3112
3177
|
...this.resolveOptions(),
|
|
3113
3178
|
waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
|
|
3114
3179
|
});
|
|
@@ -3166,7 +3231,7 @@ function $(e) {
|
|
|
3166
3231
|
}
|
|
3167
3232
|
//#endregion
|
|
3168
3233
|
//#region src/embed/host.ts
|
|
3169
|
-
function
|
|
3234
|
+
function Tn(e) {
|
|
3170
3235
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3171
3236
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3172
3237
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3225,15 +3290,15 @@ function gn(e) {
|
|
|
3225
3290
|
}
|
|
3226
3291
|
//#endregion
|
|
3227
3292
|
//#region src/embed/page.ts
|
|
3228
|
-
var
|
|
3229
|
-
function
|
|
3293
|
+
var En = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3294
|
+
function Dn(e) {
|
|
3230
3295
|
if (typeof e == "boolean") return e;
|
|
3231
3296
|
if (typeof e == "object" && e) {
|
|
3232
3297
|
let t = e.endpoint;
|
|
3233
3298
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3234
3299
|
}
|
|
3235
3300
|
}
|
|
3236
|
-
function
|
|
3301
|
+
function On() {
|
|
3237
3302
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3238
3303
|
if (e) return {
|
|
3239
3304
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3243,7 +3308,7 @@ function yn() {
|
|
|
3243
3308
|
autoplay: e.autoplay ?? !0,
|
|
3244
3309
|
muted: e.muted ?? !0,
|
|
3245
3310
|
waitForLive: e.waitForLive ?? !0,
|
|
3246
|
-
analytics:
|
|
3311
|
+
analytics: Dn(e.analytics)
|
|
3247
3312
|
};
|
|
3248
3313
|
let t = new URLSearchParams(location.search);
|
|
3249
3314
|
return {
|
|
@@ -3256,9 +3321,9 @@ function yn() {
|
|
|
3256
3321
|
waitForLive: !0
|
|
3257
3322
|
};
|
|
3258
3323
|
}
|
|
3259
|
-
async function
|
|
3260
|
-
let e =
|
|
3261
|
-
|
|
3324
|
+
async function kn() {
|
|
3325
|
+
let e = On();
|
|
3326
|
+
jn();
|
|
3262
3327
|
let t = document.createElement("video");
|
|
3263
3328
|
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);
|
|
3264
3329
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3313,12 +3378,12 @@ async function bn() {
|
|
|
3313
3378
|
code: e.code,
|
|
3314
3379
|
message: e.message
|
|
3315
3380
|
})), e.on("autoplayblocked", () => {
|
|
3316
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3381
|
+
i({ type: "oddin:autoplayblocked" }), An(t, e);
|
|
3317
3382
|
});
|
|
3318
3383
|
}, s = async (r) => {
|
|
3319
3384
|
a?.destroy(), a = null;
|
|
3320
3385
|
try {
|
|
3321
|
-
let n = await
|
|
3386
|
+
let n = await Cn({
|
|
3322
3387
|
video: t,
|
|
3323
3388
|
baseUrl: e.baseUrl,
|
|
3324
3389
|
matchUrn: r,
|
|
@@ -3380,7 +3445,7 @@ async function bn() {
|
|
|
3380
3445
|
a?.retry();
|
|
3381
3446
|
break;
|
|
3382
3447
|
case "oddin:load":
|
|
3383
|
-
typeof e.matchUrn == "string" &&
|
|
3448
|
+
typeof e.matchUrn == "string" && En.test(e.matchUrn) && s(e.matchUrn);
|
|
3384
3449
|
break;
|
|
3385
3450
|
case "oddin:destroy": c();
|
|
3386
3451
|
}
|
|
@@ -3392,18 +3457,18 @@ async function bn() {
|
|
|
3392
3457
|
protocol: 1
|
|
3393
3458
|
});
|
|
3394
3459
|
}
|
|
3395
|
-
function
|
|
3460
|
+
function An(e, t) {
|
|
3396
3461
|
if (document.getElementById("havik-tap")) return;
|
|
3397
3462
|
let n = document.createElement("button");
|
|
3398
3463
|
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", () => {
|
|
3399
3464
|
n.remove(), t.play();
|
|
3400
3465
|
}), document.body.appendChild(n);
|
|
3401
3466
|
}
|
|
3402
|
-
function
|
|
3467
|
+
function jn() {
|
|
3403
3468
|
let e = document.createElement("style");
|
|
3404
3469
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3405
3470
|
}
|
|
3406
3471
|
//#endregion
|
|
3407
|
-
export {
|
|
3472
|
+
export { tn as ODDIN_THEME, n as PlaybackError, rn as applyTheme, B as baseUrlForEnv, kn as bootEmbed, Te as clearDeviceId, Cn as createPlayer, E as deriveEventsBaseUrl, He as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, k as getDeviceId, We as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, Tn as mountEmbed, de as pollToLive, y as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
|
|
3408
3473
|
|
|
3409
3474
|
//# sourceMappingURL=index.js.map
|