@oddin-gg/havik-player 2.16.13 → 2.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/havik-player.global.js +18 -18
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +434 -315
- package/dist/index.js.map +1 -1
- package/docs/API.md +44 -20
- package/docs/STABILITY.md +1 -1
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -290,32 +290,32 @@ function he(e, t) {
|
|
|
290
290
|
function ge(e) {
|
|
291
291
|
return e.ownerDocument ?? document;
|
|
292
292
|
}
|
|
293
|
-
function
|
|
293
|
+
function _e(e) {
|
|
294
294
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
295
295
|
}
|
|
296
|
-
function
|
|
297
|
-
let n =
|
|
296
|
+
function x(e, t) {
|
|
297
|
+
let n = _e(ge(e));
|
|
298
298
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
299
299
|
}
|
|
300
|
-
async function
|
|
300
|
+
async function S(e, t) {
|
|
301
301
|
let n = t ?? e;
|
|
302
302
|
if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
|
|
303
303
|
if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
|
|
304
304
|
let r = e;
|
|
305
305
|
return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
|
|
306
306
|
}
|
|
307
|
-
async function
|
|
307
|
+
async function C(e, t) {
|
|
308
308
|
let n = e;
|
|
309
309
|
if (n.webkitDisplayingFullscreen) {
|
|
310
310
|
n.webkitExitFullscreen?.();
|
|
311
311
|
return;
|
|
312
312
|
}
|
|
313
|
-
let r = ge(e), i =
|
|
313
|
+
let r = ge(e), i = _e(r);
|
|
314
314
|
i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
|
|
315
315
|
}
|
|
316
316
|
//#endregion
|
|
317
317
|
//#region src/core/catalog.ts
|
|
318
|
-
async function
|
|
318
|
+
async function ve(e) {
|
|
319
319
|
let t = new URLSearchParams();
|
|
320
320
|
e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
|
|
321
321
|
let i = t.toString(), a = d(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
|
|
@@ -333,12 +333,12 @@ async function _e(e) {
|
|
|
333
333
|
};
|
|
334
334
|
if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
|
|
335
335
|
return {
|
|
336
|
-
tournaments:
|
|
336
|
+
tournaments: ye(await s.json()),
|
|
337
337
|
etag: s.headers.get("etag") ?? void 0,
|
|
338
338
|
notModified: !1
|
|
339
339
|
};
|
|
340
340
|
}
|
|
341
|
-
function
|
|
341
|
+
function ye(e) {
|
|
342
342
|
return (e.tournaments ?? []).map((e) => {
|
|
343
343
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
344
344
|
return {
|
|
@@ -360,7 +360,7 @@ function ve(e) {
|
|
|
360
360
|
};
|
|
361
361
|
});
|
|
362
362
|
}
|
|
363
|
-
async function
|
|
363
|
+
async function be(e) {
|
|
364
364
|
let t = d(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
365
365
|
e.etag && i.set("If-None-Match", e.etag);
|
|
366
366
|
let a = await p(t, {
|
|
@@ -380,13 +380,13 @@ async function ye(e) {
|
|
|
380
380
|
};
|
|
381
381
|
if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
382
382
|
return {
|
|
383
|
-
tournament:
|
|
383
|
+
tournament: xe(await a.json()),
|
|
384
384
|
etag: a.headers.get("etag") ?? void 0,
|
|
385
385
|
notModified: !1,
|
|
386
386
|
notFound: !1
|
|
387
387
|
};
|
|
388
388
|
}
|
|
389
|
-
function
|
|
389
|
+
function xe(e) {
|
|
390
390
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
391
391
|
return {
|
|
392
392
|
urn: t,
|
|
@@ -406,17 +406,17 @@ function be(e) {
|
|
|
406
406
|
}))
|
|
407
407
|
};
|
|
408
408
|
}
|
|
409
|
-
function
|
|
409
|
+
function Se(e) {
|
|
410
410
|
return e.tournaments.flatMap((e) => e.matches);
|
|
411
411
|
}
|
|
412
412
|
//#endregion
|
|
413
413
|
//#region src/core/poll.ts
|
|
414
|
-
var
|
|
414
|
+
var Ce = /* @__PURE__ */ new Set([
|
|
415
415
|
"NOT_FOUND",
|
|
416
416
|
"GONE",
|
|
417
417
|
"INVALID_URN"
|
|
418
418
|
]);
|
|
419
|
-
function
|
|
419
|
+
function we(e) {
|
|
420
420
|
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
|
|
421
421
|
u || (a = setTimeout(m, t));
|
|
422
422
|
}, m = async () => {
|
|
@@ -449,7 +449,7 @@ function Ce(e) {
|
|
|
449
449
|
} catch (t) {
|
|
450
450
|
if (!i.signal.aborted) {
|
|
451
451
|
let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
|
|
452
|
-
|
|
452
|
+
Ce.has(r.code) && (u = !0), e.onError?.(r);
|
|
453
453
|
}
|
|
454
454
|
} finally {
|
|
455
455
|
f();
|
|
@@ -461,15 +461,16 @@ function Ce(e) {
|
|
|
461
461
|
}
|
|
462
462
|
//#endregion
|
|
463
463
|
//#region src/core/events.ts
|
|
464
|
-
var
|
|
465
|
-
function
|
|
466
|
-
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ??
|
|
464
|
+
var Te = 45e3;
|
|
465
|
+
function w(e) {
|
|
466
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? Te, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
|
|
467
467
|
if (a.signal.aborted) return t();
|
|
468
468
|
let n = setTimeout(t, e);
|
|
469
469
|
a.signal.addEventListener("abort", () => {
|
|
470
470
|
clearTimeout(n), t();
|
|
471
471
|
}, { once: !0 });
|
|
472
472
|
}), l = (t) => {
|
|
473
|
+
if (o) return;
|
|
473
474
|
e.onAlive?.();
|
|
474
475
|
let n = "message", r = [];
|
|
475
476
|
for (let e of t.split("\n")) {
|
|
@@ -544,7 +545,7 @@ function T(e) {
|
|
|
544
545
|
o || (o = !0, a.abort());
|
|
545
546
|
} };
|
|
546
547
|
}
|
|
547
|
-
function
|
|
548
|
+
function T(e) {
|
|
548
549
|
try {
|
|
549
550
|
let t = new URL(e);
|
|
550
551
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -554,27 +555,27 @@ function E(e) {
|
|
|
554
555
|
}
|
|
555
556
|
//#endregion
|
|
556
557
|
//#region src/core/drm/deviceId.ts
|
|
557
|
-
var
|
|
558
|
-
function
|
|
559
|
-
if (
|
|
558
|
+
var E = "havik.player.deviceId", D;
|
|
559
|
+
function O() {
|
|
560
|
+
if (D) return D;
|
|
560
561
|
try {
|
|
561
|
-
let e = globalThis.localStorage?.getItem(
|
|
562
|
-
if (e) return
|
|
562
|
+
let e = globalThis.localStorage?.getItem(E);
|
|
563
|
+
if (e) return D = e, e;
|
|
563
564
|
} catch {}
|
|
564
|
-
let e =
|
|
565
|
-
|
|
565
|
+
let e = De();
|
|
566
|
+
D = e;
|
|
566
567
|
try {
|
|
567
|
-
globalThis.localStorage?.setItem(
|
|
568
|
+
globalThis.localStorage?.setItem(E, e);
|
|
568
569
|
} catch {}
|
|
569
570
|
return e;
|
|
570
571
|
}
|
|
571
|
-
function
|
|
572
|
-
|
|
572
|
+
function Ee() {
|
|
573
|
+
D = void 0;
|
|
573
574
|
try {
|
|
574
|
-
globalThis.localStorage?.removeItem(
|
|
575
|
+
globalThis.localStorage?.removeItem(E);
|
|
575
576
|
} catch {}
|
|
576
577
|
}
|
|
577
|
-
function
|
|
578
|
+
function De() {
|
|
578
579
|
let e = globalThis.crypto;
|
|
579
580
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
580
581
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -586,21 +587,69 @@ function Ee() {
|
|
|
586
587
|
}
|
|
587
588
|
//#endregion
|
|
588
589
|
//#region src/core/drm/headers.ts
|
|
589
|
-
function
|
|
590
|
+
function Oe(e, t, n = {}) {
|
|
590
591
|
let r = {
|
|
591
592
|
"x-api-key": t.apiKey,
|
|
592
593
|
"X-Match-Urn": e.matchUrn,
|
|
593
|
-
"X-Device-Id": n.deviceId ??
|
|
594
|
+
"X-Device-Id": n.deviceId ?? O(),
|
|
594
595
|
"Content-Type": "application/octet-stream"
|
|
595
596
|
};
|
|
596
597
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
597
598
|
}
|
|
598
599
|
//#endregion
|
|
600
|
+
//#region src/core/bandwidthMemory.ts
|
|
601
|
+
var k = "havik.player.bandwidth", ke = .8, Ae = 2e7, je = 3e5;
|
|
602
|
+
function Me() {
|
|
603
|
+
return globalThis.navigator?.connection;
|
|
604
|
+
}
|
|
605
|
+
function Ne() {
|
|
606
|
+
let e = Me()?.type;
|
|
607
|
+
return typeof e == "string" && e !== "" && e !== "unknown" ? e : "any";
|
|
608
|
+
}
|
|
609
|
+
function Pe() {
|
|
610
|
+
let e = Me()?.downlink;
|
|
611
|
+
return typeof e == "number" && Number.isFinite(e) && e > 0 ? e * 1e6 : void 0;
|
|
612
|
+
}
|
|
613
|
+
function Fe() {
|
|
614
|
+
try {
|
|
615
|
+
let e = globalThis.localStorage?.getItem(k);
|
|
616
|
+
if (!e) return {};
|
|
617
|
+
let t = JSON.parse(e);
|
|
618
|
+
return t && typeof t == "object" && !Array.isArray(t) ? t : {};
|
|
619
|
+
} catch {
|
|
620
|
+
return {};
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
function Ie(e = Date.now()) {
|
|
624
|
+
let t = Fe()[Ne()];
|
|
625
|
+
if (!t || typeof t.bps != "number" || typeof t.at != "number" || !Number.isFinite(t.bps) || t.bps <= 0) return;
|
|
626
|
+
let n = e - t.at;
|
|
627
|
+
if (n < 0 || n > 2592e5) return;
|
|
628
|
+
let r = Pe(), i = r === void 0 ? t.bps : Math.min(t.bps, r);
|
|
629
|
+
return Math.round(Math.min(Ae, Math.max(je, i * ke)));
|
|
630
|
+
}
|
|
631
|
+
function Le(e, t = Date.now()) {
|
|
632
|
+
if (!Number.isFinite(e) || e <= 0) return;
|
|
633
|
+
let n = Fe();
|
|
634
|
+
n[Ne()] = {
|
|
635
|
+
bps: Math.round(e),
|
|
636
|
+
at: t
|
|
637
|
+
};
|
|
638
|
+
try {
|
|
639
|
+
globalThis.localStorage?.setItem(k, JSON.stringify(n));
|
|
640
|
+
} catch {}
|
|
641
|
+
}
|
|
642
|
+
function Re() {
|
|
643
|
+
try {
|
|
644
|
+
globalThis.localStorage?.removeItem(k);
|
|
645
|
+
} catch {}
|
|
646
|
+
}
|
|
647
|
+
//#endregion
|
|
599
648
|
//#region src/core/drm/cdm.ts
|
|
600
|
-
var
|
|
601
|
-
function
|
|
602
|
-
let n =
|
|
603
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
649
|
+
var ze = /* @__PURE__ */ new WeakMap();
|
|
650
|
+
function Be(e, t) {
|
|
651
|
+
let n = ze.get(e);
|
|
652
|
+
n || (n = /* @__PURE__ */ new Map(), ze.set(e, n));
|
|
604
653
|
let r = n.get(t.keySystem);
|
|
605
654
|
if (r) return r;
|
|
606
655
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -608,22 +657,22 @@ function Oe(e, t) {
|
|
|
608
657
|
});
|
|
609
658
|
return n.set(t.keySystem, i), i;
|
|
610
659
|
}
|
|
611
|
-
function
|
|
660
|
+
function A() {
|
|
612
661
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
613
662
|
}
|
|
614
|
-
var
|
|
615
|
-
function
|
|
663
|
+
var j = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
664
|
+
function Ve(e) {
|
|
616
665
|
return e.startsWith("com.widevine");
|
|
617
666
|
}
|
|
618
|
-
function
|
|
619
|
-
if (!
|
|
667
|
+
function M(e, t) {
|
|
668
|
+
if (!Ve(e)) return t;
|
|
620
669
|
let n = (e, t) => {
|
|
621
670
|
let n = e.videoCapabilities;
|
|
622
671
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
623
|
-
let n =
|
|
624
|
-
return n === -1 ||
|
|
672
|
+
let n = j.indexOf(e.robustness);
|
|
673
|
+
return n === -1 || j.indexOf(t) > n;
|
|
625
674
|
});
|
|
626
|
-
}, r =
|
|
675
|
+
}, r = j.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
627
676
|
...t,
|
|
628
677
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
629
678
|
...t,
|
|
@@ -632,53 +681,53 @@ function N(e, t) {
|
|
|
632
681
|
})));
|
|
633
682
|
return [...t, ...r];
|
|
634
683
|
}
|
|
635
|
-
function
|
|
636
|
-
return (t, n) =>
|
|
684
|
+
function He(e) {
|
|
685
|
+
return (t, n) => A() ? navigator.requestMediaKeySystemAccess(t, M(t, n)).then((t) => ({
|
|
637
686
|
keySystem: t.keySystem,
|
|
638
687
|
getConfiguration: () => t.getConfiguration(),
|
|
639
|
-
createMediaKeys: () =>
|
|
688
|
+
createMediaKeys: () => Be(e, t)
|
|
640
689
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
641
690
|
}
|
|
642
|
-
var
|
|
691
|
+
var N = {
|
|
643
692
|
video: "SW_SECURE_DECODE",
|
|
644
693
|
audio: "SW_SECURE_CRYPTO",
|
|
645
694
|
scheme: "cbcs"
|
|
646
695
|
};
|
|
647
|
-
function
|
|
648
|
-
if (!
|
|
696
|
+
function Ue(e) {
|
|
697
|
+
if (!A()) return;
|
|
649
698
|
let t = (e, t) => ({
|
|
650
699
|
contentType: e,
|
|
651
700
|
robustness: t,
|
|
652
|
-
encryptionScheme:
|
|
701
|
+
encryptionScheme: N.scheme
|
|
653
702
|
});
|
|
654
|
-
|
|
703
|
+
He(e)("com.widevine.alpha", [{
|
|
655
704
|
initDataTypes: ["cenc"],
|
|
656
705
|
distinctiveIdentifier: "optional",
|
|
657
706
|
persistentState: "optional",
|
|
658
707
|
sessionTypes: ["temporary"],
|
|
659
|
-
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"",
|
|
660
|
-
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"",
|
|
708
|
+
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", N.audio)],
|
|
709
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", N.video)]
|
|
661
710
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
662
711
|
}
|
|
663
|
-
function
|
|
664
|
-
let t =
|
|
712
|
+
function P(e) {
|
|
713
|
+
let t = F(e);
|
|
665
714
|
if (/^avc[13]/.test(t)) return "avc";
|
|
666
715
|
if (/^(hvc1|hev1)/.test(t)) return "hevc";
|
|
667
716
|
if (/^(dvh1|dvhe)/.test(t)) return "dv";
|
|
668
717
|
if (t.startsWith("av01")) return "av1";
|
|
669
718
|
if (/^vp0?9/.test(t)) return "vp9";
|
|
670
719
|
}
|
|
671
|
-
function
|
|
720
|
+
function F(e) {
|
|
672
721
|
return (e ?? "").trim().toLowerCase();
|
|
673
722
|
}
|
|
674
|
-
var
|
|
723
|
+
var We = {
|
|
675
724
|
hevc: "hvc1.1.6.L93.90",
|
|
676
725
|
dv: "dvh1.05.06",
|
|
677
726
|
av1: "av01.0.05M.08",
|
|
678
727
|
vp9: "vp09.00.10.08"
|
|
679
|
-
},
|
|
680
|
-
function
|
|
681
|
-
let t =
|
|
728
|
+
}, Ge = /* @__PURE__ */ new Map(), I = /* @__PURE__ */ new Map();
|
|
729
|
+
function Ke(e) {
|
|
730
|
+
let t = F(e), n = Ge.get(t);
|
|
682
731
|
if (n) return n;
|
|
683
732
|
let r = {
|
|
684
733
|
initDataTypes: ["cenc"],
|
|
@@ -687,32 +736,32 @@ function Ne(e) {
|
|
|
687
736
|
sessionTypes: ["temporary"],
|
|
688
737
|
videoCapabilities: [{
|
|
689
738
|
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
690
|
-
robustness:
|
|
691
|
-
encryptionScheme:
|
|
739
|
+
robustness: N.video,
|
|
740
|
+
encryptionScheme: N.scheme
|
|
692
741
|
}]
|
|
693
742
|
}, i = (async () => {
|
|
694
743
|
try {
|
|
695
|
-
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha",
|
|
744
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", M("com.widevine.alpha", [r])), !0;
|
|
696
745
|
} catch {
|
|
697
746
|
return !1;
|
|
698
747
|
}
|
|
699
|
-
})().then((e) => (
|
|
700
|
-
return
|
|
748
|
+
})().then((e) => (I.set(t, e), e));
|
|
749
|
+
return Ge.set(t, i), i;
|
|
701
750
|
}
|
|
702
|
-
function
|
|
703
|
-
if (
|
|
751
|
+
function qe() {
|
|
752
|
+
if (A()) for (let e of Object.values(We)) Ke(e);
|
|
704
753
|
}
|
|
705
|
-
function
|
|
706
|
-
let t =
|
|
707
|
-
if (t) return t === "avc" ? !0 :
|
|
754
|
+
function Je(e) {
|
|
755
|
+
let t = P(e);
|
|
756
|
+
if (t) return t === "avc" ? !0 : I.get(F(e)) ?? I.get(F(We[t]));
|
|
708
757
|
}
|
|
709
758
|
//#endregion
|
|
710
759
|
//#region src/core/drm/support.ts
|
|
711
|
-
var
|
|
760
|
+
var Ye = 5e3, Xe = "video/mp4; codecs=\"avc1.42E01E\"", Ze = "audio/mp4; codecs=\"mp4a.40.2\"", Qe = {
|
|
712
761
|
widevine: ["com.widevine.alpha"],
|
|
713
762
|
fairplay: ["com.apple.fps"]
|
|
714
763
|
};
|
|
715
|
-
function
|
|
764
|
+
function $e(e) {
|
|
716
765
|
return e === "fairplay" ? [{
|
|
717
766
|
initDataTypes: [
|
|
718
767
|
"sinf",
|
|
@@ -720,30 +769,30 @@ function Be(e) {
|
|
|
720
769
|
"cenc"
|
|
721
770
|
],
|
|
722
771
|
videoCapabilities: [{
|
|
723
|
-
contentType:
|
|
772
|
+
contentType: Xe,
|
|
724
773
|
robustness: "",
|
|
725
774
|
encryptionScheme: "cbcs"
|
|
726
775
|
}],
|
|
727
776
|
audioCapabilities: [{
|
|
728
|
-
contentType:
|
|
777
|
+
contentType: Ze,
|
|
729
778
|
robustness: "",
|
|
730
779
|
encryptionScheme: "cbcs"
|
|
731
780
|
}]
|
|
732
|
-
}] :
|
|
781
|
+
}] : M("com.widevine.alpha", [{
|
|
733
782
|
initDataTypes: ["cenc"],
|
|
734
783
|
videoCapabilities: [{
|
|
735
|
-
contentType:
|
|
736
|
-
robustness:
|
|
737
|
-
encryptionScheme:
|
|
784
|
+
contentType: Xe,
|
|
785
|
+
robustness: N.video,
|
|
786
|
+
encryptionScheme: N.scheme
|
|
738
787
|
}],
|
|
739
788
|
audioCapabilities: [{
|
|
740
|
-
contentType:
|
|
741
|
-
robustness:
|
|
742
|
-
encryptionScheme:
|
|
789
|
+
contentType: Ze,
|
|
790
|
+
robustness: N.audio,
|
|
791
|
+
encryptionScheme: N.scheme
|
|
743
792
|
}]
|
|
744
793
|
}]);
|
|
745
794
|
}
|
|
746
|
-
function
|
|
795
|
+
function et(e, t) {
|
|
747
796
|
return new Promise((n, r) => {
|
|
748
797
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
749
798
|
e.then((e) => {
|
|
@@ -753,8 +802,8 @@ function Ve(e, t) {
|
|
|
753
802
|
});
|
|
754
803
|
});
|
|
755
804
|
}
|
|
756
|
-
async function
|
|
757
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
805
|
+
async function tt(e = {}) {
|
|
806
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ye, r = {};
|
|
758
807
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
759
808
|
verdict: "insecure-context",
|
|
760
809
|
detail: r
|
|
@@ -766,7 +815,7 @@ async function He(e = {}) {
|
|
|
766
815
|
};
|
|
767
816
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
768
817
|
for (let e of t) {
|
|
769
|
-
let t =
|
|
818
|
+
let t = Qe[e];
|
|
770
819
|
if (!t) {
|
|
771
820
|
r[e] = "unknown system";
|
|
772
821
|
continue;
|
|
@@ -777,7 +826,7 @@ async function He(e = {}) {
|
|
|
777
826
|
break;
|
|
778
827
|
}
|
|
779
828
|
try {
|
|
780
|
-
return await
|
|
829
|
+
return await et((await et(i(n, $e(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
781
830
|
verdict: "supported",
|
|
782
831
|
system: e,
|
|
783
832
|
detail: r
|
|
@@ -801,49 +850,49 @@ async function He(e = {}) {
|
|
|
801
850
|
}
|
|
802
851
|
//#endregion
|
|
803
852
|
//#region src/core/manifest.ts
|
|
804
|
-
var
|
|
805
|
-
function
|
|
806
|
-
return
|
|
853
|
+
var nt = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
854
|
+
function rt(e) {
|
|
855
|
+
return nt.test(e);
|
|
807
856
|
}
|
|
808
857
|
//#endregion
|
|
809
858
|
//#region src/core/env.ts
|
|
810
|
-
var
|
|
859
|
+
var it = {
|
|
811
860
|
integration: "https://feed-dev.oddin-video.gg",
|
|
812
861
|
production: "https://feed.oddin-video.gg"
|
|
813
862
|
};
|
|
814
|
-
function
|
|
815
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
863
|
+
function L(e) {
|
|
864
|
+
let t = Object.prototype.hasOwnProperty.call(it, e) ? it[e] : void 0;
|
|
816
865
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
817
866
|
return t;
|
|
818
867
|
}
|
|
819
868
|
//#endregion
|
|
820
869
|
//#region src/core/stats.ts
|
|
821
|
-
var
|
|
822
|
-
function
|
|
870
|
+
var R = { droppedFrames: 0 };
|
|
871
|
+
function z(e) {
|
|
823
872
|
try {
|
|
824
873
|
return new URL(e).host;
|
|
825
874
|
} catch {
|
|
826
875
|
return "";
|
|
827
876
|
}
|
|
828
877
|
}
|
|
829
|
-
var
|
|
830
|
-
function
|
|
878
|
+
var at = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
879
|
+
function ot(e) {
|
|
831
880
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
832
881
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
833
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
834
|
-
let e =
|
|
882
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || at.test(i.name)) && i.startTime >= n) {
|
|
883
|
+
let e = z(i.name);
|
|
835
884
|
e && (t = e, n = i.startTime);
|
|
836
885
|
}
|
|
837
886
|
return t;
|
|
838
887
|
}
|
|
839
|
-
function
|
|
888
|
+
function B(e) {
|
|
840
889
|
let t = e.getVideoPlaybackQuality?.();
|
|
841
890
|
return {
|
|
842
891
|
dropped: t?.droppedVideoFrames ?? 0,
|
|
843
892
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
844
893
|
};
|
|
845
894
|
}
|
|
846
|
-
var
|
|
895
|
+
var st = class {
|
|
847
896
|
video;
|
|
848
897
|
baseFrames = 0;
|
|
849
898
|
baseDropped = 0;
|
|
@@ -853,7 +902,7 @@ var B = class {
|
|
|
853
902
|
this.video = e;
|
|
854
903
|
}
|
|
855
904
|
read() {
|
|
856
|
-
let e =
|
|
905
|
+
let e = B(this.video);
|
|
857
906
|
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, {
|
|
858
907
|
dropped: this.baseDropped + e.dropped,
|
|
859
908
|
totalFrames: this.baseFrames + e.totalFrames
|
|
@@ -866,7 +915,7 @@ var B = class {
|
|
|
866
915
|
};
|
|
867
916
|
}
|
|
868
917
|
};
|
|
869
|
-
function
|
|
918
|
+
function ct(e, t) {
|
|
870
919
|
let n = [
|
|
871
920
|
["playing", () => t("playing")],
|
|
872
921
|
["waiting", () => t("buffering")],
|
|
@@ -883,8 +932,8 @@ function Ze(e, t) {
|
|
|
883
932
|
}
|
|
884
933
|
//#endregion
|
|
885
934
|
//#region src/core/engine/native.ts
|
|
886
|
-
var
|
|
887
|
-
function
|
|
935
|
+
var lt = 2e3, ut = 3, V = 500, dt = 6e3, ft = .25, pt = 250, mt = .05, ht = 4, gt = 12e3, _t = .25, vt = 1e3;
|
|
936
|
+
function yt(e) {
|
|
888
937
|
try {
|
|
889
938
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
890
939
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -900,7 +949,7 @@ function U() {
|
|
|
900
949
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
901
950
|
return e || t;
|
|
902
951
|
}
|
|
903
|
-
function
|
|
952
|
+
function bt() {
|
|
904
953
|
if (typeof navigator > "u" || !U()) return !1;
|
|
905
954
|
let e = navigator.userAgent ?? "";
|
|
906
955
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
@@ -922,6 +971,10 @@ var W = class {
|
|
|
922
971
|
onEdgeReset = null;
|
|
923
972
|
lastBufferedEnd = null;
|
|
924
973
|
bufferedAdvancedAt = null;
|
|
974
|
+
lastSeekableEnd = null;
|
|
975
|
+
edgeStampedAt = null;
|
|
976
|
+
lastTickAt = null;
|
|
977
|
+
endedEmitted = !1;
|
|
925
978
|
fairplayKeyIV;
|
|
926
979
|
loadStarted;
|
|
927
980
|
preloadTouched = !1;
|
|
@@ -931,12 +984,12 @@ var W = class {
|
|
|
931
984
|
frameCounter;
|
|
932
985
|
detachFrames = null;
|
|
933
986
|
constructor(e) {
|
|
934
|
-
this.deps = e, this.frameCounter = new
|
|
987
|
+
this.deps = e, this.frameCounter = new st(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
|
|
935
988
|
}
|
|
936
989
|
async load() {
|
|
937
990
|
this.detachFrames ??= this.frameCounter.attach();
|
|
938
991
|
let { video: e, descriptor: t, emit: r } = this.deps;
|
|
939
|
-
if (this.watchRefocus(), this.watchBufferedEnd(), this.loadStarted || (this.preloadTouched = !0, this.savedPreload = e.getAttribute("preload"), e.preload = "none"), t.drmEnabled) {
|
|
992
|
+
if (this.endedEmitted = !1, this.watchRefocus(), this.watchBufferedEnd(), this.loadStarted || (this.preloadTouched = !0, this.savedPreload = e.getAttribute("preload"), e.preload = "none"), t.drmEnabled) {
|
|
940
993
|
if (!t.drm?.fairplay) {
|
|
941
994
|
r({
|
|
942
995
|
type: "error",
|
|
@@ -952,7 +1005,7 @@ var W = class {
|
|
|
952
1005
|
type: "error",
|
|
953
1006
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
954
1007
|
fatal: !0
|
|
955
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
1008
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = St(t.manifestUrl, t.analytics?.sid), e.load();
|
|
956
1009
|
}
|
|
957
1010
|
startLoad() {
|
|
958
1011
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -974,7 +1027,7 @@ var W = class {
|
|
|
974
1027
|
});
|
|
975
1028
|
this.onEncrypted = (n) => {
|
|
976
1029
|
let i = n;
|
|
977
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
1030
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = yt(i.initData), (async () => {
|
|
978
1031
|
try {
|
|
979
1032
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
980
1033
|
initDataTypes: [i.initDataType],
|
|
@@ -1073,10 +1126,10 @@ var W = class {
|
|
|
1073
1126
|
droppedFrames: t.dropped,
|
|
1074
1127
|
decodedFrames: t.totalFrames
|
|
1075
1128
|
};
|
|
1076
|
-
if (this.cdnHost ||=
|
|
1129
|
+
if (this.cdnHost ||= ot(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1077
1130
|
n.isLive = !0;
|
|
1078
1131
|
let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
|
|
1079
|
-
Number.isFinite(r) && (n.atLiveEdge = r <=
|
|
1132
|
+
Number.isFinite(r) && (n.atLiveEdge = r <= ht, !e.paused && r >= 0 && (n.latencySeconds = r));
|
|
1080
1133
|
} else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
|
|
1081
1134
|
return n;
|
|
1082
1135
|
}
|
|
@@ -1094,7 +1147,7 @@ var W = class {
|
|
|
1094
1147
|
return;
|
|
1095
1148
|
}
|
|
1096
1149
|
let t = this.hiddenSince;
|
|
1097
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1150
|
+
this.hiddenSince = null, t != null && e - t >= lt && this.armRefocus();
|
|
1098
1151
|
}, this.onPageShow = (e) => {
|
|
1099
1152
|
e.persisted && this.armRefocus();
|
|
1100
1153
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
@@ -1104,7 +1157,7 @@ var W = class {
|
|
|
1104
1157
|
let e = this.liveEnd(), t = G, n = t(), r = 0, i = () => {
|
|
1105
1158
|
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1106
1159
|
r += V;
|
|
1107
|
-
let a = this.liveEnd(), o = a != null && (e == null || a >= e +
|
|
1160
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + ft), s = Math.max(r, t() - n) >= dt;
|
|
1108
1161
|
if (o || s && a != null) {
|
|
1109
1162
|
this.snapToLive();
|
|
1110
1163
|
return;
|
|
@@ -1119,21 +1172,43 @@ var W = class {
|
|
|
1119
1172
|
watchBufferedEnd() {
|
|
1120
1173
|
if (this.edgeTimer != null) return;
|
|
1121
1174
|
let { video: e } = this.deps;
|
|
1122
|
-
this.onEdgeReset = () => {
|
|
1123
|
-
this.lastBufferedEnd = null, this.bufferedAdvancedAt = null;
|
|
1175
|
+
this.onEdgeReset = (e) => {
|
|
1176
|
+
this.lastBufferedEnd = null, this.bufferedAdvancedAt = null, e.type === "emptied" && this.resetEndStale();
|
|
1124
1177
|
}, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
|
|
1125
1178
|
if (e.duration !== Infinity) return;
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1179
|
+
this.checkEndStale();
|
|
1180
|
+
let t = xt(e, e.currentTime);
|
|
1181
|
+
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= mt) && (this.bufferedAdvancedAt = G()), this.lastBufferedEnd = t);
|
|
1182
|
+
}, pt);
|
|
1183
|
+
}
|
|
1184
|
+
checkEndStale() {
|
|
1185
|
+
if (this.endedEmitted) return;
|
|
1186
|
+
let e = G(), t = this.lastTickAt == null ? 0 : e - this.lastTickAt;
|
|
1187
|
+
this.lastTickAt = e;
|
|
1188
|
+
let n = this.liveEnd();
|
|
1189
|
+
if (n == null) return;
|
|
1190
|
+
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= _t;
|
|
1191
|
+
this.lastSeekableEnd = n;
|
|
1192
|
+
let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
|
|
1193
|
+
if (r || t > vt || a || i.paused) {
|
|
1194
|
+
this.edgeStampedAt = e;
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1197
|
+
e - (this.edgeStampedAt ?? e) > gt && (this.endedEmitted = !0, this.deps.emit({
|
|
1198
|
+
type: "ended",
|
|
1199
|
+
reason: "stalled"
|
|
1200
|
+
}));
|
|
1201
|
+
}
|
|
1202
|
+
resetEndStale() {
|
|
1203
|
+
this.lastSeekableEnd = null, this.edgeStampedAt = null, this.lastTickAt = null;
|
|
1129
1204
|
}
|
|
1130
1205
|
unwatchBufferedEnd() {
|
|
1131
|
-
this.edgeTimer != null && clearInterval(this.edgeTimer), this.edgeTimer = null, this.onEdgeReset &&= (this.deps.video.removeEventListener("seeking", this.onEdgeReset), this.deps.video.removeEventListener("emptied", this.onEdgeReset), null), this.lastBufferedEnd = null, this.bufferedAdvancedAt = null;
|
|
1206
|
+
this.edgeTimer != null && clearInterval(this.edgeTimer), this.edgeTimer = null, this.onEdgeReset &&= (this.deps.video.removeEventListener("seeking", this.onEdgeReset), this.deps.video.removeEventListener("emptied", this.onEdgeReset), null), this.resetEndStale(), this.lastBufferedEnd = null, this.bufferedAdvancedAt = null;
|
|
1132
1207
|
}
|
|
1133
1208
|
liveEdgeEstimate() {
|
|
1134
1209
|
let e = this.deps.video;
|
|
1135
1210
|
if (e.duration !== Infinity) return null;
|
|
1136
|
-
let t = this.liveEnd(), n =
|
|
1211
|
+
let t = this.liveEnd(), n = xt(e, e.currentTime) ?? this.lastBufferedEnd;
|
|
1137
1212
|
if (n != null) {
|
|
1138
1213
|
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (G() - e) / 1e3));
|
|
1139
1214
|
(t == null || r > t) && (t = r);
|
|
@@ -1149,7 +1224,7 @@ var W = class {
|
|
|
1149
1224
|
snapToLive() {
|
|
1150
1225
|
let e = this.deps.video, t = this.liveEnd();
|
|
1151
1226
|
if (t == null) return;
|
|
1152
|
-
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t -
|
|
1227
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - ut, r);
|
|
1153
1228
|
try {
|
|
1154
1229
|
e.currentTime = i;
|
|
1155
1230
|
} catch {}
|
|
@@ -1170,7 +1245,7 @@ var W = class {
|
|
|
1170
1245
|
function G() {
|
|
1171
1246
|
return typeof performance < "u" ? performance.now() : Date.now();
|
|
1172
1247
|
}
|
|
1173
|
-
function
|
|
1248
|
+
function xt(e, t) {
|
|
1174
1249
|
let n = e.buffered;
|
|
1175
1250
|
if (!n || !Number.isFinite(t)) return null;
|
|
1176
1251
|
for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
|
|
@@ -1179,7 +1254,7 @@ function st(e, t) {
|
|
|
1179
1254
|
}
|
|
1180
1255
|
return null;
|
|
1181
1256
|
}
|
|
1182
|
-
function
|
|
1257
|
+
function St(e, t) {
|
|
1183
1258
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1184
1259
|
}
|
|
1185
1260
|
//#endregion
|
|
@@ -1196,8 +1271,8 @@ function K(e, t = Date.now()) {
|
|
|
1196
1271
|
}
|
|
1197
1272
|
//#endregion
|
|
1198
1273
|
//#region src/core/engine/prefetch.ts
|
|
1199
|
-
var
|
|
1200
|
-
function
|
|
1274
|
+
var Ct = 15e3, wt = 5e3, Tt = 6;
|
|
1275
|
+
function Et(e) {
|
|
1201
1276
|
try {
|
|
1202
1277
|
let t = new URL(e);
|
|
1203
1278
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1205,7 +1280,7 @@ function ft(e) {
|
|
|
1205
1280
|
return e;
|
|
1206
1281
|
}
|
|
1207
1282
|
}
|
|
1208
|
-
var
|
|
1283
|
+
var Dt = class {
|
|
1209
1284
|
cmcd;
|
|
1210
1285
|
entries = /* @__PURE__ */ new Map();
|
|
1211
1286
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1228,10 +1303,10 @@ var pt = class {
|
|
|
1228
1303
|
}
|
|
1229
1304
|
prefetch(e, t, n) {
|
|
1230
1305
|
if (!this.isActive(t)) return;
|
|
1231
|
-
let r =
|
|
1306
|
+
let r = Et(e);
|
|
1232
1307
|
if (this.entries.has(r)) return;
|
|
1233
1308
|
let i = this.perTrack.get(t) ?? 0;
|
|
1234
|
-
if (i >=
|
|
1309
|
+
if (i >= Tt) return;
|
|
1235
1310
|
this.perTrack.set(t, i + 1);
|
|
1236
1311
|
let a = new AbortController(), o = {
|
|
1237
1312
|
started: performance.now(),
|
|
@@ -1245,10 +1320,10 @@ var pt = class {
|
|
|
1245
1320
|
signal: a.signal
|
|
1246
1321
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1247
1322
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1248
|
-
},
|
|
1323
|
+
}, Ct);
|
|
1249
1324
|
}
|
|
1250
1325
|
take(e) {
|
|
1251
|
-
let t =
|
|
1326
|
+
let t = Et(e), n = this.entries.get(t);
|
|
1252
1327
|
return n && this.entries.delete(t), n;
|
|
1253
1328
|
}
|
|
1254
1329
|
destroy() {
|
|
@@ -1268,13 +1343,13 @@ var pt = class {
|
|
|
1268
1343
|
}
|
|
1269
1344
|
}
|
|
1270
1345
|
};
|
|
1271
|
-
function
|
|
1346
|
+
function Ot(t) {
|
|
1272
1347
|
let n = e.DefaultConfig?.loader;
|
|
1273
1348
|
if (typeof n != "function") return;
|
|
1274
1349
|
class r extends n {
|
|
1275
1350
|
served = !1;
|
|
1276
1351
|
cancelled = !1;
|
|
1277
|
-
stats =
|
|
1352
|
+
stats = kt();
|
|
1278
1353
|
load(e, n, r) {
|
|
1279
1354
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1280
1355
|
if (!i) {
|
|
@@ -1282,7 +1357,7 @@ function mt(t) {
|
|
|
1282
1357
|
return;
|
|
1283
1358
|
}
|
|
1284
1359
|
this.served = !0;
|
|
1285
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1360
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || wt, s = setTimeout(() => {
|
|
1286
1361
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1287
1362
|
}, o);
|
|
1288
1363
|
i.bytes.then((o) => {
|
|
@@ -1309,7 +1384,7 @@ function mt(t) {
|
|
|
1309
1384
|
}
|
|
1310
1385
|
return r;
|
|
1311
1386
|
}
|
|
1312
|
-
function
|
|
1387
|
+
function kt() {
|
|
1313
1388
|
return {
|
|
1314
1389
|
aborted: !1,
|
|
1315
1390
|
loaded: 0,
|
|
@@ -1333,10 +1408,10 @@ function ht() {
|
|
|
1333
1408
|
}
|
|
1334
1409
|
};
|
|
1335
1410
|
}
|
|
1336
|
-
function
|
|
1411
|
+
function At(e) {
|
|
1337
1412
|
return e === "audio" ? "audio" : "main";
|
|
1338
1413
|
}
|
|
1339
|
-
function
|
|
1414
|
+
function jt(e, t) {
|
|
1340
1415
|
let n = [];
|
|
1341
1416
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1342
1417
|
url: t.initSegment.url,
|
|
@@ -1355,24 +1430,24 @@ function _t(e, t) {
|
|
|
1355
1430
|
}
|
|
1356
1431
|
//#endregion
|
|
1357
1432
|
//#region src/core/engine/hls.ts
|
|
1358
|
-
function
|
|
1433
|
+
function Mt() {
|
|
1359
1434
|
return e.isSupported();
|
|
1360
1435
|
}
|
|
1361
|
-
var
|
|
1362
|
-
function
|
|
1436
|
+
var Nt = 1e6, Pt = 20, Ft = 1e4, It = 3, Lt = 5, Rt = 3, zt = 1e4, Bt = 3e4, Vt = 12e3, Ht = 3e3, Ut = .02, Wt = 6e3, Gt = .5, Kt = 3, qt = .5, Jt = 1.1, Yt = .25, Xt = 5e3, Zt = 4e3, Qt = 2, $t = 5, en = 2, tn = 2, nn = 4, rn = 4, an = 2e3, on = 3e4, sn = .2, cn = 30, ln = 2, un = 2, dn = 9, fn = .5, pn = 64;
|
|
1437
|
+
function mn(e) {
|
|
1363
1438
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1364
1439
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1365
1440
|
return;
|
|
1366
1441
|
}
|
|
1367
|
-
e.liveSyncDuration ??=
|
|
1368
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1369
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1442
|
+
e.liveSyncDuration ??= un;
|
|
1443
|
+
let t = Math.max(12, e.liveSyncDuration + dn);
|
|
1444
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), hn(e, e.liveSyncDuration);
|
|
1370
1445
|
}
|
|
1371
|
-
function
|
|
1446
|
+
function hn(e, t) {
|
|
1372
1447
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1373
1448
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1374
1449
|
}
|
|
1375
|
-
var
|
|
1450
|
+
var gn = class {
|
|
1376
1451
|
name = "hls";
|
|
1377
1452
|
hls = null;
|
|
1378
1453
|
deps;
|
|
@@ -1424,6 +1499,8 @@ var Qt = class {
|
|
|
1424
1499
|
starvedFrames = 0;
|
|
1425
1500
|
deadTicks = 0;
|
|
1426
1501
|
mainFragsSinceTick = 0;
|
|
1502
|
+
bwFragsLoaded = 0;
|
|
1503
|
+
bwSavedAt = 0;
|
|
1427
1504
|
recentMainFrags = [];
|
|
1428
1505
|
chaseSuspended = !1;
|
|
1429
1506
|
savedLiveMaxLatency;
|
|
@@ -1438,6 +1515,8 @@ var Qt = class {
|
|
|
1438
1515
|
capTimer = null;
|
|
1439
1516
|
sizeCapLevel = null;
|
|
1440
1517
|
bitrateCapLevel = -1;
|
|
1518
|
+
pushedCapLevel = -1;
|
|
1519
|
+
pushedCapReason = null;
|
|
1441
1520
|
fpsCapBitrate = null;
|
|
1442
1521
|
fpsCapFailedHeight = null;
|
|
1443
1522
|
fpsCapManaged = !0;
|
|
@@ -1452,7 +1531,7 @@ var Qt = class {
|
|
|
1452
1531
|
frameCounter;
|
|
1453
1532
|
detachFrames = null;
|
|
1454
1533
|
constructor(e) {
|
|
1455
|
-
this.deps = e, this.frameCounter = new
|
|
1534
|
+
this.deps = e, this.frameCounter = new st(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1456
1535
|
}
|
|
1457
1536
|
async load() {
|
|
1458
1537
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1465,7 +1544,7 @@ var Qt = class {
|
|
|
1465
1544
|
});
|
|
1466
1545
|
return;
|
|
1467
1546
|
}
|
|
1468
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1547
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ue(r), qe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1469
1548
|
let e = this.hls;
|
|
1470
1549
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1471
1550
|
let t = e.liveSyncPosition;
|
|
@@ -1488,7 +1567,7 @@ var Qt = class {
|
|
|
1488
1567
|
}
|
|
1489
1568
|
this.loadSuspended = !0;
|
|
1490
1569
|
}
|
|
1491
|
-
},
|
|
1570
|
+
}, Xt));
|
|
1492
1571
|
}
|
|
1493
1572
|
resumeLoading() {
|
|
1494
1573
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1520,7 +1599,7 @@ var Qt = class {
|
|
|
1520
1599
|
let t = e.liveSyncPosition;
|
|
1521
1600
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1522
1601
|
let { video: n } = this.deps;
|
|
1523
|
-
n.currentTime <= t +
|
|
1602
|
+
n.currentTime <= t + fn || (n.currentTime = t);
|
|
1524
1603
|
}
|
|
1525
1604
|
reanchorPartTimeline(e, t) {
|
|
1526
1605
|
let { frag: n, part: r } = t;
|
|
@@ -1532,7 +1611,7 @@ var Qt = class {
|
|
|
1532
1611
|
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1533
1612
|
if (!s) return;
|
|
1534
1613
|
let c = a.startPTS - s.start;
|
|
1535
|
-
if (!(!Number.isFinite(c) || Math.abs(c) <
|
|
1614
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < Ut)) {
|
|
1536
1615
|
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1537
1616
|
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})`);
|
|
1538
1617
|
}
|
|
@@ -1548,19 +1627,19 @@ var Qt = class {
|
|
|
1548
1627
|
liveDurationInfinity: !0,
|
|
1549
1628
|
maxBufferHole: .5,
|
|
1550
1629
|
maxLiveSyncPlaybackRate: d ? 1 : 1.1,
|
|
1551
|
-
abrEwmaDefaultEstimate:
|
|
1630
|
+
abrEwmaDefaultEstimate: this.startEstimate(),
|
|
1552
1631
|
capLevelToPlayerSize: !1,
|
|
1553
1632
|
...this.loadStarted ? {} : { autoStartLoad: !1 },
|
|
1554
1633
|
...u ? {
|
|
1555
1634
|
emeEnabled: !0,
|
|
1556
1635
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1557
1636
|
drmSystemOptions: {
|
|
1558
|
-
videoRobustness:
|
|
1559
|
-
audioRobustness:
|
|
1560
|
-
videoEncryptionScheme:
|
|
1561
|
-
audioEncryptionScheme:
|
|
1637
|
+
videoRobustness: N.video,
|
|
1638
|
+
audioRobustness: N.audio,
|
|
1639
|
+
videoEncryptionScheme: N.scheme,
|
|
1640
|
+
audioEncryptionScheme: N.scheme
|
|
1562
1641
|
},
|
|
1563
|
-
...
|
|
1642
|
+
...A() ? { requestMediaKeySystemAccessFunc: He(t) } : {},
|
|
1564
1643
|
licenseXhrSetup: (e, t) => {
|
|
1565
1644
|
let o = performance.now(), s = () => {
|
|
1566
1645
|
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", () => {
|
|
@@ -1572,7 +1651,7 @@ var Qt = class {
|
|
|
1572
1651
|
return;
|
|
1573
1652
|
}
|
|
1574
1653
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1575
|
-
u = setTimeout(() => e(void 0),
|
|
1654
|
+
u = setTimeout(() => e(void 0), zt);
|
|
1576
1655
|
});
|
|
1577
1656
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1578
1657
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1588,31 +1667,31 @@ var Qt = class {
|
|
|
1588
1667
|
...c
|
|
1589
1668
|
};
|
|
1590
1669
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !f.fLoader) {
|
|
1591
|
-
let e = new
|
|
1670
|
+
let e = new Dt({
|
|
1592
1671
|
sessionId: n.analytics?.sid,
|
|
1593
1672
|
contentId: n.matchUrn
|
|
1594
|
-
}), t =
|
|
1673
|
+
}), t = Ot(e);
|
|
1595
1674
|
t && (this.prefetch = e, f.fLoader = t);
|
|
1596
1675
|
}
|
|
1597
|
-
|
|
1676
|
+
mn(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;
|
|
1598
1677
|
let p = new e(f);
|
|
1599
1678
|
if (this.hls = p, p.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(p, t)), p.on(e.Events.MANIFEST_PARSED, () => {
|
|
1600
1679
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(p), this.measureLadder(p), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1601
1680
|
}), p.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1602
1681
|
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(() => {
|
|
1603
1682
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1604
|
-
},
|
|
1683
|
+
}, Bt)));
|
|
1605
1684
|
}), p.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1606
1685
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1607
1686
|
}), p.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
1608
|
-
t?.frag?.type === "main" && (this.mainFragsSinceTick += 1);
|
|
1687
|
+
t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
|
|
1609
1688
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1610
1689
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1611
1690
|
let i = n?.loading;
|
|
1612
|
-
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length >
|
|
1691
|
+
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > pn && this.requestTimesMs.shift());
|
|
1613
1692
|
let a = t?.frag?.url;
|
|
1614
1693
|
if (a) {
|
|
1615
|
-
let e =
|
|
1694
|
+
let e = z(a);
|
|
1616
1695
|
e && (this.cdnHost = e);
|
|
1617
1696
|
}
|
|
1618
1697
|
}), p.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1626,15 +1705,15 @@ var Qt = class {
|
|
|
1626
1705
|
}), p.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1627
1706
|
let t = this.prefetch;
|
|
1628
1707
|
p.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1629
|
-
let r = n?.frag, i =
|
|
1630
|
-
if (r && t.isActive(i)) for (let e of
|
|
1631
|
-
}), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1708
|
+
let r = n?.frag, i = At(r?.type);
|
|
1709
|
+
if (r && t.isActive(i)) for (let e of jt(p, r)) t.prefetch(e.url, i, e.kind);
|
|
1710
|
+
}), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(At(n?.frag?.type)));
|
|
1632
1711
|
}
|
|
1633
1712
|
p.on(e.Events.KEY_LOADED, () => {
|
|
1634
1713
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1635
1714
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1636
1715
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1637
|
-
},
|
|
1716
|
+
}, Ht), p.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1638
1717
|
this.renditionSwitches += 1;
|
|
1639
1718
|
let n = this.lastLevelIndex >= 0 ? p.levels[this.lastLevelIndex] : void 0, r = p.levels[t.level];
|
|
1640
1719
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1698,7 +1777,7 @@ var Qt = class {
|
|
|
1698
1777
|
return;
|
|
1699
1778
|
}
|
|
1700
1779
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1701
|
-
let t = e > this.sizeCapLevel ?
|
|
1780
|
+
let t = e > this.sizeCapLevel ? an : on;
|
|
1702
1781
|
this.capTimer = setTimeout(() => {
|
|
1703
1782
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1704
1783
|
}, t);
|
|
@@ -1708,9 +1787,9 @@ var Qt = class {
|
|
|
1708
1787
|
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;
|
|
1709
1788
|
}
|
|
1710
1789
|
dropLevelsWidevineCannotPlay(e) {
|
|
1711
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1712
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1713
|
-
for (let n of t)
|
|
1790
|
+
this.removeLevelsWhere(e, (e) => Je(e) !== !0);
|
|
1791
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && P(e) !== "avc" && !!P(e)));
|
|
1792
|
+
for (let n of t) Ke(n).then((t) => {
|
|
1714
1793
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1715
1794
|
});
|
|
1716
1795
|
}
|
|
@@ -1718,10 +1797,10 @@ var Qt = class {
|
|
|
1718
1797
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1719
1798
|
if (n.forEach((e, n) => {
|
|
1720
1799
|
let a = e.videoCodec;
|
|
1721
|
-
a &&
|
|
1800
|
+
a && P(a) && t(a) && (r.push(n), i.add(a));
|
|
1722
1801
|
}), !r.length) return !1;
|
|
1723
1802
|
let a = [...i].join(", ");
|
|
1724
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !
|
|
1803
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !P(e.videoCodec) || Je(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1725
1804
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1726
1805
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1727
1806
|
}
|
|
@@ -1735,11 +1814,12 @@ var Qt = class {
|
|
|
1735
1814
|
let e = this.hls;
|
|
1736
1815
|
if (!e) return;
|
|
1737
1816
|
let t = [
|
|
1738
|
-
this.sizeCapLevel ?? -1,
|
|
1739
|
-
this.bitrateCapLevel,
|
|
1740
|
-
this.fpsCapLevel(e)
|
|
1741
|
-
]
|
|
1742
|
-
e
|
|
1817
|
+
["size", this.sizeCapLevel ?? -1],
|
|
1818
|
+
["bitrate", this.bitrateCapLevel],
|
|
1819
|
+
["fps", this.fpsCapLevel(e)]
|
|
1820
|
+
], n = -1, r = null;
|
|
1821
|
+
for (let [e, i] of t) i >= 0 && (n < 0 || i < n) && (n = i, r = e);
|
|
1822
|
+
e.autoLevelCapping = n, this.pushedCapLevel = n, this.pushedCapReason = r;
|
|
1743
1823
|
}
|
|
1744
1824
|
getAudioTracks() {
|
|
1745
1825
|
return this.hls ? this.hls.audioTracks.map((e) => ({
|
|
@@ -1792,7 +1872,14 @@ var Qt = class {
|
|
|
1792
1872
|
if (this.cdnHost && (n.cdnHost = this.cdnHost), this.licenseRequested && (n.keySystem = "widevine", n.drmSecurityLevel = "L3"), e) {
|
|
1793
1873
|
n.qualityPinned = !e.autoLevelEnabled, typeof e.latency == "number" && (n.latencySeconds = e.latency), typeof e.targetLatency == "number" && e.targetLatency > 0 && (n.targetLatencySeconds = e.targetLatency), typeof e.bandwidthEstimate == "number" && (n.bandwidthKbps = Math.round(e.bandwidthEstimate / 1e3));
|
|
1794
1874
|
let t = e.currentLevel >= 0 ? e.levels[e.currentLevel] : void 0;
|
|
1795
|
-
t && (n.levelHeight = t.height)
|
|
1875
|
+
t && (n.levelHeight = t.height);
|
|
1876
|
+
let r = e.autoLevelCapping, i = r >= 0 ? e.levels[r] : void 0;
|
|
1877
|
+
if (i && i.height > 0) {
|
|
1878
|
+
n.maxLevelHeight = i.height;
|
|
1879
|
+
let t = e.config ?? {};
|
|
1880
|
+
t.capLevelToPlayerSize !== !0 && t.capLevelOnFPSDrop !== !0 && r === this.pushedCapLevel && this.pushedCapReason && (n.capReason = this.pushedCapReason);
|
|
1881
|
+
}
|
|
1882
|
+
t?.videoCodec && (n.videoCodec = t.videoCodec), t?.audioCodec && (n.audioCodec = t.audioCodec), t && typeof t.bitrate == "number" && (n.renditionBitrateKbps = Math.round(t.bitrate / 1e3)), typeof t?.details?.live == "boolean" && (n.isLive = t.details.live, typeof e.liveSyncPosition == "number" && (n.atLiveEdge = this.deps.video.currentTime >= e.liveSyncPosition - 1.5));
|
|
1796
1883
|
}
|
|
1797
1884
|
return n;
|
|
1798
1885
|
}
|
|
@@ -1819,7 +1906,7 @@ var Qt = class {
|
|
|
1819
1906
|
return;
|
|
1820
1907
|
}
|
|
1821
1908
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1822
|
-
!this.chaseSuspended && e >
|
|
1909
|
+
!this.chaseSuspended && e > Wt && this.suspendChasing(), e > Vt && this.emitEnded("stalled");
|
|
1823
1910
|
}
|
|
1824
1911
|
resetStarvationWindow() {
|
|
1825
1912
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1834,7 +1921,7 @@ var Qt = class {
|
|
|
1834
1921
|
this.resetStarvationWindow();
|
|
1835
1922
|
return;
|
|
1836
1923
|
}
|
|
1837
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1924
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < Wt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Zt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
|
|
1838
1925
|
if (this.starvedFrames = c, !a || l) {
|
|
1839
1926
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1840
1927
|
return;
|
|
@@ -1843,12 +1930,12 @@ var Qt = class {
|
|
|
1843
1930
|
this.resetStarvationWindow();
|
|
1844
1931
|
return;
|
|
1845
1932
|
}
|
|
1846
|
-
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 >
|
|
1933
|
+
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > nn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= en && (this.clearKick(), this.starvationRebuilds < tn)) {
|
|
1847
1934
|
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");
|
|
1848
1935
|
return;
|
|
1849
1936
|
}
|
|
1850
|
-
let u = i && this.starvedTicks >=
|
|
1851
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1937
|
+
let u = i && this.starvedTicks >= Qt, d = !i && this.deadTicks >= nn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= rn;
|
|
1938
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= $t))) {
|
|
1852
1939
|
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");
|
|
1853
1940
|
try {
|
|
1854
1941
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1863,7 +1950,7 @@ var Qt = class {
|
|
|
1863
1950
|
let t = e.latency, n = e.targetLatency;
|
|
1864
1951
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1865
1952
|
let r = t - n;
|
|
1866
|
-
!this.catchUpEngaged && r >
|
|
1953
|
+
!this.catchUpEngaged && r > Gt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Gt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1867
1954
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1868
1955
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1869
1956
|
}
|
|
@@ -1884,16 +1971,16 @@ var Qt = class {
|
|
|
1884
1971
|
this.resetFrameDropWindow();
|
|
1885
1972
|
return;
|
|
1886
1973
|
}
|
|
1887
|
-
let { totalFrames: n, dropped: r } =
|
|
1888
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
1974
|
+
let { totalFrames: n, dropped: r } = B(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
1975
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < cn || o < 0) {
|
|
1889
1976
|
this.fpsBadTicks = 0;
|
|
1890
1977
|
return;
|
|
1891
1978
|
}
|
|
1892
|
-
if (o <=
|
|
1979
|
+
if (o <= sn * a) {
|
|
1893
1980
|
this.fpsBadTicks = 0;
|
|
1894
1981
|
return;
|
|
1895
1982
|
}
|
|
1896
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
1983
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < ln) return;
|
|
1897
1984
|
this.fpsBadTicks = 0;
|
|
1898
1985
|
let s = e.levels, c = s[e.currentLevel];
|
|
1899
1986
|
if (!c) return;
|
|
@@ -1910,20 +1997,20 @@ var Qt = class {
|
|
|
1910
1997
|
return;
|
|
1911
1998
|
}
|
|
1912
1999
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
1913
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
2000
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Jt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
1914
2001
|
this.resetChaseWindow();
|
|
1915
2002
|
return;
|
|
1916
2003
|
}
|
|
1917
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
2004
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= qt) {
|
|
1918
2005
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
1919
2006
|
return;
|
|
1920
2007
|
}
|
|
1921
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
2008
|
+
if (this.chaseTicks += 1, this.chaseTicks < Kt) return;
|
|
1922
2009
|
this.resetChaseWindow();
|
|
1923
2010
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
1924
2011
|
if (!(a > 1)) return;
|
|
1925
2012
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
1926
|
-
s < o +
|
|
2013
|
+
s < o + Yt || (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);
|
|
1927
2014
|
}
|
|
1928
2015
|
suspendChasing() {
|
|
1929
2016
|
let e = this.hls;
|
|
@@ -1952,8 +2039,18 @@ var Qt = class {
|
|
|
1952
2039
|
this.deps.video.pause();
|
|
1953
2040
|
} catch {}
|
|
1954
2041
|
}
|
|
2042
|
+
startEstimate() {
|
|
2043
|
+
return this.deps.rememberBandwidth === !1 ? Nt : Ie() ?? Nt;
|
|
2044
|
+
}
|
|
2045
|
+
maybeRememberBandwidth(e) {
|
|
2046
|
+
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Pt) return;
|
|
2047
|
+
let t = Date.now();
|
|
2048
|
+
if (!e && t - this.bwSavedAt < Ft) return;
|
|
2049
|
+
let n = this.hls?.bandwidthEstimate;
|
|
2050
|
+
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Le(n));
|
|
2051
|
+
}
|
|
1955
2052
|
destroy() {
|
|
1956
|
-
if (this.detachFrames?.(), this.detachFrames = null, this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
|
|
2053
|
+
if (this.maybeRememberBandwidth(!0), this.detachFrames?.(), this.detachFrames = null, this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
|
|
1957
2054
|
try {
|
|
1958
2055
|
this.hls.destroy();
|
|
1959
2056
|
} catch (e) {
|
|
@@ -1968,7 +2065,7 @@ var Qt = class {
|
|
|
1968
2065
|
scheduleLicenseRetry(t) {
|
|
1969
2066
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1970
2067
|
let n = t.response?.code ?? 0;
|
|
1971
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
2068
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Rt) return !1;
|
|
1972
2069
|
this.licenseRecoveries += 1;
|
|
1973
2070
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1974
2071
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -2000,7 +2097,7 @@ var Qt = class {
|
|
|
2000
2097
|
return;
|
|
2001
2098
|
}
|
|
2002
2099
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
2003
|
-
if (this.networkRecoveries <
|
|
2100
|
+
if (this.networkRecoveries < Lt) {
|
|
2004
2101
|
this.networkRecoveries += 1;
|
|
2005
2102
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
2006
2103
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -2017,7 +2114,7 @@ var Qt = class {
|
|
|
2017
2114
|
return;
|
|
2018
2115
|
}
|
|
2019
2116
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
2020
|
-
if (this.mediaRecoveries <
|
|
2117
|
+
if (this.mediaRecoveries < It) {
|
|
2021
2118
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
2022
2119
|
return;
|
|
2023
2120
|
}
|
|
@@ -2041,19 +2138,19 @@ var Qt = class {
|
|
|
2041
2138
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
2042
2139
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
2043
2140
|
}
|
|
2044
|
-
},
|
|
2141
|
+
}, _n = 15e3, vn = 6e5, yn = 3e5, bn = 100, q = 1, xn = 1e3, Sn = 3e4, Cn = 1e3, wn = {
|
|
2045
2142
|
inline: "PRESENTATION_INLINE",
|
|
2046
2143
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2047
2144
|
pip: "PRESENTATION_PIP"
|
|
2048
|
-
},
|
|
2145
|
+
}, Tn = {
|
|
2049
2146
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2050
2147
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2051
2148
|
none: "KEY_SYSTEM_NONE"
|
|
2052
2149
|
};
|
|
2053
|
-
function
|
|
2150
|
+
function En(e, t) {
|
|
2054
2151
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
2055
2152
|
}
|
|
2056
|
-
var
|
|
2153
|
+
var Dn = /* @__PURE__ */ new Set([
|
|
2057
2154
|
"INVALID_URN",
|
|
2058
2155
|
"NOT_FOUND",
|
|
2059
2156
|
"GONE",
|
|
@@ -2073,7 +2170,7 @@ var un = /* @__PURE__ */ new Set([
|
|
|
2073
2170
|
ended: "PLAYER_STATE_ENDED",
|
|
2074
2171
|
error: "PLAYER_STATE_ERROR"
|
|
2075
2172
|
};
|
|
2076
|
-
function
|
|
2173
|
+
function On(e) {
|
|
2077
2174
|
try {
|
|
2078
2175
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2079
2176
|
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);
|
|
@@ -2081,8 +2178,8 @@ function dn(e) {
|
|
|
2081
2178
|
return;
|
|
2082
2179
|
}
|
|
2083
2180
|
}
|
|
2084
|
-
var
|
|
2085
|
-
function
|
|
2181
|
+
var kn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), An = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), jn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2182
|
+
function Mn(e) {
|
|
2086
2183
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2087
2184
|
let t;
|
|
2088
2185
|
try {
|
|
@@ -2091,19 +2188,19 @@ function hn(e) {
|
|
|
2091
2188
|
} catch {
|
|
2092
2189
|
return;
|
|
2093
2190
|
}
|
|
2094
|
-
if (
|
|
2095
|
-
Y.add(t), g(
|
|
2191
|
+
if (An.has(t) && !Y.has(t)) {
|
|
2192
|
+
Y.add(t), g(jn(new URL(t).origin));
|
|
2096
2193
|
for (let e of X) e.noteCspBlocked();
|
|
2097
2194
|
}
|
|
2098
2195
|
}
|
|
2099
|
-
function
|
|
2196
|
+
function Nn(e, t) {
|
|
2100
2197
|
return g(t, e), { disabledReason: t };
|
|
2101
2198
|
}
|
|
2102
|
-
function
|
|
2103
|
-
if (n) return t && !
|
|
2199
|
+
function Pn(e, t, n) {
|
|
2200
|
+
if (n) return t && !kn(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2104
2201
|
if (t) return { endpoint: t };
|
|
2105
|
-
if (t !== void 0) return
|
|
2106
|
-
let r =
|
|
2202
|
+
if (t !== void 0) return Nn("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).");
|
|
2203
|
+
let r = On(e);
|
|
2107
2204
|
if (r) return { endpoint: r };
|
|
2108
2205
|
let i;
|
|
2109
2206
|
try {
|
|
@@ -2111,9 +2208,9 @@ function gn(e, t, n) {
|
|
|
2111
2208
|
} catch {
|
|
2112
2209
|
i = e;
|
|
2113
2210
|
}
|
|
2114
|
-
return
|
|
2211
|
+
return Nn(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).`);
|
|
2115
2212
|
}
|
|
2116
|
-
var
|
|
2213
|
+
var Fn = class {
|
|
2117
2214
|
opts;
|
|
2118
2215
|
url;
|
|
2119
2216
|
cspKey;
|
|
@@ -2195,8 +2292,8 @@ var _n = class {
|
|
|
2195
2292
|
constructor(e) {
|
|
2196
2293
|
this.opts = {
|
|
2197
2294
|
...e,
|
|
2198
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2199
|
-
idleMs: e.idleMs ??
|
|
2295
|
+
heartbeatMs: e.heartbeatMs ?? _n,
|
|
2296
|
+
idleMs: e.idleMs ?? vn
|
|
2200
2297
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2201
2298
|
try {
|
|
2202
2299
|
let e = new URL(this.url);
|
|
@@ -2213,11 +2310,11 @@ var _n = class {
|
|
|
2213
2310
|
sdkVersion: this.opts.sdkVersion,
|
|
2214
2311
|
...this.opts.environment
|
|
2215
2312
|
};
|
|
2216
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2313
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), xn), 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 && An.add(this.cspKey), document.addEventListener("securitypolicyviolation", Mn), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2217
2314
|
}
|
|
2218
2315
|
checkSuspension(e) {
|
|
2219
2316
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2220
|
-
let t = Math.max(this.opts.idleMs,
|
|
2317
|
+
let t = Math.max(this.opts.idleMs, yn);
|
|
2221
2318
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2222
2319
|
}
|
|
2223
2320
|
syncIdle(e) {
|
|
@@ -2240,12 +2337,12 @@ var _n = class {
|
|
|
2240
2337
|
let a = {
|
|
2241
2338
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2242
2339
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2243
|
-
presentation:
|
|
2340
|
+
presentation: wn[this.presentation]
|
|
2244
2341
|
}, o = this.causeOf(e, t, i);
|
|
2245
2342
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2246
2343
|
}
|
|
2247
2344
|
seekInduced(e) {
|
|
2248
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2345
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < Cn;
|
|
2249
2346
|
}
|
|
2250
2347
|
causeOf(e, t, n) {
|
|
2251
2348
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2319,7 +2416,7 @@ var _n = class {
|
|
|
2319
2416
|
let r = n ?? "";
|
|
2320
2417
|
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";
|
|
2321
2418
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2322
|
-
if (
|
|
2419
|
+
if (Dn.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2323
2420
|
let i = t ?? "";
|
|
2324
2421
|
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";
|
|
2325
2422
|
}
|
|
@@ -2366,14 +2463,14 @@ var _n = class {
|
|
|
2366
2463
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2367
2464
|
o.requestCountDelta = _;
|
|
2368
2465
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2369
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2466
|
+
n.length > 0 && (o.requestTimeP50Ms = En(n, 50), o.requestTimeP95Ms = En(n, 95));
|
|
2370
2467
|
}
|
|
2371
2468
|
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();
|
|
2372
2469
|
}
|
|
2373
2470
|
maybeEmitMediaInfo(e) {
|
|
2374
2471
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2375
2472
|
let t = {};
|
|
2376
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2473
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Tn[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);
|
|
2377
2474
|
let n = JSON.stringify(t);
|
|
2378
2475
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2379
2476
|
}
|
|
@@ -2393,7 +2490,7 @@ var _n = class {
|
|
|
2393
2490
|
let c = r?.positionMs ?? 0;
|
|
2394
2491
|
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));
|
|
2395
2492
|
let l = e !== "END_REASON_ENDED";
|
|
2396
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2493
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= Sn && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Sn && (i.abandonAfterErrorMs = Math.max(q, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
|
|
2397
2494
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2398
2495
|
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");
|
|
2399
2496
|
}
|
|
@@ -2413,13 +2510,13 @@ var _n = class {
|
|
|
2413
2510
|
};
|
|
2414
2511
|
}
|
|
2415
2512
|
noteCspBlocked() {
|
|
2416
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2513
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(jn(new URL(this.url).origin)));
|
|
2417
2514
|
}
|
|
2418
2515
|
cspBlocked() {
|
|
2419
2516
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2420
2517
|
}
|
|
2421
2518
|
enqueue(e) {
|
|
2422
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2519
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > bn;) {
|
|
2423
2520
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2424
2521
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2425
2522
|
}
|
|
@@ -2446,7 +2543,7 @@ var _n = class {
|
|
|
2446
2543
|
};
|
|
2447
2544
|
//#endregion
|
|
2448
2545
|
//#region src/core/environment.ts
|
|
2449
|
-
function
|
|
2546
|
+
function In() {
|
|
2450
2547
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2451
2548
|
let e;
|
|
2452
2549
|
try {
|
|
@@ -2471,14 +2568,14 @@ function vn() {
|
|
|
2471
2568
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2472
2569
|
};
|
|
2473
2570
|
}
|
|
2474
|
-
function
|
|
2571
|
+
function Ln() {
|
|
2475
2572
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2476
2573
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2477
2574
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2478
2575
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2479
2576
|
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";
|
|
2480
2577
|
}
|
|
2481
|
-
function
|
|
2578
|
+
function Rn() {
|
|
2482
2579
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2483
2580
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2484
2581
|
let t = {
|
|
@@ -2497,17 +2594,17 @@ function bn() {
|
|
|
2497
2594
|
}
|
|
2498
2595
|
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;
|
|
2499
2596
|
}
|
|
2500
|
-
function
|
|
2501
|
-
let t =
|
|
2502
|
-
deviceClass:
|
|
2597
|
+
function zn(e) {
|
|
2598
|
+
let t = In(), n = {
|
|
2599
|
+
deviceClass: Ln(),
|
|
2503
2600
|
integration: t.integration,
|
|
2504
|
-
...
|
|
2601
|
+
...Rn()
|
|
2505
2602
|
};
|
|
2506
2603
|
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);
|
|
2507
2604
|
let r = e.getBoundingClientRect?.();
|
|
2508
2605
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2509
2606
|
}
|
|
2510
|
-
async function
|
|
2607
|
+
async function Bn() {
|
|
2511
2608
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2512
2609
|
if (!e?.getHighEntropyValues) return {};
|
|
2513
2610
|
try {
|
|
@@ -2519,7 +2616,7 @@ async function Sn() {
|
|
|
2519
2616
|
}
|
|
2520
2617
|
//#endregion
|
|
2521
2618
|
//#region src/core/version.ts
|
|
2522
|
-
var
|
|
2619
|
+
var Vn = "2.18.0", Hn = {
|
|
2523
2620
|
accent: "#E1B600",
|
|
2524
2621
|
accentText: "#1B1C23",
|
|
2525
2622
|
background: "#0e0f13",
|
|
@@ -2530,7 +2627,7 @@ var Cn = "2.16.13", wn = {
|
|
|
2530
2627
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2531
2628
|
radius: "8px",
|
|
2532
2629
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2533
|
-
},
|
|
2630
|
+
}, Un = {
|
|
2534
2631
|
accent: "--havik-accent",
|
|
2535
2632
|
accentText: "--havik-accent-text",
|
|
2536
2633
|
background: "--havik-bg",
|
|
@@ -2542,26 +2639,26 @@ var Cn = "2.16.13", wn = {
|
|
|
2542
2639
|
radius: "--havik-radius",
|
|
2543
2640
|
fontFamily: "--havik-font"
|
|
2544
2641
|
};
|
|
2545
|
-
function
|
|
2642
|
+
function Wn(e, t) {
|
|
2546
2643
|
let n = {
|
|
2547
|
-
...
|
|
2644
|
+
...Hn,
|
|
2548
2645
|
...t
|
|
2549
2646
|
};
|
|
2550
|
-
for (let t of Object.keys(
|
|
2647
|
+
for (let t of Object.keys(Un)) e.style.setProperty(Un[t], n[t]);
|
|
2551
2648
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2552
2649
|
}
|
|
2553
2650
|
//#endregion
|
|
2554
2651
|
//#region src/ui/styles.ts
|
|
2555
|
-
var
|
|
2556
|
-
function
|
|
2557
|
-
let n = e.querySelector(`style#${
|
|
2558
|
-
if (n && (!t ||
|
|
2652
|
+
var Gn = "havik-player-styles", Kn = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", Z = /* @__PURE__ */ new WeakMap();
|
|
2653
|
+
function qn(e = document, t) {
|
|
2654
|
+
let n = e.querySelector(`style#${Gn}`);
|
|
2655
|
+
if (n && (!t || Z.get(n) === t)) return;
|
|
2559
2656
|
let r = e.createElement("style");
|
|
2560
|
-
r.id =
|
|
2657
|
+
r.id = Gn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Kn, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2561
2658
|
}
|
|
2562
2659
|
//#endregion
|
|
2563
2660
|
//#region src/ui/icons.ts
|
|
2564
|
-
var
|
|
2661
|
+
var Jn = {
|
|
2565
2662
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2566
2663
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2567
2664
|
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\"/>",
|
|
@@ -2575,20 +2672,20 @@ var jn = {
|
|
|
2575
2672
|
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\"/>"
|
|
2576
2673
|
};
|
|
2577
2674
|
function Q(e) {
|
|
2578
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2675
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Jn[e]}</svg>`;
|
|
2579
2676
|
}
|
|
2580
2677
|
//#endregion
|
|
2581
2678
|
//#region src/ui/controls.ts
|
|
2582
|
-
var
|
|
2679
|
+
var Yn = 3e3, Xn = 250, Zn = /* @__PURE__ */ new Set([
|
|
2583
2680
|
"GONE",
|
|
2584
2681
|
"NOT_FOUND",
|
|
2585
2682
|
"INVALID_URN",
|
|
2586
2683
|
"UNAUTHORIZED"
|
|
2587
2684
|
]);
|
|
2588
|
-
function
|
|
2589
|
-
return new
|
|
2685
|
+
function Qn(e) {
|
|
2686
|
+
return new $n(e);
|
|
2590
2687
|
}
|
|
2591
|
-
var
|
|
2688
|
+
var $n = class {
|
|
2592
2689
|
root;
|
|
2593
2690
|
video;
|
|
2594
2691
|
player;
|
|
@@ -2635,7 +2732,7 @@ var In = class {
|
|
|
2635
2732
|
scrubbing = !1;
|
|
2636
2733
|
offFns = [];
|
|
2637
2734
|
constructor(e) {
|
|
2638
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2735
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Yn, 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, qn(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");
|
|
2639
2736
|
let t = (e, t, n) => {
|
|
2640
2737
|
let r = this.doc.createElement(e);
|
|
2641
2738
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2721,7 +2818,7 @@ var In = class {
|
|
|
2721
2818
|
let t = this.surfaceWasHidden;
|
|
2722
2819
|
this.tapTimer = setTimeout(() => {
|
|
2723
2820
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2724
|
-
},
|
|
2821
|
+
}, Xn);
|
|
2725
2822
|
}
|
|
2726
2823
|
toggleBar(e) {
|
|
2727
2824
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2756,7 +2853,7 @@ var In = class {
|
|
|
2756
2853
|
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);
|
|
2757
2854
|
} else {
|
|
2758
2855
|
let r = this.doc.createElement("div");
|
|
2759
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2856
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Zn.has(this.lastError.code)) {
|
|
2760
2857
|
let e = this.doc.createElement("button");
|
|
2761
2858
|
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);
|
|
2762
2859
|
}
|
|
@@ -2797,7 +2894,7 @@ var In = class {
|
|
|
2797
2894
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2798
2895
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2799
2896
|
}
|
|
2800
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2897
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${er(this.video.currentTime)} / ${er(this.video.duration)}`);
|
|
2801
2898
|
}
|
|
2802
2899
|
syncLive() {
|
|
2803
2900
|
let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
|
|
@@ -2847,17 +2944,17 @@ var In = class {
|
|
|
2847
2944
|
renderQualityMenu() {
|
|
2848
2945
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2849
2946
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2850
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2947
|
+
for (let n of e) this.menu.append(this.menuItem(tr(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2851
2948
|
}
|
|
2852
2949
|
renderAudioMenu() {
|
|
2853
2950
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2854
2951
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2855
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2952
|
+
for (let t of e) this.menu.append(this.menuItem(nr(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2856
2953
|
}
|
|
2857
2954
|
renderCcMenu() {
|
|
2858
2955
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2859
2956
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2860
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2957
|
+
for (let t of e) this.menu.append(this.menuItem(rr(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2861
2958
|
}
|
|
2862
2959
|
onTracksChanged() {
|
|
2863
2960
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2877,11 +2974,11 @@ var In = class {
|
|
|
2877
2974
|
}
|
|
2878
2975
|
async toggleFullscreen() {
|
|
2879
2976
|
try {
|
|
2880
|
-
|
|
2977
|
+
x(this.video, this.root) ? await C(this.video, this.root) : await S(this.video, this.root);
|
|
2881
2978
|
} catch {}
|
|
2882
2979
|
}
|
|
2883
2980
|
syncFullscreen() {
|
|
2884
|
-
let e =
|
|
2981
|
+
let e = x(this.video, this.root);
|
|
2885
2982
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
2886
2983
|
}
|
|
2887
2984
|
poke() {
|
|
@@ -2958,41 +3055,41 @@ var In = class {
|
|
|
2958
3055
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2959
3056
|
}
|
|
2960
3057
|
};
|
|
2961
|
-
function
|
|
3058
|
+
function er(e) {
|
|
2962
3059
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2963
3060
|
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");
|
|
2964
3061
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2965
3062
|
}
|
|
2966
|
-
function
|
|
3063
|
+
function tr(e) {
|
|
2967
3064
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2968
3065
|
}
|
|
2969
|
-
function
|
|
3066
|
+
function nr(e) {
|
|
2970
3067
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2971
3068
|
}
|
|
2972
|
-
function
|
|
3069
|
+
function rr(e) {
|
|
2973
3070
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2974
3071
|
}
|
|
2975
3072
|
//#endregion
|
|
2976
3073
|
//#region src/managed/index.ts
|
|
2977
|
-
var
|
|
2978
|
-
function
|
|
3074
|
+
var ir = 6e3, ar = 45e3, or = 2e3, sr = 3, cr = 5e3, lr = 2e3, ur = 48e4, dr = "keySystemLicenseRequestFailed";
|
|
3075
|
+
function fr(e) {
|
|
2979
3076
|
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)})`);
|
|
2980
|
-
if (e.env !== void 0) return
|
|
3077
|
+
if (e.env !== void 0) return L(e.env);
|
|
2981
3078
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2982
3079
|
return e.baseUrl;
|
|
2983
3080
|
}
|
|
2984
|
-
async function
|
|
3081
|
+
async function pr(e) {
|
|
2985
3082
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2986
|
-
let t =
|
|
3083
|
+
let t = fr(e);
|
|
2987
3084
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2988
3085
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2989
|
-
let r = new
|
|
3086
|
+
let r = new mr({
|
|
2990
3087
|
...e,
|
|
2991
3088
|
baseUrl: t
|
|
2992
3089
|
});
|
|
2993
3090
|
return await r.start(), r;
|
|
2994
3091
|
}
|
|
2995
|
-
var
|
|
3092
|
+
var mr = class {
|
|
2996
3093
|
opts;
|
|
2997
3094
|
abort = new AbortController();
|
|
2998
3095
|
listeners = {};
|
|
@@ -3006,6 +3103,9 @@ var Xn = class {
|
|
|
3006
3103
|
refreshTimer;
|
|
3007
3104
|
refreshInFlight;
|
|
3008
3105
|
onRefocus;
|
|
3106
|
+
onReturnVisible = null;
|
|
3107
|
+
onReturnPageShow = null;
|
|
3108
|
+
hiddenAtMs = null;
|
|
3009
3109
|
staleLicenseReloaded = !1;
|
|
3010
3110
|
_state = "idle";
|
|
3011
3111
|
_descriptor = null;
|
|
@@ -3063,7 +3163,7 @@ var Xn = class {
|
|
|
3063
3163
|
};
|
|
3064
3164
|
}
|
|
3065
3165
|
beginArming(e, t, n = !1) {
|
|
3066
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
3166
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? T(this.opts.baseUrl);
|
|
3067
3167
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
3068
3168
|
}
|
|
3069
3169
|
beginArmingByPolling(e) {
|
|
@@ -3084,7 +3184,7 @@ var Xn = class {
|
|
|
3084
3184
|
setTimeout(() => {
|
|
3085
3185
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3086
3186
|
phase: i ? "unavailable" : "tooEarly",
|
|
3087
|
-
retryInMs:
|
|
3187
|
+
retryInMs: ar,
|
|
3088
3188
|
attempt: 1,
|
|
3089
3189
|
elapsedMs: 0,
|
|
3090
3190
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3123,13 +3223,13 @@ var Xn = class {
|
|
|
3123
3223
|
!a && !p() && h();
|
|
3124
3224
|
}, e);
|
|
3125
3225
|
};
|
|
3126
|
-
_(
|
|
3226
|
+
_(ir), this.armingSub = w({
|
|
3127
3227
|
eventsBaseUrl: t,
|
|
3128
3228
|
matchUrn: this.opts.matchUrn,
|
|
3129
3229
|
credential: this.opts.credential,
|
|
3130
|
-
onAlive: () => _(
|
|
3230
|
+
onAlive: () => _(ar),
|
|
3131
3231
|
onState: (e) => {
|
|
3132
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3232
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * or);
|
|
3133
3233
|
},
|
|
3134
3234
|
onError: () => h()
|
|
3135
3235
|
});
|
|
@@ -3152,7 +3252,7 @@ var Xn = class {
|
|
|
3152
3252
|
let n = await s(this.opts.credential);
|
|
3153
3253
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3154
3254
|
this.setState("loading");
|
|
3155
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3255
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = ct(this.opts.video, (e) => {
|
|
3156
3256
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3157
3257
|
});
|
|
3158
3258
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3163,7 +3263,7 @@ var Xn = class {
|
|
|
3163
3263
|
a(), i.destroy();
|
|
3164
3264
|
return;
|
|
3165
3265
|
}
|
|
3166
|
-
this.engine = i, this.detachMedia = a, this.opts.maxBitrate != null && i.setMaxBitrate(this.opts.maxBitrate), this.startStats(), this.scheduleLicenseRefresh(), this.startLiveState(t), this.startAnalytics(e, i, t), r && (this.pendingStartLoad = !0, this.setState("paused"), i.name === "native" && setTimeout(() => {
|
|
3266
|
+
this.engine = i, this.detachMedia = a, this.opts.maxBitrate != null && i.setMaxBitrate(this.opts.maxBitrate), this.startStats(), this.scheduleLicenseRefresh(), this.startLiveState(t), this.watchReturn(), this.startAnalytics(e, i, t), r && (this.pendingStartLoad = !0, this.setState("paused"), i.name === "native" && setTimeout(() => {
|
|
3167
3267
|
this.destroyed || t !== this.loadGen || this.engine !== i || (this.analyticsSession?.noteReady(), this.emit("ready"));
|
|
3168
3268
|
}, 0));
|
|
3169
3269
|
}
|
|
@@ -3174,26 +3274,26 @@ var Xn = class {
|
|
|
3174
3274
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3175
3275
|
let i = e.analytics?.sid;
|
|
3176
3276
|
if (!i) return;
|
|
3177
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3277
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Pn(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3178
3278
|
if (!o) {
|
|
3179
3279
|
s && setTimeout(() => {
|
|
3180
3280
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3181
3281
|
}, 0);
|
|
3182
3282
|
return;
|
|
3183
3283
|
}
|
|
3184
|
-
let c = this.opts.video, l = new
|
|
3284
|
+
let c = this.opts.video, l = new Fn({
|
|
3185
3285
|
endpoint: o,
|
|
3186
3286
|
sid: i,
|
|
3187
3287
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3188
|
-
sdkVersion:
|
|
3189
|
-
environment:
|
|
3288
|
+
sdkVersion: Vn,
|
|
3289
|
+
environment: zn(c),
|
|
3190
3290
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3191
3291
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3192
3292
|
onBlocked: (e) => setTimeout(() => {
|
|
3193
3293
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3194
3294
|
}, 0),
|
|
3195
3295
|
sample: () => {
|
|
3196
|
-
let e = this.engine?.getStats() ??
|
|
3296
|
+
let e = this.engine?.getStats() ?? R, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3197
3297
|
return {
|
|
3198
3298
|
...e,
|
|
3199
3299
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3207,7 +3307,7 @@ var Xn = class {
|
|
|
3207
3307
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3208
3308
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3209
3309
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3210
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3310
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Bn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3211
3311
|
}
|
|
3212
3312
|
currentPresentation() {
|
|
3213
3313
|
let e = this.opts.video;
|
|
@@ -3222,10 +3322,11 @@ var Xn = class {
|
|
|
3222
3322
|
video: this.opts.video,
|
|
3223
3323
|
descriptor: e,
|
|
3224
3324
|
credential: t,
|
|
3225
|
-
deviceId:
|
|
3325
|
+
deviceId: O(),
|
|
3226
3326
|
userId: this.opts.userId,
|
|
3227
3327
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
3228
3328
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
3329
|
+
rememberBandwidth: this.opts.rememberBandwidth,
|
|
3229
3330
|
mediaDuringKey: this.opts.mediaDuringKey,
|
|
3230
3331
|
debug: this.opts.debug,
|
|
3231
3332
|
deferLoad: r,
|
|
@@ -3234,9 +3335,9 @@ var Xn = class {
|
|
|
3234
3335
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3235
3336
|
}, o = this.opts.engine ?? "auto";
|
|
3236
3337
|
if (o === "native") return new W(a);
|
|
3237
|
-
if (o === "hls") return new
|
|
3238
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled &&
|
|
3239
|
-
if (
|
|
3338
|
+
if (o === "hls") return new gn(a);
|
|
3339
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled && bt() && H(this.opts.video)) return new W(a);
|
|
3340
|
+
if (Mt()) return new gn(a);
|
|
3240
3341
|
if (H(this.opts.video)) return new W(a);
|
|
3241
3342
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3242
3343
|
}
|
|
@@ -3284,11 +3385,11 @@ var Xn = class {
|
|
|
3284
3385
|
}
|
|
3285
3386
|
startLiveState(e) {
|
|
3286
3387
|
if (this.opts.liveStateEvents === !1) return;
|
|
3287
|
-
let t = this.opts.eventsBaseUrl ??
|
|
3388
|
+
let t = this.opts.eventsBaseUrl ?? T(this.opts.baseUrl);
|
|
3288
3389
|
if (!t) return;
|
|
3289
3390
|
this.closeLiveState();
|
|
3290
3391
|
let r = 0, i = !1;
|
|
3291
|
-
this.liveStateSub =
|
|
3392
|
+
this.liveStateSub = w({
|
|
3292
3393
|
eventsBaseUrl: t,
|
|
3293
3394
|
matchUrn: this.opts.matchUrn,
|
|
3294
3395
|
credential: this.opts.credential,
|
|
@@ -3299,13 +3400,31 @@ var Xn = class {
|
|
|
3299
3400
|
r = 0, i = !1;
|
|
3300
3401
|
},
|
|
3301
3402
|
onError: () => {
|
|
3302
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
3403
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= sr && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
|
|
3303
3404
|
}
|
|
3304
3405
|
});
|
|
3305
3406
|
}
|
|
3306
3407
|
closeLiveState() {
|
|
3307
3408
|
this.liveStateSub?.close(), this.liveStateSub = null;
|
|
3308
3409
|
}
|
|
3410
|
+
watchReturn() {
|
|
3411
|
+
this.onReturnVisible || typeof document > "u" || this.opts.liveStateEvents !== !1 && (document.visibilityState === "hidden" && (this.hiddenAtMs = Date.now()), this.onReturnVisible = () => {
|
|
3412
|
+
if (document.visibilityState === "hidden") {
|
|
3413
|
+
this.hiddenAtMs ??= Date.now();
|
|
3414
|
+
return;
|
|
3415
|
+
}
|
|
3416
|
+
let e = this.hiddenAtMs;
|
|
3417
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= cr && this.resyncLiveState();
|
|
3418
|
+
}, this.onReturnPageShow = (e) => {
|
|
3419
|
+
e.persisted && this.resyncLiveState();
|
|
3420
|
+
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
3421
|
+
}
|
|
3422
|
+
unwatchReturn() {
|
|
3423
|
+
this.onReturnVisible && typeof document < "u" && document.removeEventListener("visibilitychange", this.onReturnVisible), this.onReturnPageShow && typeof window < "u" && window.removeEventListener("pageshow", this.onReturnPageShow), this.onReturnVisible = null, this.onReturnPageShow = null, this.hiddenAtMs = null;
|
|
3424
|
+
}
|
|
3425
|
+
resyncLiveState() {
|
|
3426
|
+
!this.destroyed && this.liveStateSub && this.startLiveState(this.loadGen);
|
|
3427
|
+
}
|
|
3309
3428
|
onStreamEnded(e = !1, t) {
|
|
3310
3429
|
if (!this.destroyed) {
|
|
3311
3430
|
if ((e || !this.rejoinEnabled()) && (this.cancelRejoin(), this.closeLiveState()), this.endedHandled) {
|
|
@@ -3327,7 +3446,7 @@ var Xn = class {
|
|
|
3327
3446
|
scheduleRejoin(e) {
|
|
3328
3447
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3329
3448
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3330
|
-
}, Math.random() *
|
|
3449
|
+
}, Math.random() * or));
|
|
3331
3450
|
}
|
|
3332
3451
|
cancelRejoin() {
|
|
3333
3452
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3351,7 +3470,7 @@ var Xn = class {
|
|
|
3351
3470
|
}
|
|
3352
3471
|
t.controls = !1;
|
|
3353
3472
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3354
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3473
|
+
r && r.insertBefore(n, t), n.appendChild(t), Wn(n, this.opts.theme), this.container = n, this.controlBar = Qn({
|
|
3355
3474
|
root: n,
|
|
3356
3475
|
video: t,
|
|
3357
3476
|
player: this,
|
|
@@ -3389,7 +3508,7 @@ var Xn = class {
|
|
|
3389
3508
|
}
|
|
3390
3509
|
startStats() {
|
|
3391
3510
|
this.stopStats();
|
|
3392
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3511
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? lr);
|
|
3393
3512
|
this.statsTimer = setInterval(() => {
|
|
3394
3513
|
if (!this.engine) return;
|
|
3395
3514
|
let e = this.engine.getStats();
|
|
@@ -3400,14 +3519,14 @@ var Xn = class {
|
|
|
3400
3519
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3401
3520
|
}
|
|
3402
3521
|
isStaleLicenseDenial(e) {
|
|
3403
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3522
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== dr || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3404
3523
|
}
|
|
3405
3524
|
scheduleLicenseRefresh() {
|
|
3406
3525
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3407
3526
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3408
3527
|
document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3409
3528
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3410
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3529
|
+
let e = this.opts.licenseRefreshMs ?? ur;
|
|
3411
3530
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3412
3531
|
}
|
|
3413
3532
|
stopRefresh() {
|
|
@@ -3464,7 +3583,7 @@ var Xn = class {
|
|
|
3464
3583
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3465
3584
|
}
|
|
3466
3585
|
getStats() {
|
|
3467
|
-
return this.engine?.getStats() ??
|
|
3586
|
+
return this.engine?.getStats() ?? R;
|
|
3468
3587
|
}
|
|
3469
3588
|
getQualityLevels() {
|
|
3470
3589
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3503,10 +3622,10 @@ var Xn = class {
|
|
|
3503
3622
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
3504
3623
|
}
|
|
3505
3624
|
async enterFullscreen() {
|
|
3506
|
-
return !this.destroyed &&
|
|
3625
|
+
return !this.destroyed && S(this.opts.video, this.container ?? void 0);
|
|
3507
3626
|
}
|
|
3508
3627
|
async exitFullscreen() {
|
|
3509
|
-
await
|
|
3628
|
+
await C(this.opts.video, this.container ?? void 0);
|
|
3510
3629
|
}
|
|
3511
3630
|
retry() {
|
|
3512
3631
|
return this.reload();
|
|
@@ -3531,7 +3650,7 @@ var Xn = class {
|
|
|
3531
3650
|
return n.add(t), () => n.delete(t);
|
|
3532
3651
|
}
|
|
3533
3652
|
destroy() {
|
|
3534
|
-
this.destroyed || (this.destroyed = !0, this.loadGen += 1, this.abort.abort(), this.stopStats(), this.stopRefresh(), this.unmountControls(), this.cancelRejoin(), this.closeArming(), this.closeLiveState(), this.detachMedia?.(), this.detachPip?.(), this.detachEndedPlayGuard?.(), this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.engine?.destroy(), this.engine = null, this.setState("idle"), this.clearListeners());
|
|
3653
|
+
this.destroyed || (this.destroyed = !0, this.loadGen += 1, this.abort.abort(), this.stopStats(), this.stopRefresh(), this.unmountControls(), this.cancelRejoin(), this.closeArming(), this.closeLiveState(), this.unwatchReturn(), this.detachMedia?.(), this.detachPip?.(), this.detachEndedPlayGuard?.(), this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.engine?.destroy(), this.engine = null, this.setState("idle"), this.clearListeners());
|
|
3535
3654
|
}
|
|
3536
3655
|
clearListeners() {
|
|
3537
3656
|
for (let e of Object.keys(this.listeners)) this.listeners[e]?.clear();
|
|
@@ -3574,7 +3693,7 @@ function $(e) {
|
|
|
3574
3693
|
}
|
|
3575
3694
|
//#endregion
|
|
3576
3695
|
//#region src/embed/host.ts
|
|
3577
|
-
function
|
|
3696
|
+
function hr(e) {
|
|
3578
3697
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3579
3698
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3580
3699
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3633,15 +3752,15 @@ function Zn(e) {
|
|
|
3633
3752
|
}
|
|
3634
3753
|
//#endregion
|
|
3635
3754
|
//#region src/embed/page.ts
|
|
3636
|
-
var
|
|
3637
|
-
function
|
|
3755
|
+
var gr = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3756
|
+
function _r(e) {
|
|
3638
3757
|
if (typeof e == "boolean") return e;
|
|
3639
3758
|
if (typeof e == "object" && e) {
|
|
3640
3759
|
let t = e.endpoint;
|
|
3641
3760
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3642
3761
|
}
|
|
3643
3762
|
}
|
|
3644
|
-
function
|
|
3763
|
+
function vr() {
|
|
3645
3764
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3646
3765
|
if (e) return {
|
|
3647
3766
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3651,7 +3770,7 @@ function er() {
|
|
|
3651
3770
|
autoplay: e.autoplay ?? !0,
|
|
3652
3771
|
muted: e.muted ?? !0,
|
|
3653
3772
|
waitForLive: e.waitForLive ?? !0,
|
|
3654
|
-
analytics:
|
|
3773
|
+
analytics: _r(e.analytics)
|
|
3655
3774
|
};
|
|
3656
3775
|
let t = new URLSearchParams(location.search);
|
|
3657
3776
|
return {
|
|
@@ -3664,9 +3783,9 @@ function er() {
|
|
|
3664
3783
|
waitForLive: !0
|
|
3665
3784
|
};
|
|
3666
3785
|
}
|
|
3667
|
-
async function
|
|
3668
|
-
let e =
|
|
3669
|
-
|
|
3786
|
+
async function yr() {
|
|
3787
|
+
let e = vr();
|
|
3788
|
+
xr();
|
|
3670
3789
|
let t = document.createElement("video");
|
|
3671
3790
|
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);
|
|
3672
3791
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3721,12 +3840,12 @@ async function tr() {
|
|
|
3721
3840
|
code: e.code,
|
|
3722
3841
|
message: e.message
|
|
3723
3842
|
})), e.on("autoplayblocked", () => {
|
|
3724
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3843
|
+
i({ type: "oddin:autoplayblocked" }), br(t, e);
|
|
3725
3844
|
});
|
|
3726
3845
|
}, s = async (r) => {
|
|
3727
3846
|
a?.destroy(), a = null;
|
|
3728
3847
|
try {
|
|
3729
|
-
let n = await
|
|
3848
|
+
let n = await pr({
|
|
3730
3849
|
video: t,
|
|
3731
3850
|
baseUrl: e.baseUrl,
|
|
3732
3851
|
matchUrn: r,
|
|
@@ -3788,7 +3907,7 @@ async function tr() {
|
|
|
3788
3907
|
a?.retry();
|
|
3789
3908
|
break;
|
|
3790
3909
|
case "oddin:load":
|
|
3791
|
-
typeof e.matchUrn == "string" &&
|
|
3910
|
+
typeof e.matchUrn == "string" && gr.test(e.matchUrn) && s(e.matchUrn);
|
|
3792
3911
|
break;
|
|
3793
3912
|
case "oddin:destroy": c();
|
|
3794
3913
|
}
|
|
@@ -3800,18 +3919,18 @@ async function tr() {
|
|
|
3800
3919
|
protocol: 1
|
|
3801
3920
|
});
|
|
3802
3921
|
}
|
|
3803
|
-
function
|
|
3922
|
+
function br(e, t) {
|
|
3804
3923
|
if (document.getElementById("havik-tap")) return;
|
|
3805
3924
|
let n = document.createElement("button");
|
|
3806
3925
|
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", () => {
|
|
3807
3926
|
n.remove(), t.play();
|
|
3808
3927
|
}), document.body.appendChild(n);
|
|
3809
3928
|
}
|
|
3810
|
-
function
|
|
3929
|
+
function xr() {
|
|
3811
3930
|
let e = document.createElement("style");
|
|
3812
3931
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3813
3932
|
}
|
|
3814
3933
|
//#endregion
|
|
3815
|
-
export {
|
|
3934
|
+
export { Hn as ODDIN_THEME, n as PlaybackError, Wn as applyTheme, L as baseUrlForEnv, yr as bootEmbed, Ee as clearDeviceId, Re as clearRememberedBandwidth, pr as createPlayer, T as deriveEventsBaseUrl, tt as detectDrmSupport, S as enterVideoFullscreen, C as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, O as getDeviceId, rt as isLowLatencyManifest, $ as isOddinMessage, Oe as licenseRequestHeaders, hr as mountEmbed, de as pollToLive, y as resolveStream, w as subscribeLiveState, x as videoFullscreenActive, we as watchStatus };
|
|
3816
3935
|
|
|
3817
3936
|
//# sourceMappingURL=index.js.map
|