@oddin-gg/havik-player 2.25.0 → 2.26.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/dist/havik-player.global.js +2 -2
- 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 +9 -4
- package/dist/index.d.ts +9 -4
- package/dist/index.js +525 -444
- package/dist/index.js.map +1 -1
- package/docs/API.md +54 -49
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -309,42 +309,42 @@ function ge(e, t) {
|
|
|
309
309
|
}
|
|
310
310
|
//#endregion
|
|
311
311
|
//#region src/core/fullscreen.ts
|
|
312
|
-
function
|
|
312
|
+
function x(e) {
|
|
313
313
|
return e.ownerDocument ?? document;
|
|
314
314
|
}
|
|
315
|
-
function
|
|
315
|
+
function _e(e) {
|
|
316
316
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
317
317
|
}
|
|
318
|
-
function
|
|
319
|
-
let n =
|
|
318
|
+
function S(e, t) {
|
|
319
|
+
let n = _e(x(e));
|
|
320
320
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
321
321
|
}
|
|
322
|
-
function
|
|
323
|
-
let n = t ?? e, r =
|
|
322
|
+
function C(e, t) {
|
|
323
|
+
let n = t ?? e, r = x(e);
|
|
324
324
|
if (typeof n.requestFullscreen == "function") return r.fullscreenEnabled !== !1;
|
|
325
325
|
if (typeof n.webkitRequestFullscreen == "function") return r.webkitFullscreenEnabled !== !1;
|
|
326
326
|
let i = e;
|
|
327
327
|
return i.webkitSupportsFullscreen === !0 && typeof i.webkitEnterFullscreen == "function" || e.readyState < 1;
|
|
328
328
|
}
|
|
329
|
-
async function
|
|
329
|
+
async function w(e, t) {
|
|
330
330
|
let n = t ?? e;
|
|
331
331
|
if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
|
|
332
332
|
if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
|
|
333
333
|
let r = e;
|
|
334
334
|
return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
|
|
335
335
|
}
|
|
336
|
-
async function
|
|
336
|
+
async function T(e, t) {
|
|
337
337
|
let n = e;
|
|
338
338
|
if (n.webkitDisplayingFullscreen) {
|
|
339
339
|
n.webkitExitFullscreen?.();
|
|
340
340
|
return;
|
|
341
341
|
}
|
|
342
|
-
let r =
|
|
342
|
+
let r = x(e), i = _e(r);
|
|
343
343
|
i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
|
|
344
344
|
}
|
|
345
345
|
//#endregion
|
|
346
346
|
//#region src/core/catalog.ts
|
|
347
|
-
async function
|
|
347
|
+
async function ve(e) {
|
|
348
348
|
let t = new URLSearchParams();
|
|
349
349
|
e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
|
|
350
350
|
let i = t.toString(), a = f(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
|
|
@@ -362,12 +362,12 @@ async function be(e) {
|
|
|
362
362
|
};
|
|
363
363
|
if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
|
|
364
364
|
return {
|
|
365
|
-
tournaments:
|
|
365
|
+
tournaments: ye(await s.json()),
|
|
366
366
|
etag: s.headers.get("etag") ?? void 0,
|
|
367
367
|
notModified: !1
|
|
368
368
|
};
|
|
369
369
|
}
|
|
370
|
-
function
|
|
370
|
+
function ye(e) {
|
|
371
371
|
return (e.tournaments ?? []).map((e) => {
|
|
372
372
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
373
373
|
return {
|
|
@@ -389,7 +389,7 @@ function xe(e) {
|
|
|
389
389
|
};
|
|
390
390
|
});
|
|
391
391
|
}
|
|
392
|
-
async function
|
|
392
|
+
async function be(e) {
|
|
393
393
|
let t = f(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
394
394
|
e.etag && i.set("If-None-Match", e.etag);
|
|
395
395
|
let a = await m(t, {
|
|
@@ -409,13 +409,13 @@ async function Se(e) {
|
|
|
409
409
|
};
|
|
410
410
|
if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
411
411
|
return {
|
|
412
|
-
tournament:
|
|
412
|
+
tournament: xe(await a.json()),
|
|
413
413
|
etag: a.headers.get("etag") ?? void 0,
|
|
414
414
|
notModified: !1,
|
|
415
415
|
notFound: !1
|
|
416
416
|
};
|
|
417
417
|
}
|
|
418
|
-
function
|
|
418
|
+
function xe(e) {
|
|
419
419
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
420
420
|
return {
|
|
421
421
|
urn: t,
|
|
@@ -435,18 +435,18 @@ function Ce(e) {
|
|
|
435
435
|
}))
|
|
436
436
|
};
|
|
437
437
|
}
|
|
438
|
-
function
|
|
438
|
+
function Se(e) {
|
|
439
439
|
return e.tournaments.flatMap((e) => e.matches);
|
|
440
440
|
}
|
|
441
441
|
//#endregion
|
|
442
442
|
//#region src/core/poll.ts
|
|
443
|
-
var
|
|
443
|
+
var Ce = /* @__PURE__ */ new Set([
|
|
444
444
|
"NOT_FOUND",
|
|
445
445
|
"GEO_DENIED",
|
|
446
446
|
"GONE",
|
|
447
447
|
"INVALID_URN"
|
|
448
448
|
]);
|
|
449
|
-
function
|
|
449
|
+
function we(e) {
|
|
450
450
|
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, c = !1, d = () => {
|
|
451
451
|
c || (a = setTimeout(p, t));
|
|
452
452
|
}, p = async () => {
|
|
@@ -479,7 +479,7 @@ function Ee(e) {
|
|
|
479
479
|
} catch (t) {
|
|
480
480
|
if (!i.signal.aborted) {
|
|
481
481
|
let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
|
|
482
|
-
|
|
482
|
+
Ce.has(r.code) && (c = !0), e.onError?.(r);
|
|
483
483
|
}
|
|
484
484
|
} finally {
|
|
485
485
|
d();
|
|
@@ -491,16 +491,16 @@ function Ee(e) {
|
|
|
491
491
|
}
|
|
492
492
|
//#endregion
|
|
493
493
|
//#region src/core/events.ts
|
|
494
|
-
var
|
|
494
|
+
var Te = 45e3, E = class extends Error {
|
|
495
495
|
status;
|
|
496
496
|
terminal;
|
|
497
497
|
constructor(e) {
|
|
498
498
|
let t = e === 410;
|
|
499
499
|
super(t ? `live-state subscribe failed: HTTP ${e} — match is gone, not retrying` : e === 404 ? `live-state subscribe failed: HTTP ${e} — match not in the catalog, retrying slowly` : `live-state subscribe failed: HTTP ${e}`), this.name = "LiveStateHttpError", this.status = e, this.terminal = t;
|
|
500
500
|
}
|
|
501
|
-
},
|
|
502
|
-
function
|
|
503
|
-
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = Math.max(t, e.notFoundRetryMs ??
|
|
501
|
+
}, Ee = 3e5;
|
|
502
|
+
function D(e) {
|
|
503
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = Math.max(t, e.notFoundRetryMs ?? Ee), i = e.idleTimeoutMs ?? Te, a = Number.isFinite(i) && i > 0 ? i : 0, o = new AbortController(), s = !1, l = (e) => new Promise((t) => {
|
|
504
504
|
if (o.signal.aborted) return t();
|
|
505
505
|
let n = setTimeout(t, e);
|
|
506
506
|
o.signal.addEventListener("abort", () => {
|
|
@@ -567,7 +567,7 @@ function T(e) {
|
|
|
567
567
|
});
|
|
568
568
|
if (clearTimeout(_), s) return;
|
|
569
569
|
if (!o.ok || !o.body) {
|
|
570
|
-
let t = new
|
|
570
|
+
let t = new E(o.status);
|
|
571
571
|
h = t.terminal, g = o.status === 404, e.onError?.(t);
|
|
572
572
|
} else await p(o.body, () => {
|
|
573
573
|
i = t;
|
|
@@ -585,7 +585,7 @@ function T(e) {
|
|
|
585
585
|
s || (s = !0, o.abort());
|
|
586
586
|
} };
|
|
587
587
|
}
|
|
588
|
-
function
|
|
588
|
+
function O(e) {
|
|
589
589
|
try {
|
|
590
590
|
let t = new URL(e);
|
|
591
591
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -595,24 +595,24 @@ function E(e) {
|
|
|
595
595
|
}
|
|
596
596
|
//#endregion
|
|
597
597
|
//#region src/core/drm/deviceId.ts
|
|
598
|
-
var
|
|
599
|
-
function
|
|
600
|
-
if (
|
|
598
|
+
var De = "havik.player.deviceId", k;
|
|
599
|
+
function Oe() {
|
|
600
|
+
if (k) return k;
|
|
601
601
|
try {
|
|
602
|
-
let e = globalThis.localStorage?.getItem(
|
|
603
|
-
if (e) return
|
|
602
|
+
let e = globalThis.localStorage?.getItem(De);
|
|
603
|
+
if (e) return k = e, e;
|
|
604
604
|
} catch {}
|
|
605
605
|
let e = Ae();
|
|
606
|
-
|
|
606
|
+
k = e;
|
|
607
607
|
try {
|
|
608
|
-
globalThis.localStorage?.setItem(
|
|
608
|
+
globalThis.localStorage?.setItem(De, e);
|
|
609
609
|
} catch {}
|
|
610
610
|
return e;
|
|
611
611
|
}
|
|
612
612
|
function ke() {
|
|
613
|
-
|
|
613
|
+
k = void 0;
|
|
614
614
|
try {
|
|
615
|
-
globalThis.localStorage?.removeItem(
|
|
615
|
+
globalThis.localStorage?.removeItem(De);
|
|
616
616
|
} catch {}
|
|
617
617
|
}
|
|
618
618
|
function Ae() {
|
|
@@ -631,28 +631,28 @@ function je(e, t, n = {}) {
|
|
|
631
631
|
let r = {
|
|
632
632
|
"x-api-key": t.apiKey,
|
|
633
633
|
"X-Match-Urn": e.matchUrn,
|
|
634
|
-
"X-Device-Id": n.deviceId ??
|
|
634
|
+
"X-Device-Id": n.deviceId ?? Oe(),
|
|
635
635
|
"Content-Type": "application/octet-stream"
|
|
636
636
|
};
|
|
637
637
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
638
638
|
}
|
|
639
639
|
//#endregion
|
|
640
640
|
//#region src/core/bandwidthMemory.ts
|
|
641
|
-
var
|
|
642
|
-
function
|
|
641
|
+
var Me = "havik.player.bandwidth", Ne = .8, Pe = 2e7, Fe = 3e5;
|
|
642
|
+
function Ie() {
|
|
643
643
|
return globalThis.navigator?.connection;
|
|
644
644
|
}
|
|
645
|
-
function
|
|
646
|
-
let e =
|
|
645
|
+
function Le() {
|
|
646
|
+
let e = Ie()?.type;
|
|
647
647
|
return typeof e == "string" && e !== "" && e !== "unknown" ? e : "any";
|
|
648
648
|
}
|
|
649
|
-
function
|
|
650
|
-
let e =
|
|
649
|
+
function Re() {
|
|
650
|
+
let e = Ie()?.downlink;
|
|
651
651
|
return typeof e == "number" && Number.isFinite(e) && e > 0 ? e * 1e6 : void 0;
|
|
652
652
|
}
|
|
653
|
-
function
|
|
653
|
+
function ze() {
|
|
654
654
|
try {
|
|
655
|
-
let e = globalThis.localStorage?.getItem(
|
|
655
|
+
let e = globalThis.localStorage?.getItem(Me);
|
|
656
656
|
if (!e) return {};
|
|
657
657
|
let t = JSON.parse(e);
|
|
658
658
|
return t && typeof t == "object" && !Array.isArray(t) ? t : {};
|
|
@@ -660,36 +660,36 @@ function Re() {
|
|
|
660
660
|
return {};
|
|
661
661
|
}
|
|
662
662
|
}
|
|
663
|
-
function
|
|
664
|
-
let t =
|
|
663
|
+
function Be(e = Date.now()) {
|
|
664
|
+
let t = ze()[Le()];
|
|
665
665
|
if (!t || typeof t.bps != "number" || typeof t.at != "number" || !Number.isFinite(t.bps) || t.bps <= 0) return;
|
|
666
666
|
let n = e - t.at;
|
|
667
667
|
if (n < 0 || n > 2592e5) return;
|
|
668
|
-
let r =
|
|
669
|
-
return Math.round(Math.min(
|
|
668
|
+
let r = Re(), i = r === void 0 ? t.bps : Math.min(t.bps, r);
|
|
669
|
+
return Math.round(Math.min(Pe, Math.max(Fe, i * Ne)));
|
|
670
670
|
}
|
|
671
|
-
function
|
|
671
|
+
function Ve(e, t = Date.now()) {
|
|
672
672
|
if (!Number.isFinite(e) || e <= 0) return;
|
|
673
|
-
let n =
|
|
674
|
-
n[
|
|
673
|
+
let n = ze();
|
|
674
|
+
n[Le()] = {
|
|
675
675
|
bps: Math.round(e),
|
|
676
676
|
at: t
|
|
677
677
|
};
|
|
678
678
|
try {
|
|
679
|
-
globalThis.localStorage?.setItem(
|
|
679
|
+
globalThis.localStorage?.setItem(Me, JSON.stringify(n));
|
|
680
680
|
} catch {}
|
|
681
681
|
}
|
|
682
|
-
function
|
|
682
|
+
function He() {
|
|
683
683
|
try {
|
|
684
|
-
globalThis.localStorage?.removeItem(
|
|
684
|
+
globalThis.localStorage?.removeItem(Me);
|
|
685
685
|
} catch {}
|
|
686
686
|
}
|
|
687
687
|
//#endregion
|
|
688
688
|
//#region src/core/drm/cdm.ts
|
|
689
|
-
var
|
|
690
|
-
function
|
|
691
|
-
let n =
|
|
692
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
689
|
+
var Ue = /* @__PURE__ */ new WeakMap();
|
|
690
|
+
function We(e, t) {
|
|
691
|
+
let n = Ue.get(e);
|
|
692
|
+
n || (n = /* @__PURE__ */ new Map(), Ue.set(e, n));
|
|
693
693
|
let r = n.get(t.keySystem);
|
|
694
694
|
if (r) return r;
|
|
695
695
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -697,22 +697,22 @@ function Ue(e, t) {
|
|
|
697
697
|
});
|
|
698
698
|
return n.set(t.keySystem, i), i;
|
|
699
699
|
}
|
|
700
|
-
function
|
|
700
|
+
function A() {
|
|
701
701
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
702
702
|
}
|
|
703
|
-
var
|
|
704
|
-
function
|
|
703
|
+
var j = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
704
|
+
function Ge(e) {
|
|
705
705
|
return e.startsWith("com.widevine");
|
|
706
706
|
}
|
|
707
|
-
function
|
|
708
|
-
if (!
|
|
707
|
+
function M(e, t) {
|
|
708
|
+
if (!Ge(e)) return t;
|
|
709
709
|
let n = (e, t) => {
|
|
710
710
|
let n = e.videoCapabilities;
|
|
711
711
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
712
|
-
let n =
|
|
713
|
-
return n === -1 ||
|
|
712
|
+
let n = j.indexOf(e.robustness);
|
|
713
|
+
return n === -1 || j.indexOf(t) > n;
|
|
714
714
|
});
|
|
715
|
-
}, r =
|
|
715
|
+
}, r = j.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
716
716
|
...t,
|
|
717
717
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
718
718
|
...t,
|
|
@@ -721,53 +721,53 @@ function N(e, t) {
|
|
|
721
721
|
})));
|
|
722
722
|
return [...t, ...r];
|
|
723
723
|
}
|
|
724
|
-
function
|
|
725
|
-
return (t, n) =>
|
|
724
|
+
function Ke(e) {
|
|
725
|
+
return (t, n) => A() ? navigator.requestMediaKeySystemAccess(t, M(t, n)).then((t) => ({
|
|
726
726
|
keySystem: t.keySystem,
|
|
727
727
|
getConfiguration: () => t.getConfiguration(),
|
|
728
|
-
createMediaKeys: () =>
|
|
728
|
+
createMediaKeys: () => We(e, t)
|
|
729
729
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
730
730
|
}
|
|
731
|
-
var
|
|
731
|
+
var N = {
|
|
732
732
|
video: "SW_SECURE_DECODE",
|
|
733
733
|
audio: "SW_SECURE_CRYPTO",
|
|
734
734
|
scheme: "cbcs"
|
|
735
735
|
};
|
|
736
|
-
function
|
|
737
|
-
if (!
|
|
736
|
+
function qe(e) {
|
|
737
|
+
if (!A()) return;
|
|
738
738
|
let t = (e, t) => ({
|
|
739
739
|
contentType: e,
|
|
740
740
|
robustness: t,
|
|
741
|
-
encryptionScheme:
|
|
741
|
+
encryptionScheme: N.scheme
|
|
742
742
|
});
|
|
743
|
-
|
|
743
|
+
Ke(e)("com.widevine.alpha", [{
|
|
744
744
|
initDataTypes: ["cenc"],
|
|
745
745
|
distinctiveIdentifier: "optional",
|
|
746
746
|
persistentState: "optional",
|
|
747
747
|
sessionTypes: ["temporary"],
|
|
748
|
-
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"",
|
|
749
|
-
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"",
|
|
748
|
+
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", N.audio)],
|
|
749
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", N.video)]
|
|
750
750
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
751
751
|
}
|
|
752
|
-
function
|
|
753
|
-
let t =
|
|
752
|
+
function P(e) {
|
|
753
|
+
let t = F(e);
|
|
754
754
|
if (/^avc[13]/.test(t)) return "avc";
|
|
755
755
|
if (/^(hvc1|hev1)/.test(t)) return "hevc";
|
|
756
756
|
if (/^(dvh1|dvhe)/.test(t)) return "dv";
|
|
757
757
|
if (t.startsWith("av01")) return "av1";
|
|
758
758
|
if (/^vp0?9/.test(t)) return "vp9";
|
|
759
759
|
}
|
|
760
|
-
function
|
|
760
|
+
function F(e) {
|
|
761
761
|
return (e ?? "").trim().toLowerCase();
|
|
762
762
|
}
|
|
763
|
-
var
|
|
763
|
+
var Je = {
|
|
764
764
|
hevc: "hvc1.1.6.L93.90",
|
|
765
765
|
dv: "dvh1.05.06",
|
|
766
766
|
av1: "av01.0.05M.08",
|
|
767
767
|
vp9: "vp09.00.10.08"
|
|
768
|
-
},
|
|
769
|
-
function
|
|
770
|
-
let t =
|
|
768
|
+
}, Ye = /* @__PURE__ */ new Map(), I = /* @__PURE__ */ new Map();
|
|
769
|
+
function Xe(e) {
|
|
770
|
+
let t = F(e), n = Ye.get(t);
|
|
771
771
|
if (n) return n;
|
|
772
772
|
let r = {
|
|
773
773
|
initDataTypes: ["cenc"],
|
|
@@ -776,32 +776,32 @@ function Ye(e) {
|
|
|
776
776
|
sessionTypes: ["temporary"],
|
|
777
777
|
videoCapabilities: [{
|
|
778
778
|
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
779
|
-
robustness:
|
|
780
|
-
encryptionScheme:
|
|
779
|
+
robustness: N.video,
|
|
780
|
+
encryptionScheme: N.scheme
|
|
781
781
|
}]
|
|
782
782
|
}, i = (async () => {
|
|
783
783
|
try {
|
|
784
|
-
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha",
|
|
784
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", M("com.widevine.alpha", [r])), !0;
|
|
785
785
|
} catch {
|
|
786
786
|
return !1;
|
|
787
787
|
}
|
|
788
|
-
})().then((e) => (
|
|
789
|
-
return
|
|
788
|
+
})().then((e) => (I.set(t, e), e));
|
|
789
|
+
return Ye.set(t, i), i;
|
|
790
790
|
}
|
|
791
|
-
function
|
|
792
|
-
if (
|
|
791
|
+
function Ze() {
|
|
792
|
+
if (A()) for (let e of Object.values(Je)) Xe(e);
|
|
793
793
|
}
|
|
794
|
-
function
|
|
795
|
-
let t =
|
|
796
|
-
if (t) return t === "avc" ? !0 :
|
|
794
|
+
function Qe(e) {
|
|
795
|
+
let t = P(e);
|
|
796
|
+
if (t) return t === "avc" ? !0 : I.get(F(e)) ?? I.get(F(Je[t]));
|
|
797
797
|
}
|
|
798
798
|
//#endregion
|
|
799
799
|
//#region src/core/drm/support.ts
|
|
800
|
-
var
|
|
800
|
+
var $e = 5e3, et = "video/mp4; codecs=\"avc1.42E01E\"", tt = "audio/mp4; codecs=\"mp4a.40.2\"", nt = {
|
|
801
801
|
widevine: ["com.widevine.alpha"],
|
|
802
802
|
fairplay: ["com.apple.fps"]
|
|
803
803
|
};
|
|
804
|
-
function
|
|
804
|
+
function rt(e) {
|
|
805
805
|
return e === "fairplay" ? [{
|
|
806
806
|
initDataTypes: [
|
|
807
807
|
"sinf",
|
|
@@ -809,30 +809,30 @@ function nt(e) {
|
|
|
809
809
|
"cenc"
|
|
810
810
|
],
|
|
811
811
|
videoCapabilities: [{
|
|
812
|
-
contentType:
|
|
812
|
+
contentType: et,
|
|
813
813
|
robustness: "",
|
|
814
814
|
encryptionScheme: "cbcs"
|
|
815
815
|
}],
|
|
816
816
|
audioCapabilities: [{
|
|
817
|
-
contentType:
|
|
817
|
+
contentType: tt,
|
|
818
818
|
robustness: "",
|
|
819
819
|
encryptionScheme: "cbcs"
|
|
820
820
|
}]
|
|
821
|
-
}] :
|
|
821
|
+
}] : M("com.widevine.alpha", [{
|
|
822
822
|
initDataTypes: ["cenc"],
|
|
823
823
|
videoCapabilities: [{
|
|
824
|
-
contentType:
|
|
825
|
-
robustness:
|
|
826
|
-
encryptionScheme:
|
|
824
|
+
contentType: et,
|
|
825
|
+
robustness: N.video,
|
|
826
|
+
encryptionScheme: N.scheme
|
|
827
827
|
}],
|
|
828
828
|
audioCapabilities: [{
|
|
829
|
-
contentType:
|
|
830
|
-
robustness:
|
|
831
|
-
encryptionScheme:
|
|
829
|
+
contentType: tt,
|
|
830
|
+
robustness: N.audio,
|
|
831
|
+
encryptionScheme: N.scheme
|
|
832
832
|
}]
|
|
833
833
|
}]);
|
|
834
834
|
}
|
|
835
|
-
function
|
|
835
|
+
function it(e, t) {
|
|
836
836
|
return new Promise((n, r) => {
|
|
837
837
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
838
838
|
e.then((e) => {
|
|
@@ -842,8 +842,8 @@ function rt(e, t) {
|
|
|
842
842
|
});
|
|
843
843
|
});
|
|
844
844
|
}
|
|
845
|
-
async function
|
|
846
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
845
|
+
async function at(e = {}) {
|
|
846
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? $e, r = {};
|
|
847
847
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
848
848
|
verdict: "insecure-context",
|
|
849
849
|
detail: r
|
|
@@ -855,7 +855,7 @@ async function it(e = {}) {
|
|
|
855
855
|
};
|
|
856
856
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
857
857
|
for (let e of t) {
|
|
858
|
-
let t =
|
|
858
|
+
let t = nt[e];
|
|
859
859
|
if (!t) {
|
|
860
860
|
r[e] = "unknown system";
|
|
861
861
|
continue;
|
|
@@ -866,7 +866,7 @@ async function it(e = {}) {
|
|
|
866
866
|
break;
|
|
867
867
|
}
|
|
868
868
|
try {
|
|
869
|
-
return await
|
|
869
|
+
return await it((await it(i(n, rt(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
870
870
|
verdict: "supported",
|
|
871
871
|
system: e,
|
|
872
872
|
detail: r
|
|
@@ -890,32 +890,32 @@ async function it(e = {}) {
|
|
|
890
890
|
}
|
|
891
891
|
//#endregion
|
|
892
892
|
//#region src/core/manifest.ts
|
|
893
|
-
var
|
|
894
|
-
function
|
|
895
|
-
return
|
|
893
|
+
var ot = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
894
|
+
function st(e) {
|
|
895
|
+
return ot.test(e);
|
|
896
896
|
}
|
|
897
897
|
//#endregion
|
|
898
898
|
//#region src/core/env.ts
|
|
899
|
-
var
|
|
899
|
+
var ct = {
|
|
900
900
|
integration: "https://feed-dev.oddin-video.gg",
|
|
901
901
|
production: "https://feed.oddin-video.gg"
|
|
902
902
|
};
|
|
903
|
-
function
|
|
904
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
903
|
+
function lt(e) {
|
|
904
|
+
let t = Object.prototype.hasOwnProperty.call(ct, e) ? ct[e] : void 0;
|
|
905
905
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
906
906
|
return t;
|
|
907
907
|
}
|
|
908
908
|
//#endregion
|
|
909
909
|
//#region src/core/connectivity.ts
|
|
910
|
-
function
|
|
910
|
+
function L() {
|
|
911
911
|
return typeof navigator > "u" || navigator.onLine !== !1;
|
|
912
912
|
}
|
|
913
|
-
function
|
|
913
|
+
function ut() {
|
|
914
914
|
let e = /* @__PURE__ */ new Set(), t = (t) => {
|
|
915
915
|
for (let n of Array.from(e)) n(t);
|
|
916
916
|
}, n = () => t(!0), r = () => t(!1), i = typeof window < "u" && typeof window.addEventListener == "function";
|
|
917
917
|
return i && (window.addEventListener("online", n), window.addEventListener("offline", r)), {
|
|
918
|
-
isOnline:
|
|
918
|
+
isOnline: L,
|
|
919
919
|
onChange(t) {
|
|
920
920
|
return e.add(t), () => {
|
|
921
921
|
e.delete(t);
|
|
@@ -928,32 +928,32 @@ function lt() {
|
|
|
928
928
|
}
|
|
929
929
|
//#endregion
|
|
930
930
|
//#region src/core/stats.ts
|
|
931
|
-
var
|
|
932
|
-
function
|
|
931
|
+
var dt = { droppedFrames: 0 };
|
|
932
|
+
function ft(e) {
|
|
933
933
|
try {
|
|
934
934
|
return new URL(e).host;
|
|
935
935
|
} catch {
|
|
936
936
|
return "";
|
|
937
937
|
}
|
|
938
938
|
}
|
|
939
|
-
var
|
|
940
|
-
function
|
|
939
|
+
var pt = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
940
|
+
function mt(e) {
|
|
941
941
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
942
942
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
943
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
944
|
-
let e =
|
|
943
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || pt.test(i.name)) && i.startTime >= n) {
|
|
944
|
+
let e = ft(i.name);
|
|
945
945
|
e && (t = e, n = i.startTime);
|
|
946
946
|
}
|
|
947
947
|
return t;
|
|
948
948
|
}
|
|
949
|
-
function
|
|
949
|
+
function R(e) {
|
|
950
950
|
let t = e.getVideoPlaybackQuality?.();
|
|
951
951
|
return {
|
|
952
952
|
dropped: t?.droppedVideoFrames ?? 0,
|
|
953
953
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
954
954
|
};
|
|
955
955
|
}
|
|
956
|
-
var
|
|
956
|
+
var ht = class {
|
|
957
957
|
video;
|
|
958
958
|
baseFrames = 0;
|
|
959
959
|
baseDropped = 0;
|
|
@@ -963,7 +963,7 @@ var mt = class {
|
|
|
963
963
|
this.video = e;
|
|
964
964
|
}
|
|
965
965
|
read() {
|
|
966
|
-
let e =
|
|
966
|
+
let e = R(this.video);
|
|
967
967
|
return e.totalFrames < this.lastFrames && (this.baseFrames += this.lastFrames), e.dropped < this.lastDropped && (this.baseDropped += this.lastDropped), this.lastFrames = e.totalFrames, this.lastDropped = e.dropped, {
|
|
968
968
|
dropped: this.baseDropped + e.dropped,
|
|
969
969
|
totalFrames: this.baseFrames + e.totalFrames
|
|
@@ -976,7 +976,7 @@ var mt = class {
|
|
|
976
976
|
};
|
|
977
977
|
}
|
|
978
978
|
};
|
|
979
|
-
function
|
|
979
|
+
function gt(e, t) {
|
|
980
980
|
let n = [
|
|
981
981
|
["playing", () => t("playing")],
|
|
982
982
|
["waiting", () => t("buffering")],
|
|
@@ -993,8 +993,8 @@ function ht(e, t) {
|
|
|
993
993
|
}
|
|
994
994
|
//#endregion
|
|
995
995
|
//#region src/core/engine/native.ts
|
|
996
|
-
var
|
|
997
|
-
function
|
|
996
|
+
var _t = 2e3, vt = 3, z = 500, yt = 6e3, bt = .25, xt = 250, St = .05, Ct = 4, wt = 12e3, Tt = .25, Et = 1e3;
|
|
997
|
+
function Dt(e) {
|
|
998
998
|
try {
|
|
999
999
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
1000
1000
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -1002,20 +1002,20 @@ function Et(e) {
|
|
|
1002
1002
|
return;
|
|
1003
1003
|
}
|
|
1004
1004
|
}
|
|
1005
|
-
function
|
|
1005
|
+
function B(e) {
|
|
1006
1006
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
1007
1007
|
}
|
|
1008
|
-
function
|
|
1008
|
+
function V() {
|
|
1009
1009
|
if (typeof window > "u") return !1;
|
|
1010
1010
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
1011
1011
|
return e || t;
|
|
1012
1012
|
}
|
|
1013
|
-
function
|
|
1014
|
-
if (typeof navigator > "u" || !
|
|
1013
|
+
function Ot() {
|
|
1014
|
+
if (typeof navigator > "u" || !V()) return !1;
|
|
1015
1015
|
let e = navigator.userAgent ?? "";
|
|
1016
1016
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
1017
1017
|
}
|
|
1018
|
-
var
|
|
1018
|
+
var H = class {
|
|
1019
1019
|
name = "native";
|
|
1020
1020
|
deps;
|
|
1021
1021
|
onLoaded;
|
|
@@ -1045,7 +1045,7 @@ var U = class {
|
|
|
1045
1045
|
frameCounter;
|
|
1046
1046
|
detachFrames = null;
|
|
1047
1047
|
constructor(e) {
|
|
1048
|
-
this.deps = e, this.frameCounter = new
|
|
1048
|
+
this.deps = e, this.frameCounter = new ht(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
|
|
1049
1049
|
}
|
|
1050
1050
|
async load() {
|
|
1051
1051
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1064,9 +1064,9 @@ var U = class {
|
|
|
1064
1064
|
let i = !this.loadStarted;
|
|
1065
1065
|
this.onLoaded = i ? void 0 : () => r({ type: "ready" }), this.onError = () => r({
|
|
1066
1066
|
type: "error",
|
|
1067
|
-
error:
|
|
1067
|
+
error: L() ? new n("INTERNAL", 0, "native HLS playback error") : new n("NETWORK", 0, "native HLS playback error while offline"),
|
|
1068
1068
|
fatal: !0
|
|
1069
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
1069
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = At(t.manifestUrl, t.analytics?.sid), e.load();
|
|
1070
1070
|
}
|
|
1071
1071
|
startLoad() {
|
|
1072
1072
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -1094,7 +1094,7 @@ var U = class {
|
|
|
1094
1094
|
};
|
|
1095
1095
|
this.onEncrypted = (n) => {
|
|
1096
1096
|
let a = n;
|
|
1097
|
-
a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
1097
|
+
a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Dt(a.initData), (async () => {
|
|
1098
1098
|
try {
|
|
1099
1099
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
1100
1100
|
initDataTypes: [a.initDataType],
|
|
@@ -1194,10 +1194,10 @@ var U = class {
|
|
|
1194
1194
|
droppedFrames: t.dropped,
|
|
1195
1195
|
decodedFrames: t.totalFrames
|
|
1196
1196
|
};
|
|
1197
|
-
if (this.cdnHost ||=
|
|
1197
|
+
if (this.cdnHost ||= mt(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1198
1198
|
n.isLive = !0;
|
|
1199
1199
|
let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
|
|
1200
|
-
Number.isFinite(r) && (n.atLiveEdge = r <=
|
|
1200
|
+
Number.isFinite(r) && (n.atLiveEdge = r <= Ct, !e.paused && r >= 0 && (n.latencySeconds = r));
|
|
1201
1201
|
} else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
|
|
1202
1202
|
return n;
|
|
1203
1203
|
}
|
|
@@ -1209,30 +1209,30 @@ var U = class {
|
|
|
1209
1209
|
}
|
|
1210
1210
|
watchRefocus() {
|
|
1211
1211
|
this.deps.snapToLiveOnRefocus === !1 || typeof document > "u" || this.onVisibility || (this.onVisibility = () => {
|
|
1212
|
-
let e =
|
|
1212
|
+
let e = U();
|
|
1213
1213
|
if (document.visibilityState === "hidden") {
|
|
1214
1214
|
this.hiddenSince = e, this.cancelRefocus();
|
|
1215
1215
|
return;
|
|
1216
1216
|
}
|
|
1217
1217
|
let t = this.hiddenSince;
|
|
1218
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1218
|
+
this.hiddenSince = null, t != null && e - t >= _t && this.armRefocus();
|
|
1219
1219
|
}, this.onPageShow = (e) => {
|
|
1220
1220
|
e.persisted && this.armRefocus();
|
|
1221
1221
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
1222
1222
|
}
|
|
1223
1223
|
armRefocus() {
|
|
1224
1224
|
if (this.cancelRefocus(), Number.isFinite(this.deps.video.duration)) return;
|
|
1225
|
-
let e = this.liveEnd(), t =
|
|
1225
|
+
let e = this.liveEnd(), t = U, n = t(), r = 0, i = () => {
|
|
1226
1226
|
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1227
|
-
r +=
|
|
1228
|
-
let a = this.liveEnd(), o = a != null && (e == null || a >= e +
|
|
1227
|
+
r += z;
|
|
1228
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + bt), s = Math.max(r, t() - n) >= yt;
|
|
1229
1229
|
if (o || s && a != null) {
|
|
1230
1230
|
this.snapToLive();
|
|
1231
1231
|
return;
|
|
1232
1232
|
}
|
|
1233
|
-
this.refocusTimer = setTimeout(i,
|
|
1233
|
+
this.refocusTimer = setTimeout(i, z);
|
|
1234
1234
|
};
|
|
1235
|
-
this.refocusTimer = setTimeout(i,
|
|
1235
|
+
this.refocusTimer = setTimeout(i, z);
|
|
1236
1236
|
}
|
|
1237
1237
|
cancelRefocus() {
|
|
1238
1238
|
this.refocusTimer != null && clearTimeout(this.refocusTimer), this.refocusTimer = null;
|
|
@@ -1245,24 +1245,24 @@ var U = class {
|
|
|
1245
1245
|
}, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
|
|
1246
1246
|
if (e.duration !== Infinity) return;
|
|
1247
1247
|
this.checkEndStale();
|
|
1248
|
-
let t =
|
|
1249
|
-
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >=
|
|
1250
|
-
},
|
|
1248
|
+
let t = kt(e, e.currentTime);
|
|
1249
|
+
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= St) && (this.bufferedAdvancedAt = U()), this.lastBufferedEnd = t);
|
|
1250
|
+
}, xt);
|
|
1251
1251
|
}
|
|
1252
1252
|
checkEndStale() {
|
|
1253
1253
|
if (this.endedEmitted) return;
|
|
1254
|
-
let e =
|
|
1254
|
+
let e = U(), t = this.lastTickAt == null ? 0 : e - this.lastTickAt;
|
|
1255
1255
|
this.lastTickAt = e;
|
|
1256
1256
|
let n = this.liveEnd();
|
|
1257
1257
|
if (n == null) return;
|
|
1258
|
-
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >=
|
|
1258
|
+
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= Tt;
|
|
1259
1259
|
this.lastSeekableEnd = n;
|
|
1260
1260
|
let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
|
|
1261
|
-
if (r || t >
|
|
1261
|
+
if (r || t > Et || a || i.paused) {
|
|
1262
1262
|
this.edgeStampedAt = e;
|
|
1263
1263
|
return;
|
|
1264
1264
|
}
|
|
1265
|
-
e - (this.edgeStampedAt ?? e) >
|
|
1265
|
+
e - (this.edgeStampedAt ?? e) > wt && (this.endedEmitted = !0, this.deps.emit({
|
|
1266
1266
|
type: "ended",
|
|
1267
1267
|
reason: "stalled"
|
|
1268
1268
|
}));
|
|
@@ -1276,9 +1276,9 @@ var U = class {
|
|
|
1276
1276
|
liveEdgeEstimate() {
|
|
1277
1277
|
let e = this.deps.video;
|
|
1278
1278
|
if (e.duration !== Infinity) return null;
|
|
1279
|
-
let t = this.liveEnd(), n =
|
|
1279
|
+
let t = this.liveEnd(), n = kt(e, e.currentTime) ?? this.lastBufferedEnd;
|
|
1280
1280
|
if (n != null) {
|
|
1281
|
-
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (
|
|
1281
|
+
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (U() - e) / 1e3));
|
|
1282
1282
|
(t == null || r > t) && (t = r);
|
|
1283
1283
|
}
|
|
1284
1284
|
return t != null && Number.isFinite(t) ? t : null;
|
|
@@ -1292,7 +1292,7 @@ var U = class {
|
|
|
1292
1292
|
snapToLive() {
|
|
1293
1293
|
let e = this.deps.video, t = this.liveEnd();
|
|
1294
1294
|
if (t == null) return;
|
|
1295
|
-
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t -
|
|
1295
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - vt, r);
|
|
1296
1296
|
try {
|
|
1297
1297
|
e.currentTime = i;
|
|
1298
1298
|
} catch {}
|
|
@@ -1310,10 +1310,10 @@ var U = class {
|
|
|
1310
1310
|
} catch {}
|
|
1311
1311
|
}
|
|
1312
1312
|
};
|
|
1313
|
-
function
|
|
1313
|
+
function U() {
|
|
1314
1314
|
return typeof performance < "u" ? performance.now() : Date.now();
|
|
1315
1315
|
}
|
|
1316
|
-
function
|
|
1316
|
+
function kt(e, t) {
|
|
1317
1317
|
let n = e.buffered;
|
|
1318
1318
|
if (!n || !Number.isFinite(t)) return null;
|
|
1319
1319
|
for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
|
|
@@ -1322,12 +1322,12 @@ function Ot(e, t) {
|
|
|
1322
1322
|
}
|
|
1323
1323
|
return null;
|
|
1324
1324
|
}
|
|
1325
|
-
function
|
|
1325
|
+
function At(e, t) {
|
|
1326
1326
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1327
1327
|
}
|
|
1328
1328
|
//#endregion
|
|
1329
1329
|
//#region src/core/drm/signedUrl.ts
|
|
1330
|
-
function
|
|
1330
|
+
function W(e, t = Date.now()) {
|
|
1331
1331
|
if (!e) return !1;
|
|
1332
1332
|
let n;
|
|
1333
1333
|
try {
|
|
@@ -1339,13 +1339,13 @@ function G(e, t = Date.now()) {
|
|
|
1339
1339
|
}
|
|
1340
1340
|
//#endregion
|
|
1341
1341
|
//#region src/core/drm/xhrBody.ts
|
|
1342
|
-
var
|
|
1343
|
-
function
|
|
1342
|
+
var jt = 4096;
|
|
1343
|
+
function Mt(e) {
|
|
1344
1344
|
if (!e || typeof e != "object") return;
|
|
1345
1345
|
let { response: t } = e;
|
|
1346
1346
|
if (typeof t == "string") return t;
|
|
1347
1347
|
let n;
|
|
1348
|
-
if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength >
|
|
1348
|
+
if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength > jt)) try {
|
|
1349
1349
|
return new TextDecoder().decode(n);
|
|
1350
1350
|
} catch {
|
|
1351
1351
|
return;
|
|
@@ -1353,8 +1353,8 @@ function jt(e) {
|
|
|
1353
1353
|
}
|
|
1354
1354
|
//#endregion
|
|
1355
1355
|
//#region src/core/engine/prefetch.ts
|
|
1356
|
-
var
|
|
1357
|
-
function
|
|
1356
|
+
var Nt = 15e3, Pt = 5e3, Ft = 6, It = 4e3, Lt = 2;
|
|
1357
|
+
function G(e) {
|
|
1358
1358
|
try {
|
|
1359
1359
|
let t = new URL(e);
|
|
1360
1360
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1362,7 +1362,7 @@ function K(e) {
|
|
|
1362
1362
|
return e;
|
|
1363
1363
|
}
|
|
1364
1364
|
}
|
|
1365
|
-
var
|
|
1365
|
+
var Rt = class {
|
|
1366
1366
|
cmcd;
|
|
1367
1367
|
entries = /* @__PURE__ */ new Map();
|
|
1368
1368
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1391,20 +1391,20 @@ var Lt = class {
|
|
|
1391
1391
|
}
|
|
1392
1392
|
prefetch(e, t, n) {
|
|
1393
1393
|
if (!this.isActive(t)) return;
|
|
1394
|
-
let r =
|
|
1394
|
+
let r = G(e);
|
|
1395
1395
|
if (this.entries.has(r)) return;
|
|
1396
1396
|
let i = this.perTrack.get(t) ?? 0;
|
|
1397
|
-
i >=
|
|
1397
|
+
i >= Ft || (this.perTrack.set(t, i + 1), this.start(r, this.withCmcd(e, t, n), !1, Nt), this.stats.started += 1);
|
|
1398
1398
|
}
|
|
1399
1399
|
prefetchHint(e, t) {
|
|
1400
|
-
let n =
|
|
1400
|
+
let n = G(e);
|
|
1401
1401
|
if (this.entries.has(n)) return;
|
|
1402
1402
|
let r = this.hints.get(t) ?? [];
|
|
1403
|
-
for (; r.length >=
|
|
1403
|
+
for (; r.length >= Lt;) {
|
|
1404
1404
|
let e = r.shift();
|
|
1405
1405
|
e !== void 0 && this.drop(e) && (this.stats.hintDropped += 1);
|
|
1406
1406
|
}
|
|
1407
|
-
r.push(n), this.hints.set(t, r), this.start(n, this.withCmcd(e, t, "media"), !0,
|
|
1407
|
+
r.push(n), this.hints.set(t, r), this.start(n, this.withCmcd(e, t, "media"), !0, It), this.stats.hintStarted += 1;
|
|
1408
1408
|
}
|
|
1409
1409
|
dropHints(e) {
|
|
1410
1410
|
for (let t of this.hints.get(e) ?? []) this.drop(t) && (this.stats.hintDropped += 1);
|
|
@@ -1437,7 +1437,7 @@ var Lt = class {
|
|
|
1437
1437
|
}, r);
|
|
1438
1438
|
}
|
|
1439
1439
|
take(e) {
|
|
1440
|
-
let t =
|
|
1440
|
+
let t = G(e), n = this.entries.get(t);
|
|
1441
1441
|
return n && this.entries.delete(t), n;
|
|
1442
1442
|
}
|
|
1443
1443
|
destroy() {
|
|
@@ -1457,14 +1457,14 @@ var Lt = class {
|
|
|
1457
1457
|
}
|
|
1458
1458
|
}
|
|
1459
1459
|
};
|
|
1460
|
-
function
|
|
1461
|
-
let
|
|
1462
|
-
if (typeof
|
|
1463
|
-
class
|
|
1460
|
+
function zt(t, n) {
|
|
1461
|
+
let r = typeof n == "function" ? n : e.DefaultConfig?.loader;
|
|
1462
|
+
if (typeof r != "function") return;
|
|
1463
|
+
class i extends r {
|
|
1464
1464
|
served = !1;
|
|
1465
1465
|
cancelled = !1;
|
|
1466
1466
|
entry;
|
|
1467
|
-
stats =
|
|
1467
|
+
stats = Bt();
|
|
1468
1468
|
load(e, n, r) {
|
|
1469
1469
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1470
1470
|
if (!i) {
|
|
@@ -1476,7 +1476,7 @@ function Rt(t) {
|
|
|
1476
1476
|
i.hint ? t.stats.hintFailed += 1 : t.stats.failed += 1;
|
|
1477
1477
|
}, s = () => {
|
|
1478
1478
|
!this.cancelled && this.served && (i.abort.abort(), o(), this.served = !1, this.entry = void 0, super.load(e, n, r));
|
|
1479
|
-
}, c = n?.loadPolicy, l = c?.maxTimeToFirstByteMs ||
|
|
1479
|
+
}, c = n?.loadPolicy, l = c?.maxTimeToFirstByteMs || Pt, u = setTimeout(s, l);
|
|
1480
1480
|
i.headers.then(() => {
|
|
1481
1481
|
clearTimeout(u);
|
|
1482
1482
|
let e = c?.maxLoadTimeMs;
|
|
@@ -1507,9 +1507,9 @@ function Rt(t) {
|
|
|
1507
1507
|
super.abort();
|
|
1508
1508
|
}
|
|
1509
1509
|
}
|
|
1510
|
-
return
|
|
1510
|
+
return i;
|
|
1511
1511
|
}
|
|
1512
|
-
function
|
|
1512
|
+
function Bt() {
|
|
1513
1513
|
return {
|
|
1514
1514
|
aborted: !1,
|
|
1515
1515
|
loaded: 0,
|
|
@@ -1533,10 +1533,10 @@ function zt() {
|
|
|
1533
1533
|
}
|
|
1534
1534
|
};
|
|
1535
1535
|
}
|
|
1536
|
-
function
|
|
1536
|
+
function Vt(e) {
|
|
1537
1537
|
return e === "audio" ? "audio" : "main";
|
|
1538
1538
|
}
|
|
1539
|
-
function
|
|
1539
|
+
function Ht(e, t) {
|
|
1540
1540
|
let n = [];
|
|
1541
1541
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1542
1542
|
url: t.initSegment.url,
|
|
@@ -1553,7 +1553,7 @@ function Vt(e, t) {
|
|
|
1553
1553
|
});
|
|
1554
1554
|
return n;
|
|
1555
1555
|
}
|
|
1556
|
-
function
|
|
1556
|
+
function Ut(e) {
|
|
1557
1557
|
let t = e, n = t?.preloadHint;
|
|
1558
1558
|
if (!n || !t?.url || n.TYPE !== "PART" || n["BYTERANGE-START"] !== void 0 || n["BYTERANGE-LENGTH"] !== void 0) return null;
|
|
1559
1559
|
let r = n.URI;
|
|
@@ -1566,16 +1566,16 @@ function Ht(e) {
|
|
|
1566
1566
|
}
|
|
1567
1567
|
//#endregion
|
|
1568
1568
|
//#region src/core/percentile.ts
|
|
1569
|
-
function
|
|
1569
|
+
function K(e, t) {
|
|
1570
1570
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1571
1571
|
}
|
|
1572
1572
|
//#endregion
|
|
1573
1573
|
//#region src/core/engine/hls.ts
|
|
1574
|
-
function
|
|
1574
|
+
function Wt() {
|
|
1575
1575
|
return e.isSupported();
|
|
1576
1576
|
}
|
|
1577
|
-
var
|
|
1578
|
-
function
|
|
1577
|
+
var Gt = 3, Kt = 1e6, qt = 20, Jt = 1e4, Yt = 3, Xt = 5, Zt = 3, Qt = 1e4, $t = 3e4, en = 12e3, tn = 3e3, nn = .02, rn = 6e3, an = .5, on = 3, sn = .5, cn = 1.1, ln = .25, un = 5e3, dn = 4e3, fn = 2, pn = 5, mn = 2, hn = 2, gn = 4, _n = 4, vn = 2e3, yn = 3e4, bn = 1, xn = 2, Sn = .5, Cn = .6, wn = 2, Tn = 1.5, En = 1e4, q = 8, Dn = 12e4, On = 6e4;
|
|
1578
|
+
function J(e, t, n) {
|
|
1579
1579
|
if (n <= 0 || t < 0 || t >= e.length) return t;
|
|
1580
1580
|
let r = (t, n) => e[t].width === e[n].width && e[t].height === e[n].height, i = (t) => {
|
|
1581
1581
|
for (; t + 1 < e.length && r(t + 1, t);) t++;
|
|
@@ -1584,11 +1584,14 @@ function xn(e, t, n) {
|
|
|
1584
1584
|
for (let t = 0; t < n && a + 1 < e.length; t++) a = i(a + 1);
|
|
1585
1585
|
return a;
|
|
1586
1586
|
}
|
|
1587
|
-
|
|
1588
|
-
|
|
1587
|
+
function Y() {
|
|
1588
|
+
return typeof self < "u" && self.devicePixelRatio > 0 ? self.devicePixelRatio : 1;
|
|
1589
|
+
}
|
|
1590
|
+
var kn = .2, An = 30, jn = 2, Mn = 2, Nn = 2, Pn = 9, Fn = .5, In = 64, Ln = 1e4, Rn = 8, zn = .6, Bn = .4, Vn = .4, Hn = 2, Un = 6e4, X = .5, Wn = 3.5, Gn = 300;
|
|
1591
|
+
function Kn(e) {
|
|
1589
1592
|
return (e?.part ?? e?.frag)?.stats;
|
|
1590
1593
|
}
|
|
1591
|
-
function
|
|
1594
|
+
function qn() {
|
|
1592
1595
|
if (typeof navigator > "u") return 0;
|
|
1593
1596
|
try {
|
|
1594
1597
|
let e = navigator.connection?.rtt;
|
|
@@ -1597,20 +1600,20 @@ function Bn() {
|
|
|
1597
1600
|
return 0;
|
|
1598
1601
|
}
|
|
1599
1602
|
}
|
|
1600
|
-
function
|
|
1603
|
+
function Jn(e) {
|
|
1601
1604
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1602
1605
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1603
1606
|
return;
|
|
1604
1607
|
}
|
|
1605
|
-
e.liveSyncDuration ??=
|
|
1606
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1607
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1608
|
+
e.liveSyncDuration ??= Nn;
|
|
1609
|
+
let t = Math.max(12, e.liveSyncDuration + Pn);
|
|
1610
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Yn(e, e.liveSyncDuration);
|
|
1608
1611
|
}
|
|
1609
|
-
function
|
|
1612
|
+
function Yn(e, t) {
|
|
1610
1613
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1611
1614
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1612
1615
|
}
|
|
1613
|
-
var
|
|
1616
|
+
var Xn = class {
|
|
1614
1617
|
name = "hls";
|
|
1615
1618
|
hls = null;
|
|
1616
1619
|
deps;
|
|
@@ -1641,6 +1644,7 @@ var Un = class {
|
|
|
1641
1644
|
networkRetryTimer = null;
|
|
1642
1645
|
licenseRetryTimer = null;
|
|
1643
1646
|
offlineHold = !1;
|
|
1647
|
+
onOffline = null;
|
|
1644
1648
|
onOnline = null;
|
|
1645
1649
|
onVisibility = null;
|
|
1646
1650
|
onSeeking = null;
|
|
@@ -1678,6 +1682,12 @@ var Un = class {
|
|
|
1678
1682
|
liveRetargets = 0;
|
|
1679
1683
|
holdBackEnabled;
|
|
1680
1684
|
holdBackSamples = [];
|
|
1685
|
+
headroomSamples = [];
|
|
1686
|
+
headroomGranted = !1;
|
|
1687
|
+
lastStallAt = 0;
|
|
1688
|
+
headroomRegrantAt = 0;
|
|
1689
|
+
headroomUngated = !1;
|
|
1690
|
+
playingSince = 0;
|
|
1681
1691
|
holdBackBase = -1;
|
|
1682
1692
|
holdBackStepCount = 0;
|
|
1683
1693
|
holdBackApplied = 0;
|
|
@@ -1706,11 +1716,11 @@ var Un = class {
|
|
|
1706
1716
|
frameCounter;
|
|
1707
1717
|
detachFrames = null;
|
|
1708
1718
|
constructor(e) {
|
|
1709
|
-
this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.frameCounter = new
|
|
1719
|
+
this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.frameCounter = new ht(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1710
1720
|
}
|
|
1711
1721
|
async load() {
|
|
1712
1722
|
this.detachFrames ??= this.frameCounter.attach();
|
|
1713
|
-
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a =
|
|
1723
|
+
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = B(r) && V(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
1714
1724
|
if (e.drmEnabled && !o) {
|
|
1715
1725
|
i({
|
|
1716
1726
|
type: "error",
|
|
@@ -1719,21 +1729,23 @@ var Un = class {
|
|
|
1719
1729
|
});
|
|
1720
1730
|
return;
|
|
1721
1731
|
}
|
|
1722
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1732
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (qe(r), Ze()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1723
1733
|
let e = this.hls;
|
|
1724
1734
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1725
1735
|
let t = e.liveSyncPosition;
|
|
1726
1736
|
if (typeof t != "number") return;
|
|
1727
1737
|
let n = typeof e.targetLatency == "number" && e.targetLatency > 0 ? e.targetLatency : 3;
|
|
1728
1738
|
t - r.currentTime > Math.max(n * 3, 8) && (r.currentTime = t);
|
|
1729
|
-
}, document.addEventListener("visibilitychange", this.onVisibility)), typeof window < "u" && (this.
|
|
1730
|
-
|
|
1739
|
+
}, document.addEventListener("visibilitychange", this.onVisibility)), typeof window < "u" && (this.onOffline = () => {
|
|
1740
|
+
this.offlineHold = !0, this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.lastAdvanceMs = this.lastAdvanceMs ? Date.now() : 0, this.resetStarvationWindow(), this.clearKick();
|
|
1741
|
+
}, this.onOnline = () => {
|
|
1742
|
+
if (this.offlineHold && (this.offlineHold = !1, this.networkRecoveries = 0, this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), !this.stopped && this.hls && this.loadStarted && !this.loadSuspended)) {
|
|
1731
1743
|
this.lastAdvanceMs = Date.now(), this.lastFragLoadingMs = 0, this.resetStarvationWindow(), this.resetChaseWindow(), this.clearKick();
|
|
1732
1744
|
try {
|
|
1733
|
-
this.hls.startLoad();
|
|
1745
|
+
this.hls.startLoad(-1);
|
|
1734
1746
|
} catch {}
|
|
1735
1747
|
}
|
|
1736
|
-
}, window.addEventListener("online", this.onOnline)), this.onSeeking = () => {
|
|
1748
|
+
}, window.addEventListener("offline", this.onOffline), window.addEventListener("online", this.onOnline), L() || this.onOffline()), this.onSeeking = () => {
|
|
1737
1749
|
this.clampOverSeek(), this.loadSuspended && (this.resumeLoading(), this.schedulePauseSuspend());
|
|
1738
1750
|
}, r.addEventListener("seeking", this.onSeeking), this.onTimeUpdate = () => this.updateCatchUpBand(), r.addEventListener("timeupdate", this.onTimeUpdate), this.onPause = () => this.schedulePauseSuspend(), this.onPlay = () => this.resumeLoading(), r.addEventListener("pause", this.onPause), r.addEventListener("play", this.onPlay), this.sizeCapManaged && typeof ResizeObserver < "u" && (this.capObserver = new ResizeObserver(() => this.onMediaResize()), this.capObserver.observe(r), this.watchDprChanges());
|
|
1739
1751
|
}
|
|
@@ -1749,7 +1761,7 @@ var Un = class {
|
|
|
1749
1761
|
}
|
|
1750
1762
|
this.loadSuspended = !0;
|
|
1751
1763
|
}
|
|
1752
|
-
},
|
|
1764
|
+
}, un));
|
|
1753
1765
|
}
|
|
1754
1766
|
resumeLoading() {
|
|
1755
1767
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1765,7 +1777,7 @@ var Un = class {
|
|
|
1765
1777
|
watchDprChanges() {
|
|
1766
1778
|
if (typeof matchMedia != "function") return;
|
|
1767
1779
|
this.unwatchDprChanges();
|
|
1768
|
-
let e =
|
|
1780
|
+
let e = Y(), t = matchMedia(`(resolution: ${e}dppx)`);
|
|
1769
1781
|
if (typeof t.addEventListener != "function") return;
|
|
1770
1782
|
let n = () => {
|
|
1771
1783
|
this.onMediaResize(), this.watchDprChanges();
|
|
@@ -1781,7 +1793,7 @@ var Un = class {
|
|
|
1781
1793
|
let t = e.liveSyncPosition;
|
|
1782
1794
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1783
1795
|
let { video: n } = this.deps;
|
|
1784
|
-
n.currentTime <= t +
|
|
1796
|
+
n.currentTime <= t + Fn || (n.currentTime = t);
|
|
1785
1797
|
}
|
|
1786
1798
|
reanchorPartTimeline(e, t) {
|
|
1787
1799
|
let { frag: n, part: r } = t;
|
|
@@ -1793,7 +1805,7 @@ var Un = class {
|
|
|
1793
1805
|
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1794
1806
|
if (!s) return;
|
|
1795
1807
|
let c = a.startPTS - s.start;
|
|
1796
|
-
if (!(!Number.isFinite(c) || Math.abs(c) <
|
|
1808
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < nn)) {
|
|
1797
1809
|
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1798
1810
|
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})`);
|
|
1799
1811
|
}
|
|
@@ -1801,7 +1813,7 @@ var Un = class {
|
|
|
1801
1813
|
startHls() {
|
|
1802
1814
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
1803
1815
|
this.clearKick(), this.resetStarvationWindow(), this.resetChaseWindow(), this.resetFrameDropWindow(), this.lastFragLoadingMs = 0, this.lastEndSN = -1, this.lastAdvanceMs = 0;
|
|
1804
|
-
let u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d =
|
|
1816
|
+
let u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d = B(this.deps.video) && V(), f = {
|
|
1805
1817
|
debug: s === !0,
|
|
1806
1818
|
enableWorker: !o,
|
|
1807
1819
|
lowLatencyMode: o,
|
|
@@ -1816,24 +1828,24 @@ var Un = class {
|
|
|
1816
1828
|
emeEnabled: !0,
|
|
1817
1829
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1818
1830
|
drmSystemOptions: {
|
|
1819
|
-
videoRobustness:
|
|
1820
|
-
audioRobustness:
|
|
1821
|
-
videoEncryptionScheme:
|
|
1822
|
-
audioEncryptionScheme:
|
|
1831
|
+
videoRobustness: N.video,
|
|
1832
|
+
audioRobustness: N.audio,
|
|
1833
|
+
videoEncryptionScheme: N.scheme,
|
|
1834
|
+
audioEncryptionScheme: N.scheme
|
|
1823
1835
|
},
|
|
1824
|
-
...
|
|
1836
|
+
...A() ? { requestMediaKeySystemAccessFunc: Ke(t) } : {},
|
|
1825
1837
|
licenseXhrSetup: (e, t) => {
|
|
1826
1838
|
let o = performance.now(), s = () => {
|
|
1827
1839
|
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", () => {
|
|
1828
1840
|
this.licenseTimeMs === 0 && (this.licenseTimeMs = Math.max(1, Math.round(performance.now() - o)));
|
|
1829
1841
|
});
|
|
1830
1842
|
}, { freshLicenseUrl: c } = this.deps;
|
|
1831
|
-
if (!c || !
|
|
1843
|
+
if (!c || !W(this.licenseUrl)) {
|
|
1832
1844
|
s();
|
|
1833
1845
|
return;
|
|
1834
1846
|
}
|
|
1835
1847
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1836
|
-
u = setTimeout(() => e(void 0),
|
|
1848
|
+
u = setTimeout(() => e(void 0), Qt);
|
|
1837
1849
|
});
|
|
1838
1850
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1839
1851
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1849,51 +1861,51 @@ var Un = class {
|
|
|
1849
1861
|
...c
|
|
1850
1862
|
};
|
|
1851
1863
|
this.prefetch?.destroy(), this.prefetch = null;
|
|
1852
|
-
let p = !1, m = !1, h = u && this.deps.mediaDuringKey !== !1, g = this.deps.preloadHints
|
|
1864
|
+
let p = !1, m = !1, h = u && this.deps.mediaDuringKey !== !1, g = this.deps.preloadHints !== !1;
|
|
1853
1865
|
if ((h || g) && !f.fLoader) {
|
|
1854
|
-
let e = new
|
|
1866
|
+
let e = new Rt({
|
|
1855
1867
|
sessionId: n.analytics?.sid,
|
|
1856
1868
|
contentId: n.matchUrn
|
|
1857
|
-
}), t =
|
|
1869
|
+
}), t = zt(e, f.loader);
|
|
1858
1870
|
t && (this.prefetch = e, p = h, m = g, f.fLoader = t);
|
|
1859
1871
|
}
|
|
1860
|
-
|
|
1872
|
+
Jn(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;
|
|
1861
1873
|
let _ = new e(f);
|
|
1862
1874
|
if (this.hls = _, this.armHoldBack(_, f), _.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(_, t)), _.on(e.Events.MANIFEST_PARSED, () => {
|
|
1863
1875
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(_), this.measureLadder(_), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1864
1876
|
}), _.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1865
1877
|
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(() => {
|
|
1866
1878
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1867
|
-
},
|
|
1879
|
+
}, $t)));
|
|
1868
1880
|
}), _.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1869
1881
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1870
1882
|
}), _.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
1871
1883
|
t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
|
|
1872
|
-
let n = t?.frag, r =
|
|
1884
|
+
let n = t?.frag, r = Kn(t), i = r?.loaded;
|
|
1873
1885
|
typeof i == "number" && (this.bytesLoaded += i), !this.reportedFirstBytes && typeof i == "number" && i > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1874
1886
|
let a = r?.loading;
|
|
1875
|
-
a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length >
|
|
1887
|
+
a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length > In && this.requestTimesMs.shift()), this.sampleHoldBack(t), this.sampleHeadroom(t);
|
|
1876
1888
|
let o = n?.url;
|
|
1877
1889
|
if (o) {
|
|
1878
|
-
let e =
|
|
1890
|
+
let e = ft(o);
|
|
1879
1891
|
e && (this.cdnHost = e);
|
|
1880
1892
|
}
|
|
1881
1893
|
}), _.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
1882
1894
|
let n = t?.stats?.loaded;
|
|
1883
1895
|
if (typeof n == "number" && (this.playlistBytesLoaded += n), this.reportedFirstPlaylist || (this.reportedFirstPlaylist = !0, l({ type: "firstPlaylist" })), this.detectedLowLatency) return;
|
|
1884
1896
|
let r = t.details;
|
|
1885
|
-
|
|
1897
|
+
r?.partList?.length || (r?.partTarget ?? 0) > 0 ? (this.detectedLowLatency = !0, l({
|
|
1886
1898
|
type: "lowLatencyDetected",
|
|
1887
1899
|
value: !0
|
|
1888
|
-
}));
|
|
1900
|
+
}), this.headroomUngated && (this.headroomUngated = !1, this.applySizeCapUnlessPending())) : r && !this.headroomUngated && (this.headroomUngated = !0, this.applySizeCapUnlessPending());
|
|
1889
1901
|
}), _.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch && m) {
|
|
1890
1902
|
let t = this.prefetch, n = this.deps.video, r = (e, r) => {
|
|
1891
1903
|
if (n.paused) return;
|
|
1892
1904
|
let i = e;
|
|
1893
1905
|
if (!i?.live || !i.partList?.length || typeof i.edge != "number") return;
|
|
1894
1906
|
let a = n.buffered, o = a.length ? a.end(a.length - 1) : 0;
|
|
1895
|
-
if (i.edge - o >
|
|
1896
|
-
let s =
|
|
1907
|
+
if (i.edge - o > Gt * (i.partTarget || .5)) return;
|
|
1908
|
+
let s = Ut(e);
|
|
1897
1909
|
s && t.prefetchHint(s, r);
|
|
1898
1910
|
};
|
|
1899
1911
|
_.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1905,15 +1917,15 @@ var Un = class {
|
|
|
1905
1917
|
if (this.prefetch && p) {
|
|
1906
1918
|
let t = this.prefetch;
|
|
1907
1919
|
_.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1908
|
-
let r = n?.frag, i =
|
|
1909
|
-
if (r && t.isActive(i)) for (let e of
|
|
1910
|
-
}), _.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1920
|
+
let r = n?.frag, i = Vt(r?.type);
|
|
1921
|
+
if (r && t.isActive(i)) for (let e of Ht(_, r)) t.prefetch(e.url, i, e.kind);
|
|
1922
|
+
}), _.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Vt(n?.frag?.type)));
|
|
1911
1923
|
}
|
|
1912
1924
|
_.on(e.Events.KEY_LOADED, () => {
|
|
1913
1925
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1914
1926
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1915
|
-
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.adaptHoldBack(), this.checkFrameDrops();
|
|
1916
|
-
},
|
|
1927
|
+
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.adaptHoldBack(), this.reviewSizeCapHeadroom(), this.checkFrameDrops();
|
|
1928
|
+
}, tn), _.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1917
1929
|
this.renditionSwitches += 1;
|
|
1918
1930
|
let n = this.lastLevelIndex >= 0 ? _.levels[this.lastLevelIndex] : void 0, r = _.levels[t.level];
|
|
1919
1931
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, this.armFrameDropGrace(), l({
|
|
@@ -1956,17 +1968,28 @@ var Un = class {
|
|
|
1956
1968
|
this.pushCap();
|
|
1957
1969
|
}
|
|
1958
1970
|
}
|
|
1959
|
-
|
|
1971
|
+
sizeCapCover() {
|
|
1960
1972
|
let e = this.hls;
|
|
1961
1973
|
if (!e || e.levels.length === 0) return null;
|
|
1962
1974
|
let { video: n } = this.deps, r = n.getBoundingClientRect(), i = r.width, a = r.height;
|
|
1963
1975
|
if (!i && !a && (i = n.width || 0, a = n.height || 0), !(i > 0) || !(a > 0)) return null;
|
|
1964
|
-
let o = e.config ?? {}, s =
|
|
1965
|
-
c = Math.min(c, o.maxDevicePixelRatio ?? Infinity)
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1976
|
+
let o = e.config ?? {}, s = Y(), c = o.ignoreDevicePixelRatio ? 1 : s;
|
|
1977
|
+
return c = Math.min(c, o.maxDevicePixelRatio ?? Infinity), {
|
|
1978
|
+
cover: t.getMaxLevelByMediaSize(e.levels, i * c, a * c),
|
|
1979
|
+
deviceRatio: s
|
|
1980
|
+
};
|
|
1981
|
+
}
|
|
1982
|
+
sizeCapCoverLevel() {
|
|
1983
|
+
return this.sizeCapCover()?.cover ?? null;
|
|
1984
|
+
}
|
|
1985
|
+
computeSizeCapTarget() {
|
|
1986
|
+
let e = this.hls, t = this.sizeCapCover();
|
|
1987
|
+
if (!e || !t) return null;
|
|
1988
|
+
let { cover: n, deviceRatio: r } = t, i = this.deps.sizeCapHeadroom, a = i == null || Number.isNaN(i);
|
|
1989
|
+
if (a && r >= xn) return n;
|
|
1990
|
+
if (a) return this.headroomUngated || this.headroomGranted ? J(e.levels, n, bn) : n;
|
|
1991
|
+
let o = i === Infinity ? e.levels.length : Math.max(0, Math.floor(i));
|
|
1992
|
+
return J(e.levels, n, o);
|
|
1970
1993
|
}
|
|
1971
1994
|
onMediaResize() {
|
|
1972
1995
|
if (!this.sizeCapManaged) return;
|
|
@@ -1981,9 +2004,11 @@ var Un = class {
|
|
|
1981
2004
|
return;
|
|
1982
2005
|
}
|
|
1983
2006
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1984
|
-
let t = e > this.sizeCapLevel ?
|
|
2007
|
+
let t = e > this.sizeCapLevel ? vn : yn;
|
|
1985
2008
|
this.capTimer = setTimeout(() => {
|
|
1986
|
-
this.capTimer = null
|
|
2009
|
+
this.capTimer = null;
|
|
2010
|
+
let n = this.computeSizeCapTarget();
|
|
2011
|
+
n === e || t === yn && n != null && n < e ? this.applySizeCap() : this.onMediaResize();
|
|
1987
2012
|
}, t);
|
|
1988
2013
|
}
|
|
1989
2014
|
measureLadder(e) {
|
|
@@ -1991,9 +2016,9 @@ var Un = class {
|
|
|
1991
2016
|
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;
|
|
1992
2017
|
}
|
|
1993
2018
|
dropLevelsWidevineCannotPlay(e) {
|
|
1994
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1995
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1996
|
-
for (let n of t)
|
|
2019
|
+
this.removeLevelsWhere(e, (e) => Qe(e) !== !0);
|
|
2020
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && P(e) !== "avc" && !!P(e)));
|
|
2021
|
+
for (let n of t) Xe(n).then((t) => {
|
|
1997
2022
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1998
2023
|
});
|
|
1999
2024
|
}
|
|
@@ -2001,13 +2026,69 @@ var Un = class {
|
|
|
2001
2026
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
2002
2027
|
if (n.forEach((e, n) => {
|
|
2003
2028
|
let a = e.videoCodec;
|
|
2004
|
-
a &&
|
|
2029
|
+
a && P(a) && t(a) && (r.push(n), i.add(a));
|
|
2005
2030
|
}), !r.length) return !1;
|
|
2006
2031
|
let a = [...i].join(", ");
|
|
2007
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !
|
|
2032
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !P(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;
|
|
2008
2033
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
2009
2034
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
2010
2035
|
}
|
|
2036
|
+
defaultHeadroomApplies() {
|
|
2037
|
+
let e = this.deps.sizeCapHeadroom;
|
|
2038
|
+
return e != null && !Number.isNaN(e) || this.headroomUngated ? !1 : Y() < xn;
|
|
2039
|
+
}
|
|
2040
|
+
applySizeCapUnlessPending() {
|
|
2041
|
+
this.capTimer || this.applySizeCap();
|
|
2042
|
+
}
|
|
2043
|
+
sampleHeadroom(e) {
|
|
2044
|
+
if (!this.sizeCapManaged || !this.defaultHeadroomApplies() || e.frag?.type !== "main" || typeof e.frag.level != "number" || typeof document < "u" && document.hidden) return;
|
|
2045
|
+
let t = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag.duration;
|
|
2046
|
+
if (typeof t != "number" || !(t > 0)) return;
|
|
2047
|
+
let n = Kn(e)?.loading;
|
|
2048
|
+
if (!n || !(n.start > 0) || !(n.end >= n.start)) return;
|
|
2049
|
+
let r = this.hls?.levels?.[e.frag.level]?.bitrate;
|
|
2050
|
+
if (!(typeof r == "number" && r > 0)) return;
|
|
2051
|
+
let i = (n.end - n.start) / (t * 1e3);
|
|
2052
|
+
this.headroomSamples.push({
|
|
2053
|
+
t: Date.now(),
|
|
2054
|
+
ratio: i,
|
|
2055
|
+
bitrate: r
|
|
2056
|
+
}), this.headroomSamples.length > 256 && this.headroomSamples.shift();
|
|
2057
|
+
}
|
|
2058
|
+
onPlaybackStall() {
|
|
2059
|
+
let e = Date.now();
|
|
2060
|
+
this.deps.video.seeking || !this.playingSince || e - this.playingSince < En || (this.lastStallAt = e, this.headroomGranted && (this.headroomGranted = !1, this.applySizeCapUnlessPending()));
|
|
2061
|
+
}
|
|
2062
|
+
reviewSizeCapHeadroom() {
|
|
2063
|
+
let e = Date.now(), { video: t } = this.deps;
|
|
2064
|
+
!t.paused && !t.seeking && t.readyState >= 3 ? this.playingSince ||= e : this.playingSince = 0;
|
|
2065
|
+
let n = this.hls;
|
|
2066
|
+
if (!n || !this.sizeCapManaged) return;
|
|
2067
|
+
if (!this.defaultHeadroomApplies()) {
|
|
2068
|
+
this.headroomGranted = !1, this.headroomSamples = [];
|
|
2069
|
+
return;
|
|
2070
|
+
}
|
|
2071
|
+
this.headroomSamples = this.headroomSamples.filter((t) => t.t >= e - Ln);
|
|
2072
|
+
let r = this.headroomEarned(n, e);
|
|
2073
|
+
r !== this.headroomGranted && (r || (this.headroomRegrantAt = e + On), this.headroomGranted = r, this.applySizeCapUnlessPending());
|
|
2074
|
+
}
|
|
2075
|
+
headroomEarned(e, t) {
|
|
2076
|
+
if (t - this.lastStallAt < Dn || !this.headroomGranted && t < this.headroomRegrantAt || !this.headroomGranted && this.headroomSamples.length < q) return !1;
|
|
2077
|
+
let n = e.levels, r = this.sizeCapCoverLevel();
|
|
2078
|
+
if (r == null) return this.headroomGranted;
|
|
2079
|
+
let i = J(n, r, bn);
|
|
2080
|
+
if (i === r) return this.headroomGranted;
|
|
2081
|
+
let a = n[i]?.bitrate, o = e.bandwidthEstimate, s = this.headroomGranted ? Tn : wn;
|
|
2082
|
+
if (!(a > 0) || !(o >= s * a)) return !1;
|
|
2083
|
+
let c = (e) => K([...e].sort((e, t) => e - t), 90);
|
|
2084
|
+
if (this.headroomGranted) {
|
|
2085
|
+
let e = this.headroomSamples.filter((e) => e.bitrate >= a).map((e) => e.ratio);
|
|
2086
|
+
return e.length < q || c(e) <= Cn;
|
|
2087
|
+
}
|
|
2088
|
+
let l = [];
|
|
2089
|
+
for (let e of this.headroomSamples) e.bitrate < a && l.push(e.ratio * (a / e.bitrate));
|
|
2090
|
+
return l.length >= q && c(l) <= Sn;
|
|
2091
|
+
}
|
|
2011
2092
|
applySizeCap() {
|
|
2012
2093
|
if (!this.sizeCapManaged) return;
|
|
2013
2094
|
this.capTimer &&= (clearTimeout(this.capTimer), null);
|
|
@@ -2107,12 +2188,12 @@ var Un = class {
|
|
|
2107
2188
|
this.lastAdvanceMs = Date.now();
|
|
2108
2189
|
return;
|
|
2109
2190
|
}
|
|
2110
|
-
if (this.loadSuspended || this.offlineHold) {
|
|
2191
|
+
if (this.loadSuspended || this.offlineHold || !L()) {
|
|
2111
2192
|
this.lastAdvanceMs = Date.now();
|
|
2112
2193
|
return;
|
|
2113
2194
|
}
|
|
2114
2195
|
let e = Date.now() - this.lastAdvanceMs;
|
|
2115
|
-
!this.chaseSuspended && e >
|
|
2196
|
+
!this.chaseSuspended && e > rn && this.suspendChasing(), e > en && this.emitEnded("stalled");
|
|
2116
2197
|
}
|
|
2117
2198
|
resetStarvationWindow() {
|
|
2118
2199
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -2123,11 +2204,11 @@ var Un = class {
|
|
|
2123
2204
|
checkStarvation() {
|
|
2124
2205
|
let e = this.hls, { video: t } = this.deps;
|
|
2125
2206
|
if (!e || this.endedEmitted || !this.sawLive || this.chaseSuspended) return;
|
|
2126
|
-
if (typeof document < "u" && document.hidden || this.loadSuspended || this.offlineHold) {
|
|
2207
|
+
if (typeof document < "u" && document.hidden || this.loadSuspended || this.offlineHold || !L()) {
|
|
2127
2208
|
this.resetStarvationWindow();
|
|
2128
2209
|
return;
|
|
2129
2210
|
}
|
|
2130
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
2211
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < rn, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > dn, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = R(t), c = o - s, l = c !== this.starvedFrames;
|
|
2131
2212
|
if (this.starvedFrames = c, !a || l) {
|
|
2132
2213
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
2133
2214
|
return;
|
|
@@ -2136,12 +2217,12 @@ var Un = class {
|
|
|
2136
2217
|
this.resetStarvationWindow();
|
|
2137
2218
|
return;
|
|
2138
2219
|
}
|
|
2139
|
-
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 >
|
|
2220
|
+
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 > gn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= mn && (this.clearKick(), this.starvationRebuilds < hn)) {
|
|
2140
2221
|
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");
|
|
2141
2222
|
return;
|
|
2142
2223
|
}
|
|
2143
|
-
let u = i && this.starvedTicks >=
|
|
2144
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
2224
|
+
let u = i && this.starvedTicks >= fn, d = !i && this.deadTicks >= gn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= _n;
|
|
2225
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= pn))) {
|
|
2145
2226
|
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");
|
|
2146
2227
|
try {
|
|
2147
2228
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -2156,7 +2237,7 @@ var Un = class {
|
|
|
2156
2237
|
let t = e.latency, n = e.targetLatency;
|
|
2157
2238
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
2158
2239
|
let r = t - n;
|
|
2159
|
-
!this.catchUpEngaged && r >
|
|
2240
|
+
!this.catchUpEngaged && r > an ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= an && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
2160
2241
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
2161
2242
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
2162
2243
|
}
|
|
@@ -2169,7 +2250,7 @@ var Un = class {
|
|
|
2169
2250
|
}), n < 0 ? 0 : n;
|
|
2170
2251
|
}
|
|
2171
2252
|
armFrameDropGrace() {
|
|
2172
|
-
this.fpsGraceTicks > 0 || (this.fpsGraceTicks =
|
|
2253
|
+
this.fpsGraceTicks > 0 || (this.fpsGraceTicks = Mn, this.fpsBadTicks = 0);
|
|
2173
2254
|
}
|
|
2174
2255
|
resetFrameDropWindow() {
|
|
2175
2256
|
this.fpsLastFrames = -1, this.fpsLastDropped = -1, this.fpsBadTicks = 0;
|
|
@@ -2180,8 +2261,8 @@ var Un = class {
|
|
|
2180
2261
|
this.resetFrameDropWindow();
|
|
2181
2262
|
return;
|
|
2182
2263
|
}
|
|
2183
|
-
let { totalFrames: n, dropped: r } =
|
|
2184
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
2264
|
+
let { totalFrames: n, dropped: r } = R(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
2265
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < An || o < 0) {
|
|
2185
2266
|
this.fpsBadTicks = 0;
|
|
2186
2267
|
return;
|
|
2187
2268
|
}
|
|
@@ -2189,11 +2270,11 @@ var Un = class {
|
|
|
2189
2270
|
--this.fpsGraceTicks, this.fpsBadTicks = 0;
|
|
2190
2271
|
return;
|
|
2191
2272
|
}
|
|
2192
|
-
if (o <=
|
|
2273
|
+
if (o <= kn * a) {
|
|
2193
2274
|
this.fpsBadTicks = 0;
|
|
2194
2275
|
return;
|
|
2195
2276
|
}
|
|
2196
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
2277
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < jn) return;
|
|
2197
2278
|
this.fpsBadTicks = 0;
|
|
2198
2279
|
let s = e.levels, c = s[e.currentLevel];
|
|
2199
2280
|
if (!c) return;
|
|
@@ -2210,22 +2291,22 @@ var Un = class {
|
|
|
2210
2291
|
return;
|
|
2211
2292
|
}
|
|
2212
2293
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
2213
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
2294
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(cn, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
2214
2295
|
this.resetChaseWindow();
|
|
2215
2296
|
return;
|
|
2216
2297
|
}
|
|
2217
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
2298
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= sn) {
|
|
2218
2299
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
2219
2300
|
return;
|
|
2220
2301
|
}
|
|
2221
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
2302
|
+
if (this.chaseTicks += 1, this.chaseTicks < on) return;
|
|
2222
2303
|
this.resetChaseWindow();
|
|
2223
2304
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2224
2305
|
if (!(a > 1)) return;
|
|
2225
2306
|
let o = e.targetLatency;
|
|
2226
2307
|
if (typeof o != "number" || !(o > 0)) return;
|
|
2227
2308
|
let s = Math.min(n, a - 1);
|
|
2228
|
-
s < o +
|
|
2309
|
+
s < o + ln || (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, this.deps.emit({
|
|
2229
2310
|
type: "livetargetchange",
|
|
2230
2311
|
change: {
|
|
2231
2312
|
targetSeconds: s,
|
|
@@ -2235,20 +2316,20 @@ var Un = class {
|
|
|
2235
2316
|
}));
|
|
2236
2317
|
}
|
|
2237
2318
|
armHoldBack(e, t) {
|
|
2238
|
-
this.holdBackEnabled && (this.holdBackSlowTicks = 0, this.holdBackFastSince = 0, this.holdBackSamples = [], this.holdBackBase < 0 && typeof t.liveSyncDuration == "number" && (this.holdBackBase = t.liveSyncDuration), this.holdBackApplied > 0 && (e.targetLatency = this.holdBackApplied));
|
|
2319
|
+
this.headroomSamples = [], this.headroomGranted = !1, this.holdBackEnabled && (this.holdBackSlowTicks = 0, this.holdBackFastSince = 0, this.holdBackSamples = [], this.holdBackBase < 0 && typeof t.liveSyncDuration == "number" && (this.holdBackBase = t.liveSyncDuration), this.holdBackApplied > 0 && (e.targetLatency = this.holdBackApplied));
|
|
2239
2320
|
}
|
|
2240
2321
|
applyHoldBackPrior() {
|
|
2241
2322
|
let e = this.hls;
|
|
2242
2323
|
if (!this.holdBackEnabled || this.holdBackPriorChecked || !e || (this.holdBackPriorChecked = !0, this.holdBackApplied > 0 || this.holdBackStepCount > 0)) return;
|
|
2243
2324
|
let t = e.targetLatency;
|
|
2244
2325
|
if (this.holdBackBase < 0 && typeof t == "number" && t > 0 && (this.holdBackBase = t), this.holdBackBase < 0) return;
|
|
2245
|
-
let n =
|
|
2246
|
-
if (!(n >=
|
|
2247
|
-
let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase +
|
|
2326
|
+
let n = qn();
|
|
2327
|
+
if (!(n >= Gn)) return;
|
|
2328
|
+
let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase + X);
|
|
2248
2329
|
i > r && (this.holdBackStepCount = 1, this.moveHoldBack(e, r, i, "connection-rtt", `connection rtt ${n} ms`));
|
|
2249
2330
|
}
|
|
2250
2331
|
holdBackCeiling(e) {
|
|
2251
|
-
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t :
|
|
2332
|
+
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t : Wn, r = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2252
2333
|
return r > 1 ? Math.min(n, r - 1) : n;
|
|
2253
2334
|
}
|
|
2254
2335
|
sampleHoldBack(e) {
|
|
@@ -2257,7 +2338,7 @@ var Un = class {
|
|
|
2257
2338
|
if (t !== "main" && t !== "audio") return;
|
|
2258
2339
|
let n = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag?.duration;
|
|
2259
2340
|
if (typeof n != "number" || !(n > 0)) return;
|
|
2260
|
-
let r =
|
|
2341
|
+
let r = Kn(e)?.loading;
|
|
2261
2342
|
if (!r || !(r.start > 0) || !(r.end > 0)) return;
|
|
2262
2343
|
let i = r.first > r.start ? r.first : r.end, a = Math.max(0, i - r.start) / (n * 1e3);
|
|
2263
2344
|
this.holdBackSamples.push({
|
|
@@ -2272,30 +2353,30 @@ var Un = class {
|
|
|
2272
2353
|
this.holdBackSlowTicks = 0, this.holdBackFastSince = 0, this.holdBackSamples = [];
|
|
2273
2354
|
return;
|
|
2274
2355
|
}
|
|
2275
|
-
let t = Date.now(), n = t -
|
|
2356
|
+
let t = Date.now(), n = t - Ln, r = this.holdBackSamples, i = 0;
|
|
2276
2357
|
for (; i < r.length && r[i].t < n;) i += 1;
|
|
2277
2358
|
i > 0 && r.splice(0, i);
|
|
2278
2359
|
let a = e.targetLatency;
|
|
2279
2360
|
if (typeof a != "number" || !(a > 0)) return;
|
|
2280
2361
|
this.holdBackBase < 0 && (this.holdBackBase = a);
|
|
2281
2362
|
let o = this.holdBackBase, s = this.holdBackCeiling(e);
|
|
2282
|
-
if (r.length <
|
|
2363
|
+
if (r.length < Rn) {
|
|
2283
2364
|
this.holdBackSlowTicks = 0;
|
|
2284
2365
|
return;
|
|
2285
2366
|
}
|
|
2286
|
-
let c = r.map((e) => e.ratio).sort((e, t) => e - t), l =
|
|
2287
|
-
if (l >=
|
|
2288
|
-
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks <
|
|
2367
|
+
let c = r.map((e) => e.ratio).sort((e, t) => e - t), l = K(c, 95), u = K(c, 50), d = Math.round(l * 1e3);
|
|
2368
|
+
if (l >= zn && u >= Bn) {
|
|
2369
|
+
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks < Hn) return;
|
|
2289
2370
|
this.holdBackSlowTicks = 0;
|
|
2290
|
-
let t = Math.ceil((s - o) /
|
|
2371
|
+
let t = Math.ceil((s - o) / X), n = Math.ceil((a - o) / X - 1e-9);
|
|
2291
2372
|
if (n > this.holdBackStepCount && (this.holdBackStepCount = n), this.holdBackStepCount >= t) return;
|
|
2292
2373
|
this.holdBackStepCount += 1;
|
|
2293
|
-
let r = Math.min(s, o + this.holdBackStepCount *
|
|
2374
|
+
let r = Math.min(s, o + this.holdBackStepCount * X);
|
|
2294
2375
|
if (r <= a) return;
|
|
2295
2376
|
this.moveHoldBack(e, a, r, "slow-fetches", `part fetches slow (first byte p50 ${Math.round(u * 1e3)} / p95 ${d} ms per 1 s of media)`);
|
|
2296
2377
|
return;
|
|
2297
2378
|
}
|
|
2298
|
-
if (this.holdBackSlowTicks = 0, l >=
|
|
2379
|
+
if (this.holdBackSlowTicks = 0, l >= Vn) {
|
|
2299
2380
|
this.holdBackFastSince = 0;
|
|
2300
2381
|
return;
|
|
2301
2382
|
}
|
|
@@ -2303,9 +2384,9 @@ var Un = class {
|
|
|
2303
2384
|
this.holdBackFastSince = t;
|
|
2304
2385
|
return;
|
|
2305
2386
|
}
|
|
2306
|
-
if (t - this.holdBackFastSince <
|
|
2387
|
+
if (t - this.holdBackFastSince < Un || (this.holdBackFastSince = t, this.holdBackStepCount === 0 || a !== this.holdBackApplied)) return;
|
|
2307
2388
|
--this.holdBackStepCount;
|
|
2308
|
-
let f = Math.max(o, o + this.holdBackStepCount *
|
|
2389
|
+
let f = Math.max(o, o + this.holdBackStepCount * X);
|
|
2309
2390
|
f >= a || this.moveHoldBack(e, a, f, "fast-fetches", `part fetches fast again (p95 first byte ${d} ms per 1 s of media)`);
|
|
2310
2391
|
}
|
|
2311
2392
|
moveHoldBack(e, t, n, r, i) {
|
|
@@ -2346,17 +2427,17 @@ var Un = class {
|
|
|
2346
2427
|
} catch {}
|
|
2347
2428
|
}
|
|
2348
2429
|
startEstimate() {
|
|
2349
|
-
return this.deps.rememberBandwidth === !1 ?
|
|
2430
|
+
return this.deps.rememberBandwidth === !1 ? Kt : Be() ?? Kt;
|
|
2350
2431
|
}
|
|
2351
2432
|
maybeRememberBandwidth(e) {
|
|
2352
|
-
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded <
|
|
2433
|
+
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < qt) return;
|
|
2353
2434
|
let t = Date.now();
|
|
2354
|
-
if (!e && t - this.bwSavedAt <
|
|
2435
|
+
if (!e && t - this.bwSavedAt < Jt) return;
|
|
2355
2436
|
let n = this.hls?.bandwidthEstimate;
|
|
2356
|
-
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t,
|
|
2437
|
+
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Ve(n));
|
|
2357
2438
|
}
|
|
2358
2439
|
destroy() {
|
|
2359
|
-
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.onOnline && typeof window < "u" && (window.removeEventListener("online", this.onOnline), this.onOnline = 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) {
|
|
2440
|
+
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.onOffline && typeof window < "u" && (window.removeEventListener("offline", this.onOffline), this.onOffline = null), this.onOnline && typeof window < "u" && (window.removeEventListener("online", this.onOnline), this.onOnline = 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) {
|
|
2360
2441
|
try {
|
|
2361
2442
|
this.hls.destroy();
|
|
2362
2443
|
} catch (e) {
|
|
@@ -2371,7 +2452,7 @@ var Un = class {
|
|
|
2371
2452
|
scheduleLicenseRetry(t) {
|
|
2372
2453
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
2373
2454
|
let n = t.response?.code ?? 0;
|
|
2374
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
2455
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Zt) return !1;
|
|
2375
2456
|
this.licenseRecoveries += 1;
|
|
2376
2457
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
2377
2458
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -2389,7 +2470,7 @@ var Un = class {
|
|
|
2389
2470
|
}
|
|
2390
2471
|
}
|
|
2391
2472
|
onError(t) {
|
|
2392
|
-
if (t.type === e.ErrorTypes.NETWORK_ERROR && String(t.details ?? "").startsWith("frag") && (this.requestErrors += 1), !t.fatal) return;
|
|
2473
|
+
if (t.details === e.ErrorDetails.BUFFER_STALLED_ERROR && this.onPlaybackStall(), t.type === e.ErrorTypes.NETWORK_ERROR && String(t.details ?? "").startsWith("frag") && (this.requestErrors += 1), !t.fatal) return;
|
|
2393
2474
|
let n = this.hls;
|
|
2394
2475
|
if (n) {
|
|
2395
2476
|
if (this.clearRecoveryReset(), t.type === e.ErrorTypes.KEY_SYSTEM_ERROR) {
|
|
@@ -2403,11 +2484,11 @@ var Un = class {
|
|
|
2403
2484
|
return;
|
|
2404
2485
|
}
|
|
2405
2486
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
2406
|
-
if (!
|
|
2487
|
+
if (!L() && (t.response?.code ?? 0) === 0) {
|
|
2407
2488
|
this.offlineHold = !0, this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null);
|
|
2408
2489
|
return;
|
|
2409
2490
|
}
|
|
2410
|
-
if (this.networkRecoveries <
|
|
2491
|
+
if (this.networkRecoveries < Xt) {
|
|
2411
2492
|
this.networkRecoveries += 1;
|
|
2412
2493
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
2413
2494
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -2424,7 +2505,7 @@ var Un = class {
|
|
|
2424
2505
|
return;
|
|
2425
2506
|
}
|
|
2426
2507
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
2427
|
-
if (this.mediaRecoveries <
|
|
2508
|
+
if (this.mediaRecoveries < Yt) {
|
|
2428
2509
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
2429
2510
|
return;
|
|
2430
2511
|
}
|
|
@@ -2445,18 +2526,18 @@ var Un = class {
|
|
|
2445
2526
|
}
|
|
2446
2527
|
}
|
|
2447
2528
|
toError(t, r = "PLAYBACK") {
|
|
2448
|
-
let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(
|
|
2529
|
+
let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(Mt(t.networkDetails)) : void 0;
|
|
2449
2530
|
return new n(r === "DRM" ? a(o, l) : r === "NETWORK" && o === 0 ? "NETWORK" : o === 401 ? "UNAUTHORIZED" : o === 403 ? "FORBIDDEN" : "INTERNAL", o, `${r} error: ${s}${c ? ` (${c})` : ""}`, l ? { serverCode: l } : void 0);
|
|
2450
2531
|
}
|
|
2451
|
-
},
|
|
2532
|
+
}, Zn = 15e3, Qn = 6e5, $n = 3e5, er = 100, Z = 1, tr = 1e3, nr = 3e4, rr = 1e3, ir = {
|
|
2452
2533
|
inline: "PRESENTATION_INLINE",
|
|
2453
2534
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2454
2535
|
pip: "PRESENTATION_PIP"
|
|
2455
|
-
},
|
|
2536
|
+
}, ar = {
|
|
2456
2537
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2457
2538
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2458
2539
|
none: "KEY_SYSTEM_NONE"
|
|
2459
|
-
},
|
|
2540
|
+
}, or = /* @__PURE__ */ new Set([
|
|
2460
2541
|
"INVALID_URN",
|
|
2461
2542
|
"NOT_FOUND",
|
|
2462
2543
|
"GEO_DENIED",
|
|
@@ -2467,7 +2548,7 @@ var Un = class {
|
|
|
2467
2548
|
"FORBIDDEN",
|
|
2468
2549
|
"RATE_LIMITED",
|
|
2469
2550
|
"TIMEOUT"
|
|
2470
|
-
]),
|
|
2551
|
+
]), sr = {
|
|
2471
2552
|
idle: "PLAYER_STATE_IDLE",
|
|
2472
2553
|
waiting: "PLAYER_STATE_WAITING",
|
|
2473
2554
|
loading: "PLAYER_STATE_LOADING",
|
|
@@ -2477,7 +2558,7 @@ var Un = class {
|
|
|
2477
2558
|
ended: "PLAYER_STATE_ENDED",
|
|
2478
2559
|
error: "PLAYER_STATE_ERROR"
|
|
2479
2560
|
};
|
|
2480
|
-
function
|
|
2561
|
+
function cr(e) {
|
|
2481
2562
|
try {
|
|
2482
2563
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2483
2564
|
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);
|
|
@@ -2485,8 +2566,8 @@ function er(e) {
|
|
|
2485
2566
|
return;
|
|
2486
2567
|
}
|
|
2487
2568
|
}
|
|
2488
|
-
var
|
|
2489
|
-
function
|
|
2569
|
+
var lr = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), ur = /* @__PURE__ */ new Set(), dr = /* @__PURE__ */ new Set(), fr = /* @__PURE__ */ new Set(), pr = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2570
|
+
function mr(e) {
|
|
2490
2571
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2491
2572
|
let t;
|
|
2492
2573
|
try {
|
|
@@ -2495,19 +2576,19 @@ function ir(e) {
|
|
|
2495
2576
|
} catch {
|
|
2496
2577
|
return;
|
|
2497
2578
|
}
|
|
2498
|
-
if (
|
|
2499
|
-
|
|
2500
|
-
for (let e of
|
|
2579
|
+
if (ur.has(t) && !dr.has(t)) {
|
|
2580
|
+
dr.add(t), _(pr(new URL(t).origin));
|
|
2581
|
+
for (let e of fr) e.noteCspBlocked();
|
|
2501
2582
|
}
|
|
2502
2583
|
}
|
|
2503
|
-
function
|
|
2584
|
+
function hr(e, t) {
|
|
2504
2585
|
return _(t, e), { disabledReason: t };
|
|
2505
2586
|
}
|
|
2506
|
-
function
|
|
2507
|
-
if (n) return t && !
|
|
2587
|
+
function gr(e, t, n) {
|
|
2588
|
+
if (n) return t && !lr(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2508
2589
|
if (t) return { endpoint: t };
|
|
2509
|
-
if (t !== void 0) return
|
|
2510
|
-
let r =
|
|
2590
|
+
if (t !== void 0) return hr("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).");
|
|
2591
|
+
let r = cr(e);
|
|
2511
2592
|
if (r) return { endpoint: r };
|
|
2512
2593
|
let i;
|
|
2513
2594
|
try {
|
|
@@ -2515,9 +2596,9 @@ function or(e, t, n) {
|
|
|
2515
2596
|
} catch {
|
|
2516
2597
|
i = e;
|
|
2517
2598
|
}
|
|
2518
|
-
return
|
|
2599
|
+
return hr(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).`);
|
|
2519
2600
|
}
|
|
2520
|
-
var
|
|
2601
|
+
var _r = class {
|
|
2521
2602
|
opts;
|
|
2522
2603
|
url;
|
|
2523
2604
|
cspKey;
|
|
@@ -2599,8 +2680,8 @@ var sr = class {
|
|
|
2599
2680
|
constructor(e) {
|
|
2600
2681
|
this.opts = {
|
|
2601
2682
|
...e,
|
|
2602
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2603
|
-
idleMs: e.idleMs ??
|
|
2683
|
+
heartbeatMs: e.heartbeatMs ?? Zn,
|
|
2684
|
+
idleMs: e.idleMs ?? Qn
|
|
2604
2685
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2605
2686
|
try {
|
|
2606
2687
|
let e = new URL(this.url);
|
|
@@ -2617,11 +2698,11 @@ var sr = class {
|
|
|
2617
2698
|
sdkVersion: this.opts.sdkVersion,
|
|
2618
2699
|
...this.opts.environment
|
|
2619
2700
|
};
|
|
2620
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2701
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), tr), 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 && ur.add(this.cspKey), document.addEventListener("securitypolicyviolation", mr), fr.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2621
2702
|
}
|
|
2622
2703
|
checkSuspension(e) {
|
|
2623
2704
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2624
|
-
let t = Math.max(this.opts.idleMs,
|
|
2705
|
+
let t = Math.max(this.opts.idleMs, $n);
|
|
2625
2706
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2626
2707
|
}
|
|
2627
2708
|
syncIdle(e) {
|
|
@@ -2635,21 +2716,21 @@ var sr = class {
|
|
|
2635
2716
|
noteStateChange(e, t, n, r) {
|
|
2636
2717
|
if (this.endedFlag || e === t) return;
|
|
2637
2718
|
let i = this.now();
|
|
2638
|
-
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(
|
|
2719
|
+
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(Z, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(Z, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
|
|
2639
2720
|
this.stallIsSeekInduced = this.seekInduced(i);
|
|
2640
2721
|
let e = !this.isHidden && !this.stallIsSeekInduced;
|
|
2641
|
-
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(
|
|
2722
|
+
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(Z, Math.round(this.playingTotalMs)));
|
|
2642
2723
|
} else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
|
|
2643
2724
|
this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
|
|
2644
2725
|
let a = {
|
|
2645
|
-
fromState:
|
|
2646
|
-
toState:
|
|
2647
|
-
presentation:
|
|
2726
|
+
fromState: sr[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2727
|
+
toState: sr[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2728
|
+
presentation: ir[this.presentation]
|
|
2648
2729
|
}, o = this.causeOf(e, t, i);
|
|
2649
2730
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2650
2731
|
}
|
|
2651
2732
|
seekInduced(e) {
|
|
2652
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2733
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < rr;
|
|
2653
2734
|
}
|
|
2654
2735
|
causeOf(e, t, n) {
|
|
2655
2736
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2686,25 +2767,25 @@ var sr = class {
|
|
|
2686
2767
|
}
|
|
2687
2768
|
this.muteChanges += 1;
|
|
2688
2769
|
let r = this.now();
|
|
2689
|
-
n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(
|
|
2770
|
+
n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(Z, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
|
|
2690
2771
|
}
|
|
2691
2772
|
notePresentation(e) {
|
|
2692
2773
|
this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
|
|
2693
2774
|
}
|
|
2694
2775
|
notePlayIntent() {
|
|
2695
|
-
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs =
|
|
2776
|
+
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = Z), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = Z), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = Z), this.drmSetupMs > 0 && (this.drmSetupMs = Z));
|
|
2696
2777
|
}
|
|
2697
2778
|
noteReady() {
|
|
2698
|
-
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(
|
|
2779
|
+
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(Z, this.now() - this.startupAnchorMs));
|
|
2699
2780
|
}
|
|
2700
2781
|
noteFirstPlaylist() {
|
|
2701
|
-
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(
|
|
2782
|
+
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(Z, this.now() - this.startupAnchorMs));
|
|
2702
2783
|
}
|
|
2703
2784
|
noteDrmReady() {
|
|
2704
|
-
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(
|
|
2785
|
+
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(Z, this.now() - this.startupAnchorMs));
|
|
2705
2786
|
}
|
|
2706
2787
|
noteFirstBytes() {
|
|
2707
|
-
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(
|
|
2788
|
+
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(Z, this.now() - this.startupAnchorMs));
|
|
2708
2789
|
}
|
|
2709
2790
|
noteSeek() {
|
|
2710
2791
|
this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
|
|
@@ -2723,7 +2804,7 @@ var sr = class {
|
|
|
2723
2804
|
let r = n ?? "";
|
|
2724
2805
|
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";
|
|
2725
2806
|
if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
|
|
2726
|
-
if (
|
|
2807
|
+
if (or.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2727
2808
|
let i = t ?? "";
|
|
2728
2809
|
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";
|
|
2729
2810
|
}
|
|
@@ -2755,7 +2836,7 @@ var sr = class {
|
|
|
2755
2836
|
let l = t.droppedFrames ?? 0;
|
|
2756
2837
|
l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
|
|
2757
2838
|
let u = t.renditionSwitches ?? 0;
|
|
2758
|
-
u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState =
|
|
2839
|
+
u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = sr[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
|
|
2759
2840
|
let d = this.mutedTotalMs;
|
|
2760
2841
|
this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
|
|
2761
2842
|
let f = t.upshifts ?? 0;
|
|
@@ -2770,20 +2851,20 @@ var sr = class {
|
|
|
2770
2851
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2771
2852
|
o.requestCountDelta = _;
|
|
2772
2853
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2773
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2854
|
+
n.length > 0 && (o.requestTimeP50Ms = K(n, 50), o.requestTimeP95Ms = K(n, 95));
|
|
2774
2855
|
}
|
|
2775
2856
|
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();
|
|
2776
2857
|
}
|
|
2777
2858
|
maybeEmitMediaInfo(e) {
|
|
2778
2859
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2779
2860
|
let t = {};
|
|
2780
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2861
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = ar[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);
|
|
2781
2862
|
let n = JSON.stringify(t);
|
|
2782
2863
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2783
2864
|
}
|
|
2784
2865
|
end(e, t) {
|
|
2785
2866
|
if (this.endedFlag) return;
|
|
2786
|
-
this.endedFlag = !0,
|
|
2867
|
+
this.endedFlag = !0, fr.delete(this);
|
|
2787
2868
|
let n = t ?? this.now();
|
|
2788
2869
|
this.playingSinceMs !== null && (this.playingTotalMs += n - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += n - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += n - this.bufferingSinceMs, this.bufferingSinceMs = null), this.mutedSinceMs !== null && (this.mutedTotalMs += n - this.mutedSinceMs, this.mutedSinceMs = null), this.waitingSinceMs !== null && (this.waitingTotalMs += n - this.waitingSinceMs, this.waitingSinceMs = null), this.isPlaying = !1, this.syncActive(n), this.closePresentation(n), this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.timer &&= (clearInterval(this.timer), null), this.idleTimer &&= (clearTimeout(this.idleTimer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), document.removeEventListener("freeze", this.onFreeze), document.removeEventListener("resume", this.onResume));
|
|
2789
2870
|
let r = this.safeSample();
|
|
@@ -2797,7 +2878,7 @@ var sr = class {
|
|
|
2797
2878
|
let c = r?.positionMs ?? 0;
|
|
2798
2879
|
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));
|
|
2799
2880
|
let l = e !== "END_REASON_ENDED";
|
|
2800
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2881
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= nr && (i.abandonAfterStallMs = Math.max(Z, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= nr && (i.abandonAfterErrorMs = Math.max(Z, 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);
|
|
2801
2882
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2802
2883
|
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");
|
|
2803
2884
|
}
|
|
@@ -2817,13 +2898,13 @@ var sr = class {
|
|
|
2817
2898
|
};
|
|
2818
2899
|
}
|
|
2819
2900
|
noteCspBlocked() {
|
|
2820
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2901
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(pr(new URL(this.url).origin)));
|
|
2821
2902
|
}
|
|
2822
2903
|
cspBlocked() {
|
|
2823
|
-
return !!this.cspKey &&
|
|
2904
|
+
return !!this.cspKey && dr.has(this.cspKey);
|
|
2824
2905
|
}
|
|
2825
2906
|
enqueue(e) {
|
|
2826
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2907
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > er;) {
|
|
2827
2908
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2828
2909
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2829
2910
|
}
|
|
@@ -2850,7 +2931,7 @@ var sr = class {
|
|
|
2850
2931
|
};
|
|
2851
2932
|
//#endregion
|
|
2852
2933
|
//#region src/core/environment.ts
|
|
2853
|
-
function
|
|
2934
|
+
function vr() {
|
|
2854
2935
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2855
2936
|
let e;
|
|
2856
2937
|
try {
|
|
@@ -2875,14 +2956,14 @@ function cr() {
|
|
|
2875
2956
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2876
2957
|
};
|
|
2877
2958
|
}
|
|
2878
|
-
function
|
|
2959
|
+
function yr() {
|
|
2879
2960
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2880
2961
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2881
2962
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2882
2963
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2883
2964
|
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";
|
|
2884
2965
|
}
|
|
2885
|
-
function
|
|
2966
|
+
function br() {
|
|
2886
2967
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2887
2968
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2888
2969
|
let t = {
|
|
@@ -2901,17 +2982,17 @@ function ur() {
|
|
|
2901
2982
|
}
|
|
2902
2983
|
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;
|
|
2903
2984
|
}
|
|
2904
|
-
function
|
|
2905
|
-
let t =
|
|
2906
|
-
deviceClass:
|
|
2985
|
+
function xr(e) {
|
|
2986
|
+
let t = vr(), n = {
|
|
2987
|
+
deviceClass: yr(),
|
|
2907
2988
|
integration: t.integration,
|
|
2908
|
-
...
|
|
2989
|
+
...br()
|
|
2909
2990
|
};
|
|
2910
2991
|
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);
|
|
2911
2992
|
let r = e.getBoundingClientRect?.();
|
|
2912
2993
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2913
2994
|
}
|
|
2914
|
-
async function
|
|
2995
|
+
async function Sr() {
|
|
2915
2996
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2916
2997
|
if (!e?.getHighEntropyValues) return {};
|
|
2917
2998
|
try {
|
|
@@ -2923,7 +3004,7 @@ async function fr() {
|
|
|
2923
3004
|
}
|
|
2924
3005
|
//#endregion
|
|
2925
3006
|
//#region src/core/version.ts
|
|
2926
|
-
var
|
|
3007
|
+
var Cr = "2.26.0", wr = {
|
|
2927
3008
|
accent: "#E1B600",
|
|
2928
3009
|
accentText: "#1B1C23",
|
|
2929
3010
|
background: "#0e0f13",
|
|
@@ -2934,7 +3015,7 @@ var pr = "2.25.0", mr = {
|
|
|
2934
3015
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2935
3016
|
radius: "8px",
|
|
2936
3017
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2937
|
-
},
|
|
3018
|
+
}, Tr = {
|
|
2938
3019
|
accent: "--havik-accent",
|
|
2939
3020
|
accentText: "--havik-accent-text",
|
|
2940
3021
|
background: "--havik-bg",
|
|
@@ -2946,26 +3027,26 @@ var pr = "2.25.0", mr = {
|
|
|
2946
3027
|
radius: "--havik-radius",
|
|
2947
3028
|
fontFamily: "--havik-font"
|
|
2948
3029
|
};
|
|
2949
|
-
function
|
|
3030
|
+
function Er(e, t) {
|
|
2950
3031
|
let n = {
|
|
2951
|
-
...
|
|
3032
|
+
...wr,
|
|
2952
3033
|
...t
|
|
2953
3034
|
};
|
|
2954
|
-
for (let t of Object.keys(
|
|
3035
|
+
for (let t of Object.keys(Tr)) e.style.setProperty(Tr[t], n[t]);
|
|
2955
3036
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2956
3037
|
}
|
|
2957
3038
|
//#endregion
|
|
2958
3039
|
//#region src/ui/styles.ts
|
|
2959
|
-
var
|
|
2960
|
-
function
|
|
2961
|
-
let n = e.querySelector(`style#${
|
|
2962
|
-
if (n && (!t ||
|
|
3040
|
+
var Dr = "havik-player-styles", Or = "\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", kr = /* @__PURE__ */ new WeakMap();
|
|
3041
|
+
function Ar(e = document, t) {
|
|
3042
|
+
let n = e.querySelector(`style#${Dr}`);
|
|
3043
|
+
if (n && (!t || kr.get(n) === t)) return;
|
|
2963
3044
|
let r = e.createElement("style");
|
|
2964
|
-
r.id =
|
|
3045
|
+
r.id = Dr, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Or, kr.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2965
3046
|
}
|
|
2966
3047
|
//#endregion
|
|
2967
3048
|
//#region src/ui/icons.ts
|
|
2968
|
-
var
|
|
3049
|
+
var jr = {
|
|
2969
3050
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2970
3051
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2971
3052
|
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\"/>",
|
|
@@ -2978,12 +3059,12 @@ var xr = {
|
|
|
2978
3059
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
2979
3060
|
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\"/>"
|
|
2980
3061
|
};
|
|
2981
|
-
function
|
|
2982
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
3062
|
+
function Q(e) {
|
|
3063
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${jr[e]}</svg>`;
|
|
2983
3064
|
}
|
|
2984
3065
|
//#endregion
|
|
2985
3066
|
//#region src/ui/controls.ts
|
|
2986
|
-
var
|
|
3067
|
+
var Mr = 3e3, Nr = 250, Pr = /* @__PURE__ */ new Set([
|
|
2987
3068
|
"GONE",
|
|
2988
3069
|
"NOT_FOUND",
|
|
2989
3070
|
"GEO_DENIED",
|
|
@@ -2991,15 +3072,15 @@ var Sr = 3e3, Cr = 250, wr = /* @__PURE__ */ new Set([
|
|
|
2991
3072
|
"UNAUTHORIZED",
|
|
2992
3073
|
"DRM_DEVICE_REVOKED"
|
|
2993
3074
|
]);
|
|
2994
|
-
function
|
|
3075
|
+
function Fr(e) {
|
|
2995
3076
|
let t = "This match isn't available in your country";
|
|
2996
3077
|
return e ? `${t} (${e})` : t;
|
|
2997
3078
|
}
|
|
2998
|
-
var
|
|
2999
|
-
function
|
|
3000
|
-
return new
|
|
3079
|
+
var Ir = "This device can't play protected video";
|
|
3080
|
+
function Lr(e) {
|
|
3081
|
+
return new Rr(e);
|
|
3001
3082
|
}
|
|
3002
|
-
var
|
|
3083
|
+
var Rr = class {
|
|
3003
3084
|
root;
|
|
3004
3085
|
video;
|
|
3005
3086
|
player;
|
|
@@ -3048,7 +3129,7 @@ var Or = class {
|
|
|
3048
3129
|
scrubbing = !1;
|
|
3049
3130
|
offFns = [];
|
|
3050
3131
|
constructor(e) {
|
|
3051
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
3132
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Mr, 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, this.offlineMessage = e.offlineMessage ?? "No internet connection — waiting to reconnect", Ar(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");
|
|
3052
3133
|
let t = (e, t, n) => {
|
|
3053
3134
|
let r = this.doc.createElement(e);
|
|
3054
3135
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -3059,12 +3140,12 @@ var Or = class {
|
|
|
3059
3140
|
"aria-label": r,
|
|
3060
3141
|
title: r
|
|
3061
3142
|
});
|
|
3062
|
-
return i.innerHTML =
|
|
3143
|
+
return i.innerHTML = Q(n), i;
|
|
3063
3144
|
};
|
|
3064
3145
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
3065
3146
|
type: "button",
|
|
3066
3147
|
"aria-label": "Play"
|
|
3067
|
-
}), this.center.innerHTML =
|
|
3148
|
+
}), this.center.innerHTML = Q("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
|
|
3068
3149
|
role: "slider",
|
|
3069
3150
|
"aria-label": "Seek",
|
|
3070
3151
|
"aria-valuemin": "0",
|
|
@@ -3082,7 +3163,7 @@ var Or = class {
|
|
|
3082
3163
|
"aria-label": "Volume"
|
|
3083
3164
|
});
|
|
3084
3165
|
let a = t("div", "havik-vol");
|
|
3085
|
-
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML =
|
|
3166
|
+
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Q("liveDot");
|
|
3086
3167
|
let o = this.doc.createElement("span");
|
|
3087
3168
|
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";
|
|
3088
3169
|
let s = t("div", "havik-spacer");
|
|
@@ -3134,7 +3215,7 @@ var Or = class {
|
|
|
3134
3215
|
let t = this.surfaceWasHidden;
|
|
3135
3216
|
this.tapTimer = setTimeout(() => {
|
|
3136
3217
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
3137
|
-
},
|
|
3218
|
+
}, Nr);
|
|
3138
3219
|
}
|
|
3139
3220
|
toggleBar(e) {
|
|
3140
3221
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -3158,7 +3239,7 @@ var Or = class {
|
|
|
3158
3239
|
this.renderStatus(t);
|
|
3159
3240
|
}
|
|
3160
3241
|
statusMessageFor(e) {
|
|
3161
|
-
return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "offline" ? this.offlineMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ?
|
|
3242
|
+
return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "offline" ? this.offlineMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? Fr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? Ir : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
|
|
3162
3243
|
}
|
|
3163
3244
|
renderStatus(e) {
|
|
3164
3245
|
let t = this.statusMessageFor(e);
|
|
@@ -3170,12 +3251,12 @@ var Or = class {
|
|
|
3170
3251
|
}
|
|
3171
3252
|
if (e === "preplay") {
|
|
3172
3253
|
let e = this.doc.createElement("button");
|
|
3173
|
-
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML =
|
|
3254
|
+
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);
|
|
3174
3255
|
} else {
|
|
3175
3256
|
let r = this.doc.createElement("div");
|
|
3176
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
3257
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Pr.has(this.lastError.code)) {
|
|
3177
3258
|
let e = this.doc.createElement("button");
|
|
3178
|
-
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${
|
|
3259
|
+
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);
|
|
3179
3260
|
}
|
|
3180
3261
|
}
|
|
3181
3262
|
this.root.append(n), this.statusBox = n, this.show();
|
|
@@ -3214,7 +3295,7 @@ var Or = class {
|
|
|
3214
3295
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
3215
3296
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
3216
3297
|
}
|
|
3217
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
3298
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${zr(this.video.currentTime)} / ${zr(this.video.duration)}`);
|
|
3218
3299
|
}
|
|
3219
3300
|
syncLive() {
|
|
3220
3301
|
let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
|
|
@@ -3264,17 +3345,17 @@ var Or = class {
|
|
|
3264
3345
|
renderQualityMenu() {
|
|
3265
3346
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
3266
3347
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
3267
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
3348
|
+
for (let n of e) this.menu.append(this.menuItem(Br(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
3268
3349
|
}
|
|
3269
3350
|
renderAudioMenu() {
|
|
3270
3351
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
3271
3352
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
3272
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3353
|
+
for (let t of e) this.menu.append(this.menuItem(Vr(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
3273
3354
|
}
|
|
3274
3355
|
renderCcMenu() {
|
|
3275
3356
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
3276
3357
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
3277
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3358
|
+
for (let t of e) this.menu.append(this.menuItem(Hr(t), !1, () => this.player.setTextTrack(t.id)));
|
|
3278
3359
|
}
|
|
3279
3360
|
onTracksChanged() {
|
|
3280
3361
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -3294,14 +3375,14 @@ var Or = class {
|
|
|
3294
3375
|
}
|
|
3295
3376
|
async toggleFullscreen() {
|
|
3296
3377
|
try {
|
|
3297
|
-
|
|
3378
|
+
S(this.video, this.root) ? await T(this.video, this.root) : await w(this.video, this.root);
|
|
3298
3379
|
} catch {}
|
|
3299
3380
|
}
|
|
3300
3381
|
syncFullscreenSupport() {
|
|
3301
|
-
this.fsSupported =
|
|
3382
|
+
this.fsSupported = C(this.video, this.root), this.fsBtn.style.display = this.fsSupported ? "" : "none";
|
|
3302
3383
|
}
|
|
3303
3384
|
syncFullscreen() {
|
|
3304
|
-
let e =
|
|
3385
|
+
let e = S(this.video, this.root);
|
|
3305
3386
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
3306
3387
|
}
|
|
3307
3388
|
poke() {
|
|
@@ -3362,7 +3443,7 @@ var Or = class {
|
|
|
3362
3443
|
}
|
|
3363
3444
|
}
|
|
3364
3445
|
setIcon(e, t) {
|
|
3365
|
-
e.innerHTML =
|
|
3446
|
+
e.innerHTML = Q(t);
|
|
3366
3447
|
}
|
|
3367
3448
|
destroy() {
|
|
3368
3449
|
this.hideTimer && clearTimeout(this.hideTimer), this.tapTimer && clearTimeout(this.tapTimer);
|
|
@@ -3379,23 +3460,23 @@ var Or = class {
|
|
|
3379
3460
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
3380
3461
|
}
|
|
3381
3462
|
};
|
|
3382
|
-
function
|
|
3463
|
+
function zr(e) {
|
|
3383
3464
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
3384
3465
|
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");
|
|
3385
3466
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
3386
3467
|
}
|
|
3387
|
-
function
|
|
3468
|
+
function Br(e) {
|
|
3388
3469
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
3389
3470
|
}
|
|
3390
|
-
function
|
|
3471
|
+
function Vr(e) {
|
|
3391
3472
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3392
3473
|
}
|
|
3393
|
-
function
|
|
3474
|
+
function Hr(e) {
|
|
3394
3475
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3395
3476
|
}
|
|
3396
3477
|
//#endregion
|
|
3397
3478
|
//#region src/managed/index.ts
|
|
3398
|
-
var
|
|
3479
|
+
var Ur = 6e3, Wr = 45e3, Gr = 2e3, Kr = 3, qr = 5e3, Jr = 2e3, Yr = 48e4, Xr = "keySystemLicenseRequestFailed", Zr = /* @__PURE__ */ new Set([
|
|
3399
3480
|
"GONE",
|
|
3400
3481
|
"NOT_FOUND",
|
|
3401
3482
|
"INVALID_URN",
|
|
@@ -3403,27 +3484,27 @@ var Nr = 6e3, Pr = 45e3, Fr = 2e3, Ir = 3, Lr = 5e3, Rr = 2e3, zr = 48e4, Br = "
|
|
|
3403
3484
|
"GEO_DENIED",
|
|
3404
3485
|
"DRM_DEVICE_REVOKED"
|
|
3405
3486
|
]);
|
|
3406
|
-
function
|
|
3407
|
-
return !
|
|
3487
|
+
function Qr(e) {
|
|
3488
|
+
return !Zr.has(e);
|
|
3408
3489
|
}
|
|
3409
|
-
function
|
|
3490
|
+
function $r(e) {
|
|
3410
3491
|
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)})`);
|
|
3411
|
-
if (e.env !== void 0) return
|
|
3492
|
+
if (e.env !== void 0) return lt(e.env);
|
|
3412
3493
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
3413
3494
|
return e.baseUrl;
|
|
3414
3495
|
}
|
|
3415
|
-
async function
|
|
3496
|
+
async function ei(e) {
|
|
3416
3497
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
3417
|
-
let t =
|
|
3498
|
+
let t = $r(e);
|
|
3418
3499
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
3419
3500
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
3420
|
-
let r = new
|
|
3501
|
+
let r = new ti({
|
|
3421
3502
|
...e,
|
|
3422
3503
|
baseUrl: t
|
|
3423
3504
|
});
|
|
3424
3505
|
return await r.start(), r;
|
|
3425
3506
|
}
|
|
3426
|
-
var
|
|
3507
|
+
var ti = class {
|
|
3427
3508
|
opts;
|
|
3428
3509
|
abort = new AbortController();
|
|
3429
3510
|
listeners = {};
|
|
@@ -3467,7 +3548,7 @@ var Gr = class {
|
|
|
3467
3548
|
return this._state;
|
|
3468
3549
|
}
|
|
3469
3550
|
get offline() {
|
|
3470
|
-
return !
|
|
3551
|
+
return !L();
|
|
3471
3552
|
}
|
|
3472
3553
|
get descriptor() {
|
|
3473
3554
|
return this._descriptor;
|
|
@@ -3502,7 +3583,7 @@ var Gr = class {
|
|
|
3502
3583
|
};
|
|
3503
3584
|
}
|
|
3504
3585
|
beginArming(e, t, n = !1) {
|
|
3505
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
3586
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
|
|
3506
3587
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
3507
3588
|
}
|
|
3508
3589
|
beginArmingByPolling(e) {
|
|
@@ -3523,7 +3604,7 @@ var Gr = class {
|
|
|
3523
3604
|
setTimeout(() => {
|
|
3524
3605
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3525
3606
|
phase: i ? "unavailable" : "tooEarly",
|
|
3526
|
-
retryInMs:
|
|
3607
|
+
retryInMs: Wr,
|
|
3527
3608
|
attempt: 1,
|
|
3528
3609
|
elapsedMs: 0,
|
|
3529
3610
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3562,13 +3643,13 @@ var Gr = class {
|
|
|
3562
3643
|
!a && !p() && h();
|
|
3563
3644
|
}, e);
|
|
3564
3645
|
};
|
|
3565
|
-
_(
|
|
3646
|
+
_(Ur), this.armingSub = D({
|
|
3566
3647
|
eventsBaseUrl: t,
|
|
3567
3648
|
matchUrn: this.opts.matchUrn,
|
|
3568
3649
|
credential: this.opts.credential,
|
|
3569
|
-
onAlive: () => _(
|
|
3650
|
+
onAlive: () => _(Wr),
|
|
3570
3651
|
onState: (e) => {
|
|
3571
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3652
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Gr);
|
|
3572
3653
|
},
|
|
3573
3654
|
onError: () => h()
|
|
3574
3655
|
});
|
|
@@ -3591,7 +3672,7 @@ var Gr = class {
|
|
|
3591
3672
|
let n = await c(this.opts.credential);
|
|
3592
3673
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3593
3674
|
this.setState("loading");
|
|
3594
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3675
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = gt(this.opts.video, (e) => {
|
|
3595
3676
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3596
3677
|
});
|
|
3597
3678
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3613,26 +3694,26 @@ var Gr = class {
|
|
|
3613
3694
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3614
3695
|
let i = e.analytics?.sid;
|
|
3615
3696
|
if (!i) return;
|
|
3616
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3697
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = gr(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3617
3698
|
if (!o) {
|
|
3618
3699
|
s && setTimeout(() => {
|
|
3619
3700
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3620
3701
|
}, 0);
|
|
3621
3702
|
return;
|
|
3622
3703
|
}
|
|
3623
|
-
let c = this.opts.video, l = new
|
|
3704
|
+
let c = this.opts.video, l = new _r({
|
|
3624
3705
|
endpoint: o,
|
|
3625
3706
|
sid: i,
|
|
3626
3707
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3627
|
-
sdkVersion:
|
|
3628
|
-
environment:
|
|
3708
|
+
sdkVersion: Cr,
|
|
3709
|
+
environment: xr(c),
|
|
3629
3710
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3630
3711
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3631
3712
|
onBlocked: (e) => setTimeout(() => {
|
|
3632
3713
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3633
3714
|
}, 0),
|
|
3634
3715
|
sample: () => {
|
|
3635
|
-
let e = this.engine?.getStats() ??
|
|
3716
|
+
let e = this.engine?.getStats() ?? dt, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3636
3717
|
return {
|
|
3637
3718
|
...e,
|
|
3638
3719
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3646,7 +3727,7 @@ var Gr = class {
|
|
|
3646
3727
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3647
3728
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3648
3729
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3649
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3730
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Sr().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3650
3731
|
}
|
|
3651
3732
|
currentPresentation() {
|
|
3652
3733
|
let e = this.opts.video;
|
|
@@ -3661,7 +3742,7 @@ var Gr = class {
|
|
|
3661
3742
|
video: this.opts.video,
|
|
3662
3743
|
descriptor: e,
|
|
3663
3744
|
credential: t,
|
|
3664
|
-
deviceId:
|
|
3745
|
+
deviceId: Oe(),
|
|
3665
3746
|
userId: this.opts.userId,
|
|
3666
3747
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
3667
3748
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -3677,11 +3758,11 @@ var Gr = class {
|
|
|
3677
3758
|
emit: (e) => this.onEngineEvent(e),
|
|
3678
3759
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3679
3760
|
}, o = this.opts.engine ?? "auto";
|
|
3680
|
-
if (o === "native") return new
|
|
3681
|
-
if (o === "hls") return new
|
|
3682
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
3683
|
-
if (
|
|
3684
|
-
if (
|
|
3761
|
+
if (o === "native") return new H(a);
|
|
3762
|
+
if (o === "hls") return new Xn(a);
|
|
3763
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && B(this.opts.video) && V() || !e.drmEnabled && Ot() && B(this.opts.video)) return new H(a);
|
|
3764
|
+
if (Wt()) return new Xn(a);
|
|
3765
|
+
if (B(this.opts.video)) return new H(a);
|
|
3685
3766
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3686
3767
|
}
|
|
3687
3768
|
onEngineEvent(e) {
|
|
@@ -3731,11 +3812,11 @@ var Gr = class {
|
|
|
3731
3812
|
}
|
|
3732
3813
|
startLiveState(e) {
|
|
3733
3814
|
if (this.opts.liveStateEvents === !1) return;
|
|
3734
|
-
let t = this.opts.eventsBaseUrl ??
|
|
3815
|
+
let t = this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
|
|
3735
3816
|
if (!t) return;
|
|
3736
3817
|
this.closeLiveState();
|
|
3737
3818
|
let i = 0, a = !1;
|
|
3738
|
-
this.liveStateSub =
|
|
3819
|
+
this.liveStateSub = D({
|
|
3739
3820
|
eventsBaseUrl: t,
|
|
3740
3821
|
matchUrn: this.opts.matchUrn,
|
|
3741
3822
|
credential: this.opts.credential,
|
|
@@ -3747,11 +3828,11 @@ var Gr = class {
|
|
|
3747
3828
|
},
|
|
3748
3829
|
onError: (o) => {
|
|
3749
3830
|
if (!(this.destroyed || e !== this.loadGen || a) && !this.endedHandled) {
|
|
3750
|
-
if (o instanceof
|
|
3831
|
+
if (o instanceof E && (o.terminal || o.status === 404)) {
|
|
3751
3832
|
a = !0, this.emit("warning", new n(r(o.status), o.status, `live-state events answered HTTP ${o.status} for ${this.opts.matchUrn}: the match is ` + (o.terminal ? "gone, so the subscription stopped" : "not in the catalog (ended and dropped, or not listed yet), so it retries every 5 min") + " — end-of-stream detection falls back to the HLS staleness watchdog."));
|
|
3752
3833
|
return;
|
|
3753
3834
|
}
|
|
3754
|
-
i += 1, i >=
|
|
3835
|
+
i += 1, i >= Kr && (a = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${i} 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.`)));
|
|
3755
3836
|
}
|
|
3756
3837
|
}
|
|
3757
3838
|
});
|
|
@@ -3760,7 +3841,7 @@ var Gr = class {
|
|
|
3760
3841
|
this.liveStateSub?.close(), this.liveStateSub = null;
|
|
3761
3842
|
}
|
|
3762
3843
|
watchConnectivity() {
|
|
3763
|
-
this.connectivity || (this.connectivity =
|
|
3844
|
+
this.connectivity || (this.connectivity = ut(), this.connectivity.onChange((e) => {
|
|
3764
3845
|
if (this.destroyed) return;
|
|
3765
3846
|
if (!e) {
|
|
3766
3847
|
this.emit("offline");
|
|
@@ -3768,7 +3849,7 @@ var Gr = class {
|
|
|
3768
3849
|
}
|
|
3769
3850
|
if (this.emit("online"), this._state !== "error" || !this._lastError) return;
|
|
3770
3851
|
let t = this._lastError.code;
|
|
3771
|
-
|
|
3852
|
+
Qr(t) && (t === "NETWORK" || this.failedWhileOffline) && this.retry().catch(() => void 0);
|
|
3772
3853
|
}));
|
|
3773
3854
|
}
|
|
3774
3855
|
watchReturn() {
|
|
@@ -3778,7 +3859,7 @@ var Gr = class {
|
|
|
3778
3859
|
return;
|
|
3779
3860
|
}
|
|
3780
3861
|
let e = this.hiddenAtMs;
|
|
3781
|
-
this.hiddenAtMs = null, e != null && Date.now() - e >=
|
|
3862
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= qr && this.resyncLiveState();
|
|
3782
3863
|
}, this.onReturnPageShow = (e) => {
|
|
3783
3864
|
e.persisted && this.resyncLiveState();
|
|
3784
3865
|
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
@@ -3810,7 +3891,7 @@ var Gr = class {
|
|
|
3810
3891
|
scheduleRejoin(e) {
|
|
3811
3892
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3812
3893
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3813
|
-
}, Math.random() *
|
|
3894
|
+
}, Math.random() * Gr));
|
|
3814
3895
|
}
|
|
3815
3896
|
cancelRejoin() {
|
|
3816
3897
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3834,7 +3915,7 @@ var Gr = class {
|
|
|
3834
3915
|
}
|
|
3835
3916
|
t.controls = !1;
|
|
3836
3917
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3837
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3918
|
+
r && r.insertBefore(n, t), n.appendChild(t), Er(n, this.opts.theme), this.container = n, this.controlBar = Lr({
|
|
3838
3919
|
root: n,
|
|
3839
3920
|
video: t,
|
|
3840
3921
|
player: this,
|
|
@@ -3873,7 +3954,7 @@ var Gr = class {
|
|
|
3873
3954
|
}
|
|
3874
3955
|
startStats() {
|
|
3875
3956
|
this.stopStats();
|
|
3876
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3957
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Jr);
|
|
3877
3958
|
this.statsTimer = setInterval(() => {
|
|
3878
3959
|
if (!this.engine) return;
|
|
3879
3960
|
let e = this.engine.getStats();
|
|
@@ -3884,14 +3965,14 @@ var Gr = class {
|
|
|
3884
3965
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3885
3966
|
}
|
|
3886
3967
|
isStaleLicenseDenial(e) {
|
|
3887
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3968
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Xr || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : W(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3888
3969
|
}
|
|
3889
3970
|
scheduleLicenseRefresh() {
|
|
3890
3971
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3891
3972
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3892
|
-
document.visibilityState !== "visible" || this.destroyed ||
|
|
3973
|
+
document.visibilityState !== "visible" || this.destroyed || W(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3893
3974
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3894
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3975
|
+
let e = this.opts.licenseRefreshMs ?? Yr;
|
|
3895
3976
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3896
3977
|
}
|
|
3897
3978
|
stopRefresh() {
|
|
@@ -3948,7 +4029,7 @@ var Gr = class {
|
|
|
3948
4029
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3949
4030
|
}
|
|
3950
4031
|
getStats() {
|
|
3951
|
-
return this.engine?.getStats() ??
|
|
4032
|
+
return this.engine?.getStats() ?? dt;
|
|
3952
4033
|
}
|
|
3953
4034
|
getQualityLevels() {
|
|
3954
4035
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3987,13 +4068,13 @@ var Gr = class {
|
|
|
3987
4068
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
3988
4069
|
}
|
|
3989
4070
|
async enterFullscreen() {
|
|
3990
|
-
return !this.destroyed &&
|
|
4071
|
+
return !this.destroyed && w(this.opts.video, this.container ?? void 0);
|
|
3991
4072
|
}
|
|
3992
4073
|
async exitFullscreen() {
|
|
3993
|
-
await
|
|
4074
|
+
await T(this.opts.video, this.container ?? void 0);
|
|
3994
4075
|
}
|
|
3995
4076
|
fullscreenSupported() {
|
|
3996
|
-
return !this.destroyed &&
|
|
4077
|
+
return !this.destroyed && C(this.opts.video, this.container ?? void 0);
|
|
3997
4078
|
}
|
|
3998
4079
|
retry() {
|
|
3999
4080
|
return this.reload();
|
|
@@ -4024,7 +4105,7 @@ var Gr = class {
|
|
|
4024
4105
|
for (let e of Object.keys(this.listeners)) this.listeners[e]?.clear();
|
|
4025
4106
|
}
|
|
4026
4107
|
fail(e) {
|
|
4027
|
-
this._lastError = e, this.failedWhileOffline = !
|
|
4108
|
+
this._lastError = e, this.failedWhileOffline = !L(), this.setState("error"), this.analyticsSession?.noteFatal(), this.emit("error", e);
|
|
4028
4109
|
}
|
|
4029
4110
|
setState(e) {
|
|
4030
4111
|
if (e === this._state) return;
|
|
@@ -4056,12 +4137,12 @@ var Gr = class {
|
|
|
4056
4137
|
};
|
|
4057
4138
|
//#endregion
|
|
4058
4139
|
//#region src/embed/protocol.ts
|
|
4059
|
-
function
|
|
4140
|
+
function $(e) {
|
|
4060
4141
|
return !!e && typeof e == "object" && typeof e.type == "string" && e.type.startsWith("oddin:");
|
|
4061
4142
|
}
|
|
4062
4143
|
//#endregion
|
|
4063
4144
|
//#region src/embed/host.ts
|
|
4064
|
-
function
|
|
4145
|
+
function ni(e) {
|
|
4065
4146
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
4066
4147
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
4067
4148
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -4070,7 +4151,7 @@ function qr(e) {
|
|
|
4070
4151
|
let r = document.createElement("iframe");
|
|
4071
4152
|
r.src = t.toString(), r.allow = "autoplay; encrypted-media; fullscreen", r.setAttribute("allowfullscreen", ""), r.referrerPolicy = "no-referrer", r.setAttribute("sandbox", e.sandbox ?? "allow-scripts allow-same-origin allow-presentation"), r.style.cssText = "border:0;width:100%;height:100%;display:block", e.container.appendChild(r);
|
|
4072
4153
|
let i = /* @__PURE__ */ new Set(), a = (t) => {
|
|
4073
|
-
if (t.source !== r.contentWindow || t.origin !== n ||
|
|
4154
|
+
if (t.source !== r.contentWindow || t.origin !== n || !$(t.data)) return;
|
|
4074
4155
|
let a = t.data;
|
|
4075
4156
|
a.type === "oddin:ready" && a.protocol !== 1 && console.warn(`havik-player: embed protocol v${a.protocol} != host v1. Pin the embed page version to the SDK version to avoid skew.`), e.onEvent?.(a), i.forEach((e) => e(a));
|
|
4076
4157
|
};
|
|
@@ -4120,15 +4201,15 @@ function qr(e) {
|
|
|
4120
4201
|
}
|
|
4121
4202
|
//#endregion
|
|
4122
4203
|
//#region src/embed/page.ts
|
|
4123
|
-
var
|
|
4124
|
-
function
|
|
4204
|
+
var ri = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
4205
|
+
function ii(e) {
|
|
4125
4206
|
if (typeof e == "boolean") return e;
|
|
4126
4207
|
if (typeof e == "object" && e) {
|
|
4127
4208
|
let t = e.endpoint;
|
|
4128
4209
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
4129
4210
|
}
|
|
4130
4211
|
}
|
|
4131
|
-
function
|
|
4212
|
+
function ai() {
|
|
4132
4213
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
4133
4214
|
if (e) return {
|
|
4134
4215
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -4138,7 +4219,7 @@ function Xr() {
|
|
|
4138
4219
|
autoplay: e.autoplay ?? !0,
|
|
4139
4220
|
muted: e.muted ?? !0,
|
|
4140
4221
|
waitForLive: e.waitForLive ?? !0,
|
|
4141
|
-
analytics:
|
|
4222
|
+
analytics: ii(e.analytics)
|
|
4142
4223
|
};
|
|
4143
4224
|
let t = new URLSearchParams(location.search);
|
|
4144
4225
|
return {
|
|
@@ -4151,9 +4232,9 @@ function Xr() {
|
|
|
4151
4232
|
waitForLive: !0
|
|
4152
4233
|
};
|
|
4153
4234
|
}
|
|
4154
|
-
async function
|
|
4155
|
-
let e =
|
|
4156
|
-
|
|
4235
|
+
async function oi() {
|
|
4236
|
+
let e = ai();
|
|
4237
|
+
ci();
|
|
4157
4238
|
let t = document.createElement("video");
|
|
4158
4239
|
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);
|
|
4159
4240
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -4209,12 +4290,12 @@ async function Zr() {
|
|
|
4209
4290
|
message: e.message,
|
|
4210
4291
|
...e.country === void 0 ? {} : { country: e.country }
|
|
4211
4292
|
})), e.on("autoplayblocked", () => {
|
|
4212
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
4293
|
+
i({ type: "oddin:autoplayblocked" }), si(t, e);
|
|
4213
4294
|
});
|
|
4214
4295
|
}, s = async (r) => {
|
|
4215
4296
|
a?.destroy(), a = null;
|
|
4216
4297
|
try {
|
|
4217
|
-
let n = await
|
|
4298
|
+
let n = await ei({
|
|
4218
4299
|
video: t,
|
|
4219
4300
|
baseUrl: e.baseUrl,
|
|
4220
4301
|
matchUrn: r,
|
|
@@ -4277,30 +4358,30 @@ async function Zr() {
|
|
|
4277
4358
|
a?.retry();
|
|
4278
4359
|
break;
|
|
4279
4360
|
case "oddin:load":
|
|
4280
|
-
typeof e.matchUrn == "string" &&
|
|
4361
|
+
typeof e.matchUrn == "string" && ri.test(e.matchUrn) && s(e.matchUrn);
|
|
4281
4362
|
break;
|
|
4282
4363
|
case "oddin:destroy": c();
|
|
4283
4364
|
}
|
|
4284
4365
|
}, u = (e) => {
|
|
4285
|
-
r && e.origin === r &&
|
|
4366
|
+
r && e.origin === r && $(e.data) && l(e.data);
|
|
4286
4367
|
};
|
|
4287
4368
|
r && window.addEventListener("message", u), window.addEventListener("pagehide", c, { once: !0 }), await s(e.matchUrn), i({
|
|
4288
4369
|
type: "oddin:ready",
|
|
4289
4370
|
protocol: 1
|
|
4290
4371
|
});
|
|
4291
4372
|
}
|
|
4292
|
-
function
|
|
4373
|
+
function si(e, t) {
|
|
4293
4374
|
if (document.getElementById("havik-tap")) return;
|
|
4294
4375
|
let n = document.createElement("button");
|
|
4295
4376
|
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", () => {
|
|
4296
4377
|
n.remove(), t.play();
|
|
4297
4378
|
}), document.body.appendChild(n);
|
|
4298
4379
|
}
|
|
4299
|
-
function
|
|
4380
|
+
function ci() {
|
|
4300
4381
|
let e = document.createElement("style");
|
|
4301
4382
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
4302
4383
|
}
|
|
4303
4384
|
//#endregion
|
|
4304
|
-
export {
|
|
4385
|
+
export { E as LiveStateHttpError, wr as ODDIN_THEME, n as PlaybackError, Er as applyTheme, lt as baseUrlForEnv, oi as bootEmbed, ke as clearDeviceId, He as clearRememberedBandwidth, ei as createPlayer, O as deriveEventsBaseUrl, at as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, Oe as getDeviceId, st as isLowLatencyManifest, $ as isOddinMessage, je as licenseRequestHeaders, ni as mountEmbed, fe as pollToLive, y as resolveStream, D as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
|
|
4305
4386
|
|
|
4306
4387
|
//# sourceMappingURL=index.js.map
|