@oddin-gg/havik-player 2.15.3 → 2.15.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/havik-player.global.js +2 -2
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +319 -298
- package/dist/index.js.map +1 -1
- package/docs/API.md +21 -15
- 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 me(e, t) {
|
|
|
290
290
|
function he(e) {
|
|
291
291
|
return e.ownerDocument ?? document;
|
|
292
292
|
}
|
|
293
|
-
function
|
|
293
|
+
function S(e) {
|
|
294
294
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
295
295
|
}
|
|
296
|
-
function
|
|
297
|
-
let n =
|
|
296
|
+
function C(e, t) {
|
|
297
|
+
let n = S(he(e));
|
|
298
298
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
299
299
|
}
|
|
300
|
-
async function
|
|
300
|
+
async function w(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 T(e, t) {
|
|
308
308
|
let n = e;
|
|
309
309
|
if (n.webkitDisplayingFullscreen) {
|
|
310
310
|
n.webkitExitFullscreen?.();
|
|
311
311
|
return;
|
|
312
312
|
}
|
|
313
|
-
let r = he(e), i =
|
|
313
|
+
let r = he(e), i = S(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 ge(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: _e(await s.json()),
|
|
337
337
|
etag: s.headers.get("etag") ?? void 0,
|
|
338
338
|
notModified: !1
|
|
339
339
|
};
|
|
340
340
|
}
|
|
341
|
-
function
|
|
341
|
+
function _e(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 ve(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: ye(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 ye(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 be(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 xe = /* @__PURE__ */ new Set([
|
|
415
415
|
"NOT_FOUND",
|
|
416
416
|
"GONE",
|
|
417
417
|
"INVALID_URN"
|
|
418
418
|
]);
|
|
419
|
-
function
|
|
419
|
+
function Se(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
|
+
xe.has(r.code) && (u = !0), e.onError?.(r);
|
|
453
453
|
}
|
|
454
454
|
} finally {
|
|
455
455
|
f();
|
|
@@ -461,9 +461,9 @@ 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 Ce = 45e3;
|
|
465
|
+
function E(e) {
|
|
466
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? Ce, 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", () => {
|
|
@@ -544,7 +544,7 @@ function T(e) {
|
|
|
544
544
|
o || (o = !0, a.abort());
|
|
545
545
|
} };
|
|
546
546
|
}
|
|
547
|
-
function
|
|
547
|
+
function D(e) {
|
|
548
548
|
try {
|
|
549
549
|
let t = new URL(e);
|
|
550
550
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -554,27 +554,27 @@ function E(e) {
|
|
|
554
554
|
}
|
|
555
555
|
//#endregion
|
|
556
556
|
//#region src/core/drm/deviceId.ts
|
|
557
|
-
var
|
|
558
|
-
function
|
|
559
|
-
if (
|
|
557
|
+
var O = "havik.player.deviceId", k;
|
|
558
|
+
function A() {
|
|
559
|
+
if (k) return k;
|
|
560
560
|
try {
|
|
561
|
-
let e = globalThis.localStorage?.getItem(
|
|
562
|
-
if (e) return
|
|
561
|
+
let e = globalThis.localStorage?.getItem(O);
|
|
562
|
+
if (e) return k = e, e;
|
|
563
563
|
} catch {}
|
|
564
|
-
let e =
|
|
565
|
-
|
|
564
|
+
let e = Te();
|
|
565
|
+
k = e;
|
|
566
566
|
try {
|
|
567
|
-
globalThis.localStorage?.setItem(
|
|
567
|
+
globalThis.localStorage?.setItem(O, e);
|
|
568
568
|
} catch {}
|
|
569
569
|
return e;
|
|
570
570
|
}
|
|
571
|
-
function
|
|
572
|
-
|
|
571
|
+
function we() {
|
|
572
|
+
k = void 0;
|
|
573
573
|
try {
|
|
574
|
-
globalThis.localStorage?.removeItem(
|
|
574
|
+
globalThis.localStorage?.removeItem(O);
|
|
575
575
|
} catch {}
|
|
576
576
|
}
|
|
577
|
-
function
|
|
577
|
+
function Te() {
|
|
578
578
|
let e = globalThis.crypto;
|
|
579
579
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
580
580
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -586,21 +586,21 @@ function Ee() {
|
|
|
586
586
|
}
|
|
587
587
|
//#endregion
|
|
588
588
|
//#region src/core/drm/headers.ts
|
|
589
|
-
function
|
|
589
|
+
function Ee(e, t, n = {}) {
|
|
590
590
|
let r = {
|
|
591
591
|
"x-api-key": t.apiKey,
|
|
592
592
|
"X-Match-Urn": e.matchUrn,
|
|
593
|
-
"X-Device-Id": n.deviceId ??
|
|
593
|
+
"X-Device-Id": n.deviceId ?? A(),
|
|
594
594
|
"Content-Type": "application/octet-stream"
|
|
595
595
|
};
|
|
596
596
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
597
597
|
}
|
|
598
598
|
//#endregion
|
|
599
599
|
//#region src/core/drm/cdm.ts
|
|
600
|
-
var
|
|
601
|
-
function
|
|
602
|
-
let n =
|
|
603
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
600
|
+
var j = /* @__PURE__ */ new WeakMap();
|
|
601
|
+
function De(e, t) {
|
|
602
|
+
let n = j.get(e);
|
|
603
|
+
n || (n = /* @__PURE__ */ new Map(), j.set(e, n));
|
|
604
604
|
let r = n.get(t.keySystem);
|
|
605
605
|
if (r) return r;
|
|
606
606
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -608,22 +608,22 @@ function Oe(e, t) {
|
|
|
608
608
|
});
|
|
609
609
|
return n.set(t.keySystem, i), i;
|
|
610
610
|
}
|
|
611
|
-
function
|
|
611
|
+
function M() {
|
|
612
612
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
613
613
|
}
|
|
614
|
-
var
|
|
615
|
-
function
|
|
614
|
+
var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
615
|
+
function Oe(e) {
|
|
616
616
|
return e.startsWith("com.widevine");
|
|
617
617
|
}
|
|
618
|
-
function
|
|
619
|
-
if (!
|
|
618
|
+
function P(e, t) {
|
|
619
|
+
if (!Oe(e)) return t;
|
|
620
620
|
let n = (e, t) => {
|
|
621
621
|
let n = e.videoCapabilities;
|
|
622
622
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
623
|
-
let n =
|
|
624
|
-
return n === -1 ||
|
|
623
|
+
let n = N.indexOf(e.robustness);
|
|
624
|
+
return n === -1 || N.indexOf(t) > n;
|
|
625
625
|
});
|
|
626
|
-
}, r =
|
|
626
|
+
}, r = N.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
627
627
|
...t,
|
|
628
628
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
629
629
|
...t,
|
|
@@ -632,53 +632,53 @@ function N(e, t) {
|
|
|
632
632
|
})));
|
|
633
633
|
return [...t, ...r];
|
|
634
634
|
}
|
|
635
|
-
function
|
|
636
|
-
return (t, n) =>
|
|
635
|
+
function F(e) {
|
|
636
|
+
return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, P(t, n)).then((t) => ({
|
|
637
637
|
keySystem: t.keySystem,
|
|
638
638
|
getConfiguration: () => t.getConfiguration(),
|
|
639
|
-
createMediaKeys: () =>
|
|
639
|
+
createMediaKeys: () => De(e, t)
|
|
640
640
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
641
641
|
}
|
|
642
|
-
var
|
|
642
|
+
var I = {
|
|
643
643
|
video: "SW_SECURE_DECODE",
|
|
644
644
|
audio: "SW_SECURE_CRYPTO",
|
|
645
645
|
scheme: "cbcs"
|
|
646
646
|
};
|
|
647
|
-
function
|
|
648
|
-
if (!
|
|
647
|
+
function ke(e) {
|
|
648
|
+
if (!M()) return;
|
|
649
649
|
let t = (e, t) => ({
|
|
650
650
|
contentType: e,
|
|
651
651
|
robustness: t,
|
|
652
|
-
encryptionScheme:
|
|
652
|
+
encryptionScheme: I.scheme
|
|
653
653
|
});
|
|
654
|
-
|
|
654
|
+
F(e)("com.widevine.alpha", [{
|
|
655
655
|
initDataTypes: ["cenc"],
|
|
656
656
|
distinctiveIdentifier: "optional",
|
|
657
657
|
persistentState: "optional",
|
|
658
658
|
sessionTypes: ["temporary"],
|
|
659
|
-
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"",
|
|
660
|
-
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"",
|
|
659
|
+
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", I.audio)],
|
|
660
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", I.video)]
|
|
661
661
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
662
662
|
}
|
|
663
|
-
function
|
|
664
|
-
let t =
|
|
663
|
+
function L(e) {
|
|
664
|
+
let t = R(e);
|
|
665
665
|
if (/^avc[13]/.test(t)) return "avc";
|
|
666
666
|
if (/^(hvc1|hev1)/.test(t)) return "hevc";
|
|
667
667
|
if (/^(dvh1|dvhe)/.test(t)) return "dv";
|
|
668
668
|
if (t.startsWith("av01")) return "av1";
|
|
669
669
|
if (/^vp0?9/.test(t)) return "vp9";
|
|
670
670
|
}
|
|
671
|
-
function
|
|
671
|
+
function R(e) {
|
|
672
672
|
return (e ?? "").trim().toLowerCase();
|
|
673
673
|
}
|
|
674
|
-
var
|
|
674
|
+
var Ae = {
|
|
675
675
|
hevc: "hvc1.1.6.L93.90",
|
|
676
676
|
dv: "dvh1.05.06",
|
|
677
677
|
av1: "av01.0.05M.08",
|
|
678
678
|
vp9: "vp09.00.10.08"
|
|
679
|
-
},
|
|
680
|
-
function
|
|
681
|
-
let t =
|
|
679
|
+
}, je = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Map();
|
|
680
|
+
function Me(e) {
|
|
681
|
+
let t = R(e), n = je.get(t);
|
|
682
682
|
if (n) return n;
|
|
683
683
|
let r = {
|
|
684
684
|
initDataTypes: ["cenc"],
|
|
@@ -687,32 +687,32 @@ function V(e) {
|
|
|
687
687
|
sessionTypes: ["temporary"],
|
|
688
688
|
videoCapabilities: [{
|
|
689
689
|
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
690
|
-
robustness:
|
|
691
|
-
encryptionScheme:
|
|
690
|
+
robustness: I.video,
|
|
691
|
+
encryptionScheme: I.scheme
|
|
692
692
|
}]
|
|
693
693
|
}, i = (async () => {
|
|
694
694
|
try {
|
|
695
|
-
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha",
|
|
695
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", P("com.widevine.alpha", [r])), !0;
|
|
696
696
|
} catch {
|
|
697
697
|
return !1;
|
|
698
698
|
}
|
|
699
|
-
})().then((e) => (
|
|
700
|
-
return
|
|
699
|
+
})().then((e) => (z.set(t, e), e));
|
|
700
|
+
return je.set(t, i), i;
|
|
701
701
|
}
|
|
702
|
-
function
|
|
703
|
-
if (
|
|
702
|
+
function Ne() {
|
|
703
|
+
if (M()) for (let e of Object.values(Ae)) Me(e);
|
|
704
704
|
}
|
|
705
|
-
function
|
|
706
|
-
let t =
|
|
707
|
-
if (t) return t === "avc" ? !0 :
|
|
705
|
+
function Pe(e) {
|
|
706
|
+
let t = L(e);
|
|
707
|
+
if (t) return t === "avc" ? !0 : z.get(R(e)) ?? z.get(R(Ae[t]));
|
|
708
708
|
}
|
|
709
709
|
//#endregion
|
|
710
710
|
//#region src/core/drm/support.ts
|
|
711
|
-
var
|
|
711
|
+
var Fe = 5e3, Ie = "video/mp4; codecs=\"avc1.42E01E\"", Le = "audio/mp4; codecs=\"mp4a.40.2\"", Re = {
|
|
712
712
|
widevine: ["com.widevine.alpha"],
|
|
713
713
|
fairplay: ["com.apple.fps"]
|
|
714
714
|
};
|
|
715
|
-
function
|
|
715
|
+
function ze(e) {
|
|
716
716
|
return e === "fairplay" ? [{
|
|
717
717
|
initDataTypes: [
|
|
718
718
|
"sinf",
|
|
@@ -720,30 +720,30 @@ function Fe(e) {
|
|
|
720
720
|
"cenc"
|
|
721
721
|
],
|
|
722
722
|
videoCapabilities: [{
|
|
723
|
-
contentType:
|
|
723
|
+
contentType: Ie,
|
|
724
724
|
robustness: "",
|
|
725
725
|
encryptionScheme: "cbcs"
|
|
726
726
|
}],
|
|
727
727
|
audioCapabilities: [{
|
|
728
|
-
contentType:
|
|
728
|
+
contentType: Le,
|
|
729
729
|
robustness: "",
|
|
730
730
|
encryptionScheme: "cbcs"
|
|
731
731
|
}]
|
|
732
|
-
}] :
|
|
732
|
+
}] : P("com.widevine.alpha", [{
|
|
733
733
|
initDataTypes: ["cenc"],
|
|
734
734
|
videoCapabilities: [{
|
|
735
|
-
contentType:
|
|
736
|
-
robustness:
|
|
737
|
-
encryptionScheme:
|
|
735
|
+
contentType: Ie,
|
|
736
|
+
robustness: I.video,
|
|
737
|
+
encryptionScheme: I.scheme
|
|
738
738
|
}],
|
|
739
739
|
audioCapabilities: [{
|
|
740
|
-
contentType:
|
|
741
|
-
robustness:
|
|
742
|
-
encryptionScheme:
|
|
740
|
+
contentType: Le,
|
|
741
|
+
robustness: I.audio,
|
|
742
|
+
encryptionScheme: I.scheme
|
|
743
743
|
}]
|
|
744
744
|
}]);
|
|
745
745
|
}
|
|
746
|
-
function
|
|
746
|
+
function Be(e, t) {
|
|
747
747
|
return new Promise((n, r) => {
|
|
748
748
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
749
749
|
e.then((e) => {
|
|
@@ -753,8 +753,8 @@ function Ie(e, t) {
|
|
|
753
753
|
});
|
|
754
754
|
});
|
|
755
755
|
}
|
|
756
|
-
async function
|
|
757
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
756
|
+
async function Ve(e = {}) {
|
|
757
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Fe, r = {};
|
|
758
758
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
759
759
|
verdict: "insecure-context",
|
|
760
760
|
detail: r
|
|
@@ -766,7 +766,7 @@ async function Le(e = {}) {
|
|
|
766
766
|
};
|
|
767
767
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
768
768
|
for (let e of t) {
|
|
769
|
-
let t =
|
|
769
|
+
let t = Re[e];
|
|
770
770
|
if (!t) {
|
|
771
771
|
r[e] = "unknown system";
|
|
772
772
|
continue;
|
|
@@ -777,7 +777,7 @@ async function Le(e = {}) {
|
|
|
777
777
|
break;
|
|
778
778
|
}
|
|
779
779
|
try {
|
|
780
|
-
return await
|
|
780
|
+
return await Be((await Be(i(n, ze(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
781
781
|
verdict: "supported",
|
|
782
782
|
system: e,
|
|
783
783
|
detail: r
|
|
@@ -801,49 +801,49 @@ async function Le(e = {}) {
|
|
|
801
801
|
}
|
|
802
802
|
//#endregion
|
|
803
803
|
//#region src/core/manifest.ts
|
|
804
|
-
var
|
|
805
|
-
function
|
|
806
|
-
return
|
|
804
|
+
var He = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
805
|
+
function Ue(e) {
|
|
806
|
+
return He.test(e);
|
|
807
807
|
}
|
|
808
808
|
//#endregion
|
|
809
809
|
//#region src/core/env.ts
|
|
810
|
-
var
|
|
810
|
+
var We = {
|
|
811
811
|
integration: "https://feed-dev.oddin-video.gg",
|
|
812
812
|
production: "https://feed.oddin-video.gg"
|
|
813
813
|
};
|
|
814
|
-
function
|
|
815
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
814
|
+
function B(e) {
|
|
815
|
+
let t = Object.prototype.hasOwnProperty.call(We, e) ? We[e] : void 0;
|
|
816
816
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
817
817
|
return t;
|
|
818
818
|
}
|
|
819
819
|
//#endregion
|
|
820
820
|
//#region src/core/stats.ts
|
|
821
|
-
var
|
|
822
|
-
function
|
|
821
|
+
var V = { droppedFrames: 0 };
|
|
822
|
+
function H(e) {
|
|
823
823
|
try {
|
|
824
824
|
return new URL(e).host;
|
|
825
825
|
} catch {
|
|
826
826
|
return "";
|
|
827
827
|
}
|
|
828
828
|
}
|
|
829
|
-
var
|
|
830
|
-
function
|
|
829
|
+
var Ge = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
830
|
+
function Ke(e) {
|
|
831
831
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
832
832
|
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 =
|
|
833
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Ge.test(i.name)) && i.startTime >= n) {
|
|
834
|
+
let e = H(i.name);
|
|
835
835
|
e && (t = e, n = i.startTime);
|
|
836
836
|
}
|
|
837
837
|
return t;
|
|
838
838
|
}
|
|
839
|
-
function
|
|
839
|
+
function U(e) {
|
|
840
840
|
let t = e.getVideoPlaybackQuality?.();
|
|
841
841
|
return {
|
|
842
842
|
dropped: t?.droppedVideoFrames ?? 0,
|
|
843
843
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
844
844
|
};
|
|
845
845
|
}
|
|
846
|
-
function
|
|
846
|
+
function qe(e, t) {
|
|
847
847
|
let n = [
|
|
848
848
|
["playing", () => t("playing")],
|
|
849
849
|
["waiting", () => t("buffering")],
|
|
@@ -860,7 +860,7 @@ function Ke(e, t) {
|
|
|
860
860
|
}
|
|
861
861
|
//#endregion
|
|
862
862
|
//#region src/core/engine/native.ts
|
|
863
|
-
function
|
|
863
|
+
function Je(e) {
|
|
864
864
|
try {
|
|
865
865
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
866
866
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -868,14 +868,19 @@ function qe(e) {
|
|
|
868
868
|
return;
|
|
869
869
|
}
|
|
870
870
|
}
|
|
871
|
-
function
|
|
871
|
+
function W(e) {
|
|
872
872
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
873
873
|
}
|
|
874
|
-
function
|
|
874
|
+
function G() {
|
|
875
875
|
if (typeof window > "u") return !1;
|
|
876
876
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
877
877
|
return e || t;
|
|
878
878
|
}
|
|
879
|
+
function Ye() {
|
|
880
|
+
if (typeof navigator > "u" || !G()) return !1;
|
|
881
|
+
let e = navigator.userAgent ?? "";
|
|
882
|
+
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
883
|
+
}
|
|
879
884
|
var K = class {
|
|
880
885
|
name = "native";
|
|
881
886
|
deps;
|
|
@@ -912,7 +917,7 @@ var K = class {
|
|
|
912
917
|
type: "error",
|
|
913
918
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
914
919
|
fatal: !0
|
|
915
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
920
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Xe(t.manifestUrl, t.analytics?.sid), e.load();
|
|
916
921
|
}
|
|
917
922
|
startLoad() {
|
|
918
923
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -934,7 +939,7 @@ var K = class {
|
|
|
934
939
|
});
|
|
935
940
|
this.onEncrypted = (n) => {
|
|
936
941
|
let i = n;
|
|
937
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
942
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Je(i.initData), (async () => {
|
|
938
943
|
try {
|
|
939
944
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
940
945
|
initDataTypes: [i.initDataType],
|
|
@@ -1029,11 +1034,11 @@ var K = class {
|
|
|
1029
1034
|
e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
|
|
1030
1035
|
}
|
|
1031
1036
|
getStats() {
|
|
1032
|
-
let e = this.deps.video, t =
|
|
1037
|
+
let e = this.deps.video, t = U(e), n = {
|
|
1033
1038
|
droppedFrames: t.dropped,
|
|
1034
1039
|
decodedFrames: t.totalFrames
|
|
1035
1040
|
};
|
|
1036
|
-
return this.cdnHost ||=
|
|
1041
|
+
return this.cdnHost ||= Ke(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity ? (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)) : Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1), n;
|
|
1037
1042
|
}
|
|
1038
1043
|
stop() {
|
|
1039
1044
|
try {
|
|
@@ -1052,13 +1057,13 @@ var K = class {
|
|
|
1052
1057
|
} catch {}
|
|
1053
1058
|
}
|
|
1054
1059
|
};
|
|
1055
|
-
function
|
|
1060
|
+
function Xe(e, t) {
|
|
1056
1061
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1057
1062
|
}
|
|
1058
1063
|
//#endregion
|
|
1059
1064
|
//#region src/core/engine/prefetch.ts
|
|
1060
|
-
var
|
|
1061
|
-
function
|
|
1065
|
+
var Ze = 15e3, Qe = 5e3, $e = 6;
|
|
1066
|
+
function et(e) {
|
|
1062
1067
|
try {
|
|
1063
1068
|
let t = new URL(e);
|
|
1064
1069
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1066,7 +1071,7 @@ function $e(e) {
|
|
|
1066
1071
|
return e;
|
|
1067
1072
|
}
|
|
1068
1073
|
}
|
|
1069
|
-
var
|
|
1074
|
+
var tt = class {
|
|
1070
1075
|
cmcd;
|
|
1071
1076
|
entries = /* @__PURE__ */ new Map();
|
|
1072
1077
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1089,10 +1094,10 @@ var et = class {
|
|
|
1089
1094
|
}
|
|
1090
1095
|
prefetch(e, t, n) {
|
|
1091
1096
|
if (!this.isActive(t)) return;
|
|
1092
|
-
let r =
|
|
1097
|
+
let r = et(e);
|
|
1093
1098
|
if (this.entries.has(r)) return;
|
|
1094
1099
|
let i = this.perTrack.get(t) ?? 0;
|
|
1095
|
-
if (i >=
|
|
1100
|
+
if (i >= $e) return;
|
|
1096
1101
|
this.perTrack.set(t, i + 1);
|
|
1097
1102
|
let a = new AbortController(), o = {
|
|
1098
1103
|
started: performance.now(),
|
|
@@ -1106,10 +1111,10 @@ var et = class {
|
|
|
1106
1111
|
signal: a.signal
|
|
1107
1112
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1108
1113
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1109
|
-
},
|
|
1114
|
+
}, Ze);
|
|
1110
1115
|
}
|
|
1111
1116
|
take(e) {
|
|
1112
|
-
let t =
|
|
1117
|
+
let t = et(e), n = this.entries.get(t);
|
|
1113
1118
|
return n && this.entries.delete(t), n;
|
|
1114
1119
|
}
|
|
1115
1120
|
destroy() {
|
|
@@ -1129,13 +1134,13 @@ var et = class {
|
|
|
1129
1134
|
}
|
|
1130
1135
|
}
|
|
1131
1136
|
};
|
|
1132
|
-
function
|
|
1137
|
+
function nt(t) {
|
|
1133
1138
|
let n = e.DefaultConfig?.loader;
|
|
1134
1139
|
if (typeof n != "function") return;
|
|
1135
1140
|
class r extends n {
|
|
1136
1141
|
served = !1;
|
|
1137
1142
|
cancelled = !1;
|
|
1138
|
-
stats =
|
|
1143
|
+
stats = rt();
|
|
1139
1144
|
load(e, n, r) {
|
|
1140
1145
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1141
1146
|
if (!i) {
|
|
@@ -1143,7 +1148,7 @@ function tt(t) {
|
|
|
1143
1148
|
return;
|
|
1144
1149
|
}
|
|
1145
1150
|
this.served = !0;
|
|
1146
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1151
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Qe, s = setTimeout(() => {
|
|
1147
1152
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1148
1153
|
}, o);
|
|
1149
1154
|
i.bytes.then((o) => {
|
|
@@ -1170,7 +1175,7 @@ function tt(t) {
|
|
|
1170
1175
|
}
|
|
1171
1176
|
return r;
|
|
1172
1177
|
}
|
|
1173
|
-
function
|
|
1178
|
+
function rt() {
|
|
1174
1179
|
return {
|
|
1175
1180
|
aborted: !1,
|
|
1176
1181
|
loaded: 0,
|
|
@@ -1194,10 +1199,10 @@ function nt() {
|
|
|
1194
1199
|
}
|
|
1195
1200
|
};
|
|
1196
1201
|
}
|
|
1197
|
-
function
|
|
1202
|
+
function it(e) {
|
|
1198
1203
|
return e === "audio" ? "audio" : "main";
|
|
1199
1204
|
}
|
|
1200
|
-
function
|
|
1205
|
+
function at(e, t) {
|
|
1201
1206
|
let n = [];
|
|
1202
1207
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1203
1208
|
url: t.initSegment.url,
|
|
@@ -1216,24 +1221,24 @@ function it(e, t) {
|
|
|
1216
1221
|
}
|
|
1217
1222
|
//#endregion
|
|
1218
1223
|
//#region src/core/engine/hls.ts
|
|
1219
|
-
function
|
|
1224
|
+
function ot() {
|
|
1220
1225
|
return e.isSupported();
|
|
1221
1226
|
}
|
|
1222
|
-
var
|
|
1223
|
-
function
|
|
1227
|
+
var st = 3, ct = 5, lt = 3, ut = 3e4, dt = 12e3, ft = 3e3, pt = 6e3, mt = .5, ht = 3, gt = .5, _t = 1.1, vt = .25, yt = 5e3, bt = 4e3, xt = 2, St = 5, Ct = 2, wt = 2, Tt = 4, Et = 4, Dt = 2e3, Ot = 3e4, kt = .2, At = 30, jt = 2, Mt = 2, Nt = 9, Pt = .5, Ft = 64;
|
|
1228
|
+
function It(e) {
|
|
1224
1229
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1225
1230
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1226
1231
|
return;
|
|
1227
1232
|
}
|
|
1228
|
-
e.liveSyncDuration ??=
|
|
1229
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1230
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1233
|
+
e.liveSyncDuration ??= Mt;
|
|
1234
|
+
let t = Math.max(12, e.liveSyncDuration + Nt);
|
|
1235
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Lt(e, e.liveSyncDuration);
|
|
1231
1236
|
}
|
|
1232
|
-
function
|
|
1237
|
+
function Lt(e, t) {
|
|
1233
1238
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1234
1239
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1235
1240
|
}
|
|
1236
|
-
var
|
|
1241
|
+
var Rt = class {
|
|
1237
1242
|
name = "hls";
|
|
1238
1243
|
hls = null;
|
|
1239
1244
|
deps;
|
|
@@ -1290,6 +1295,9 @@ var It = class {
|
|
|
1290
1295
|
savedLiveMaxLatency;
|
|
1291
1296
|
savedMaxSyncRate;
|
|
1292
1297
|
chaseLatency = -1;
|
|
1298
|
+
catchUpRate = 1;
|
|
1299
|
+
catchUpEngaged = !1;
|
|
1300
|
+
onTimeUpdate = null;
|
|
1293
1301
|
chaseTicks = 0;
|
|
1294
1302
|
liveRetargets = 0;
|
|
1295
1303
|
capObserver = null;
|
|
@@ -1311,7 +1319,7 @@ var It = class {
|
|
|
1311
1319
|
this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1312
1320
|
}
|
|
1313
1321
|
async load() {
|
|
1314
|
-
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a =
|
|
1322
|
+
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = W(r) && G(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
1315
1323
|
if (e.drmEnabled && !o) {
|
|
1316
1324
|
i({
|
|
1317
1325
|
type: "error",
|
|
@@ -1320,7 +1328,7 @@ var It = class {
|
|
|
1320
1328
|
});
|
|
1321
1329
|
return;
|
|
1322
1330
|
}
|
|
1323
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1331
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (ke(r), Ne()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1324
1332
|
let e = this.hls;
|
|
1325
1333
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1326
1334
|
let t = e.liveSyncPosition;
|
|
@@ -1329,7 +1337,7 @@ var It = class {
|
|
|
1329
1337
|
t - r.currentTime > Math.max(n * 3, 8) && (r.currentTime = t);
|
|
1330
1338
|
}, document.addEventListener("visibilitychange", this.onVisibility)), this.onSeeking = () => {
|
|
1331
1339
|
this.clampOverSeek(), this.loadSuspended && (this.resumeLoading(), this.schedulePauseSuspend());
|
|
1332
|
-
}, r.addEventListener("seeking", this.onSeeking), this.onPause = () => this.schedulePauseSuspend(), this.onPlay = () => this.resumeLoading(), r.addEventListener("pause", this.onPause), r.addEventListener("play", this.onPlay), this.sizeCapManaged && typeof ResizeObserver < "u" && (this.capObserver = new ResizeObserver(() => this.onMediaResize()), this.capObserver.observe(r), this.watchDprChanges());
|
|
1340
|
+
}, r.addEventListener("seeking", this.onSeeking), this.onTimeUpdate = () => this.updateCatchUpBand(), r.addEventListener("timeupdate", this.onTimeUpdate), this.onPause = () => this.schedulePauseSuspend(), this.onPlay = () => this.resumeLoading(), r.addEventListener("pause", this.onPause), r.addEventListener("play", this.onPlay), this.sizeCapManaged && typeof ResizeObserver < "u" && (this.capObserver = new ResizeObserver(() => this.onMediaResize()), this.capObserver.observe(r), this.watchDprChanges());
|
|
1333
1341
|
}
|
|
1334
1342
|
schedulePauseSuspend() {
|
|
1335
1343
|
this.pauseSuspendTimer || this.loadSuspended || this.stopped || !this.loadStarted || (this.pauseSuspendTimer = setTimeout(() => {
|
|
@@ -1343,7 +1351,7 @@ var It = class {
|
|
|
1343
1351
|
}
|
|
1344
1352
|
this.loadSuspended = !0;
|
|
1345
1353
|
}
|
|
1346
|
-
},
|
|
1354
|
+
}, yt));
|
|
1347
1355
|
}
|
|
1348
1356
|
resumeLoading() {
|
|
1349
1357
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1375,7 +1383,7 @@ var It = class {
|
|
|
1375
1383
|
let t = e.liveSyncPosition;
|
|
1376
1384
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1377
1385
|
let { video: n } = this.deps;
|
|
1378
|
-
n.currentTime <= t +
|
|
1386
|
+
n.currentTime <= t + Pt || (n.currentTime = t);
|
|
1379
1387
|
}
|
|
1380
1388
|
startHls() {
|
|
1381
1389
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1394,12 +1402,12 @@ var It = class {
|
|
|
1394
1402
|
emeEnabled: !0,
|
|
1395
1403
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1396
1404
|
drmSystemOptions: {
|
|
1397
|
-
videoRobustness:
|
|
1398
|
-
audioRobustness:
|
|
1399
|
-
videoEncryptionScheme:
|
|
1400
|
-
audioEncryptionScheme:
|
|
1405
|
+
videoRobustness: I.video,
|
|
1406
|
+
audioRobustness: I.audio,
|
|
1407
|
+
videoEncryptionScheme: I.scheme,
|
|
1408
|
+
audioEncryptionScheme: I.scheme
|
|
1401
1409
|
},
|
|
1402
|
-
...
|
|
1410
|
+
...M() ? { requestMediaKeySystemAccessFunc: F(t) } : {},
|
|
1403
1411
|
licenseXhrSetup: (e, t) => {
|
|
1404
1412
|
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;
|
|
1405
1413
|
let o = performance.now();
|
|
@@ -1416,20 +1424,20 @@ var It = class {
|
|
|
1416
1424
|
...c
|
|
1417
1425
|
};
|
|
1418
1426
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
|
|
1419
|
-
let e = new
|
|
1427
|
+
let e = new tt({
|
|
1420
1428
|
sessionId: n.analytics?.sid,
|
|
1421
1429
|
contentId: n.matchUrn
|
|
1422
|
-
}), t =
|
|
1430
|
+
}), t = nt(e);
|
|
1423
1431
|
t && (this.prefetch = e, d.fLoader = t);
|
|
1424
1432
|
}
|
|
1425
|
-
|
|
1433
|
+
It(d), this.catchUpRate = typeof d.maxLiveSyncPlaybackRate == "number" ? d.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (d.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = d.autoStartLoad !== !1;
|
|
1426
1434
|
let f = new e(d);
|
|
1427
1435
|
if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1428
1436
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(f), this.measureLadder(f), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1429
1437
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1430
1438
|
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(() => {
|
|
1431
1439
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1432
|
-
},
|
|
1440
|
+
}, ut)));
|
|
1433
1441
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1434
1442
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1435
1443
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1437,10 +1445,10 @@ var It = class {
|
|
|
1437
1445
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1438
1446
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1439
1447
|
let i = n?.loading;
|
|
1440
|
-
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 >
|
|
1448
|
+
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 > Ft && this.requestTimesMs.shift());
|
|
1441
1449
|
let a = t?.frag?.url;
|
|
1442
1450
|
if (a) {
|
|
1443
|
-
let e =
|
|
1451
|
+
let e = H(a);
|
|
1444
1452
|
e && (this.cdnHost = e);
|
|
1445
1453
|
}
|
|
1446
1454
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1454,15 +1462,15 @@ var It = class {
|
|
|
1454
1462
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1455
1463
|
let t = this.prefetch;
|
|
1456
1464
|
f.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1457
|
-
let r = n?.frag, i =
|
|
1458
|
-
if (r && t.isActive(i)) for (let e of
|
|
1459
|
-
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1465
|
+
let r = n?.frag, i = it(r?.type);
|
|
1466
|
+
if (r && t.isActive(i)) for (let e of at(f, r)) t.prefetch(e.url, i, e.kind);
|
|
1467
|
+
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(it(n?.frag?.type)));
|
|
1460
1468
|
}
|
|
1461
1469
|
f.on(e.Events.KEY_LOADED, () => {
|
|
1462
1470
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1463
1471
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1464
|
-
this.checkEndStale(), this.checkStarvation(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1465
|
-
},
|
|
1472
|
+
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1473
|
+
}, ft), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1466
1474
|
this.renditionSwitches += 1;
|
|
1467
1475
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1468
1476
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1526,7 +1534,7 @@ var It = class {
|
|
|
1526
1534
|
return;
|
|
1527
1535
|
}
|
|
1528
1536
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1529
|
-
let t = e > this.sizeCapLevel ?
|
|
1537
|
+
let t = e > this.sizeCapLevel ? Dt : Ot;
|
|
1530
1538
|
this.capTimer = setTimeout(() => {
|
|
1531
1539
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1532
1540
|
}, t);
|
|
@@ -1536,9 +1544,9 @@ var It = class {
|
|
|
1536
1544
|
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;
|
|
1537
1545
|
}
|
|
1538
1546
|
dropLevelsWidevineCannotPlay(e) {
|
|
1539
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1540
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1541
|
-
for (let n of t)
|
|
1547
|
+
this.removeLevelsWhere(e, (e) => Pe(e) !== !0);
|
|
1548
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && L(e) !== "avc" && !!L(e)));
|
|
1549
|
+
for (let n of t) Me(n).then((t) => {
|
|
1542
1550
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1543
1551
|
});
|
|
1544
1552
|
}
|
|
@@ -1546,10 +1554,10 @@ var It = class {
|
|
|
1546
1554
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1547
1555
|
if (n.forEach((e, n) => {
|
|
1548
1556
|
let a = e.videoCodec;
|
|
1549
|
-
a &&
|
|
1557
|
+
a && L(a) && t(a) && (r.push(n), i.add(a));
|
|
1550
1558
|
}), !r.length) return !1;
|
|
1551
1559
|
let a = [...i].join(", ");
|
|
1552
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !
|
|
1560
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !L(e.videoCodec) || Pe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1553
1561
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1554
1562
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1555
1563
|
}
|
|
@@ -1599,7 +1607,7 @@ var It = class {
|
|
|
1599
1607
|
e.widevine && (this.licenseUrl = e.widevine);
|
|
1600
1608
|
}
|
|
1601
1609
|
getStats() {
|
|
1602
|
-
let e = this.hls, t =
|
|
1610
|
+
let e = this.hls, t = U(this.deps.video), n = {
|
|
1603
1611
|
droppedFrames: t.dropped,
|
|
1604
1612
|
decodedFrames: t.totalFrames,
|
|
1605
1613
|
lowLatency: this.detectedLowLatency,
|
|
@@ -1647,7 +1655,7 @@ var It = class {
|
|
|
1647
1655
|
return;
|
|
1648
1656
|
}
|
|
1649
1657
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1650
|
-
!this.chaseSuspended && e >
|
|
1658
|
+
!this.chaseSuspended && e > pt && this.suspendChasing(), e > dt && this.emitEnded("stalled");
|
|
1651
1659
|
}
|
|
1652
1660
|
resetStarvationWindow() {
|
|
1653
1661
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1662,7 +1670,7 @@ var It = class {
|
|
|
1662
1670
|
this.resetStarvationWindow();
|
|
1663
1671
|
return;
|
|
1664
1672
|
}
|
|
1665
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1673
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < pt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > bt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = U(t), c = o - s, l = c !== this.starvedFrames;
|
|
1666
1674
|
if (this.starvedFrames = c, !a || l) {
|
|
1667
1675
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1668
1676
|
return;
|
|
@@ -1671,12 +1679,12 @@ var It = class {
|
|
|
1671
1679
|
this.resetStarvationWindow();
|
|
1672
1680
|
return;
|
|
1673
1681
|
}
|
|
1674
|
-
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 >
|
|
1682
|
+
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 > Tt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= Ct && (this.clearKick(), this.starvationRebuilds < wt)) {
|
|
1675
1683
|
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");
|
|
1676
1684
|
return;
|
|
1677
1685
|
}
|
|
1678
|
-
let u = i && this.starvedTicks >=
|
|
1679
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1686
|
+
let u = i && this.starvedTicks >= xt, d = !i && this.deadTicks >= Tt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Et;
|
|
1687
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= St))) {
|
|
1680
1688
|
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");
|
|
1681
1689
|
try {
|
|
1682
1690
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1685,6 +1693,16 @@ var It = class {
|
|
|
1685
1693
|
}
|
|
1686
1694
|
}
|
|
1687
1695
|
}
|
|
1696
|
+
updateCatchUpBand() {
|
|
1697
|
+
let e = this.hls;
|
|
1698
|
+
if (!e || this.catchUpRate <= 1 || this.chaseSuspended || this.loadSuspended) return;
|
|
1699
|
+
let t = e.latency, n = e.targetLatency;
|
|
1700
|
+
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1701
|
+
let r = t - n;
|
|
1702
|
+
!this.catchUpEngaged && r > mt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= mt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1703
|
+
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1704
|
+
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1705
|
+
}
|
|
1688
1706
|
fpsCapLevel(e) {
|
|
1689
1707
|
if (this.fpsCapBitrate == null) return -1;
|
|
1690
1708
|
let t = this.fpsCapFailedHeight, n = -1;
|
|
@@ -1702,16 +1720,16 @@ var It = class {
|
|
|
1702
1720
|
this.resetFrameDropWindow();
|
|
1703
1721
|
return;
|
|
1704
1722
|
}
|
|
1705
|
-
let { totalFrames: n, dropped: r } =
|
|
1706
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
1723
|
+
let { totalFrames: n, dropped: r } = U(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
1724
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < At || o < 0) {
|
|
1707
1725
|
this.fpsBadTicks = 0;
|
|
1708
1726
|
return;
|
|
1709
1727
|
}
|
|
1710
|
-
if (o <=
|
|
1728
|
+
if (o <= kt * a) {
|
|
1711
1729
|
this.fpsBadTicks = 0;
|
|
1712
1730
|
return;
|
|
1713
1731
|
}
|
|
1714
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
1732
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < jt) return;
|
|
1715
1733
|
this.fpsBadTicks = 0;
|
|
1716
1734
|
let s = e.levels, c = s[e.currentLevel];
|
|
1717
1735
|
if (!c) return;
|
|
@@ -1728,24 +1746,27 @@ var It = class {
|
|
|
1728
1746
|
return;
|
|
1729
1747
|
}
|
|
1730
1748
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
1731
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
1749
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(_t, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
1732
1750
|
this.resetChaseWindow();
|
|
1733
1751
|
return;
|
|
1734
1752
|
}
|
|
1735
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
1753
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= gt) {
|
|
1736
1754
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
1737
1755
|
return;
|
|
1738
1756
|
}
|
|
1739
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
1757
|
+
if (this.chaseTicks += 1, this.chaseTicks < ht) return;
|
|
1740
1758
|
this.resetChaseWindow();
|
|
1741
1759
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
1742
1760
|
if (!(a > 1)) return;
|
|
1743
1761
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
1744
|
-
s < o +
|
|
1762
|
+
s < o + vt || (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);
|
|
1745
1763
|
}
|
|
1746
1764
|
suspendChasing() {
|
|
1747
1765
|
let e = this.hls;
|
|
1748
|
-
|
|
1766
|
+
if (!e) return;
|
|
1767
|
+
this.chaseSuspended = !0, this.savedLiveMaxLatency = e.config.liveMaxLatencyDuration, this.savedMaxSyncRate = e.config.maxLiveSyncPlaybackRate, e.config.liveMaxLatencyDuration = 2 ** 53 - 1, e.config.maxLiveSyncPlaybackRate = 1;
|
|
1768
|
+
let { video: t } = this.deps, n = this.savedMaxSyncRate;
|
|
1769
|
+
t.playbackRate > 1 && typeof n == "number" && t.playbackRate <= n && (t.playbackRate = 1);
|
|
1749
1770
|
}
|
|
1750
1771
|
resumeChasing() {
|
|
1751
1772
|
this.chaseSuspended = !1;
|
|
@@ -1768,7 +1789,7 @@ var It = class {
|
|
|
1768
1789
|
} catch {}
|
|
1769
1790
|
}
|
|
1770
1791
|
destroy() {
|
|
1771
|
-
if (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.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) {
|
|
1792
|
+
if (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) {
|
|
1772
1793
|
try {
|
|
1773
1794
|
this.hls.destroy();
|
|
1774
1795
|
} catch (e) {
|
|
@@ -1783,7 +1804,7 @@ var It = class {
|
|
|
1783
1804
|
scheduleLicenseRetry(t) {
|
|
1784
1805
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1785
1806
|
let n = t.response?.code ?? 0;
|
|
1786
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1807
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= lt) return !1;
|
|
1787
1808
|
this.licenseRecoveries += 1;
|
|
1788
1809
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1789
1810
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1815,7 +1836,7 @@ var It = class {
|
|
|
1815
1836
|
return;
|
|
1816
1837
|
}
|
|
1817
1838
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1818
|
-
if (this.networkRecoveries <
|
|
1839
|
+
if (this.networkRecoveries < ct) {
|
|
1819
1840
|
this.networkRecoveries += 1;
|
|
1820
1841
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1821
1842
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1832,7 +1853,7 @@ var It = class {
|
|
|
1832
1853
|
return;
|
|
1833
1854
|
}
|
|
1834
1855
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1835
|
-
if (this.mediaRecoveries <
|
|
1856
|
+
if (this.mediaRecoveries < st) {
|
|
1836
1857
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1837
1858
|
return;
|
|
1838
1859
|
}
|
|
@@ -1856,19 +1877,19 @@ var It = class {
|
|
|
1856
1877
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1857
1878
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1858
1879
|
}
|
|
1859
|
-
},
|
|
1880
|
+
}, zt = 15e3, Bt = 6e5, Vt = 3e5, Ht = 100, q = 1, Ut = 1e3, Wt = 3e4, Gt = 1e3, Kt = {
|
|
1860
1881
|
inline: "PRESENTATION_INLINE",
|
|
1861
1882
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1862
1883
|
pip: "PRESENTATION_PIP"
|
|
1863
|
-
},
|
|
1884
|
+
}, qt = {
|
|
1864
1885
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1865
1886
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1866
1887
|
none: "KEY_SYSTEM_NONE"
|
|
1867
1888
|
};
|
|
1868
|
-
function
|
|
1889
|
+
function Jt(e, t) {
|
|
1869
1890
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1870
1891
|
}
|
|
1871
|
-
var
|
|
1892
|
+
var Yt = /* @__PURE__ */ new Set([
|
|
1872
1893
|
"INVALID_URN",
|
|
1873
1894
|
"NOT_FOUND",
|
|
1874
1895
|
"GONE",
|
|
@@ -1888,7 +1909,7 @@ var qt = /* @__PURE__ */ new Set([
|
|
|
1888
1909
|
ended: "PLAYER_STATE_ENDED",
|
|
1889
1910
|
error: "PLAYER_STATE_ERROR"
|
|
1890
1911
|
};
|
|
1891
|
-
function
|
|
1912
|
+
function Xt(e) {
|
|
1892
1913
|
try {
|
|
1893
1914
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1894
1915
|
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);
|
|
@@ -1896,8 +1917,8 @@ function Jt(e) {
|
|
|
1896
1917
|
return;
|
|
1897
1918
|
}
|
|
1898
1919
|
}
|
|
1899
|
-
var
|
|
1900
|
-
function
|
|
1920
|
+
var Zt = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Qt = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), $t = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
1921
|
+
function en(e) {
|
|
1901
1922
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
1902
1923
|
let t;
|
|
1903
1924
|
try {
|
|
@@ -1906,19 +1927,19 @@ function Qt(e) {
|
|
|
1906
1927
|
} catch {
|
|
1907
1928
|
return;
|
|
1908
1929
|
}
|
|
1909
|
-
if (
|
|
1910
|
-
Y.add(t), g(
|
|
1930
|
+
if (Qt.has(t) && !Y.has(t)) {
|
|
1931
|
+
Y.add(t), g($t(new URL(t).origin));
|
|
1911
1932
|
for (let e of X) e.noteCspBlocked();
|
|
1912
1933
|
}
|
|
1913
1934
|
}
|
|
1914
|
-
function
|
|
1935
|
+
function tn(e, t) {
|
|
1915
1936
|
return g(t, e), { disabledReason: t };
|
|
1916
1937
|
}
|
|
1917
|
-
function
|
|
1918
|
-
if (n) return t && !
|
|
1938
|
+
function nn(e, t, n) {
|
|
1939
|
+
if (n) return t && !Zt(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
1919
1940
|
if (t) return { endpoint: t };
|
|
1920
|
-
if (t !== void 0) return
|
|
1921
|
-
let r =
|
|
1941
|
+
if (t !== void 0) return tn("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).");
|
|
1942
|
+
let r = Xt(e);
|
|
1922
1943
|
if (r) return { endpoint: r };
|
|
1923
1944
|
let i;
|
|
1924
1945
|
try {
|
|
@@ -1926,9 +1947,9 @@ function en(e, t, n) {
|
|
|
1926
1947
|
} catch {
|
|
1927
1948
|
i = e;
|
|
1928
1949
|
}
|
|
1929
|
-
return
|
|
1950
|
+
return tn(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).`);
|
|
1930
1951
|
}
|
|
1931
|
-
var
|
|
1952
|
+
var rn = class {
|
|
1932
1953
|
opts;
|
|
1933
1954
|
url;
|
|
1934
1955
|
cspKey;
|
|
@@ -2010,8 +2031,8 @@ var tn = class {
|
|
|
2010
2031
|
constructor(e) {
|
|
2011
2032
|
this.opts = {
|
|
2012
2033
|
...e,
|
|
2013
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2014
|
-
idleMs: e.idleMs ??
|
|
2034
|
+
heartbeatMs: e.heartbeatMs ?? zt,
|
|
2035
|
+
idleMs: e.idleMs ?? Bt
|
|
2015
2036
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2016
2037
|
try {
|
|
2017
2038
|
let e = new URL(this.url);
|
|
@@ -2028,11 +2049,11 @@ var tn = class {
|
|
|
2028
2049
|
sdkVersion: this.opts.sdkVersion,
|
|
2029
2050
|
...this.opts.environment
|
|
2030
2051
|
};
|
|
2031
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2052
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Ut), 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 && Qt.add(this.cspKey), document.addEventListener("securitypolicyviolation", en), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2032
2053
|
}
|
|
2033
2054
|
checkSuspension(e) {
|
|
2034
2055
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2035
|
-
let t = Math.max(this.opts.idleMs,
|
|
2056
|
+
let t = Math.max(this.opts.idleMs, Vt);
|
|
2036
2057
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2037
2058
|
}
|
|
2038
2059
|
syncIdle(e) {
|
|
@@ -2055,12 +2076,12 @@ var tn = class {
|
|
|
2055
2076
|
let a = {
|
|
2056
2077
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2057
2078
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2058
|
-
presentation:
|
|
2079
|
+
presentation: Kt[this.presentation]
|
|
2059
2080
|
}, o = this.causeOf(e, t, i);
|
|
2060
2081
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2061
2082
|
}
|
|
2062
2083
|
seekInduced(e) {
|
|
2063
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2084
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < Gt;
|
|
2064
2085
|
}
|
|
2065
2086
|
causeOf(e, t, n) {
|
|
2066
2087
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2134,7 +2155,7 @@ var tn = class {
|
|
|
2134
2155
|
let r = n ?? "";
|
|
2135
2156
|
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";
|
|
2136
2157
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2137
|
-
if (
|
|
2158
|
+
if (Yt.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2138
2159
|
let i = t ?? "";
|
|
2139
2160
|
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";
|
|
2140
2161
|
}
|
|
@@ -2181,14 +2202,14 @@ var tn = class {
|
|
|
2181
2202
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2182
2203
|
o.requestCountDelta = _;
|
|
2183
2204
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2184
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2205
|
+
n.length > 0 && (o.requestTimeP50Ms = Jt(n, 50), o.requestTimeP95Ms = Jt(n, 95));
|
|
2185
2206
|
}
|
|
2186
2207
|
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();
|
|
2187
2208
|
}
|
|
2188
2209
|
maybeEmitMediaInfo(e) {
|
|
2189
2210
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2190
2211
|
let t = {};
|
|
2191
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2212
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = qt[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);
|
|
2192
2213
|
let n = JSON.stringify(t);
|
|
2193
2214
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2194
2215
|
}
|
|
@@ -2208,7 +2229,7 @@ var tn = class {
|
|
|
2208
2229
|
let c = r?.positionMs ?? 0;
|
|
2209
2230
|
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));
|
|
2210
2231
|
let l = e !== "END_REASON_ENDED";
|
|
2211
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2232
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= Wt && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Wt && (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);
|
|
2212
2233
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2213
2234
|
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");
|
|
2214
2235
|
}
|
|
@@ -2228,13 +2249,13 @@ var tn = class {
|
|
|
2228
2249
|
};
|
|
2229
2250
|
}
|
|
2230
2251
|
noteCspBlocked() {
|
|
2231
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2252
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.($t(new URL(this.url).origin)));
|
|
2232
2253
|
}
|
|
2233
2254
|
cspBlocked() {
|
|
2234
2255
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2235
2256
|
}
|
|
2236
2257
|
enqueue(e) {
|
|
2237
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2258
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Ht;) {
|
|
2238
2259
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2239
2260
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2240
2261
|
}
|
|
@@ -2261,7 +2282,7 @@ var tn = class {
|
|
|
2261
2282
|
};
|
|
2262
2283
|
//#endregion
|
|
2263
2284
|
//#region src/core/environment.ts
|
|
2264
|
-
function
|
|
2285
|
+
function an() {
|
|
2265
2286
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2266
2287
|
let e;
|
|
2267
2288
|
try {
|
|
@@ -2286,14 +2307,14 @@ function nn() {
|
|
|
2286
2307
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2287
2308
|
};
|
|
2288
2309
|
}
|
|
2289
|
-
function
|
|
2310
|
+
function on() {
|
|
2290
2311
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2291
2312
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2292
2313
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2293
2314
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2294
2315
|
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";
|
|
2295
2316
|
}
|
|
2296
|
-
function
|
|
2317
|
+
function sn() {
|
|
2297
2318
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2298
2319
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2299
2320
|
let t = {
|
|
@@ -2312,17 +2333,17 @@ function an() {
|
|
|
2312
2333
|
}
|
|
2313
2334
|
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;
|
|
2314
2335
|
}
|
|
2315
|
-
function
|
|
2316
|
-
let t =
|
|
2317
|
-
deviceClass:
|
|
2336
|
+
function cn(e) {
|
|
2337
|
+
let t = an(), n = {
|
|
2338
|
+
deviceClass: on(),
|
|
2318
2339
|
integration: t.integration,
|
|
2319
|
-
...
|
|
2340
|
+
...sn()
|
|
2320
2341
|
};
|
|
2321
2342
|
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);
|
|
2322
2343
|
let r = e.getBoundingClientRect?.();
|
|
2323
2344
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2324
2345
|
}
|
|
2325
|
-
async function
|
|
2346
|
+
async function ln() {
|
|
2326
2347
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2327
2348
|
if (!e?.getHighEntropyValues) return {};
|
|
2328
2349
|
try {
|
|
@@ -2334,7 +2355,7 @@ async function sn() {
|
|
|
2334
2355
|
}
|
|
2335
2356
|
//#endregion
|
|
2336
2357
|
//#region src/core/version.ts
|
|
2337
|
-
var
|
|
2358
|
+
var un = "2.15.5", dn = {
|
|
2338
2359
|
accent: "#E1B600",
|
|
2339
2360
|
accentText: "#1B1C23",
|
|
2340
2361
|
background: "#0e0f13",
|
|
@@ -2345,7 +2366,7 @@ var cn = "2.15.3", ln = {
|
|
|
2345
2366
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2346
2367
|
radius: "8px",
|
|
2347
2368
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2348
|
-
},
|
|
2369
|
+
}, fn = {
|
|
2349
2370
|
accent: "--havik-accent",
|
|
2350
2371
|
accentText: "--havik-accent-text",
|
|
2351
2372
|
background: "--havik-bg",
|
|
@@ -2357,26 +2378,26 @@ var cn = "2.15.3", ln = {
|
|
|
2357
2378
|
radius: "--havik-radius",
|
|
2358
2379
|
fontFamily: "--havik-font"
|
|
2359
2380
|
};
|
|
2360
|
-
function
|
|
2381
|
+
function pn(e, t) {
|
|
2361
2382
|
let n = {
|
|
2362
|
-
...
|
|
2383
|
+
...dn,
|
|
2363
2384
|
...t
|
|
2364
2385
|
};
|
|
2365
|
-
for (let t of Object.keys(
|
|
2386
|
+
for (let t of Object.keys(fn)) e.style.setProperty(fn[t], n[t]);
|
|
2366
2387
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2367
2388
|
}
|
|
2368
2389
|
//#endregion
|
|
2369
2390
|
//#region src/ui/styles.ts
|
|
2370
|
-
var
|
|
2371
|
-
function
|
|
2372
|
-
let n = e.querySelector(`style#${
|
|
2373
|
-
if (n && (!t ||
|
|
2391
|
+
var mn = "havik-player-styles", hn = "\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();
|
|
2392
|
+
function gn(e = document, t) {
|
|
2393
|
+
let n = e.querySelector(`style#${mn}`);
|
|
2394
|
+
if (n && (!t || Z.get(n) === t)) return;
|
|
2374
2395
|
let r = e.createElement("style");
|
|
2375
|
-
r.id =
|
|
2396
|
+
r.id = mn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = hn, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2376
2397
|
}
|
|
2377
2398
|
//#endregion
|
|
2378
2399
|
//#region src/ui/icons.ts
|
|
2379
|
-
var
|
|
2400
|
+
var _n = {
|
|
2380
2401
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2381
2402
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2382
2403
|
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\"/>",
|
|
@@ -2389,21 +2410,21 @@ var gn = {
|
|
|
2389
2410
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
2390
2411
|
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\"/>"
|
|
2391
2412
|
};
|
|
2392
|
-
function
|
|
2393
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2413
|
+
function Q(e) {
|
|
2414
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${_n[e]}</svg>`;
|
|
2394
2415
|
}
|
|
2395
2416
|
//#endregion
|
|
2396
2417
|
//#region src/ui/controls.ts
|
|
2397
|
-
var
|
|
2418
|
+
var vn = 3e3, yn = 250, bn = /* @__PURE__ */ new Set([
|
|
2398
2419
|
"GONE",
|
|
2399
2420
|
"NOT_FOUND",
|
|
2400
2421
|
"INVALID_URN",
|
|
2401
2422
|
"UNAUTHORIZED"
|
|
2402
2423
|
]);
|
|
2403
|
-
function
|
|
2404
|
-
return new
|
|
2424
|
+
function xn(e) {
|
|
2425
|
+
return new Sn(e);
|
|
2405
2426
|
}
|
|
2406
|
-
var
|
|
2427
|
+
var Sn = class {
|
|
2407
2428
|
root;
|
|
2408
2429
|
video;
|
|
2409
2430
|
player;
|
|
@@ -2449,7 +2470,7 @@ var xn = class {
|
|
|
2449
2470
|
scrubbing = !1;
|
|
2450
2471
|
offFns = [];
|
|
2451
2472
|
constructor(e) {
|
|
2452
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2473
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? vn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, gn(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");
|
|
2453
2474
|
let t = (e, t, n) => {
|
|
2454
2475
|
let r = this.doc.createElement(e);
|
|
2455
2476
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2460,12 +2481,12 @@ var xn = class {
|
|
|
2460
2481
|
"aria-label": r,
|
|
2461
2482
|
title: r
|
|
2462
2483
|
});
|
|
2463
|
-
return i.innerHTML =
|
|
2484
|
+
return i.innerHTML = Q(n), i;
|
|
2464
2485
|
};
|
|
2465
2486
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
2466
2487
|
type: "button",
|
|
2467
2488
|
"aria-label": "Play"
|
|
2468
|
-
}), this.center.innerHTML =
|
|
2489
|
+
}), this.center.innerHTML = Q("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
|
|
2469
2490
|
role: "slider",
|
|
2470
2491
|
"aria-label": "Seek",
|
|
2471
2492
|
"aria-valuemin": "0",
|
|
@@ -2483,7 +2504,7 @@ var xn = class {
|
|
|
2483
2504
|
"aria-label": "Volume"
|
|
2484
2505
|
});
|
|
2485
2506
|
let a = t("div", "havik-vol");
|
|
2486
|
-
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML =
|
|
2507
|
+
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Q("liveDot");
|
|
2487
2508
|
let o = this.doc.createElement("span");
|
|
2488
2509
|
o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
|
|
2489
2510
|
let s = t("div", "havik-spacer");
|
|
@@ -2535,7 +2556,7 @@ var xn = class {
|
|
|
2535
2556
|
let t = this.surfaceWasHidden;
|
|
2536
2557
|
this.tapTimer = setTimeout(() => {
|
|
2537
2558
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2538
|
-
},
|
|
2559
|
+
}, yn);
|
|
2539
2560
|
}
|
|
2540
2561
|
toggleBar(e) {
|
|
2541
2562
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2567,12 +2588,12 @@ var xn = class {
|
|
|
2567
2588
|
}
|
|
2568
2589
|
if (e === "preplay") {
|
|
2569
2590
|
let e = this.doc.createElement("button");
|
|
2570
|
-
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML =
|
|
2591
|
+
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);
|
|
2571
2592
|
} else {
|
|
2572
2593
|
let r = this.doc.createElement("div");
|
|
2573
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2594
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !bn.has(this.lastError.code)) {
|
|
2574
2595
|
let e = this.doc.createElement("button");
|
|
2575
|
-
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${
|
|
2596
|
+
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);
|
|
2576
2597
|
}
|
|
2577
2598
|
}
|
|
2578
2599
|
this.root.append(n), this.statusBox = n, this.show();
|
|
@@ -2611,7 +2632,7 @@ var xn = class {
|
|
|
2611
2632
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2612
2633
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2613
2634
|
}
|
|
2614
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2635
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Cn(this.video.currentTime)} / ${Cn(this.video.duration)}`);
|
|
2615
2636
|
}
|
|
2616
2637
|
syncLive() {
|
|
2617
2638
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2661,17 +2682,17 @@ var xn = class {
|
|
|
2661
2682
|
renderQualityMenu() {
|
|
2662
2683
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2663
2684
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2664
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2685
|
+
for (let n of e) this.menu.append(this.menuItem(wn(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2665
2686
|
}
|
|
2666
2687
|
renderAudioMenu() {
|
|
2667
2688
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2668
2689
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2669
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2690
|
+
for (let t of e) this.menu.append(this.menuItem(Tn(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2670
2691
|
}
|
|
2671
2692
|
renderCcMenu() {
|
|
2672
2693
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2673
2694
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2674
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2695
|
+
for (let t of e) this.menu.append(this.menuItem(En(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2675
2696
|
}
|
|
2676
2697
|
onTracksChanged() {
|
|
2677
2698
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2691,11 +2712,11 @@ var xn = class {
|
|
|
2691
2712
|
}
|
|
2692
2713
|
async toggleFullscreen() {
|
|
2693
2714
|
try {
|
|
2694
|
-
|
|
2715
|
+
C(this.video, this.root) ? await T(this.video, this.root) : await w(this.video, this.root);
|
|
2695
2716
|
} catch {}
|
|
2696
2717
|
}
|
|
2697
2718
|
syncFullscreen() {
|
|
2698
|
-
let e =
|
|
2719
|
+
let e = C(this.video, this.root);
|
|
2699
2720
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
2700
2721
|
}
|
|
2701
2722
|
poke() {
|
|
@@ -2755,7 +2776,7 @@ var xn = class {
|
|
|
2755
2776
|
}
|
|
2756
2777
|
}
|
|
2757
2778
|
setIcon(e, t) {
|
|
2758
|
-
e.innerHTML =
|
|
2779
|
+
e.innerHTML = Q(t);
|
|
2759
2780
|
}
|
|
2760
2781
|
destroy() {
|
|
2761
2782
|
this.hideTimer && clearTimeout(this.hideTimer), this.tapTimer && clearTimeout(this.tapTimer);
|
|
@@ -2772,41 +2793,41 @@ var xn = class {
|
|
|
2772
2793
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2773
2794
|
}
|
|
2774
2795
|
};
|
|
2775
|
-
function
|
|
2796
|
+
function Cn(e) {
|
|
2776
2797
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2777
2798
|
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");
|
|
2778
2799
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2779
2800
|
}
|
|
2780
|
-
function
|
|
2801
|
+
function wn(e) {
|
|
2781
2802
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2782
2803
|
}
|
|
2783
|
-
function
|
|
2804
|
+
function Tn(e) {
|
|
2784
2805
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2785
2806
|
}
|
|
2786
|
-
function
|
|
2807
|
+
function En(e) {
|
|
2787
2808
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2788
2809
|
}
|
|
2789
2810
|
//#endregion
|
|
2790
2811
|
//#region src/managed/index.ts
|
|
2791
|
-
var
|
|
2792
|
-
function
|
|
2812
|
+
var Dn = 6e3, On = 45e3, kn = 2e3, An = 3, jn = 2e3, Mn = 48e4;
|
|
2813
|
+
function Nn(e) {
|
|
2793
2814
|
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)})`);
|
|
2794
|
-
if (e.env !== void 0) return
|
|
2815
|
+
if (e.env !== void 0) return B(e.env);
|
|
2795
2816
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2796
2817
|
return e.baseUrl;
|
|
2797
2818
|
}
|
|
2798
|
-
async function
|
|
2819
|
+
async function Pn(e) {
|
|
2799
2820
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2800
|
-
let t =
|
|
2821
|
+
let t = Nn(e);
|
|
2801
2822
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2802
2823
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2803
|
-
let r = new
|
|
2824
|
+
let r = new Fn({
|
|
2804
2825
|
...e,
|
|
2805
2826
|
baseUrl: t
|
|
2806
2827
|
});
|
|
2807
2828
|
return await r.start(), r;
|
|
2808
2829
|
}
|
|
2809
|
-
var
|
|
2830
|
+
var Fn = class {
|
|
2810
2831
|
opts;
|
|
2811
2832
|
abort = new AbortController();
|
|
2812
2833
|
listeners = {};
|
|
@@ -2873,7 +2894,7 @@ var Nn = class {
|
|
|
2873
2894
|
};
|
|
2874
2895
|
}
|
|
2875
2896
|
beginArming(e, t, n = !1) {
|
|
2876
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
2897
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
|
|
2877
2898
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
2878
2899
|
}
|
|
2879
2900
|
beginArmingByPolling(e) {
|
|
@@ -2894,7 +2915,7 @@ var Nn = class {
|
|
|
2894
2915
|
setTimeout(() => {
|
|
2895
2916
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
2896
2917
|
phase: i ? "unavailable" : "tooEarly",
|
|
2897
|
-
retryInMs:
|
|
2918
|
+
retryInMs: On,
|
|
2898
2919
|
attempt: 1,
|
|
2899
2920
|
elapsedMs: 0,
|
|
2900
2921
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -2933,13 +2954,13 @@ var Nn = class {
|
|
|
2933
2954
|
!a && !p() && h();
|
|
2934
2955
|
}, e);
|
|
2935
2956
|
};
|
|
2936
|
-
_(
|
|
2957
|
+
_(Dn), this.armingSub = E({
|
|
2937
2958
|
eventsBaseUrl: t,
|
|
2938
2959
|
matchUrn: this.opts.matchUrn,
|
|
2939
2960
|
credential: this.opts.credential,
|
|
2940
|
-
onAlive: () => _(
|
|
2961
|
+
onAlive: () => _(On),
|
|
2941
2962
|
onState: (e) => {
|
|
2942
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
2963
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * kn);
|
|
2943
2964
|
},
|
|
2944
2965
|
onError: () => h()
|
|
2945
2966
|
});
|
|
@@ -2962,7 +2983,7 @@ var Nn = class {
|
|
|
2962
2983
|
let n = await s(this.opts.credential);
|
|
2963
2984
|
if (this.destroyed || t !== this.loadGen) return;
|
|
2964
2985
|
this.setState("loading");
|
|
2965
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
2986
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = qe(this.opts.video, (e) => {
|
|
2966
2987
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
2967
2988
|
});
|
|
2968
2989
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -2984,26 +3005,26 @@ var Nn = class {
|
|
|
2984
3005
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
2985
3006
|
let i = e.analytics?.sid;
|
|
2986
3007
|
if (!i) return;
|
|
2987
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3008
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = nn(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
2988
3009
|
if (!o) {
|
|
2989
3010
|
s && setTimeout(() => {
|
|
2990
3011
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
2991
3012
|
}, 0);
|
|
2992
3013
|
return;
|
|
2993
3014
|
}
|
|
2994
|
-
let c = this.opts.video, l = new
|
|
3015
|
+
let c = this.opts.video, l = new rn({
|
|
2995
3016
|
endpoint: o,
|
|
2996
3017
|
sid: i,
|
|
2997
3018
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
2998
|
-
sdkVersion:
|
|
2999
|
-
environment:
|
|
3019
|
+
sdkVersion: un,
|
|
3020
|
+
environment: cn(c),
|
|
3000
3021
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3001
3022
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3002
3023
|
onBlocked: (e) => setTimeout(() => {
|
|
3003
3024
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3004
3025
|
}, 0),
|
|
3005
3026
|
sample: () => {
|
|
3006
|
-
let e = this.engine?.getStats() ??
|
|
3027
|
+
let e = this.engine?.getStats() ?? V, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3007
3028
|
return {
|
|
3008
3029
|
...e,
|
|
3009
3030
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3017,7 +3038,7 @@ var Nn = class {
|
|
|
3017
3038
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3018
3039
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3019
3040
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3020
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3041
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), ln().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3021
3042
|
}
|
|
3022
3043
|
currentPresentation() {
|
|
3023
3044
|
let e = this.opts.video;
|
|
@@ -3032,7 +3053,7 @@ var Nn = class {
|
|
|
3032
3053
|
video: this.opts.video,
|
|
3033
3054
|
descriptor: e,
|
|
3034
3055
|
credential: t,
|
|
3035
|
-
deviceId:
|
|
3056
|
+
deviceId: A(),
|
|
3036
3057
|
userId: this.opts.userId,
|
|
3037
3058
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
3038
3059
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -3043,10 +3064,10 @@ var Nn = class {
|
|
|
3043
3064
|
emit: (e) => this.onEngineEvent(e)
|
|
3044
3065
|
}, o = this.opts.engine ?? "auto";
|
|
3045
3066
|
if (o === "native") return new K(a);
|
|
3046
|
-
if (o === "hls") return new
|
|
3047
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
3048
|
-
if (
|
|
3049
|
-
if (
|
|
3067
|
+
if (o === "hls") return new Rt(a);
|
|
3068
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G() || !e.drmEnabled && Ye() && W(this.opts.video)) return new K(a);
|
|
3069
|
+
if (ot()) return new Rt(a);
|
|
3070
|
+
if (W(this.opts.video)) return new K(a);
|
|
3050
3071
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3051
3072
|
}
|
|
3052
3073
|
onEngineEvent(e) {
|
|
@@ -3083,11 +3104,11 @@ var Nn = class {
|
|
|
3083
3104
|
}
|
|
3084
3105
|
startLiveState(e) {
|
|
3085
3106
|
if (this.opts.liveStateEvents === !1) return;
|
|
3086
|
-
let t = this.opts.eventsBaseUrl ??
|
|
3107
|
+
let t = this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
|
|
3087
3108
|
if (!t) return;
|
|
3088
3109
|
this.closeLiveState();
|
|
3089
3110
|
let r = 0, i = !1;
|
|
3090
|
-
this.liveStateSub =
|
|
3111
|
+
this.liveStateSub = E({
|
|
3091
3112
|
eventsBaseUrl: t,
|
|
3092
3113
|
matchUrn: this.opts.matchUrn,
|
|
3093
3114
|
credential: this.opts.credential,
|
|
@@ -3098,7 +3119,7 @@ var Nn = class {
|
|
|
3098
3119
|
r = 0, i = !1;
|
|
3099
3120
|
},
|
|
3100
3121
|
onError: () => {
|
|
3101
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
3122
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= An && (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.`))));
|
|
3102
3123
|
}
|
|
3103
3124
|
});
|
|
3104
3125
|
}
|
|
@@ -3120,7 +3141,7 @@ var Nn = class {
|
|
|
3120
3141
|
scheduleRejoin(e) {
|
|
3121
3142
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3122
3143
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3123
|
-
}, Math.random() *
|
|
3144
|
+
}, Math.random() * kn));
|
|
3124
3145
|
}
|
|
3125
3146
|
cancelRejoin() {
|
|
3126
3147
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3144,7 +3165,7 @@ var Nn = class {
|
|
|
3144
3165
|
}
|
|
3145
3166
|
t.controls = !1;
|
|
3146
3167
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3147
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3168
|
+
r && r.insertBefore(n, t), n.appendChild(t), pn(n, this.opts.theme), this.container = n, this.controlBar = xn({
|
|
3148
3169
|
root: n,
|
|
3149
3170
|
video: t,
|
|
3150
3171
|
player: this,
|
|
@@ -3175,7 +3196,7 @@ var Nn = class {
|
|
|
3175
3196
|
}
|
|
3176
3197
|
startStats() {
|
|
3177
3198
|
this.stopStats();
|
|
3178
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3199
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? jn);
|
|
3179
3200
|
this.statsTimer = setInterval(() => {
|
|
3180
3201
|
if (!this.engine) return;
|
|
3181
3202
|
let e = this.engine.getStats();
|
|
@@ -3187,7 +3208,7 @@ var Nn = class {
|
|
|
3187
3208
|
}
|
|
3188
3209
|
scheduleLicenseRefresh() {
|
|
3189
3210
|
this.stopRefresh();
|
|
3190
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3211
|
+
let e = this.opts.licenseRefreshMs ?? Mn;
|
|
3191
3212
|
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3192
3213
|
}
|
|
3193
3214
|
stopRefresh() {
|
|
@@ -3232,7 +3253,7 @@ var Nn = class {
|
|
|
3232
3253
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3233
3254
|
}
|
|
3234
3255
|
getStats() {
|
|
3235
|
-
return this.engine?.getStats() ??
|
|
3256
|
+
return this.engine?.getStats() ?? V;
|
|
3236
3257
|
}
|
|
3237
3258
|
getQualityLevels() {
|
|
3238
3259
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3271,10 +3292,10 @@ var Nn = class {
|
|
|
3271
3292
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
3272
3293
|
}
|
|
3273
3294
|
async enterFullscreen() {
|
|
3274
|
-
return !this.destroyed &&
|
|
3295
|
+
return !this.destroyed && w(this.opts.video, this.container ?? void 0);
|
|
3275
3296
|
}
|
|
3276
3297
|
async exitFullscreen() {
|
|
3277
|
-
await
|
|
3298
|
+
await T(this.opts.video, this.container ?? void 0);
|
|
3278
3299
|
}
|
|
3279
3300
|
retry() {
|
|
3280
3301
|
return this.reload();
|
|
@@ -3342,7 +3363,7 @@ function $(e) {
|
|
|
3342
3363
|
}
|
|
3343
3364
|
//#endregion
|
|
3344
3365
|
//#region src/embed/host.ts
|
|
3345
|
-
function
|
|
3366
|
+
function In(e) {
|
|
3346
3367
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3347
3368
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3348
3369
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3401,15 +3422,15 @@ function Pn(e) {
|
|
|
3401
3422
|
}
|
|
3402
3423
|
//#endregion
|
|
3403
3424
|
//#region src/embed/page.ts
|
|
3404
|
-
var
|
|
3405
|
-
function
|
|
3425
|
+
var Ln = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3426
|
+
function Rn(e) {
|
|
3406
3427
|
if (typeof e == "boolean") return e;
|
|
3407
3428
|
if (typeof e == "object" && e) {
|
|
3408
3429
|
let t = e.endpoint;
|
|
3409
3430
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3410
3431
|
}
|
|
3411
3432
|
}
|
|
3412
|
-
function
|
|
3433
|
+
function zn() {
|
|
3413
3434
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3414
3435
|
if (e) return {
|
|
3415
3436
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3419,7 +3440,7 @@ function Ln() {
|
|
|
3419
3440
|
autoplay: e.autoplay ?? !0,
|
|
3420
3441
|
muted: e.muted ?? !0,
|
|
3421
3442
|
waitForLive: e.waitForLive ?? !0,
|
|
3422
|
-
analytics:
|
|
3443
|
+
analytics: Rn(e.analytics)
|
|
3423
3444
|
};
|
|
3424
3445
|
let t = new URLSearchParams(location.search);
|
|
3425
3446
|
return {
|
|
@@ -3432,9 +3453,9 @@ function Ln() {
|
|
|
3432
3453
|
waitForLive: !0
|
|
3433
3454
|
};
|
|
3434
3455
|
}
|
|
3435
|
-
async function
|
|
3436
|
-
let e =
|
|
3437
|
-
|
|
3456
|
+
async function Bn() {
|
|
3457
|
+
let e = zn();
|
|
3458
|
+
Hn();
|
|
3438
3459
|
let t = document.createElement("video");
|
|
3439
3460
|
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);
|
|
3440
3461
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3489,12 +3510,12 @@ async function Rn() {
|
|
|
3489
3510
|
code: e.code,
|
|
3490
3511
|
message: e.message
|
|
3491
3512
|
})), e.on("autoplayblocked", () => {
|
|
3492
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3513
|
+
i({ type: "oddin:autoplayblocked" }), Vn(t, e);
|
|
3493
3514
|
});
|
|
3494
3515
|
}, s = async (r) => {
|
|
3495
3516
|
a?.destroy(), a = null;
|
|
3496
3517
|
try {
|
|
3497
|
-
let n = await
|
|
3518
|
+
let n = await Pn({
|
|
3498
3519
|
video: t,
|
|
3499
3520
|
baseUrl: e.baseUrl,
|
|
3500
3521
|
matchUrn: r,
|
|
@@ -3556,7 +3577,7 @@ async function Rn() {
|
|
|
3556
3577
|
a?.retry();
|
|
3557
3578
|
break;
|
|
3558
3579
|
case "oddin:load":
|
|
3559
|
-
typeof e.matchUrn == "string" &&
|
|
3580
|
+
typeof e.matchUrn == "string" && Ln.test(e.matchUrn) && s(e.matchUrn);
|
|
3560
3581
|
break;
|
|
3561
3582
|
case "oddin:destroy": c();
|
|
3562
3583
|
}
|
|
@@ -3568,18 +3589,18 @@ async function Rn() {
|
|
|
3568
3589
|
protocol: 1
|
|
3569
3590
|
});
|
|
3570
3591
|
}
|
|
3571
|
-
function
|
|
3592
|
+
function Vn(e, t) {
|
|
3572
3593
|
if (document.getElementById("havik-tap")) return;
|
|
3573
3594
|
let n = document.createElement("button");
|
|
3574
3595
|
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", () => {
|
|
3575
3596
|
n.remove(), t.play();
|
|
3576
3597
|
}), document.body.appendChild(n);
|
|
3577
3598
|
}
|
|
3578
|
-
function
|
|
3599
|
+
function Hn() {
|
|
3579
3600
|
let e = document.createElement("style");
|
|
3580
3601
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3581
3602
|
}
|
|
3582
3603
|
//#endregion
|
|
3583
|
-
export {
|
|
3604
|
+
export { dn as ODDIN_THEME, n as PlaybackError, pn as applyTheme, B as baseUrlForEnv, Bn as bootEmbed, we as clearDeviceId, Pn as createPlayer, D as deriveEventsBaseUrl, Ve as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ge as fetchCatalog, ve as fetchTournament, be as flattenMatches, A as getDeviceId, Ue as isLowLatencyManifest, $ as isOddinMessage, Ee as licenseRequestHeaders, In as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, Se as watchStatus };
|
|
3584
3605
|
|
|
3585
3606
|
//# sourceMappingURL=index.js.map
|