@oddin-gg/havik-player 2.18.0 → 2.20.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 +1 -0
- package/dist/havik-player.global.js +18 -18
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -2
- package/dist/index.d.ts +42 -2
- package/dist/index.js +361 -333
- package/dist/index.js.map +1 -1
- package/docs/API.md +67 -40
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,8 +7,9 @@ var n = class extends Error {
|
|
|
7
7
|
requestId;
|
|
8
8
|
serverCode;
|
|
9
9
|
liveStartsAtMs;
|
|
10
|
+
country;
|
|
10
11
|
constructor(e, t, n, r) {
|
|
11
|
-
super(n), this.name = "PlaybackError", this.code = e, this.httpStatus = t, this.retryAfterMs = r?.retryAfterMs, this.requestId = r?.requestId, this.serverCode = r?.serverCode, this.liveStartsAtMs = r?.liveStartsAtMs, r?.cause !== void 0 && (this.cause = r.cause);
|
|
12
|
+
super(n), this.name = "PlaybackError", this.code = e, this.httpStatus = t, this.retryAfterMs = r?.retryAfterMs, this.requestId = r?.requestId, this.serverCode = r?.serverCode, this.liveStartsAtMs = r?.liveStartsAtMs, this.country = r?.country, r?.cause !== void 0 && (this.cause = r.cause);
|
|
12
13
|
}
|
|
13
14
|
};
|
|
14
15
|
function r(e) {
|
|
@@ -20,6 +21,7 @@ function r(e) {
|
|
|
20
21
|
case 410: return "GONE";
|
|
21
22
|
case 425: return "TOO_EARLY";
|
|
22
23
|
case 429: return "RATE_LIMITED";
|
|
24
|
+
case 451: return "GEO_DENIED";
|
|
23
25
|
case 503: return "UNAVAILABLE";
|
|
24
26
|
default: return "INTERNAL";
|
|
25
27
|
}
|
|
@@ -215,19 +217,21 @@ function y(e) {
|
|
|
215
217
|
return e.waitForLive ? de(t, e.waitForLive, e.signal) : t();
|
|
216
218
|
}
|
|
217
219
|
async function fe(e) {
|
|
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;
|
|
220
|
+
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, c;
|
|
219
221
|
try {
|
|
220
222
|
let t = await e.json();
|
|
221
223
|
if (t?.error?.message && (a = t.error.message), t?.error?.code && (o = t.error.code), typeof t?.liveStartsAt == "string") {
|
|
222
224
|
let e = Date.parse(t.liveStartsAt);
|
|
223
225
|
Number.isFinite(e) && (s = e);
|
|
224
226
|
}
|
|
227
|
+
e.status === 451 && typeof t?.country == "string" && /^[A-Z]{2}$/.test(t.country) && (c = t.country);
|
|
225
228
|
} catch {}
|
|
226
229
|
return new n(r(e.status), e.status, a, {
|
|
227
230
|
retryAfterMs: t,
|
|
228
231
|
requestId: i,
|
|
229
232
|
serverCode: o,
|
|
230
|
-
liveStartsAtMs: s
|
|
233
|
+
liveStartsAtMs: s,
|
|
234
|
+
country: c
|
|
231
235
|
});
|
|
232
236
|
}
|
|
233
237
|
var pe = /* @__PURE__ */ new Set([
|
|
@@ -287,35 +291,42 @@ function he(e, t) {
|
|
|
287
291
|
}
|
|
288
292
|
//#endregion
|
|
289
293
|
//#region src/core/fullscreen.ts
|
|
290
|
-
function
|
|
294
|
+
function x(e) {
|
|
291
295
|
return e.ownerDocument ?? document;
|
|
292
296
|
}
|
|
293
|
-
function
|
|
297
|
+
function ge(e) {
|
|
294
298
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
295
299
|
}
|
|
296
|
-
function
|
|
297
|
-
let n =
|
|
300
|
+
function S(e, t) {
|
|
301
|
+
let n = ge(x(e));
|
|
298
302
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
299
303
|
}
|
|
300
|
-
|
|
304
|
+
function C(e, t) {
|
|
305
|
+
let n = t ?? e, r = x(e);
|
|
306
|
+
if (typeof n.requestFullscreen == "function") return r.fullscreenEnabled !== !1;
|
|
307
|
+
if (typeof n.webkitRequestFullscreen == "function") return r.webkitFullscreenEnabled !== !1;
|
|
308
|
+
let i = e;
|
|
309
|
+
return i.webkitSupportsFullscreen === !0 && typeof i.webkitEnterFullscreen == "function" || e.readyState < 1;
|
|
310
|
+
}
|
|
311
|
+
async function w(e, t) {
|
|
301
312
|
let n = t ?? e;
|
|
302
313
|
if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
|
|
303
314
|
if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
|
|
304
315
|
let r = e;
|
|
305
316
|
return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
|
|
306
317
|
}
|
|
307
|
-
async function
|
|
318
|
+
async function T(e, t) {
|
|
308
319
|
let n = e;
|
|
309
320
|
if (n.webkitDisplayingFullscreen) {
|
|
310
321
|
n.webkitExitFullscreen?.();
|
|
311
322
|
return;
|
|
312
323
|
}
|
|
313
|
-
let r =
|
|
324
|
+
let r = x(e), i = ge(r);
|
|
314
325
|
i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
|
|
315
326
|
}
|
|
316
327
|
//#endregion
|
|
317
328
|
//#region src/core/catalog.ts
|
|
318
|
-
async function
|
|
329
|
+
async function _e(e) {
|
|
319
330
|
let t = new URLSearchParams();
|
|
320
331
|
e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
|
|
321
332
|
let i = t.toString(), a = d(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
|
|
@@ -333,12 +344,12 @@ async function ve(e) {
|
|
|
333
344
|
};
|
|
334
345
|
if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
|
|
335
346
|
return {
|
|
336
|
-
tournaments:
|
|
347
|
+
tournaments: ve(await s.json()),
|
|
337
348
|
etag: s.headers.get("etag") ?? void 0,
|
|
338
349
|
notModified: !1
|
|
339
350
|
};
|
|
340
351
|
}
|
|
341
|
-
function
|
|
352
|
+
function ve(e) {
|
|
342
353
|
return (e.tournaments ?? []).map((e) => {
|
|
343
354
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
344
355
|
return {
|
|
@@ -360,7 +371,7 @@ function ye(e) {
|
|
|
360
371
|
};
|
|
361
372
|
});
|
|
362
373
|
}
|
|
363
|
-
async function
|
|
374
|
+
async function ye(e) {
|
|
364
375
|
let t = d(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
365
376
|
e.etag && i.set("If-None-Match", e.etag);
|
|
366
377
|
let a = await p(t, {
|
|
@@ -380,13 +391,13 @@ async function be(e) {
|
|
|
380
391
|
};
|
|
381
392
|
if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
382
393
|
return {
|
|
383
|
-
tournament:
|
|
394
|
+
tournament: be(await a.json()),
|
|
384
395
|
etag: a.headers.get("etag") ?? void 0,
|
|
385
396
|
notModified: !1,
|
|
386
397
|
notFound: !1
|
|
387
398
|
};
|
|
388
399
|
}
|
|
389
|
-
function
|
|
400
|
+
function be(e) {
|
|
390
401
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
391
402
|
return {
|
|
392
403
|
urn: t,
|
|
@@ -406,17 +417,18 @@ function xe(e) {
|
|
|
406
417
|
}))
|
|
407
418
|
};
|
|
408
419
|
}
|
|
409
|
-
function
|
|
420
|
+
function xe(e) {
|
|
410
421
|
return e.tournaments.flatMap((e) => e.matches);
|
|
411
422
|
}
|
|
412
423
|
//#endregion
|
|
413
424
|
//#region src/core/poll.ts
|
|
414
|
-
var
|
|
425
|
+
var Se = /* @__PURE__ */ new Set([
|
|
415
426
|
"NOT_FOUND",
|
|
427
|
+
"GEO_DENIED",
|
|
416
428
|
"GONE",
|
|
417
429
|
"INVALID_URN"
|
|
418
430
|
]);
|
|
419
|
-
function
|
|
431
|
+
function Ce(e) {
|
|
420
432
|
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
|
|
421
433
|
u || (a = setTimeout(m, t));
|
|
422
434
|
}, m = async () => {
|
|
@@ -449,7 +461,7 @@ function we(e) {
|
|
|
449
461
|
} catch (t) {
|
|
450
462
|
if (!i.signal.aborted) {
|
|
451
463
|
let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
|
|
452
|
-
|
|
464
|
+
Se.has(r.code) && (u = !0), e.onError?.(r);
|
|
453
465
|
}
|
|
454
466
|
} finally {
|
|
455
467
|
f();
|
|
@@ -461,9 +473,9 @@ function we(e) {
|
|
|
461
473
|
}
|
|
462
474
|
//#endregion
|
|
463
475
|
//#region src/core/events.ts
|
|
464
|
-
var
|
|
465
|
-
function
|
|
466
|
-
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ??
|
|
476
|
+
var we = 45e3;
|
|
477
|
+
function E(e) {
|
|
478
|
+
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) => {
|
|
467
479
|
if (a.signal.aborted) return t();
|
|
468
480
|
let n = setTimeout(t, e);
|
|
469
481
|
a.signal.addEventListener("abort", () => {
|
|
@@ -545,7 +557,7 @@ function w(e) {
|
|
|
545
557
|
o || (o = !0, a.abort());
|
|
546
558
|
} };
|
|
547
559
|
}
|
|
548
|
-
function
|
|
560
|
+
function D(e) {
|
|
549
561
|
try {
|
|
550
562
|
let t = new URL(e);
|
|
551
563
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -555,27 +567,27 @@ function T(e) {
|
|
|
555
567
|
}
|
|
556
568
|
//#endregion
|
|
557
569
|
//#region src/core/drm/deviceId.ts
|
|
558
|
-
var
|
|
559
|
-
function
|
|
560
|
-
if (
|
|
570
|
+
var O = "havik.player.deviceId", k;
|
|
571
|
+
function A() {
|
|
572
|
+
if (k) return k;
|
|
561
573
|
try {
|
|
562
|
-
let e = globalThis.localStorage?.getItem(
|
|
563
|
-
if (e) return
|
|
574
|
+
let e = globalThis.localStorage?.getItem(O);
|
|
575
|
+
if (e) return k = e, e;
|
|
564
576
|
} catch {}
|
|
565
|
-
let e =
|
|
566
|
-
|
|
577
|
+
let e = Ee();
|
|
578
|
+
k = e;
|
|
567
579
|
try {
|
|
568
|
-
globalThis.localStorage?.setItem(
|
|
580
|
+
globalThis.localStorage?.setItem(O, e);
|
|
569
581
|
} catch {}
|
|
570
582
|
return e;
|
|
571
583
|
}
|
|
572
|
-
function
|
|
573
|
-
|
|
584
|
+
function Te() {
|
|
585
|
+
k = void 0;
|
|
574
586
|
try {
|
|
575
|
-
globalThis.localStorage?.removeItem(
|
|
587
|
+
globalThis.localStorage?.removeItem(O);
|
|
576
588
|
} catch {}
|
|
577
589
|
}
|
|
578
|
-
function
|
|
590
|
+
function Ee() {
|
|
579
591
|
let e = globalThis.crypto;
|
|
580
592
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
581
593
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -587,32 +599,32 @@ function De() {
|
|
|
587
599
|
}
|
|
588
600
|
//#endregion
|
|
589
601
|
//#region src/core/drm/headers.ts
|
|
590
|
-
function
|
|
602
|
+
function De(e, t, n = {}) {
|
|
591
603
|
let r = {
|
|
592
604
|
"x-api-key": t.apiKey,
|
|
593
605
|
"X-Match-Urn": e.matchUrn,
|
|
594
|
-
"X-Device-Id": n.deviceId ??
|
|
606
|
+
"X-Device-Id": n.deviceId ?? A(),
|
|
595
607
|
"Content-Type": "application/octet-stream"
|
|
596
608
|
};
|
|
597
609
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
598
610
|
}
|
|
599
611
|
//#endregion
|
|
600
612
|
//#region src/core/bandwidthMemory.ts
|
|
601
|
-
var
|
|
602
|
-
function
|
|
613
|
+
var j = "havik.player.bandwidth", Oe = .8, ke = 2e7, Ae = 3e5;
|
|
614
|
+
function je() {
|
|
603
615
|
return globalThis.navigator?.connection;
|
|
604
616
|
}
|
|
605
|
-
function
|
|
606
|
-
let e =
|
|
617
|
+
function Me() {
|
|
618
|
+
let e = je()?.type;
|
|
607
619
|
return typeof e == "string" && e !== "" && e !== "unknown" ? e : "any";
|
|
608
620
|
}
|
|
609
|
-
function
|
|
610
|
-
let e =
|
|
621
|
+
function Ne() {
|
|
622
|
+
let e = je()?.downlink;
|
|
611
623
|
return typeof e == "number" && Number.isFinite(e) && e > 0 ? e * 1e6 : void 0;
|
|
612
624
|
}
|
|
613
|
-
function
|
|
625
|
+
function Pe() {
|
|
614
626
|
try {
|
|
615
|
-
let e = globalThis.localStorage?.getItem(
|
|
627
|
+
let e = globalThis.localStorage?.getItem(j);
|
|
616
628
|
if (!e) return {};
|
|
617
629
|
let t = JSON.parse(e);
|
|
618
630
|
return t && typeof t == "object" && !Array.isArray(t) ? t : {};
|
|
@@ -620,36 +632,36 @@ function Fe() {
|
|
|
620
632
|
return {};
|
|
621
633
|
}
|
|
622
634
|
}
|
|
623
|
-
function
|
|
624
|
-
let t =
|
|
635
|
+
function Fe(e = Date.now()) {
|
|
636
|
+
let t = Pe()[Me()];
|
|
625
637
|
if (!t || typeof t.bps != "number" || typeof t.at != "number" || !Number.isFinite(t.bps) || t.bps <= 0) return;
|
|
626
638
|
let n = e - t.at;
|
|
627
639
|
if (n < 0 || n > 2592e5) return;
|
|
628
|
-
let r =
|
|
629
|
-
return Math.round(Math.min(
|
|
640
|
+
let r = Ne(), i = r === void 0 ? t.bps : Math.min(t.bps, r);
|
|
641
|
+
return Math.round(Math.min(ke, Math.max(Ae, i * Oe)));
|
|
630
642
|
}
|
|
631
|
-
function
|
|
643
|
+
function Ie(e, t = Date.now()) {
|
|
632
644
|
if (!Number.isFinite(e) || e <= 0) return;
|
|
633
|
-
let n =
|
|
634
|
-
n[
|
|
645
|
+
let n = Pe();
|
|
646
|
+
n[Me()] = {
|
|
635
647
|
bps: Math.round(e),
|
|
636
648
|
at: t
|
|
637
649
|
};
|
|
638
650
|
try {
|
|
639
|
-
globalThis.localStorage?.setItem(
|
|
651
|
+
globalThis.localStorage?.setItem(j, JSON.stringify(n));
|
|
640
652
|
} catch {}
|
|
641
653
|
}
|
|
642
|
-
function
|
|
654
|
+
function Le() {
|
|
643
655
|
try {
|
|
644
|
-
globalThis.localStorage?.removeItem(
|
|
656
|
+
globalThis.localStorage?.removeItem(j);
|
|
645
657
|
} catch {}
|
|
646
658
|
}
|
|
647
659
|
//#endregion
|
|
648
660
|
//#region src/core/drm/cdm.ts
|
|
649
|
-
var
|
|
650
|
-
function
|
|
651
|
-
let n =
|
|
652
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
661
|
+
var Re = /* @__PURE__ */ new WeakMap();
|
|
662
|
+
function ze(e, t) {
|
|
663
|
+
let n = Re.get(e);
|
|
664
|
+
n || (n = /* @__PURE__ */ new Map(), Re.set(e, n));
|
|
653
665
|
let r = n.get(t.keySystem);
|
|
654
666
|
if (r) return r;
|
|
655
667
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -657,22 +669,22 @@ function Be(e, t) {
|
|
|
657
669
|
});
|
|
658
670
|
return n.set(t.keySystem, i), i;
|
|
659
671
|
}
|
|
660
|
-
function
|
|
672
|
+
function M() {
|
|
661
673
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
662
674
|
}
|
|
663
|
-
var
|
|
664
|
-
function
|
|
675
|
+
var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
676
|
+
function Be(e) {
|
|
665
677
|
return e.startsWith("com.widevine");
|
|
666
678
|
}
|
|
667
|
-
function
|
|
668
|
-
if (!
|
|
679
|
+
function P(e, t) {
|
|
680
|
+
if (!Be(e)) return t;
|
|
669
681
|
let n = (e, t) => {
|
|
670
682
|
let n = e.videoCapabilities;
|
|
671
683
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
672
|
-
let n =
|
|
673
|
-
return n === -1 ||
|
|
684
|
+
let n = N.indexOf(e.robustness);
|
|
685
|
+
return n === -1 || N.indexOf(t) > n;
|
|
674
686
|
});
|
|
675
|
-
}, r =
|
|
687
|
+
}, r = N.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
676
688
|
...t,
|
|
677
689
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
678
690
|
...t,
|
|
@@ -681,53 +693,53 @@ function M(e, t) {
|
|
|
681
693
|
})));
|
|
682
694
|
return [...t, ...r];
|
|
683
695
|
}
|
|
684
|
-
function
|
|
685
|
-
return (t, n) =>
|
|
696
|
+
function Ve(e) {
|
|
697
|
+
return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, P(t, n)).then((t) => ({
|
|
686
698
|
keySystem: t.keySystem,
|
|
687
699
|
getConfiguration: () => t.getConfiguration(),
|
|
688
|
-
createMediaKeys: () =>
|
|
700
|
+
createMediaKeys: () => ze(e, t)
|
|
689
701
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
690
702
|
}
|
|
691
|
-
var
|
|
703
|
+
var F = {
|
|
692
704
|
video: "SW_SECURE_DECODE",
|
|
693
705
|
audio: "SW_SECURE_CRYPTO",
|
|
694
706
|
scheme: "cbcs"
|
|
695
707
|
};
|
|
696
|
-
function
|
|
697
|
-
if (!
|
|
708
|
+
function He(e) {
|
|
709
|
+
if (!M()) return;
|
|
698
710
|
let t = (e, t) => ({
|
|
699
711
|
contentType: e,
|
|
700
712
|
robustness: t,
|
|
701
|
-
encryptionScheme:
|
|
713
|
+
encryptionScheme: F.scheme
|
|
702
714
|
});
|
|
703
|
-
|
|
715
|
+
Ve(e)("com.widevine.alpha", [{
|
|
704
716
|
initDataTypes: ["cenc"],
|
|
705
717
|
distinctiveIdentifier: "optional",
|
|
706
718
|
persistentState: "optional",
|
|
707
719
|
sessionTypes: ["temporary"],
|
|
708
|
-
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"",
|
|
709
|
-
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"",
|
|
720
|
+
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", F.audio)],
|
|
721
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", F.video)]
|
|
710
722
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
711
723
|
}
|
|
712
|
-
function
|
|
713
|
-
let t =
|
|
724
|
+
function I(e) {
|
|
725
|
+
let t = L(e);
|
|
714
726
|
if (/^avc[13]/.test(t)) return "avc";
|
|
715
727
|
if (/^(hvc1|hev1)/.test(t)) return "hevc";
|
|
716
728
|
if (/^(dvh1|dvhe)/.test(t)) return "dv";
|
|
717
729
|
if (t.startsWith("av01")) return "av1";
|
|
718
730
|
if (/^vp0?9/.test(t)) return "vp9";
|
|
719
731
|
}
|
|
720
|
-
function
|
|
732
|
+
function L(e) {
|
|
721
733
|
return (e ?? "").trim().toLowerCase();
|
|
722
734
|
}
|
|
723
|
-
var
|
|
735
|
+
var Ue = {
|
|
724
736
|
hevc: "hvc1.1.6.L93.90",
|
|
725
737
|
dv: "dvh1.05.06",
|
|
726
738
|
av1: "av01.0.05M.08",
|
|
727
739
|
vp9: "vp09.00.10.08"
|
|
728
|
-
},
|
|
729
|
-
function
|
|
730
|
-
let t =
|
|
740
|
+
}, We = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
|
|
741
|
+
function Ge(e) {
|
|
742
|
+
let t = L(e), n = We.get(t);
|
|
731
743
|
if (n) return n;
|
|
732
744
|
let r = {
|
|
733
745
|
initDataTypes: ["cenc"],
|
|
@@ -736,32 +748,32 @@ function Ke(e) {
|
|
|
736
748
|
sessionTypes: ["temporary"],
|
|
737
749
|
videoCapabilities: [{
|
|
738
750
|
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
739
|
-
robustness:
|
|
740
|
-
encryptionScheme:
|
|
751
|
+
robustness: F.video,
|
|
752
|
+
encryptionScheme: F.scheme
|
|
741
753
|
}]
|
|
742
754
|
}, i = (async () => {
|
|
743
755
|
try {
|
|
744
|
-
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha",
|
|
756
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", P("com.widevine.alpha", [r])), !0;
|
|
745
757
|
} catch {
|
|
746
758
|
return !1;
|
|
747
759
|
}
|
|
748
|
-
})().then((e) => (
|
|
749
|
-
return
|
|
760
|
+
})().then((e) => (R.set(t, e), e));
|
|
761
|
+
return We.set(t, i), i;
|
|
750
762
|
}
|
|
751
|
-
function
|
|
752
|
-
if (
|
|
763
|
+
function Ke() {
|
|
764
|
+
if (M()) for (let e of Object.values(Ue)) Ge(e);
|
|
753
765
|
}
|
|
754
|
-
function
|
|
755
|
-
let t =
|
|
756
|
-
if (t) return t === "avc" ? !0 :
|
|
766
|
+
function qe(e) {
|
|
767
|
+
let t = I(e);
|
|
768
|
+
if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(Ue[t]));
|
|
757
769
|
}
|
|
758
770
|
//#endregion
|
|
759
771
|
//#region src/core/drm/support.ts
|
|
760
|
-
var
|
|
772
|
+
var Je = 5e3, Ye = "video/mp4; codecs=\"avc1.42E01E\"", Xe = "audio/mp4; codecs=\"mp4a.40.2\"", Ze = {
|
|
761
773
|
widevine: ["com.widevine.alpha"],
|
|
762
774
|
fairplay: ["com.apple.fps"]
|
|
763
775
|
};
|
|
764
|
-
function
|
|
776
|
+
function Qe(e) {
|
|
765
777
|
return e === "fairplay" ? [{
|
|
766
778
|
initDataTypes: [
|
|
767
779
|
"sinf",
|
|
@@ -769,30 +781,30 @@ function $e(e) {
|
|
|
769
781
|
"cenc"
|
|
770
782
|
],
|
|
771
783
|
videoCapabilities: [{
|
|
772
|
-
contentType:
|
|
784
|
+
contentType: Ye,
|
|
773
785
|
robustness: "",
|
|
774
786
|
encryptionScheme: "cbcs"
|
|
775
787
|
}],
|
|
776
788
|
audioCapabilities: [{
|
|
777
|
-
contentType:
|
|
789
|
+
contentType: Xe,
|
|
778
790
|
robustness: "",
|
|
779
791
|
encryptionScheme: "cbcs"
|
|
780
792
|
}]
|
|
781
|
-
}] :
|
|
793
|
+
}] : P("com.widevine.alpha", [{
|
|
782
794
|
initDataTypes: ["cenc"],
|
|
783
795
|
videoCapabilities: [{
|
|
784
|
-
contentType:
|
|
785
|
-
robustness:
|
|
786
|
-
encryptionScheme:
|
|
796
|
+
contentType: Ye,
|
|
797
|
+
robustness: F.video,
|
|
798
|
+
encryptionScheme: F.scheme
|
|
787
799
|
}],
|
|
788
800
|
audioCapabilities: [{
|
|
789
|
-
contentType:
|
|
790
|
-
robustness:
|
|
791
|
-
encryptionScheme:
|
|
801
|
+
contentType: Xe,
|
|
802
|
+
robustness: F.audio,
|
|
803
|
+
encryptionScheme: F.scheme
|
|
792
804
|
}]
|
|
793
805
|
}]);
|
|
794
806
|
}
|
|
795
|
-
function
|
|
807
|
+
function $e(e, t) {
|
|
796
808
|
return new Promise((n, r) => {
|
|
797
809
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
798
810
|
e.then((e) => {
|
|
@@ -802,8 +814,8 @@ function et(e, t) {
|
|
|
802
814
|
});
|
|
803
815
|
});
|
|
804
816
|
}
|
|
805
|
-
async function
|
|
806
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
817
|
+
async function et(e = {}) {
|
|
818
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Je, r = {};
|
|
807
819
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
808
820
|
verdict: "insecure-context",
|
|
809
821
|
detail: r
|
|
@@ -815,7 +827,7 @@ async function tt(e = {}) {
|
|
|
815
827
|
};
|
|
816
828
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
817
829
|
for (let e of t) {
|
|
818
|
-
let t =
|
|
830
|
+
let t = Ze[e];
|
|
819
831
|
if (!t) {
|
|
820
832
|
r[e] = "unknown system";
|
|
821
833
|
continue;
|
|
@@ -826,7 +838,7 @@ async function tt(e = {}) {
|
|
|
826
838
|
break;
|
|
827
839
|
}
|
|
828
840
|
try {
|
|
829
|
-
return await
|
|
841
|
+
return await $e((await $e(i(n, Qe(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
830
842
|
verdict: "supported",
|
|
831
843
|
system: e,
|
|
832
844
|
detail: r
|
|
@@ -850,37 +862,37 @@ async function tt(e = {}) {
|
|
|
850
862
|
}
|
|
851
863
|
//#endregion
|
|
852
864
|
//#region src/core/manifest.ts
|
|
853
|
-
var
|
|
854
|
-
function
|
|
855
|
-
return
|
|
865
|
+
var tt = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
866
|
+
function nt(e) {
|
|
867
|
+
return tt.test(e);
|
|
856
868
|
}
|
|
857
869
|
//#endregion
|
|
858
870
|
//#region src/core/env.ts
|
|
859
|
-
var
|
|
871
|
+
var rt = {
|
|
860
872
|
integration: "https://feed-dev.oddin-video.gg",
|
|
861
873
|
production: "https://feed.oddin-video.gg"
|
|
862
874
|
};
|
|
863
|
-
function
|
|
864
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
875
|
+
function it(e) {
|
|
876
|
+
let t = Object.prototype.hasOwnProperty.call(rt, e) ? rt[e] : void 0;
|
|
865
877
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
866
878
|
return t;
|
|
867
879
|
}
|
|
868
880
|
//#endregion
|
|
869
881
|
//#region src/core/stats.ts
|
|
870
|
-
var
|
|
871
|
-
function
|
|
882
|
+
var z = { droppedFrames: 0 };
|
|
883
|
+
function at(e) {
|
|
872
884
|
try {
|
|
873
885
|
return new URL(e).host;
|
|
874
886
|
} catch {
|
|
875
887
|
return "";
|
|
876
888
|
}
|
|
877
889
|
}
|
|
878
|
-
var
|
|
879
|
-
function
|
|
890
|
+
var ot = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
891
|
+
function st(e) {
|
|
880
892
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
881
893
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
882
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
883
|
-
let e =
|
|
894
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || ot.test(i.name)) && i.startTime >= n) {
|
|
895
|
+
let e = at(i.name);
|
|
884
896
|
e && (t = e, n = i.startTime);
|
|
885
897
|
}
|
|
886
898
|
return t;
|
|
@@ -892,7 +904,7 @@ function B(e) {
|
|
|
892
904
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
893
905
|
};
|
|
894
906
|
}
|
|
895
|
-
var
|
|
907
|
+
var ct = class {
|
|
896
908
|
video;
|
|
897
909
|
baseFrames = 0;
|
|
898
910
|
baseDropped = 0;
|
|
@@ -915,7 +927,7 @@ var st = class {
|
|
|
915
927
|
};
|
|
916
928
|
}
|
|
917
929
|
};
|
|
918
|
-
function
|
|
930
|
+
function lt(e, t) {
|
|
919
931
|
let n = [
|
|
920
932
|
["playing", () => t("playing")],
|
|
921
933
|
["waiting", () => t("buffering")],
|
|
@@ -932,8 +944,8 @@ function ct(e, t) {
|
|
|
932
944
|
}
|
|
933
945
|
//#endregion
|
|
934
946
|
//#region src/core/engine/native.ts
|
|
935
|
-
var
|
|
936
|
-
function
|
|
947
|
+
var ut = 2e3, dt = 3, V = 500, ft = 6e3, pt = .25, mt = 250, ht = .05, gt = 4, _t = 12e3, vt = .25, yt = 1e3;
|
|
948
|
+
function bt(e) {
|
|
937
949
|
try {
|
|
938
950
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
939
951
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -949,7 +961,7 @@ function U() {
|
|
|
949
961
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
950
962
|
return e || t;
|
|
951
963
|
}
|
|
952
|
-
function
|
|
964
|
+
function xt() {
|
|
953
965
|
if (typeof navigator > "u" || !U()) return !1;
|
|
954
966
|
let e = navigator.userAgent ?? "";
|
|
955
967
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
@@ -984,7 +996,7 @@ var W = class {
|
|
|
984
996
|
frameCounter;
|
|
985
997
|
detachFrames = null;
|
|
986
998
|
constructor(e) {
|
|
987
|
-
this.deps = e, this.frameCounter = new
|
|
999
|
+
this.deps = e, this.frameCounter = new ct(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
|
|
988
1000
|
}
|
|
989
1001
|
async load() {
|
|
990
1002
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1005,7 +1017,7 @@ var W = class {
|
|
|
1005
1017
|
type: "error",
|
|
1006
1018
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
1007
1019
|
fatal: !0
|
|
1008
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
1020
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Ct(t.manifestUrl, t.analytics?.sid), e.load();
|
|
1009
1021
|
}
|
|
1010
1022
|
startLoad() {
|
|
1011
1023
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -1027,7 +1039,7 @@ var W = class {
|
|
|
1027
1039
|
});
|
|
1028
1040
|
this.onEncrypted = (n) => {
|
|
1029
1041
|
let i = n;
|
|
1030
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
1042
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = bt(i.initData), (async () => {
|
|
1031
1043
|
try {
|
|
1032
1044
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
1033
1045
|
initDataTypes: [i.initDataType],
|
|
@@ -1126,10 +1138,10 @@ var W = class {
|
|
|
1126
1138
|
droppedFrames: t.dropped,
|
|
1127
1139
|
decodedFrames: t.totalFrames
|
|
1128
1140
|
};
|
|
1129
|
-
if (this.cdnHost ||=
|
|
1141
|
+
if (this.cdnHost ||= st(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1130
1142
|
n.isLive = !0;
|
|
1131
1143
|
let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
|
|
1132
|
-
Number.isFinite(r) && (n.atLiveEdge = r <=
|
|
1144
|
+
Number.isFinite(r) && (n.atLiveEdge = r <= gt, !e.paused && r >= 0 && (n.latencySeconds = r));
|
|
1133
1145
|
} else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
|
|
1134
1146
|
return n;
|
|
1135
1147
|
}
|
|
@@ -1147,7 +1159,7 @@ var W = class {
|
|
|
1147
1159
|
return;
|
|
1148
1160
|
}
|
|
1149
1161
|
let t = this.hiddenSince;
|
|
1150
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1162
|
+
this.hiddenSince = null, t != null && e - t >= ut && this.armRefocus();
|
|
1151
1163
|
}, this.onPageShow = (e) => {
|
|
1152
1164
|
e.persisted && this.armRefocus();
|
|
1153
1165
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
@@ -1157,7 +1169,7 @@ var W = class {
|
|
|
1157
1169
|
let e = this.liveEnd(), t = G, n = t(), r = 0, i = () => {
|
|
1158
1170
|
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1159
1171
|
r += V;
|
|
1160
|
-
let a = this.liveEnd(), o = a != null && (e == null || a >= e +
|
|
1172
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + pt), s = Math.max(r, t() - n) >= ft;
|
|
1161
1173
|
if (o || s && a != null) {
|
|
1162
1174
|
this.snapToLive();
|
|
1163
1175
|
return;
|
|
@@ -1177,9 +1189,9 @@ var W = class {
|
|
|
1177
1189
|
}, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
|
|
1178
1190
|
if (e.duration !== Infinity) return;
|
|
1179
1191
|
this.checkEndStale();
|
|
1180
|
-
let t =
|
|
1181
|
-
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >=
|
|
1182
|
-
},
|
|
1192
|
+
let t = St(e, e.currentTime);
|
|
1193
|
+
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= ht) && (this.bufferedAdvancedAt = G()), this.lastBufferedEnd = t);
|
|
1194
|
+
}, mt);
|
|
1183
1195
|
}
|
|
1184
1196
|
checkEndStale() {
|
|
1185
1197
|
if (this.endedEmitted) return;
|
|
@@ -1187,14 +1199,14 @@ var W = class {
|
|
|
1187
1199
|
this.lastTickAt = e;
|
|
1188
1200
|
let n = this.liveEnd();
|
|
1189
1201
|
if (n == null) return;
|
|
1190
|
-
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >=
|
|
1202
|
+
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= vt;
|
|
1191
1203
|
this.lastSeekableEnd = n;
|
|
1192
1204
|
let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
|
|
1193
|
-
if (r || t >
|
|
1205
|
+
if (r || t > yt || a || i.paused) {
|
|
1194
1206
|
this.edgeStampedAt = e;
|
|
1195
1207
|
return;
|
|
1196
1208
|
}
|
|
1197
|
-
e - (this.edgeStampedAt ?? e) >
|
|
1209
|
+
e - (this.edgeStampedAt ?? e) > _t && (this.endedEmitted = !0, this.deps.emit({
|
|
1198
1210
|
type: "ended",
|
|
1199
1211
|
reason: "stalled"
|
|
1200
1212
|
}));
|
|
@@ -1208,7 +1220,7 @@ var W = class {
|
|
|
1208
1220
|
liveEdgeEstimate() {
|
|
1209
1221
|
let e = this.deps.video;
|
|
1210
1222
|
if (e.duration !== Infinity) return null;
|
|
1211
|
-
let t = this.liveEnd(), n =
|
|
1223
|
+
let t = this.liveEnd(), n = St(e, e.currentTime) ?? this.lastBufferedEnd;
|
|
1212
1224
|
if (n != null) {
|
|
1213
1225
|
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (G() - e) / 1e3));
|
|
1214
1226
|
(t == null || r > t) && (t = r);
|
|
@@ -1224,7 +1236,7 @@ var W = class {
|
|
|
1224
1236
|
snapToLive() {
|
|
1225
1237
|
let e = this.deps.video, t = this.liveEnd();
|
|
1226
1238
|
if (t == null) return;
|
|
1227
|
-
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t -
|
|
1239
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - dt, r);
|
|
1228
1240
|
try {
|
|
1229
1241
|
e.currentTime = i;
|
|
1230
1242
|
} catch {}
|
|
@@ -1245,7 +1257,7 @@ var W = class {
|
|
|
1245
1257
|
function G() {
|
|
1246
1258
|
return typeof performance < "u" ? performance.now() : Date.now();
|
|
1247
1259
|
}
|
|
1248
|
-
function
|
|
1260
|
+
function St(e, t) {
|
|
1249
1261
|
let n = e.buffered;
|
|
1250
1262
|
if (!n || !Number.isFinite(t)) return null;
|
|
1251
1263
|
for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
|
|
@@ -1254,7 +1266,7 @@ function xt(e, t) {
|
|
|
1254
1266
|
}
|
|
1255
1267
|
return null;
|
|
1256
1268
|
}
|
|
1257
|
-
function
|
|
1269
|
+
function Ct(e, t) {
|
|
1258
1270
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1259
1271
|
}
|
|
1260
1272
|
//#endregion
|
|
@@ -1271,8 +1283,8 @@ function K(e, t = Date.now()) {
|
|
|
1271
1283
|
}
|
|
1272
1284
|
//#endregion
|
|
1273
1285
|
//#region src/core/engine/prefetch.ts
|
|
1274
|
-
var
|
|
1275
|
-
function
|
|
1286
|
+
var wt = 15e3, Tt = 5e3, Et = 6;
|
|
1287
|
+
function Dt(e) {
|
|
1276
1288
|
try {
|
|
1277
1289
|
let t = new URL(e);
|
|
1278
1290
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1280,7 +1292,7 @@ function Et(e) {
|
|
|
1280
1292
|
return e;
|
|
1281
1293
|
}
|
|
1282
1294
|
}
|
|
1283
|
-
var
|
|
1295
|
+
var Ot = class {
|
|
1284
1296
|
cmcd;
|
|
1285
1297
|
entries = /* @__PURE__ */ new Map();
|
|
1286
1298
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1303,10 +1315,10 @@ var Dt = class {
|
|
|
1303
1315
|
}
|
|
1304
1316
|
prefetch(e, t, n) {
|
|
1305
1317
|
if (!this.isActive(t)) return;
|
|
1306
|
-
let r =
|
|
1318
|
+
let r = Dt(e);
|
|
1307
1319
|
if (this.entries.has(r)) return;
|
|
1308
1320
|
let i = this.perTrack.get(t) ?? 0;
|
|
1309
|
-
if (i >=
|
|
1321
|
+
if (i >= Et) return;
|
|
1310
1322
|
this.perTrack.set(t, i + 1);
|
|
1311
1323
|
let a = new AbortController(), o = {
|
|
1312
1324
|
started: performance.now(),
|
|
@@ -1320,10 +1332,10 @@ var Dt = class {
|
|
|
1320
1332
|
signal: a.signal
|
|
1321
1333
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1322
1334
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1323
|
-
},
|
|
1335
|
+
}, wt);
|
|
1324
1336
|
}
|
|
1325
1337
|
take(e) {
|
|
1326
|
-
let t =
|
|
1338
|
+
let t = Dt(e), n = this.entries.get(t);
|
|
1327
1339
|
return n && this.entries.delete(t), n;
|
|
1328
1340
|
}
|
|
1329
1341
|
destroy() {
|
|
@@ -1343,13 +1355,13 @@ var Dt = class {
|
|
|
1343
1355
|
}
|
|
1344
1356
|
}
|
|
1345
1357
|
};
|
|
1346
|
-
function
|
|
1358
|
+
function kt(t) {
|
|
1347
1359
|
let n = e.DefaultConfig?.loader;
|
|
1348
1360
|
if (typeof n != "function") return;
|
|
1349
1361
|
class r extends n {
|
|
1350
1362
|
served = !1;
|
|
1351
1363
|
cancelled = !1;
|
|
1352
|
-
stats =
|
|
1364
|
+
stats = At();
|
|
1353
1365
|
load(e, n, r) {
|
|
1354
1366
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1355
1367
|
if (!i) {
|
|
@@ -1357,7 +1369,7 @@ function Ot(t) {
|
|
|
1357
1369
|
return;
|
|
1358
1370
|
}
|
|
1359
1371
|
this.served = !0;
|
|
1360
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1372
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Tt, s = setTimeout(() => {
|
|
1361
1373
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1362
1374
|
}, o);
|
|
1363
1375
|
i.bytes.then((o) => {
|
|
@@ -1384,7 +1396,7 @@ function Ot(t) {
|
|
|
1384
1396
|
}
|
|
1385
1397
|
return r;
|
|
1386
1398
|
}
|
|
1387
|
-
function
|
|
1399
|
+
function At() {
|
|
1388
1400
|
return {
|
|
1389
1401
|
aborted: !1,
|
|
1390
1402
|
loaded: 0,
|
|
@@ -1408,10 +1420,10 @@ function kt() {
|
|
|
1408
1420
|
}
|
|
1409
1421
|
};
|
|
1410
1422
|
}
|
|
1411
|
-
function
|
|
1423
|
+
function jt(e) {
|
|
1412
1424
|
return e === "audio" ? "audio" : "main";
|
|
1413
1425
|
}
|
|
1414
|
-
function
|
|
1426
|
+
function Mt(e, t) {
|
|
1415
1427
|
let n = [];
|
|
1416
1428
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1417
1429
|
url: t.initSegment.url,
|
|
@@ -1430,24 +1442,24 @@ function jt(e, t) {
|
|
|
1430
1442
|
}
|
|
1431
1443
|
//#endregion
|
|
1432
1444
|
//#region src/core/engine/hls.ts
|
|
1433
|
-
function
|
|
1445
|
+
function Nt() {
|
|
1434
1446
|
return e.isSupported();
|
|
1435
1447
|
}
|
|
1436
|
-
var
|
|
1437
|
-
function
|
|
1448
|
+
var Pt = 1e6, Ft = 20, It = 1e4, Lt = 3, Rt = 5, zt = 3, Bt = 1e4, Vt = 3e4, Ht = 12e3, Ut = 3e3, Wt = .02, Gt = 6e3, Kt = .5, qt = 3, Jt = .5, Yt = 1.1, Xt = .25, Zt = 5e3, Qt = 4e3, $t = 2, en = 5, tn = 2, nn = 2, rn = 4, an = 4, on = 2e3, sn = 3e4, cn = .2, ln = 30, un = 2, dn = 2, fn = 9, pn = .5, mn = 64;
|
|
1449
|
+
function hn(e) {
|
|
1438
1450
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1439
1451
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1440
1452
|
return;
|
|
1441
1453
|
}
|
|
1442
|
-
e.liveSyncDuration ??=
|
|
1443
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1444
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1454
|
+
e.liveSyncDuration ??= dn;
|
|
1455
|
+
let t = Math.max(12, e.liveSyncDuration + fn);
|
|
1456
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), gn(e, e.liveSyncDuration);
|
|
1445
1457
|
}
|
|
1446
|
-
function
|
|
1458
|
+
function gn(e, t) {
|
|
1447
1459
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1448
1460
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1449
1461
|
}
|
|
1450
|
-
var
|
|
1462
|
+
var _n = class {
|
|
1451
1463
|
name = "hls";
|
|
1452
1464
|
hls = null;
|
|
1453
1465
|
deps;
|
|
@@ -1531,7 +1543,7 @@ var gn = class {
|
|
|
1531
1543
|
frameCounter;
|
|
1532
1544
|
detachFrames = null;
|
|
1533
1545
|
constructor(e) {
|
|
1534
|
-
this.deps = e, this.frameCounter = new
|
|
1546
|
+
this.deps = e, this.frameCounter = new ct(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1535
1547
|
}
|
|
1536
1548
|
async load() {
|
|
1537
1549
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1544,7 +1556,7 @@ var gn = class {
|
|
|
1544
1556
|
});
|
|
1545
1557
|
return;
|
|
1546
1558
|
}
|
|
1547
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1559
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (He(r), Ke()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1548
1560
|
let e = this.hls;
|
|
1549
1561
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1550
1562
|
let t = e.liveSyncPosition;
|
|
@@ -1567,7 +1579,7 @@ var gn = class {
|
|
|
1567
1579
|
}
|
|
1568
1580
|
this.loadSuspended = !0;
|
|
1569
1581
|
}
|
|
1570
|
-
},
|
|
1582
|
+
}, Zt));
|
|
1571
1583
|
}
|
|
1572
1584
|
resumeLoading() {
|
|
1573
1585
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1599,7 +1611,7 @@ var gn = class {
|
|
|
1599
1611
|
let t = e.liveSyncPosition;
|
|
1600
1612
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1601
1613
|
let { video: n } = this.deps;
|
|
1602
|
-
n.currentTime <= t +
|
|
1614
|
+
n.currentTime <= t + pn || (n.currentTime = t);
|
|
1603
1615
|
}
|
|
1604
1616
|
reanchorPartTimeline(e, t) {
|
|
1605
1617
|
let { frag: n, part: r } = t;
|
|
@@ -1611,7 +1623,7 @@ var gn = class {
|
|
|
1611
1623
|
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1612
1624
|
if (!s) return;
|
|
1613
1625
|
let c = a.startPTS - s.start;
|
|
1614
|
-
if (!(!Number.isFinite(c) || Math.abs(c) <
|
|
1626
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < Wt)) {
|
|
1615
1627
|
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1616
1628
|
i.fragmentHint?.setStart(i.fragmentHint.start + c), this.deps.debug === !0 && console.info(`havik-player: LL-HLS timeline re-anchored by ${c >= 0 ? "+" : ""}${c.toFixed(3)}s at sn ${n.sn} (level ${n.level})`);
|
|
1617
1629
|
}
|
|
@@ -1634,12 +1646,12 @@ var gn = class {
|
|
|
1634
1646
|
emeEnabled: !0,
|
|
1635
1647
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1636
1648
|
drmSystemOptions: {
|
|
1637
|
-
videoRobustness:
|
|
1638
|
-
audioRobustness:
|
|
1639
|
-
videoEncryptionScheme:
|
|
1640
|
-
audioEncryptionScheme:
|
|
1649
|
+
videoRobustness: F.video,
|
|
1650
|
+
audioRobustness: F.audio,
|
|
1651
|
+
videoEncryptionScheme: F.scheme,
|
|
1652
|
+
audioEncryptionScheme: F.scheme
|
|
1641
1653
|
},
|
|
1642
|
-
...
|
|
1654
|
+
...M() ? { requestMediaKeySystemAccessFunc: Ve(t) } : {},
|
|
1643
1655
|
licenseXhrSetup: (e, t) => {
|
|
1644
1656
|
let o = performance.now(), s = () => {
|
|
1645
1657
|
e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a), this.licenseRequested = !0, e.addEventListener("loadend", () => {
|
|
@@ -1651,7 +1663,7 @@ var gn = class {
|
|
|
1651
1663
|
return;
|
|
1652
1664
|
}
|
|
1653
1665
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1654
|
-
u = setTimeout(() => e(void 0),
|
|
1666
|
+
u = setTimeout(() => e(void 0), Bt);
|
|
1655
1667
|
});
|
|
1656
1668
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1657
1669
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1667,20 +1679,20 @@ var gn = class {
|
|
|
1667
1679
|
...c
|
|
1668
1680
|
};
|
|
1669
1681
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !f.fLoader) {
|
|
1670
|
-
let e = new
|
|
1682
|
+
let e = new Ot({
|
|
1671
1683
|
sessionId: n.analytics?.sid,
|
|
1672
1684
|
contentId: n.matchUrn
|
|
1673
|
-
}), t =
|
|
1685
|
+
}), t = kt(e);
|
|
1674
1686
|
t && (this.prefetch = e, f.fLoader = t);
|
|
1675
1687
|
}
|
|
1676
|
-
|
|
1688
|
+
hn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
|
|
1677
1689
|
let p = new e(f);
|
|
1678
1690
|
if (this.hls = p, p.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(p, t)), p.on(e.Events.MANIFEST_PARSED, () => {
|
|
1679
1691
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(p), this.measureLadder(p), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1680
1692
|
}), p.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1681
1693
|
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(() => {
|
|
1682
1694
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1683
|
-
},
|
|
1695
|
+
}, Vt)));
|
|
1684
1696
|
}), p.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1685
1697
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1686
1698
|
}), p.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1688,10 +1700,10 @@ var gn = class {
|
|
|
1688
1700
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1689
1701
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1690
1702
|
let i = n?.loading;
|
|
1691
|
-
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 >
|
|
1703
|
+
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > mn && this.requestTimesMs.shift());
|
|
1692
1704
|
let a = t?.frag?.url;
|
|
1693
1705
|
if (a) {
|
|
1694
|
-
let e =
|
|
1706
|
+
let e = at(a);
|
|
1695
1707
|
e && (this.cdnHost = e);
|
|
1696
1708
|
}
|
|
1697
1709
|
}), p.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1705,15 +1717,15 @@ var gn = class {
|
|
|
1705
1717
|
}), p.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1706
1718
|
let t = this.prefetch;
|
|
1707
1719
|
p.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1708
|
-
let r = n?.frag, i =
|
|
1709
|
-
if (r && t.isActive(i)) for (let e of
|
|
1710
|
-
}), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1720
|
+
let r = n?.frag, i = jt(r?.type);
|
|
1721
|
+
if (r && t.isActive(i)) for (let e of Mt(p, r)) t.prefetch(e.url, i, e.kind);
|
|
1722
|
+
}), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(jt(n?.frag?.type)));
|
|
1711
1723
|
}
|
|
1712
1724
|
p.on(e.Events.KEY_LOADED, () => {
|
|
1713
1725
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1714
1726
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1715
1727
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1716
|
-
},
|
|
1728
|
+
}, Ut), p.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1717
1729
|
this.renditionSwitches += 1;
|
|
1718
1730
|
let n = this.lastLevelIndex >= 0 ? p.levels[this.lastLevelIndex] : void 0, r = p.levels[t.level];
|
|
1719
1731
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1777,7 +1789,7 @@ var gn = class {
|
|
|
1777
1789
|
return;
|
|
1778
1790
|
}
|
|
1779
1791
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1780
|
-
let t = e > this.sizeCapLevel ?
|
|
1792
|
+
let t = e > this.sizeCapLevel ? on : sn;
|
|
1781
1793
|
this.capTimer = setTimeout(() => {
|
|
1782
1794
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1783
1795
|
}, t);
|
|
@@ -1787,9 +1799,9 @@ var gn = class {
|
|
|
1787
1799
|
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;
|
|
1788
1800
|
}
|
|
1789
1801
|
dropLevelsWidevineCannotPlay(e) {
|
|
1790
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1791
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1792
|
-
for (let n of t)
|
|
1802
|
+
this.removeLevelsWhere(e, (e) => qe(e) !== !0);
|
|
1803
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
|
|
1804
|
+
for (let n of t) Ge(n).then((t) => {
|
|
1793
1805
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1794
1806
|
});
|
|
1795
1807
|
}
|
|
@@ -1797,10 +1809,10 @@ var gn = class {
|
|
|
1797
1809
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1798
1810
|
if (n.forEach((e, n) => {
|
|
1799
1811
|
let a = e.videoCodec;
|
|
1800
|
-
a &&
|
|
1812
|
+
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1801
1813
|
}), !r.length) return !1;
|
|
1802
1814
|
let a = [...i].join(", ");
|
|
1803
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !
|
|
1815
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || qe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1804
1816
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1805
1817
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1806
1818
|
}
|
|
@@ -1906,7 +1918,7 @@ var gn = class {
|
|
|
1906
1918
|
return;
|
|
1907
1919
|
}
|
|
1908
1920
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1909
|
-
!this.chaseSuspended && e >
|
|
1921
|
+
!this.chaseSuspended && e > Gt && this.suspendChasing(), e > Ht && this.emitEnded("stalled");
|
|
1910
1922
|
}
|
|
1911
1923
|
resetStarvationWindow() {
|
|
1912
1924
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1921,7 +1933,7 @@ var gn = class {
|
|
|
1921
1933
|
this.resetStarvationWindow();
|
|
1922
1934
|
return;
|
|
1923
1935
|
}
|
|
1924
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1936
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < Gt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Qt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
|
|
1925
1937
|
if (this.starvedFrames = c, !a || l) {
|
|
1926
1938
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1927
1939
|
return;
|
|
@@ -1930,12 +1942,12 @@ var gn = class {
|
|
|
1930
1942
|
this.resetStarvationWindow();
|
|
1931
1943
|
return;
|
|
1932
1944
|
}
|
|
1933
|
-
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 >
|
|
1945
|
+
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > rn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= tn && (this.clearKick(), this.starvationRebuilds < nn)) {
|
|
1934
1946
|
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");
|
|
1935
1947
|
return;
|
|
1936
1948
|
}
|
|
1937
|
-
let u = i && this.starvedTicks >=
|
|
1938
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1949
|
+
let u = i && this.starvedTicks >= $t, d = !i && this.deadTicks >= rn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= an;
|
|
1950
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= en))) {
|
|
1939
1951
|
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");
|
|
1940
1952
|
try {
|
|
1941
1953
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1950,7 +1962,7 @@ var gn = class {
|
|
|
1950
1962
|
let t = e.latency, n = e.targetLatency;
|
|
1951
1963
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1952
1964
|
let r = t - n;
|
|
1953
|
-
!this.catchUpEngaged && r >
|
|
1965
|
+
!this.catchUpEngaged && r > Kt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Kt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1954
1966
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1955
1967
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1956
1968
|
}
|
|
@@ -1972,15 +1984,15 @@ var gn = class {
|
|
|
1972
1984
|
return;
|
|
1973
1985
|
}
|
|
1974
1986
|
let { totalFrames: n, dropped: r } = B(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
1975
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
1987
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < ln || o < 0) {
|
|
1976
1988
|
this.fpsBadTicks = 0;
|
|
1977
1989
|
return;
|
|
1978
1990
|
}
|
|
1979
|
-
if (o <=
|
|
1991
|
+
if (o <= cn * a) {
|
|
1980
1992
|
this.fpsBadTicks = 0;
|
|
1981
1993
|
return;
|
|
1982
1994
|
}
|
|
1983
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
1995
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < un) return;
|
|
1984
1996
|
this.fpsBadTicks = 0;
|
|
1985
1997
|
let s = e.levels, c = s[e.currentLevel];
|
|
1986
1998
|
if (!c) return;
|
|
@@ -1997,20 +2009,20 @@ var gn = class {
|
|
|
1997
2009
|
return;
|
|
1998
2010
|
}
|
|
1999
2011
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
2000
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
2012
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Yt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
2001
2013
|
this.resetChaseWindow();
|
|
2002
2014
|
return;
|
|
2003
2015
|
}
|
|
2004
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
2016
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= Jt) {
|
|
2005
2017
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
2006
2018
|
return;
|
|
2007
2019
|
}
|
|
2008
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
2020
|
+
if (this.chaseTicks += 1, this.chaseTicks < qt) return;
|
|
2009
2021
|
this.resetChaseWindow();
|
|
2010
2022
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2011
2023
|
if (!(a > 1)) return;
|
|
2012
2024
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
2013
|
-
s < o +
|
|
2025
|
+
s < o + Xt || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s);
|
|
2014
2026
|
}
|
|
2015
2027
|
suspendChasing() {
|
|
2016
2028
|
let e = this.hls;
|
|
@@ -2040,14 +2052,14 @@ var gn = class {
|
|
|
2040
2052
|
} catch {}
|
|
2041
2053
|
}
|
|
2042
2054
|
startEstimate() {
|
|
2043
|
-
return this.deps.rememberBandwidth === !1 ?
|
|
2055
|
+
return this.deps.rememberBandwidth === !1 ? Pt : Fe() ?? Pt;
|
|
2044
2056
|
}
|
|
2045
2057
|
maybeRememberBandwidth(e) {
|
|
2046
|
-
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded <
|
|
2058
|
+
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Ft) return;
|
|
2047
2059
|
let t = Date.now();
|
|
2048
|
-
if (!e && t - this.bwSavedAt <
|
|
2060
|
+
if (!e && t - this.bwSavedAt < It) return;
|
|
2049
2061
|
let n = this.hls?.bandwidthEstimate;
|
|
2050
|
-
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t,
|
|
2062
|
+
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Ie(n));
|
|
2051
2063
|
}
|
|
2052
2064
|
destroy() {
|
|
2053
2065
|
if (this.maybeRememberBandwidth(!0), this.detachFrames?.(), this.detachFrames = null, this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
|
|
@@ -2065,7 +2077,7 @@ var gn = class {
|
|
|
2065
2077
|
scheduleLicenseRetry(t) {
|
|
2066
2078
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
2067
2079
|
let n = t.response?.code ?? 0;
|
|
2068
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
2080
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= zt) return !1;
|
|
2069
2081
|
this.licenseRecoveries += 1;
|
|
2070
2082
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
2071
2083
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -2097,7 +2109,7 @@ var gn = class {
|
|
|
2097
2109
|
return;
|
|
2098
2110
|
}
|
|
2099
2111
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
2100
|
-
if (this.networkRecoveries <
|
|
2112
|
+
if (this.networkRecoveries < Rt) {
|
|
2101
2113
|
this.networkRecoveries += 1;
|
|
2102
2114
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
2103
2115
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -2114,7 +2126,7 @@ var gn = class {
|
|
|
2114
2126
|
return;
|
|
2115
2127
|
}
|
|
2116
2128
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
2117
|
-
if (this.mediaRecoveries <
|
|
2129
|
+
if (this.mediaRecoveries < Lt) {
|
|
2118
2130
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
2119
2131
|
return;
|
|
2120
2132
|
}
|
|
@@ -2138,21 +2150,22 @@ var gn = class {
|
|
|
2138
2150
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
2139
2151
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
2140
2152
|
}
|
|
2141
|
-
},
|
|
2153
|
+
}, vn = 15e3, yn = 6e5, bn = 3e5, xn = 100, q = 1, Sn = 1e3, Cn = 3e4, wn = 1e3, Tn = {
|
|
2142
2154
|
inline: "PRESENTATION_INLINE",
|
|
2143
2155
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2144
2156
|
pip: "PRESENTATION_PIP"
|
|
2145
|
-
},
|
|
2157
|
+
}, En = {
|
|
2146
2158
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2147
2159
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2148
2160
|
none: "KEY_SYSTEM_NONE"
|
|
2149
2161
|
};
|
|
2150
|
-
function
|
|
2162
|
+
function Dn(e, t) {
|
|
2151
2163
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
2152
2164
|
}
|
|
2153
|
-
var
|
|
2165
|
+
var On = /* @__PURE__ */ new Set([
|
|
2154
2166
|
"INVALID_URN",
|
|
2155
2167
|
"NOT_FOUND",
|
|
2168
|
+
"GEO_DENIED",
|
|
2156
2169
|
"GONE",
|
|
2157
2170
|
"TOO_EARLY",
|
|
2158
2171
|
"UNAVAILABLE",
|
|
@@ -2170,7 +2183,7 @@ var Dn = /* @__PURE__ */ new Set([
|
|
|
2170
2183
|
ended: "PLAYER_STATE_ENDED",
|
|
2171
2184
|
error: "PLAYER_STATE_ERROR"
|
|
2172
2185
|
};
|
|
2173
|
-
function
|
|
2186
|
+
function kn(e) {
|
|
2174
2187
|
try {
|
|
2175
2188
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2176
2189
|
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);
|
|
@@ -2178,8 +2191,8 @@ function On(e) {
|
|
|
2178
2191
|
return;
|
|
2179
2192
|
}
|
|
2180
2193
|
}
|
|
2181
|
-
var
|
|
2182
|
-
function
|
|
2194
|
+
var An = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), jn = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), Mn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2195
|
+
function Nn(e) {
|
|
2183
2196
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2184
2197
|
let t;
|
|
2185
2198
|
try {
|
|
@@ -2188,19 +2201,19 @@ function Mn(e) {
|
|
|
2188
2201
|
} catch {
|
|
2189
2202
|
return;
|
|
2190
2203
|
}
|
|
2191
|
-
if (
|
|
2192
|
-
Y.add(t), g(
|
|
2204
|
+
if (jn.has(t) && !Y.has(t)) {
|
|
2205
|
+
Y.add(t), g(Mn(new URL(t).origin));
|
|
2193
2206
|
for (let e of X) e.noteCspBlocked();
|
|
2194
2207
|
}
|
|
2195
2208
|
}
|
|
2196
|
-
function
|
|
2209
|
+
function Pn(e, t) {
|
|
2197
2210
|
return g(t, e), { disabledReason: t };
|
|
2198
2211
|
}
|
|
2199
|
-
function
|
|
2200
|
-
if (n) return t && !
|
|
2212
|
+
function Fn(e, t, n) {
|
|
2213
|
+
if (n) return t && !An(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2201
2214
|
if (t) return { endpoint: t };
|
|
2202
|
-
if (t !== void 0) return
|
|
2203
|
-
let r =
|
|
2215
|
+
if (t !== void 0) return Pn("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).");
|
|
2216
|
+
let r = kn(e);
|
|
2204
2217
|
if (r) return { endpoint: r };
|
|
2205
2218
|
let i;
|
|
2206
2219
|
try {
|
|
@@ -2208,9 +2221,9 @@ function Pn(e, t, n) {
|
|
|
2208
2221
|
} catch {
|
|
2209
2222
|
i = e;
|
|
2210
2223
|
}
|
|
2211
|
-
return
|
|
2224
|
+
return Pn(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).`);
|
|
2212
2225
|
}
|
|
2213
|
-
var
|
|
2226
|
+
var In = class {
|
|
2214
2227
|
opts;
|
|
2215
2228
|
url;
|
|
2216
2229
|
cspKey;
|
|
@@ -2292,8 +2305,8 @@ var Fn = class {
|
|
|
2292
2305
|
constructor(e) {
|
|
2293
2306
|
this.opts = {
|
|
2294
2307
|
...e,
|
|
2295
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2296
|
-
idleMs: e.idleMs ??
|
|
2308
|
+
heartbeatMs: e.heartbeatMs ?? vn,
|
|
2309
|
+
idleMs: e.idleMs ?? yn
|
|
2297
2310
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2298
2311
|
try {
|
|
2299
2312
|
let e = new URL(this.url);
|
|
@@ -2310,11 +2323,11 @@ var Fn = class {
|
|
|
2310
2323
|
sdkVersion: this.opts.sdkVersion,
|
|
2311
2324
|
...this.opts.environment
|
|
2312
2325
|
};
|
|
2313
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2326
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Sn), 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 && jn.add(this.cspKey), document.addEventListener("securitypolicyviolation", Nn), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2314
2327
|
}
|
|
2315
2328
|
checkSuspension(e) {
|
|
2316
2329
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2317
|
-
let t = Math.max(this.opts.idleMs,
|
|
2330
|
+
let t = Math.max(this.opts.idleMs, bn);
|
|
2318
2331
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2319
2332
|
}
|
|
2320
2333
|
syncIdle(e) {
|
|
@@ -2337,12 +2350,12 @@ var Fn = class {
|
|
|
2337
2350
|
let a = {
|
|
2338
2351
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2339
2352
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2340
|
-
presentation:
|
|
2353
|
+
presentation: Tn[this.presentation]
|
|
2341
2354
|
}, o = this.causeOf(e, t, i);
|
|
2342
2355
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2343
2356
|
}
|
|
2344
2357
|
seekInduced(e) {
|
|
2345
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2358
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < wn;
|
|
2346
2359
|
}
|
|
2347
2360
|
causeOf(e, t, n) {
|
|
2348
2361
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2416,7 +2429,7 @@ var Fn = class {
|
|
|
2416
2429
|
let r = n ?? "";
|
|
2417
2430
|
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";
|
|
2418
2431
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2419
|
-
if (
|
|
2432
|
+
if (On.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2420
2433
|
let i = t ?? "";
|
|
2421
2434
|
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";
|
|
2422
2435
|
}
|
|
@@ -2463,14 +2476,14 @@ var Fn = class {
|
|
|
2463
2476
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2464
2477
|
o.requestCountDelta = _;
|
|
2465
2478
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2466
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2479
|
+
n.length > 0 && (o.requestTimeP50Ms = Dn(n, 50), o.requestTimeP95Ms = Dn(n, 95));
|
|
2467
2480
|
}
|
|
2468
2481
|
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();
|
|
2469
2482
|
}
|
|
2470
2483
|
maybeEmitMediaInfo(e) {
|
|
2471
2484
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2472
2485
|
let t = {};
|
|
2473
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2486
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = En[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);
|
|
2474
2487
|
let n = JSON.stringify(t);
|
|
2475
2488
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2476
2489
|
}
|
|
@@ -2490,7 +2503,7 @@ var Fn = class {
|
|
|
2490
2503
|
let c = r?.positionMs ?? 0;
|
|
2491
2504
|
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));
|
|
2492
2505
|
let l = e !== "END_REASON_ENDED";
|
|
2493
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2506
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= Cn && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Cn && (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);
|
|
2494
2507
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2495
2508
|
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");
|
|
2496
2509
|
}
|
|
@@ -2510,13 +2523,13 @@ var Fn = class {
|
|
|
2510
2523
|
};
|
|
2511
2524
|
}
|
|
2512
2525
|
noteCspBlocked() {
|
|
2513
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2526
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(Mn(new URL(this.url).origin)));
|
|
2514
2527
|
}
|
|
2515
2528
|
cspBlocked() {
|
|
2516
2529
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2517
2530
|
}
|
|
2518
2531
|
enqueue(e) {
|
|
2519
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2532
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > xn;) {
|
|
2520
2533
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2521
2534
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2522
2535
|
}
|
|
@@ -2543,7 +2556,7 @@ var Fn = class {
|
|
|
2543
2556
|
};
|
|
2544
2557
|
//#endregion
|
|
2545
2558
|
//#region src/core/environment.ts
|
|
2546
|
-
function
|
|
2559
|
+
function Ln() {
|
|
2547
2560
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2548
2561
|
let e;
|
|
2549
2562
|
try {
|
|
@@ -2568,14 +2581,14 @@ function In() {
|
|
|
2568
2581
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2569
2582
|
};
|
|
2570
2583
|
}
|
|
2571
|
-
function
|
|
2584
|
+
function Rn() {
|
|
2572
2585
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2573
2586
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2574
2587
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2575
2588
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2576
2589
|
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";
|
|
2577
2590
|
}
|
|
2578
|
-
function
|
|
2591
|
+
function zn() {
|
|
2579
2592
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2580
2593
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2581
2594
|
let t = {
|
|
@@ -2594,17 +2607,17 @@ function Rn() {
|
|
|
2594
2607
|
}
|
|
2595
2608
|
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;
|
|
2596
2609
|
}
|
|
2597
|
-
function
|
|
2598
|
-
let t =
|
|
2599
|
-
deviceClass:
|
|
2610
|
+
function Bn(e) {
|
|
2611
|
+
let t = Ln(), n = {
|
|
2612
|
+
deviceClass: Rn(),
|
|
2600
2613
|
integration: t.integration,
|
|
2601
|
-
...
|
|
2614
|
+
...zn()
|
|
2602
2615
|
};
|
|
2603
2616
|
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);
|
|
2604
2617
|
let r = e.getBoundingClientRect?.();
|
|
2605
2618
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2606
2619
|
}
|
|
2607
|
-
async function
|
|
2620
|
+
async function Vn() {
|
|
2608
2621
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2609
2622
|
if (!e?.getHighEntropyValues) return {};
|
|
2610
2623
|
try {
|
|
@@ -2616,7 +2629,7 @@ async function Bn() {
|
|
|
2616
2629
|
}
|
|
2617
2630
|
//#endregion
|
|
2618
2631
|
//#region src/core/version.ts
|
|
2619
|
-
var
|
|
2632
|
+
var Hn = "2.20.0", Un = {
|
|
2620
2633
|
accent: "#E1B600",
|
|
2621
2634
|
accentText: "#1B1C23",
|
|
2622
2635
|
background: "#0e0f13",
|
|
@@ -2627,7 +2640,7 @@ var Vn = "2.18.0", Hn = {
|
|
|
2627
2640
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2628
2641
|
radius: "8px",
|
|
2629
2642
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2630
|
-
},
|
|
2643
|
+
}, Wn = {
|
|
2631
2644
|
accent: "--havik-accent",
|
|
2632
2645
|
accentText: "--havik-accent-text",
|
|
2633
2646
|
background: "--havik-bg",
|
|
@@ -2639,26 +2652,26 @@ var Vn = "2.18.0", Hn = {
|
|
|
2639
2652
|
radius: "--havik-radius",
|
|
2640
2653
|
fontFamily: "--havik-font"
|
|
2641
2654
|
};
|
|
2642
|
-
function
|
|
2655
|
+
function Gn(e, t) {
|
|
2643
2656
|
let n = {
|
|
2644
|
-
...
|
|
2657
|
+
...Un,
|
|
2645
2658
|
...t
|
|
2646
2659
|
};
|
|
2647
|
-
for (let t of Object.keys(
|
|
2660
|
+
for (let t of Object.keys(Wn)) e.style.setProperty(Wn[t], n[t]);
|
|
2648
2661
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2649
2662
|
}
|
|
2650
2663
|
//#endregion
|
|
2651
2664
|
//#region src/ui/styles.ts
|
|
2652
|
-
var
|
|
2653
|
-
function
|
|
2654
|
-
let n = e.querySelector(`style#${
|
|
2655
|
-
if (n && (!t ||
|
|
2665
|
+
var Z = "havik-player-styles", Kn = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", qn = /* @__PURE__ */ new WeakMap();
|
|
2666
|
+
function Jn(e = document, t) {
|
|
2667
|
+
let n = e.querySelector(`style#${Z}`);
|
|
2668
|
+
if (n && (!t || qn.get(n) === t)) return;
|
|
2656
2669
|
let r = e.createElement("style");
|
|
2657
|
-
r.id =
|
|
2670
|
+
r.id = Z, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Kn, qn.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2658
2671
|
}
|
|
2659
2672
|
//#endregion
|
|
2660
2673
|
//#region src/ui/icons.ts
|
|
2661
|
-
var
|
|
2674
|
+
var Yn = {
|
|
2662
2675
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2663
2676
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2664
2677
|
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\"/>",
|
|
@@ -2672,20 +2685,25 @@ var Jn = {
|
|
|
2672
2685
|
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\"/>"
|
|
2673
2686
|
};
|
|
2674
2687
|
function Q(e) {
|
|
2675
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2688
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Yn[e]}</svg>`;
|
|
2676
2689
|
}
|
|
2677
2690
|
//#endregion
|
|
2678
2691
|
//#region src/ui/controls.ts
|
|
2679
|
-
var
|
|
2692
|
+
var Xn = 3e3, Zn = 250, Qn = /* @__PURE__ */ new Set([
|
|
2680
2693
|
"GONE",
|
|
2681
2694
|
"NOT_FOUND",
|
|
2695
|
+
"GEO_DENIED",
|
|
2682
2696
|
"INVALID_URN",
|
|
2683
2697
|
"UNAUTHORIZED"
|
|
2684
2698
|
]);
|
|
2685
|
-
function
|
|
2686
|
-
|
|
2699
|
+
function $n(e) {
|
|
2700
|
+
let t = "This match isn't available in your country";
|
|
2701
|
+
return e ? `${t} (${e})` : t;
|
|
2687
2702
|
}
|
|
2688
|
-
|
|
2703
|
+
function er(e) {
|
|
2704
|
+
return new tr(e);
|
|
2705
|
+
}
|
|
2706
|
+
var tr = class {
|
|
2689
2707
|
root;
|
|
2690
2708
|
video;
|
|
2691
2709
|
player;
|
|
@@ -2716,6 +2734,7 @@ var $n = class {
|
|
|
2716
2734
|
statusKind = null;
|
|
2717
2735
|
statusMsg = null;
|
|
2718
2736
|
hasPlayed = !1;
|
|
2737
|
+
fsSupported = !0;
|
|
2719
2738
|
lastError = null;
|
|
2720
2739
|
logoUrl;
|
|
2721
2740
|
statusOverlays;
|
|
@@ -2732,7 +2751,7 @@ var $n = class {
|
|
|
2732
2751
|
scrubbing = !1;
|
|
2733
2752
|
offFns = [];
|
|
2734
2753
|
constructor(e) {
|
|
2735
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2754
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Xn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, Jn(this.doc, e.cspNonce), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
|
|
2736
2755
|
let t = (e, t, n) => {
|
|
2737
2756
|
let r = this.doc.createElement(e);
|
|
2738
2757
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2770,7 +2789,7 @@ var $n = class {
|
|
|
2770
2789
|
let o = this.doc.createElement("span");
|
|
2771
2790
|
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";
|
|
2772
2791
|
let s = t("div", "havik-spacer");
|
|
2773
|
-
if (this.ccBtn = n("havik-btn", "cc", "Subtitles"), this.audioBtn = n("havik-btn", "settings", "Audio track"), this.qualityBtn = n("havik-btn", "settings", "Quality"), this.pipBtn = n("havik-btn", "pip", "Picture in picture"), this.fsBtn = n("havik-btn", "fullscreen", "Fullscreen"), this.ccBtn.style.display = "none", this.audioBtn.style.display = "none", this.qualityBtn.style.display = "none", this.pipSupported() || (this.pipBtn.style.display = "none"), i.append(this.playBtn, a, this.live, this.time, s, this.ccBtn, this.audioBtn, this.qualityBtn, this.pipBtn, this.fsBtn), this.bar.append(this.seek, i), this.menu = t("div", "havik-menu", { role: "menu" }), this.menu.hidden = !0, this.root.append(this.gradient, this.overlay, this.bar, this.menu), e.logoUrl) {
|
|
2792
|
+
if (this.ccBtn = n("havik-btn", "cc", "Subtitles"), this.audioBtn = n("havik-btn", "settings", "Audio track"), this.qualityBtn = n("havik-btn", "settings", "Quality"), this.pipBtn = n("havik-btn", "pip", "Picture in picture"), this.fsBtn = n("havik-btn", "fullscreen", "Fullscreen"), this.ccBtn.style.display = "none", this.audioBtn.style.display = "none", this.qualityBtn.style.display = "none", this.pipSupported() || (this.pipBtn.style.display = "none"), this.syncFullscreenSupport(), i.append(this.playBtn, a, this.live, this.time, s, this.ccBtn, this.audioBtn, this.qualityBtn, this.pipBtn, this.fsBtn), this.bar.append(this.seek, i), this.menu = t("div", "havik-menu", { role: "menu" }), this.menu.hidden = !0, this.root.append(this.gradient, this.overlay, this.bar, this.menu), e.logoUrl) {
|
|
2774
2793
|
let n = t("div", "havik-watermark");
|
|
2775
2794
|
n.style.backgroundImage = `url("${e.logoUrl}")`, this.root.append(n);
|
|
2776
2795
|
}
|
|
@@ -2788,7 +2807,7 @@ var $n = class {
|
|
|
2788
2807
|
}), this.on(this.muteBtn, "click", () => this.player.setMuted(!e.muted)), this.on(this.volSlider, "input", () => {
|
|
2789
2808
|
let t = Number(this.volSlider.value);
|
|
2790
2809
|
this.setVolumeFill(t), this.player.setVolume(t), t > 0 && e.muted && this.player.setMuted(!1);
|
|
2791
|
-
}), this.on(this.liveGo, "click", () => this.player.seekToLive()), this.on(this.pipBtn, "click", () => void this.togglePip()), this.on(this.fsBtn, "click", () => void this.toggleFullscreen()), this.on(this.ccBtn, "click", () => this.toggleMenu("cc")), this.on(this.audioBtn, "click", () => this.toggleMenu("audio")), this.on(this.qualityBtn, "click", () => this.toggleMenu("quality")), this.on(this.seek, "pointerdown", (e) => this.onSeekDown(e)), this.on(this.seek, "keydown", (e) => this.onSeekKey(e)), this.on(e, "play", () => this.syncPlayPause()), this.on(e, "pause", () => this.syncPlayPause()), this.on(e, "volumechange", () => this.syncVolume()), this.on(e, "timeupdate", () => this.syncProgress()), this.on(e, "progress", () => this.syncProgress()), this.on(e, "durationchange", () => this.syncProgress()), this.offFns.push(this.player.on("statechange", () => this.syncState())), this.offFns.push(this.player.on("ended", () => this.syncState())), this.offFns.push(this.player.on("ready", () => this.refreshTracks())), this.offFns.push(this.player.on("qualitychange", () => this.onTracksChanged())), this.offFns.push(this.player.on("audiotrackchange", () => this.onTracksChanged())), this.offFns.push(this.player.on("texttrackchange", () => this.onTracksChanged())), this.offFns.push(this.player.on("pipchange", (e) => this.syncPip(e))), this.offFns.push(this.player.on("stats", () => this.syncLive())), this.offFns.push(this.player.on("error", (e) => {
|
|
2810
|
+
}), this.on(this.liveGo, "click", () => this.player.seekToLive()), this.on(this.pipBtn, "click", () => void this.togglePip()), this.on(this.fsBtn, "click", () => void this.toggleFullscreen()), this.on(this.ccBtn, "click", () => this.toggleMenu("cc")), this.on(this.audioBtn, "click", () => this.toggleMenu("audio")), this.on(this.qualityBtn, "click", () => this.toggleMenu("quality")), this.on(this.seek, "pointerdown", (e) => this.onSeekDown(e)), this.on(this.seek, "keydown", (e) => this.onSeekKey(e)), this.on(e, "play", () => this.syncPlayPause()), this.on(e, "pause", () => this.syncPlayPause()), this.on(e, "volumechange", () => this.syncVolume()), this.on(e, "timeupdate", () => this.syncProgress()), this.on(e, "progress", () => this.syncProgress()), this.on(e, "durationchange", () => this.syncProgress()), this.on(e, "loadedmetadata", () => this.syncFullscreenSupport()), this.offFns.push(this.player.on("statechange", () => this.syncState())), this.offFns.push(this.player.on("ended", () => this.syncState())), this.offFns.push(this.player.on("ready", () => this.refreshTracks())), this.offFns.push(this.player.on("qualitychange", () => this.onTracksChanged())), this.offFns.push(this.player.on("audiotrackchange", () => this.onTracksChanged())), this.offFns.push(this.player.on("texttrackchange", () => this.onTracksChanged())), this.offFns.push(this.player.on("pipchange", (e) => this.syncPip(e))), this.offFns.push(this.player.on("stats", () => this.syncLive())), this.offFns.push(this.player.on("error", (e) => {
|
|
2792
2811
|
this.lastError = e, this.statusKind = null, this.syncState();
|
|
2793
2812
|
}));
|
|
2794
2813
|
let t = (e) => e.pointerType !== "touch";
|
|
@@ -2818,7 +2837,7 @@ var $n = class {
|
|
|
2818
2837
|
let t = this.surfaceWasHidden;
|
|
2819
2838
|
this.tapTimer = setTimeout(() => {
|
|
2820
2839
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2821
|
-
},
|
|
2840
|
+
}, Zn);
|
|
2822
2841
|
}
|
|
2823
2842
|
toggleBar(e) {
|
|
2824
2843
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2838,7 +2857,7 @@ var $n = class {
|
|
|
2838
2857
|
this.statusOverlays && (e === "ended" ? t = "ended" : e === "error" ? t = "error" : e === "waiting" ? t = "waiting" : !this.hasPlayed && (e === "idle" || e === "paused") && (t = "preplay")), this.renderStatus(t);
|
|
2839
2858
|
}
|
|
2840
2859
|
statusMessageFor(e) {
|
|
2841
|
-
return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage
|
|
2860
|
+
return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? $n(this.lastError.country) : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
|
|
2842
2861
|
}
|
|
2843
2862
|
renderStatus(e) {
|
|
2844
2863
|
let t = this.statusMessageFor(e);
|
|
@@ -2853,7 +2872,7 @@ var $n = class {
|
|
|
2853
2872
|
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Q("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
|
|
2854
2873
|
} else {
|
|
2855
2874
|
let r = this.doc.createElement("div");
|
|
2856
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2875
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Qn.has(this.lastError.code)) {
|
|
2857
2876
|
let e = this.doc.createElement("button");
|
|
2858
2877
|
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Q("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
2859
2878
|
}
|
|
@@ -2894,7 +2913,7 @@ var $n = class {
|
|
|
2894
2913
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2895
2914
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2896
2915
|
}
|
|
2897
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2916
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${nr(this.video.currentTime)} / ${nr(this.video.duration)}`);
|
|
2898
2917
|
}
|
|
2899
2918
|
syncLive() {
|
|
2900
2919
|
let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
|
|
@@ -2944,17 +2963,17 @@ var $n = class {
|
|
|
2944
2963
|
renderQualityMenu() {
|
|
2945
2964
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2946
2965
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2947
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2966
|
+
for (let n of e) this.menu.append(this.menuItem(rr(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2948
2967
|
}
|
|
2949
2968
|
renderAudioMenu() {
|
|
2950
2969
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2951
2970
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2952
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2971
|
+
for (let t of e) this.menu.append(this.menuItem(ir(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2953
2972
|
}
|
|
2954
2973
|
renderCcMenu() {
|
|
2955
2974
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2956
2975
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2957
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2976
|
+
for (let t of e) this.menu.append(this.menuItem(ar(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2958
2977
|
}
|
|
2959
2978
|
onTracksChanged() {
|
|
2960
2979
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2974,11 +2993,14 @@ var $n = class {
|
|
|
2974
2993
|
}
|
|
2975
2994
|
async toggleFullscreen() {
|
|
2976
2995
|
try {
|
|
2977
|
-
|
|
2996
|
+
S(this.video, this.root) ? await T(this.video, this.root) : await w(this.video, this.root);
|
|
2978
2997
|
} catch {}
|
|
2979
2998
|
}
|
|
2999
|
+
syncFullscreenSupport() {
|
|
3000
|
+
this.fsSupported = C(this.video, this.root), this.fsBtn.style.display = this.fsSupported ? "" : "none";
|
|
3001
|
+
}
|
|
2980
3002
|
syncFullscreen() {
|
|
2981
|
-
let e =
|
|
3003
|
+
let e = S(this.video, this.root);
|
|
2982
3004
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
2983
3005
|
}
|
|
2984
3006
|
poke() {
|
|
@@ -3012,6 +3034,7 @@ var $n = class {
|
|
|
3012
3034
|
this.player.setMuted(!this.video.muted);
|
|
3013
3035
|
break;
|
|
3014
3036
|
case "f":
|
|
3037
|
+
if (!this.fsSupported) return;
|
|
3015
3038
|
this.toggleFullscreen();
|
|
3016
3039
|
break;
|
|
3017
3040
|
case "c":
|
|
@@ -3055,41 +3078,41 @@ var $n = class {
|
|
|
3055
3078
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
3056
3079
|
}
|
|
3057
3080
|
};
|
|
3058
|
-
function
|
|
3081
|
+
function nr(e) {
|
|
3059
3082
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
3060
3083
|
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");
|
|
3061
3084
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
3062
3085
|
}
|
|
3063
|
-
function
|
|
3086
|
+
function rr(e) {
|
|
3064
3087
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
3065
3088
|
}
|
|
3066
|
-
function
|
|
3089
|
+
function ir(e) {
|
|
3067
3090
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3068
3091
|
}
|
|
3069
|
-
function
|
|
3092
|
+
function ar(e) {
|
|
3070
3093
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3071
3094
|
}
|
|
3072
3095
|
//#endregion
|
|
3073
3096
|
//#region src/managed/index.ts
|
|
3074
|
-
var
|
|
3075
|
-
function
|
|
3097
|
+
var or = 6e3, sr = 45e3, cr = 2e3, lr = 3, ur = 5e3, dr = 2e3, fr = 48e4, pr = "keySystemLicenseRequestFailed";
|
|
3098
|
+
function mr(e) {
|
|
3076
3099
|
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)})`);
|
|
3077
|
-
if (e.env !== void 0) return
|
|
3100
|
+
if (e.env !== void 0) return it(e.env);
|
|
3078
3101
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
3079
3102
|
return e.baseUrl;
|
|
3080
3103
|
}
|
|
3081
|
-
async function
|
|
3104
|
+
async function hr(e) {
|
|
3082
3105
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
3083
|
-
let t =
|
|
3106
|
+
let t = mr(e);
|
|
3084
3107
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
3085
3108
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
3086
|
-
let r = new
|
|
3109
|
+
let r = new gr({
|
|
3087
3110
|
...e,
|
|
3088
3111
|
baseUrl: t
|
|
3089
3112
|
});
|
|
3090
3113
|
return await r.start(), r;
|
|
3091
3114
|
}
|
|
3092
|
-
var
|
|
3115
|
+
var gr = class {
|
|
3093
3116
|
opts;
|
|
3094
3117
|
abort = new AbortController();
|
|
3095
3118
|
listeners = {};
|
|
@@ -3163,7 +3186,7 @@ var mr = class {
|
|
|
3163
3186
|
};
|
|
3164
3187
|
}
|
|
3165
3188
|
beginArming(e, t, n = !1) {
|
|
3166
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
3189
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
|
|
3167
3190
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
3168
3191
|
}
|
|
3169
3192
|
beginArmingByPolling(e) {
|
|
@@ -3184,7 +3207,7 @@ var mr = class {
|
|
|
3184
3207
|
setTimeout(() => {
|
|
3185
3208
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3186
3209
|
phase: i ? "unavailable" : "tooEarly",
|
|
3187
|
-
retryInMs:
|
|
3210
|
+
retryInMs: sr,
|
|
3188
3211
|
attempt: 1,
|
|
3189
3212
|
elapsedMs: 0,
|
|
3190
3213
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3223,13 +3246,13 @@ var mr = class {
|
|
|
3223
3246
|
!a && !p() && h();
|
|
3224
3247
|
}, e);
|
|
3225
3248
|
};
|
|
3226
|
-
_(
|
|
3249
|
+
_(or), this.armingSub = E({
|
|
3227
3250
|
eventsBaseUrl: t,
|
|
3228
3251
|
matchUrn: this.opts.matchUrn,
|
|
3229
3252
|
credential: this.opts.credential,
|
|
3230
|
-
onAlive: () => _(
|
|
3253
|
+
onAlive: () => _(sr),
|
|
3231
3254
|
onState: (e) => {
|
|
3232
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3255
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * cr);
|
|
3233
3256
|
},
|
|
3234
3257
|
onError: () => h()
|
|
3235
3258
|
});
|
|
@@ -3252,7 +3275,7 @@ var mr = class {
|
|
|
3252
3275
|
let n = await s(this.opts.credential);
|
|
3253
3276
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3254
3277
|
this.setState("loading");
|
|
3255
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3278
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = lt(this.opts.video, (e) => {
|
|
3256
3279
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3257
3280
|
});
|
|
3258
3281
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3274,26 +3297,26 @@ var mr = class {
|
|
|
3274
3297
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3275
3298
|
let i = e.analytics?.sid;
|
|
3276
3299
|
if (!i) return;
|
|
3277
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3300
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Fn(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3278
3301
|
if (!o) {
|
|
3279
3302
|
s && setTimeout(() => {
|
|
3280
3303
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3281
3304
|
}, 0);
|
|
3282
3305
|
return;
|
|
3283
3306
|
}
|
|
3284
|
-
let c = this.opts.video, l = new
|
|
3307
|
+
let c = this.opts.video, l = new In({
|
|
3285
3308
|
endpoint: o,
|
|
3286
3309
|
sid: i,
|
|
3287
3310
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3288
|
-
sdkVersion:
|
|
3289
|
-
environment:
|
|
3311
|
+
sdkVersion: Hn,
|
|
3312
|
+
environment: Bn(c),
|
|
3290
3313
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3291
3314
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3292
3315
|
onBlocked: (e) => setTimeout(() => {
|
|
3293
3316
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3294
3317
|
}, 0),
|
|
3295
3318
|
sample: () => {
|
|
3296
|
-
let e = this.engine?.getStats() ??
|
|
3319
|
+
let e = this.engine?.getStats() ?? z, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3297
3320
|
return {
|
|
3298
3321
|
...e,
|
|
3299
3322
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3307,7 +3330,7 @@ var mr = class {
|
|
|
3307
3330
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3308
3331
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3309
3332
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3310
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3333
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Vn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3311
3334
|
}
|
|
3312
3335
|
currentPresentation() {
|
|
3313
3336
|
let e = this.opts.video;
|
|
@@ -3322,7 +3345,7 @@ var mr = class {
|
|
|
3322
3345
|
video: this.opts.video,
|
|
3323
3346
|
descriptor: e,
|
|
3324
3347
|
credential: t,
|
|
3325
|
-
deviceId:
|
|
3348
|
+
deviceId: A(),
|
|
3326
3349
|
userId: this.opts.userId,
|
|
3327
3350
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
3328
3351
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -3335,9 +3358,9 @@ var mr = class {
|
|
|
3335
3358
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3336
3359
|
}, o = this.opts.engine ?? "auto";
|
|
3337
3360
|
if (o === "native") return new W(a);
|
|
3338
|
-
if (o === "hls") return new
|
|
3339
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled &&
|
|
3340
|
-
if (
|
|
3361
|
+
if (o === "hls") return new _n(a);
|
|
3362
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled && xt() && H(this.opts.video)) return new W(a);
|
|
3363
|
+
if (Nt()) return new _n(a);
|
|
3341
3364
|
if (H(this.opts.video)) return new W(a);
|
|
3342
3365
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3343
3366
|
}
|
|
@@ -3385,11 +3408,11 @@ var mr = class {
|
|
|
3385
3408
|
}
|
|
3386
3409
|
startLiveState(e) {
|
|
3387
3410
|
if (this.opts.liveStateEvents === !1) return;
|
|
3388
|
-
let t = this.opts.eventsBaseUrl ??
|
|
3411
|
+
let t = this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
|
|
3389
3412
|
if (!t) return;
|
|
3390
3413
|
this.closeLiveState();
|
|
3391
3414
|
let r = 0, i = !1;
|
|
3392
|
-
this.liveStateSub =
|
|
3415
|
+
this.liveStateSub = E({
|
|
3393
3416
|
eventsBaseUrl: t,
|
|
3394
3417
|
matchUrn: this.opts.matchUrn,
|
|
3395
3418
|
credential: this.opts.credential,
|
|
@@ -3400,7 +3423,7 @@ var mr = class {
|
|
|
3400
3423
|
r = 0, i = !1;
|
|
3401
3424
|
},
|
|
3402
3425
|
onError: () => {
|
|
3403
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
3426
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= lr && (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.`))));
|
|
3404
3427
|
}
|
|
3405
3428
|
});
|
|
3406
3429
|
}
|
|
@@ -3414,7 +3437,7 @@ var mr = class {
|
|
|
3414
3437
|
return;
|
|
3415
3438
|
}
|
|
3416
3439
|
let e = this.hiddenAtMs;
|
|
3417
|
-
this.hiddenAtMs = null, e != null && Date.now() - e >=
|
|
3440
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= ur && this.resyncLiveState();
|
|
3418
3441
|
}, this.onReturnPageShow = (e) => {
|
|
3419
3442
|
e.persisted && this.resyncLiveState();
|
|
3420
3443
|
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
@@ -3446,7 +3469,7 @@ var mr = class {
|
|
|
3446
3469
|
scheduleRejoin(e) {
|
|
3447
3470
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3448
3471
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3449
|
-
}, Math.random() *
|
|
3472
|
+
}, Math.random() * cr));
|
|
3450
3473
|
}
|
|
3451
3474
|
cancelRejoin() {
|
|
3452
3475
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3470,7 +3493,7 @@ var mr = class {
|
|
|
3470
3493
|
}
|
|
3471
3494
|
t.controls = !1;
|
|
3472
3495
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3473
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3496
|
+
r && r.insertBefore(n, t), n.appendChild(t), Gn(n, this.opts.theme), this.container = n, this.controlBar = er({
|
|
3474
3497
|
root: n,
|
|
3475
3498
|
video: t,
|
|
3476
3499
|
player: this,
|
|
@@ -3508,7 +3531,7 @@ var mr = class {
|
|
|
3508
3531
|
}
|
|
3509
3532
|
startStats() {
|
|
3510
3533
|
this.stopStats();
|
|
3511
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3534
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? dr);
|
|
3512
3535
|
this.statsTimer = setInterval(() => {
|
|
3513
3536
|
if (!this.engine) return;
|
|
3514
3537
|
let e = this.engine.getStats();
|
|
@@ -3519,14 +3542,14 @@ var mr = class {
|
|
|
3519
3542
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3520
3543
|
}
|
|
3521
3544
|
isStaleLicenseDenial(e) {
|
|
3522
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3545
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== pr || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3523
3546
|
}
|
|
3524
3547
|
scheduleLicenseRefresh() {
|
|
3525
3548
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3526
3549
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3527
3550
|
document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3528
3551
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3529
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3552
|
+
let e = this.opts.licenseRefreshMs ?? fr;
|
|
3530
3553
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3531
3554
|
}
|
|
3532
3555
|
stopRefresh() {
|
|
@@ -3583,7 +3606,7 @@ var mr = class {
|
|
|
3583
3606
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3584
3607
|
}
|
|
3585
3608
|
getStats() {
|
|
3586
|
-
return this.engine?.getStats() ??
|
|
3609
|
+
return this.engine?.getStats() ?? z;
|
|
3587
3610
|
}
|
|
3588
3611
|
getQualityLevels() {
|
|
3589
3612
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3622,10 +3645,13 @@ var mr = class {
|
|
|
3622
3645
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
3623
3646
|
}
|
|
3624
3647
|
async enterFullscreen() {
|
|
3625
|
-
return !this.destroyed &&
|
|
3648
|
+
return !this.destroyed && w(this.opts.video, this.container ?? void 0);
|
|
3626
3649
|
}
|
|
3627
3650
|
async exitFullscreen() {
|
|
3628
|
-
await
|
|
3651
|
+
await T(this.opts.video, this.container ?? void 0);
|
|
3652
|
+
}
|
|
3653
|
+
fullscreenSupported() {
|
|
3654
|
+
return !this.destroyed && C(this.opts.video, this.container ?? void 0);
|
|
3629
3655
|
}
|
|
3630
3656
|
retry() {
|
|
3631
3657
|
return this.reload();
|
|
@@ -3693,7 +3719,7 @@ function $(e) {
|
|
|
3693
3719
|
}
|
|
3694
3720
|
//#endregion
|
|
3695
3721
|
//#region src/embed/host.ts
|
|
3696
|
-
function
|
|
3722
|
+
function _r(e) {
|
|
3697
3723
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3698
3724
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3699
3725
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3752,15 +3778,15 @@ function hr(e) {
|
|
|
3752
3778
|
}
|
|
3753
3779
|
//#endregion
|
|
3754
3780
|
//#region src/embed/page.ts
|
|
3755
|
-
var
|
|
3756
|
-
function
|
|
3781
|
+
var vr = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3782
|
+
function yr(e) {
|
|
3757
3783
|
if (typeof e == "boolean") return e;
|
|
3758
3784
|
if (typeof e == "object" && e) {
|
|
3759
3785
|
let t = e.endpoint;
|
|
3760
3786
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3761
3787
|
}
|
|
3762
3788
|
}
|
|
3763
|
-
function
|
|
3789
|
+
function br() {
|
|
3764
3790
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3765
3791
|
if (e) return {
|
|
3766
3792
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3770,7 +3796,7 @@ function vr() {
|
|
|
3770
3796
|
autoplay: e.autoplay ?? !0,
|
|
3771
3797
|
muted: e.muted ?? !0,
|
|
3772
3798
|
waitForLive: e.waitForLive ?? !0,
|
|
3773
|
-
analytics:
|
|
3799
|
+
analytics: yr(e.analytics)
|
|
3774
3800
|
};
|
|
3775
3801
|
let t = new URLSearchParams(location.search);
|
|
3776
3802
|
return {
|
|
@@ -3783,9 +3809,9 @@ function vr() {
|
|
|
3783
3809
|
waitForLive: !0
|
|
3784
3810
|
};
|
|
3785
3811
|
}
|
|
3786
|
-
async function
|
|
3787
|
-
let e =
|
|
3788
|
-
|
|
3812
|
+
async function xr() {
|
|
3813
|
+
let e = br();
|
|
3814
|
+
Cr();
|
|
3789
3815
|
let t = document.createElement("video");
|
|
3790
3816
|
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);
|
|
3791
3817
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3838,14 +3864,15 @@ async function yr() {
|
|
|
3838
3864
|
})), e.on("error", (e) => i({
|
|
3839
3865
|
type: "oddin:error",
|
|
3840
3866
|
code: e.code,
|
|
3841
|
-
message: e.message
|
|
3867
|
+
message: e.message,
|
|
3868
|
+
...e.country === void 0 ? {} : { country: e.country }
|
|
3842
3869
|
})), e.on("autoplayblocked", () => {
|
|
3843
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3870
|
+
i({ type: "oddin:autoplayblocked" }), Sr(t, e);
|
|
3844
3871
|
});
|
|
3845
3872
|
}, s = async (r) => {
|
|
3846
3873
|
a?.destroy(), a = null;
|
|
3847
3874
|
try {
|
|
3848
|
-
let n = await
|
|
3875
|
+
let n = await hr({
|
|
3849
3876
|
video: t,
|
|
3850
3877
|
baseUrl: e.baseUrl,
|
|
3851
3878
|
matchUrn: r,
|
|
@@ -3859,11 +3886,12 @@ async function yr() {
|
|
|
3859
3886
|
let i = t.parentElement;
|
|
3860
3887
|
i?.classList.contains("havik-player") && (i.style.cssText = "position:absolute;inset:0;width:100%;height:100%;aspect-ratio:auto"), o(n);
|
|
3861
3888
|
} catch (e) {
|
|
3862
|
-
let t = e instanceof n ? e.code : "INTERNAL", r = e instanceof Error ? e.message : String(e);
|
|
3889
|
+
let t = e instanceof n ? e.code : "INTERNAL", r = e instanceof Error ? e.message : String(e), a = e instanceof n ? e.country : void 0;
|
|
3863
3890
|
i({
|
|
3864
3891
|
type: "oddin:error",
|
|
3865
3892
|
code: t,
|
|
3866
|
-
message: r
|
|
3893
|
+
message: r,
|
|
3894
|
+
...a === void 0 ? {} : { country: a }
|
|
3867
3895
|
});
|
|
3868
3896
|
}
|
|
3869
3897
|
}, c = () => {
|
|
@@ -3907,7 +3935,7 @@ async function yr() {
|
|
|
3907
3935
|
a?.retry();
|
|
3908
3936
|
break;
|
|
3909
3937
|
case "oddin:load":
|
|
3910
|
-
typeof e.matchUrn == "string" &&
|
|
3938
|
+
typeof e.matchUrn == "string" && vr.test(e.matchUrn) && s(e.matchUrn);
|
|
3911
3939
|
break;
|
|
3912
3940
|
case "oddin:destroy": c();
|
|
3913
3941
|
}
|
|
@@ -3919,18 +3947,18 @@ async function yr() {
|
|
|
3919
3947
|
protocol: 1
|
|
3920
3948
|
});
|
|
3921
3949
|
}
|
|
3922
|
-
function
|
|
3950
|
+
function Sr(e, t) {
|
|
3923
3951
|
if (document.getElementById("havik-tap")) return;
|
|
3924
3952
|
let n = document.createElement("button");
|
|
3925
3953
|
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", () => {
|
|
3926
3954
|
n.remove(), t.play();
|
|
3927
3955
|
}), document.body.appendChild(n);
|
|
3928
3956
|
}
|
|
3929
|
-
function
|
|
3957
|
+
function Cr() {
|
|
3930
3958
|
let e = document.createElement("style");
|
|
3931
3959
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3932
3960
|
}
|
|
3933
3961
|
//#endregion
|
|
3934
|
-
export {
|
|
3962
|
+
export { Un as ODDIN_THEME, n as PlaybackError, Gn as applyTheme, it as baseUrlForEnv, xr as bootEmbed, Te as clearDeviceId, Le as clearRememberedBandwidth, hr as createPlayer, D as deriveEventsBaseUrl, et as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, C as fullscreenSupported, A as getDeviceId, nt as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, _r as mountEmbed, de as pollToLive, y as resolveStream, E as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
|
|
3935
3963
|
|
|
3936
3964
|
//# sourceMappingURL=index.js.map
|