@oddin-gg/havik-player 2.16.0 → 2.16.2
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 +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.js +343 -293
- package/dist/index.js.map +1 -1
- package/docs/API.md +1 -1
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -290,32 +290,32 @@ function me(e, t) {
|
|
|
290
290
|
function he(e) {
|
|
291
291
|
return e.ownerDocument ?? document;
|
|
292
292
|
}
|
|
293
|
-
function
|
|
293
|
+
function ge(e) {
|
|
294
294
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
295
295
|
}
|
|
296
|
-
function
|
|
297
|
-
let n =
|
|
296
|
+
function S(e, t) {
|
|
297
|
+
let n = ge(he(e));
|
|
298
298
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
299
299
|
}
|
|
300
|
-
async function
|
|
300
|
+
async function C(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 w(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 = ge(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 _e(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 ge(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: ve(await s.json()),
|
|
337
337
|
etag: s.headers.get("etag") ?? void 0,
|
|
338
338
|
notModified: !1
|
|
339
339
|
};
|
|
340
340
|
}
|
|
341
|
-
function
|
|
341
|
+
function ve(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 _e(e) {
|
|
|
360
360
|
};
|
|
361
361
|
});
|
|
362
362
|
}
|
|
363
|
-
async function
|
|
363
|
+
async function ye(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 ve(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: be(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 be(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 ye(e) {
|
|
|
406
406
|
}))
|
|
407
407
|
};
|
|
408
408
|
}
|
|
409
|
-
function
|
|
409
|
+
function xe(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 Se = /* @__PURE__ */ new Set([
|
|
415
415
|
"NOT_FOUND",
|
|
416
416
|
"GONE",
|
|
417
417
|
"INVALID_URN"
|
|
418
418
|
]);
|
|
419
|
-
function
|
|
419
|
+
function Ce(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 Se(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
|
+
Se.has(r.code) && (u = !0), e.onError?.(r);
|
|
453
453
|
}
|
|
454
454
|
} finally {
|
|
455
455
|
f();
|
|
@@ -461,9 +461,9 @@ function Se(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 we = 45e3;
|
|
465
|
+
function T(e) {
|
|
466
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? we, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
|
|
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 E(e) {
|
|
|
544
544
|
o || (o = !0, a.abort());
|
|
545
545
|
} };
|
|
546
546
|
}
|
|
547
|
-
function
|
|
547
|
+
function E(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 D(e) {
|
|
|
554
554
|
}
|
|
555
555
|
//#endregion
|
|
556
556
|
//#region src/core/drm/deviceId.ts
|
|
557
|
-
var
|
|
558
|
-
function
|
|
559
|
-
if (
|
|
557
|
+
var D = "havik.player.deviceId", O;
|
|
558
|
+
function k() {
|
|
559
|
+
if (O) return O;
|
|
560
560
|
try {
|
|
561
|
-
let e = globalThis.localStorage?.getItem(
|
|
562
|
-
if (e) return
|
|
561
|
+
let e = globalThis.localStorage?.getItem(D);
|
|
562
|
+
if (e) return O = e, e;
|
|
563
563
|
} catch {}
|
|
564
|
-
let e =
|
|
565
|
-
|
|
564
|
+
let e = Ee();
|
|
565
|
+
O = e;
|
|
566
566
|
try {
|
|
567
|
-
globalThis.localStorage?.setItem(
|
|
567
|
+
globalThis.localStorage?.setItem(D, e);
|
|
568
568
|
} catch {}
|
|
569
569
|
return e;
|
|
570
570
|
}
|
|
571
|
-
function
|
|
572
|
-
|
|
571
|
+
function Te() {
|
|
572
|
+
O = void 0;
|
|
573
573
|
try {
|
|
574
|
-
globalThis.localStorage?.removeItem(
|
|
574
|
+
globalThis.localStorage?.removeItem(D);
|
|
575
575
|
} catch {}
|
|
576
576
|
}
|
|
577
|
-
function
|
|
577
|
+
function Ee() {
|
|
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 Te() {
|
|
|
586
586
|
}
|
|
587
587
|
//#endregion
|
|
588
588
|
//#region src/core/drm/headers.ts
|
|
589
|
-
function
|
|
589
|
+
function De(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 ?? k(),
|
|
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 A = /* @__PURE__ */ new WeakMap();
|
|
601
|
+
function Oe(e, t) {
|
|
602
|
+
let n = A.get(e);
|
|
603
|
+
n || (n = /* @__PURE__ */ new Map(), A.set(e, n));
|
|
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 De(e, t) {
|
|
|
608
608
|
});
|
|
609
609
|
return n.set(t.keySystem, i), i;
|
|
610
610
|
}
|
|
611
|
-
function
|
|
611
|
+
function j() {
|
|
612
612
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
613
613
|
}
|
|
614
|
-
var
|
|
615
|
-
function
|
|
614
|
+
var M = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
615
|
+
function ke(e) {
|
|
616
616
|
return e.startsWith("com.widevine");
|
|
617
617
|
}
|
|
618
|
-
function
|
|
619
|
-
if (!
|
|
618
|
+
function N(e, t) {
|
|
619
|
+
if (!ke(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 = M.indexOf(e.robustness);
|
|
624
|
+
return n === -1 || M.indexOf(t) > n;
|
|
625
625
|
});
|
|
626
|
-
}, r =
|
|
626
|
+
}, r = M.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 P(e, t) {
|
|
|
632
632
|
})));
|
|
633
633
|
return [...t, ...r];
|
|
634
634
|
}
|
|
635
|
-
function
|
|
636
|
-
return (t, n) =>
|
|
635
|
+
function P(e) {
|
|
636
|
+
return (t, n) => j() ? navigator.requestMediaKeySystemAccess(t, N(t, n)).then((t) => ({
|
|
637
637
|
keySystem: t.keySystem,
|
|
638
638
|
getConfiguration: () => t.getConfiguration(),
|
|
639
|
-
createMediaKeys: () =>
|
|
639
|
+
createMediaKeys: () => Oe(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 F = {
|
|
643
643
|
video: "SW_SECURE_DECODE",
|
|
644
644
|
audio: "SW_SECURE_CRYPTO",
|
|
645
645
|
scheme: "cbcs"
|
|
646
646
|
};
|
|
647
|
-
function
|
|
648
|
-
if (!
|
|
647
|
+
function Ae(e) {
|
|
648
|
+
if (!j()) return;
|
|
649
649
|
let t = (e, t) => ({
|
|
650
650
|
contentType: e,
|
|
651
651
|
robustness: t,
|
|
652
|
-
encryptionScheme:
|
|
652
|
+
encryptionScheme: F.scheme
|
|
653
653
|
});
|
|
654
|
-
|
|
654
|
+
P(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\"", F.audio)],
|
|
660
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", F.video)]
|
|
661
661
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
662
662
|
}
|
|
663
|
-
function
|
|
664
|
-
let t =
|
|
663
|
+
function I(e) {
|
|
664
|
+
let t = L(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 L(e) {
|
|
672
672
|
return (e ?? "").trim().toLowerCase();
|
|
673
673
|
}
|
|
674
|
-
var
|
|
674
|
+
var R = {
|
|
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
|
+
}, z = /* @__PURE__ */ new Map(), B = /* @__PURE__ */ new Map();
|
|
680
|
+
function V(e) {
|
|
681
|
+
let t = L(e), n = z.get(t);
|
|
682
682
|
if (n) return n;
|
|
683
683
|
let r = {
|
|
684
684
|
initDataTypes: ["cenc"],
|
|
@@ -687,32 +687,32 @@ function Me(e) {
|
|
|
687
687
|
sessionTypes: ["temporary"],
|
|
688
688
|
videoCapabilities: [{
|
|
689
689
|
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
690
|
-
robustness:
|
|
691
|
-
encryptionScheme:
|
|
690
|
+
robustness: F.video,
|
|
691
|
+
encryptionScheme: F.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", N("com.widevine.alpha", [r])), !0;
|
|
696
696
|
} catch {
|
|
697
697
|
return !1;
|
|
698
698
|
}
|
|
699
|
-
})().then((e) => (
|
|
700
|
-
return
|
|
699
|
+
})().then((e) => (B.set(t, e), e));
|
|
700
|
+
return z.set(t, i), i;
|
|
701
701
|
}
|
|
702
|
-
function
|
|
703
|
-
if (
|
|
702
|
+
function je() {
|
|
703
|
+
if (j()) for (let e of Object.values(R)) V(e);
|
|
704
704
|
}
|
|
705
|
-
function
|
|
706
|
-
let t =
|
|
707
|
-
if (t) return t === "avc" ? !0 :
|
|
705
|
+
function Me(e) {
|
|
706
|
+
let t = I(e);
|
|
707
|
+
if (t) return t === "avc" ? !0 : B.get(L(e)) ?? B.get(L(R[t]));
|
|
708
708
|
}
|
|
709
709
|
//#endregion
|
|
710
710
|
//#region src/core/drm/support.ts
|
|
711
|
-
var
|
|
711
|
+
var Ne = 5e3, Pe = "video/mp4; codecs=\"avc1.42E01E\"", Fe = "audio/mp4; codecs=\"mp4a.40.2\"", Ie = {
|
|
712
712
|
widevine: ["com.widevine.alpha"],
|
|
713
713
|
fairplay: ["com.apple.fps"]
|
|
714
714
|
};
|
|
715
|
-
function
|
|
715
|
+
function Le(e) {
|
|
716
716
|
return e === "fairplay" ? [{
|
|
717
717
|
initDataTypes: [
|
|
718
718
|
"sinf",
|
|
@@ -720,30 +720,30 @@ function ze(e) {
|
|
|
720
720
|
"cenc"
|
|
721
721
|
],
|
|
722
722
|
videoCapabilities: [{
|
|
723
|
-
contentType:
|
|
723
|
+
contentType: Pe,
|
|
724
724
|
robustness: "",
|
|
725
725
|
encryptionScheme: "cbcs"
|
|
726
726
|
}],
|
|
727
727
|
audioCapabilities: [{
|
|
728
|
-
contentType:
|
|
728
|
+
contentType: Fe,
|
|
729
729
|
robustness: "",
|
|
730
730
|
encryptionScheme: "cbcs"
|
|
731
731
|
}]
|
|
732
|
-
}] :
|
|
732
|
+
}] : N("com.widevine.alpha", [{
|
|
733
733
|
initDataTypes: ["cenc"],
|
|
734
734
|
videoCapabilities: [{
|
|
735
|
-
contentType:
|
|
736
|
-
robustness:
|
|
737
|
-
encryptionScheme:
|
|
735
|
+
contentType: Pe,
|
|
736
|
+
robustness: F.video,
|
|
737
|
+
encryptionScheme: F.scheme
|
|
738
738
|
}],
|
|
739
739
|
audioCapabilities: [{
|
|
740
|
-
contentType:
|
|
741
|
-
robustness:
|
|
742
|
-
encryptionScheme:
|
|
740
|
+
contentType: Fe,
|
|
741
|
+
robustness: F.audio,
|
|
742
|
+
encryptionScheme: F.scheme
|
|
743
743
|
}]
|
|
744
744
|
}]);
|
|
745
745
|
}
|
|
746
|
-
function
|
|
746
|
+
function Re(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 Be(e, t) {
|
|
|
753
753
|
});
|
|
754
754
|
});
|
|
755
755
|
}
|
|
756
|
-
async function
|
|
757
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
756
|
+
async function ze(e = {}) {
|
|
757
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ne, 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 Ve(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 = Ie[e];
|
|
770
770
|
if (!t) {
|
|
771
771
|
r[e] = "unknown system";
|
|
772
772
|
continue;
|
|
@@ -777,7 +777,7 @@ async function Ve(e = {}) {
|
|
|
777
777
|
break;
|
|
778
778
|
}
|
|
779
779
|
try {
|
|
780
|
-
return await
|
|
780
|
+
return await Re((await Re(i(n, Le(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 Ve(e = {}) {
|
|
|
801
801
|
}
|
|
802
802
|
//#endregion
|
|
803
803
|
//#region src/core/manifest.ts
|
|
804
|
-
var
|
|
805
|
-
function
|
|
806
|
-
return
|
|
804
|
+
var Be = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
805
|
+
function Ve(e) {
|
|
806
|
+
return Be.test(e);
|
|
807
807
|
}
|
|
808
808
|
//#endregion
|
|
809
809
|
//#region src/core/env.ts
|
|
810
|
-
var
|
|
810
|
+
var He = {
|
|
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 Ue(e) {
|
|
815
|
+
let t = Object.prototype.hasOwnProperty.call(He, e) ? He[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 We = { droppedFrames: 0 };
|
|
822
|
+
function Ge(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 Ke = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
830
|
+
function qe(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" || Ke.test(i.name)) && i.startTime >= n) {
|
|
834
|
+
let e = Ge(i.name);
|
|
835
835
|
e && (t = e, n = i.startTime);
|
|
836
836
|
}
|
|
837
837
|
return t;
|
|
838
838
|
}
|
|
839
|
-
function
|
|
839
|
+
function H(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 Je(e, t) {
|
|
847
847
|
let n = [
|
|
848
848
|
["playing", () => t("playing")],
|
|
849
849
|
["waiting", () => t("buffering")],
|
|
@@ -860,7 +860,8 @@ function qe(e, t) {
|
|
|
860
860
|
}
|
|
861
861
|
//#endregion
|
|
862
862
|
//#region src/core/engine/native.ts
|
|
863
|
-
|
|
863
|
+
var Ye = 2e3, Xe = 3, U = 500, Ze = 6e3, Qe = .25;
|
|
864
|
+
function $e(e) {
|
|
864
865
|
try {
|
|
865
866
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
866
867
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -876,7 +877,7 @@ function G() {
|
|
|
876
877
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
877
878
|
return e || t;
|
|
878
879
|
}
|
|
879
|
-
function
|
|
880
|
+
function et() {
|
|
880
881
|
if (typeof navigator > "u" || !G()) return !1;
|
|
881
882
|
let e = navigator.userAgent ?? "";
|
|
882
883
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
@@ -890,6 +891,10 @@ var K = class {
|
|
|
890
891
|
fairplayLicenseUrl;
|
|
891
892
|
keySession = null;
|
|
892
893
|
fairplayArmed = !1;
|
|
894
|
+
onVisibility = null;
|
|
895
|
+
onPageShow = null;
|
|
896
|
+
hiddenSince = null;
|
|
897
|
+
refocusTimer = null;
|
|
893
898
|
fairplayKeyIV;
|
|
894
899
|
loadStarted;
|
|
895
900
|
preloadTouched = !1;
|
|
@@ -901,7 +906,7 @@ var K = class {
|
|
|
901
906
|
}
|
|
902
907
|
async load() {
|
|
903
908
|
let { video: e, descriptor: t, emit: r } = this.deps;
|
|
904
|
-
if (this.loadStarted || (this.preloadTouched = !0, this.savedPreload = e.getAttribute("preload"), e.preload = "none"), t.drmEnabled) {
|
|
909
|
+
if (this.watchRefocus(), this.loadStarted || (this.preloadTouched = !0, this.savedPreload = e.getAttribute("preload"), e.preload = "none"), t.drmEnabled) {
|
|
905
910
|
if (!t.drm?.fairplay) {
|
|
906
911
|
r({
|
|
907
912
|
type: "error",
|
|
@@ -917,7 +922,7 @@ var K = class {
|
|
|
917
922
|
type: "error",
|
|
918
923
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
919
924
|
fatal: !0
|
|
920
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
925
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = tt(t.manifestUrl, t.analytics?.sid), e.load();
|
|
921
926
|
}
|
|
922
927
|
startLoad() {
|
|
923
928
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -939,7 +944,7 @@ var K = class {
|
|
|
939
944
|
});
|
|
940
945
|
this.onEncrypted = (n) => {
|
|
941
946
|
let i = n;
|
|
942
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
947
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = $e(i.initData), (async () => {
|
|
943
948
|
try {
|
|
944
949
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
945
950
|
initDataTypes: [i.initDataType],
|
|
@@ -1034,11 +1039,11 @@ var K = class {
|
|
|
1034
1039
|
e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
|
|
1035
1040
|
}
|
|
1036
1041
|
getStats() {
|
|
1037
|
-
let e = this.deps.video, t =
|
|
1042
|
+
let e = this.deps.video, t = H(e), n = {
|
|
1038
1043
|
droppedFrames: t.dropped,
|
|
1039
1044
|
decodedFrames: t.totalFrames
|
|
1040
1045
|
};
|
|
1041
|
-
if (this.cdnHost ||=
|
|
1046
|
+
if (this.cdnHost ||= qe(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1042
1047
|
if (n.isLive = !0, e.seekable.length > 0) {
|
|
1043
1048
|
let t = e.seekable.end(e.seekable.length - 1);
|
|
1044
1049
|
n.atLiveEdge = e.currentTime >= t - 2;
|
|
@@ -1053,7 +1058,52 @@ var K = class {
|
|
|
1053
1058
|
this.deps.video.pause();
|
|
1054
1059
|
} catch {}
|
|
1055
1060
|
}
|
|
1061
|
+
watchRefocus() {
|
|
1062
|
+
this.deps.snapToLiveOnRefocus === !1 || typeof document > "u" || this.onVisibility || (this.onVisibility = () => {
|
|
1063
|
+
let e = typeof performance < "u" ? performance.now() : Date.now();
|
|
1064
|
+
if (document.visibilityState === "hidden") {
|
|
1065
|
+
this.hiddenSince = e, this.cancelRefocus();
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
let t = this.hiddenSince;
|
|
1069
|
+
this.hiddenSince = null, t != null && e - t >= Ye && this.armRefocus();
|
|
1070
|
+
}, this.onPageShow = (e) => {
|
|
1071
|
+
e.persisted && this.armRefocus();
|
|
1072
|
+
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
1073
|
+
}
|
|
1074
|
+
armRefocus() {
|
|
1075
|
+
if (this.cancelRefocus(), Number.isFinite(this.deps.video.duration)) return;
|
|
1076
|
+
let e = this.liveEnd(), t = () => typeof performance < "u" ? performance.now() : Date.now(), n = t(), r = 0, i = () => {
|
|
1077
|
+
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1078
|
+
r += U;
|
|
1079
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + Qe), s = Math.max(r, t() - n) >= Ze;
|
|
1080
|
+
if (o || s && a != null) {
|
|
1081
|
+
this.snapToLive();
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
1084
|
+
this.refocusTimer = setTimeout(i, U);
|
|
1085
|
+
};
|
|
1086
|
+
this.refocusTimer = setTimeout(i, U);
|
|
1087
|
+
}
|
|
1088
|
+
cancelRefocus() {
|
|
1089
|
+
this.refocusTimer != null && clearTimeout(this.refocusTimer), this.refocusTimer = null;
|
|
1090
|
+
}
|
|
1091
|
+
liveEnd() {
|
|
1092
|
+
let e = this.deps.video;
|
|
1093
|
+
if (e.duration !== Infinity || e.seekable.length === 0) return null;
|
|
1094
|
+
let t = e.seekable.end(e.seekable.length - 1);
|
|
1095
|
+
return Number.isFinite(t) ? t : null;
|
|
1096
|
+
}
|
|
1097
|
+
snapToLive() {
|
|
1098
|
+
let e = this.deps.video, t = this.liveEnd();
|
|
1099
|
+
if (t == null) return;
|
|
1100
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - Xe, r);
|
|
1101
|
+
try {
|
|
1102
|
+
e.currentTime = i;
|
|
1103
|
+
} catch {}
|
|
1104
|
+
}
|
|
1056
1105
|
destroy() {
|
|
1106
|
+
this.cancelRefocus(), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onPageShow && typeof window < "u" && (window.removeEventListener("pageshow", this.onPageShow), this.onPageShow = null);
|
|
1057
1107
|
let { video: e } = this.deps;
|
|
1058
1108
|
this.onLoaded && e.removeEventListener("loadedmetadata", this.onLoaded), this.onError && e.removeEventListener("error", this.onError), this.onEncrypted && e.removeEventListener("encrypted", this.onEncrypted), this.keySession?.close().catch(() => {}), this.keySession = null, this.fairplayArmed = !1, this.fairplayKeyIV = void 0;
|
|
1059
1109
|
try {
|
|
@@ -1065,13 +1115,13 @@ var K = class {
|
|
|
1065
1115
|
} catch {}
|
|
1066
1116
|
}
|
|
1067
1117
|
};
|
|
1068
|
-
function
|
|
1118
|
+
function tt(e, t) {
|
|
1069
1119
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1070
1120
|
}
|
|
1071
1121
|
//#endregion
|
|
1072
1122
|
//#region src/core/engine/prefetch.ts
|
|
1073
|
-
var
|
|
1074
|
-
function
|
|
1123
|
+
var nt = 15e3, rt = 5e3, it = 6;
|
|
1124
|
+
function at(e) {
|
|
1075
1125
|
try {
|
|
1076
1126
|
let t = new URL(e);
|
|
1077
1127
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1079,7 +1129,7 @@ function et(e) {
|
|
|
1079
1129
|
return e;
|
|
1080
1130
|
}
|
|
1081
1131
|
}
|
|
1082
|
-
var
|
|
1132
|
+
var ot = class {
|
|
1083
1133
|
cmcd;
|
|
1084
1134
|
entries = /* @__PURE__ */ new Map();
|
|
1085
1135
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1102,10 +1152,10 @@ var tt = class {
|
|
|
1102
1152
|
}
|
|
1103
1153
|
prefetch(e, t, n) {
|
|
1104
1154
|
if (!this.isActive(t)) return;
|
|
1105
|
-
let r =
|
|
1155
|
+
let r = at(e);
|
|
1106
1156
|
if (this.entries.has(r)) return;
|
|
1107
1157
|
let i = this.perTrack.get(t) ?? 0;
|
|
1108
|
-
if (i >=
|
|
1158
|
+
if (i >= it) return;
|
|
1109
1159
|
this.perTrack.set(t, i + 1);
|
|
1110
1160
|
let a = new AbortController(), o = {
|
|
1111
1161
|
started: performance.now(),
|
|
@@ -1119,10 +1169,10 @@ var tt = class {
|
|
|
1119
1169
|
signal: a.signal
|
|
1120
1170
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1121
1171
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1122
|
-
},
|
|
1172
|
+
}, nt);
|
|
1123
1173
|
}
|
|
1124
1174
|
take(e) {
|
|
1125
|
-
let t =
|
|
1175
|
+
let t = at(e), n = this.entries.get(t);
|
|
1126
1176
|
return n && this.entries.delete(t), n;
|
|
1127
1177
|
}
|
|
1128
1178
|
destroy() {
|
|
@@ -1142,13 +1192,13 @@ var tt = class {
|
|
|
1142
1192
|
}
|
|
1143
1193
|
}
|
|
1144
1194
|
};
|
|
1145
|
-
function
|
|
1195
|
+
function st(t) {
|
|
1146
1196
|
let n = e.DefaultConfig?.loader;
|
|
1147
1197
|
if (typeof n != "function") return;
|
|
1148
1198
|
class r extends n {
|
|
1149
1199
|
served = !1;
|
|
1150
1200
|
cancelled = !1;
|
|
1151
|
-
stats =
|
|
1201
|
+
stats = ct();
|
|
1152
1202
|
load(e, n, r) {
|
|
1153
1203
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1154
1204
|
if (!i) {
|
|
@@ -1156,7 +1206,7 @@ function nt(t) {
|
|
|
1156
1206
|
return;
|
|
1157
1207
|
}
|
|
1158
1208
|
this.served = !0;
|
|
1159
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1209
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || rt, s = setTimeout(() => {
|
|
1160
1210
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1161
1211
|
}, o);
|
|
1162
1212
|
i.bytes.then((o) => {
|
|
@@ -1183,7 +1233,7 @@ function nt(t) {
|
|
|
1183
1233
|
}
|
|
1184
1234
|
return r;
|
|
1185
1235
|
}
|
|
1186
|
-
function
|
|
1236
|
+
function ct() {
|
|
1187
1237
|
return {
|
|
1188
1238
|
aborted: !1,
|
|
1189
1239
|
loaded: 0,
|
|
@@ -1207,10 +1257,10 @@ function rt() {
|
|
|
1207
1257
|
}
|
|
1208
1258
|
};
|
|
1209
1259
|
}
|
|
1210
|
-
function
|
|
1260
|
+
function lt(e) {
|
|
1211
1261
|
return e === "audio" ? "audio" : "main";
|
|
1212
1262
|
}
|
|
1213
|
-
function
|
|
1263
|
+
function ut(e, t) {
|
|
1214
1264
|
let n = [];
|
|
1215
1265
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1216
1266
|
url: t.initSegment.url,
|
|
@@ -1229,24 +1279,24 @@ function at(e, t) {
|
|
|
1229
1279
|
}
|
|
1230
1280
|
//#endregion
|
|
1231
1281
|
//#region src/core/engine/hls.ts
|
|
1232
|
-
function
|
|
1282
|
+
function dt() {
|
|
1233
1283
|
return e.isSupported();
|
|
1234
1284
|
}
|
|
1235
|
-
var
|
|
1236
|
-
function
|
|
1285
|
+
var ft = 3, pt = 5, mt = 3, ht = 3e4, gt = 12e3, _t = 3e3, vt = 6e3, yt = .5, bt = 3, xt = .5, St = 1.1, Ct = .25, wt = 5e3, Tt = 4e3, Et = 2, Dt = 5, Ot = 2, kt = 2, At = 4, jt = 4, Mt = 2e3, Nt = 3e4, Pt = .2, Ft = 30, It = 2, Lt = 2, Rt = 9, zt = .5, Bt = 64;
|
|
1286
|
+
function Vt(e) {
|
|
1237
1287
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1238
1288
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1239
1289
|
return;
|
|
1240
1290
|
}
|
|
1241
|
-
e.liveSyncDuration ??=
|
|
1242
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1243
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1291
|
+
e.liveSyncDuration ??= Lt;
|
|
1292
|
+
let t = Math.max(12, e.liveSyncDuration + Rt);
|
|
1293
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Ht(e, e.liveSyncDuration);
|
|
1244
1294
|
}
|
|
1245
|
-
function
|
|
1295
|
+
function Ht(e, t) {
|
|
1246
1296
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1247
1297
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1248
1298
|
}
|
|
1249
|
-
var
|
|
1299
|
+
var Ut = class {
|
|
1250
1300
|
name = "hls";
|
|
1251
1301
|
hls = null;
|
|
1252
1302
|
deps;
|
|
@@ -1336,7 +1386,7 @@ var Rt = class {
|
|
|
1336
1386
|
});
|
|
1337
1387
|
return;
|
|
1338
1388
|
}
|
|
1339
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1389
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), je()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1340
1390
|
let e = this.hls;
|
|
1341
1391
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1342
1392
|
let t = e.liveSyncPosition;
|
|
@@ -1359,7 +1409,7 @@ var Rt = class {
|
|
|
1359
1409
|
}
|
|
1360
1410
|
this.loadSuspended = !0;
|
|
1361
1411
|
}
|
|
1362
|
-
},
|
|
1412
|
+
}, wt));
|
|
1363
1413
|
}
|
|
1364
1414
|
resumeLoading() {
|
|
1365
1415
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1391,7 +1441,7 @@ var Rt = class {
|
|
|
1391
1441
|
let t = e.liveSyncPosition;
|
|
1392
1442
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1393
1443
|
let { video: n } = this.deps;
|
|
1394
|
-
n.currentTime <= t +
|
|
1444
|
+
n.currentTime <= t + zt || (n.currentTime = t);
|
|
1395
1445
|
}
|
|
1396
1446
|
startHls() {
|
|
1397
1447
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1410,12 +1460,12 @@ var Rt = class {
|
|
|
1410
1460
|
emeEnabled: !0,
|
|
1411
1461
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1412
1462
|
drmSystemOptions: {
|
|
1413
|
-
videoRobustness:
|
|
1414
|
-
audioRobustness:
|
|
1415
|
-
videoEncryptionScheme:
|
|
1416
|
-
audioEncryptionScheme:
|
|
1463
|
+
videoRobustness: F.video,
|
|
1464
|
+
audioRobustness: F.audio,
|
|
1465
|
+
videoEncryptionScheme: F.scheme,
|
|
1466
|
+
audioEncryptionScheme: F.scheme
|
|
1417
1467
|
},
|
|
1418
|
-
...
|
|
1468
|
+
...j() ? { requestMediaKeySystemAccessFunc: P(t) } : {},
|
|
1419
1469
|
licenseXhrSetup: (e, t) => {
|
|
1420
1470
|
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;
|
|
1421
1471
|
let o = performance.now();
|
|
@@ -1432,20 +1482,20 @@ var Rt = class {
|
|
|
1432
1482
|
...c
|
|
1433
1483
|
};
|
|
1434
1484
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
|
|
1435
|
-
let e = new
|
|
1485
|
+
let e = new ot({
|
|
1436
1486
|
sessionId: n.analytics?.sid,
|
|
1437
1487
|
contentId: n.matchUrn
|
|
1438
|
-
}), t =
|
|
1488
|
+
}), t = st(e);
|
|
1439
1489
|
t && (this.prefetch = e, d.fLoader = t);
|
|
1440
1490
|
}
|
|
1441
|
-
|
|
1491
|
+
Vt(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;
|
|
1442
1492
|
let f = new e(d);
|
|
1443
1493
|
if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1444
1494
|
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" });
|
|
1445
1495
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1446
1496
|
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(() => {
|
|
1447
1497
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1448
|
-
},
|
|
1498
|
+
}, ht)));
|
|
1449
1499
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1450
1500
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1451
1501
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1453,10 +1503,10 @@ var Rt = class {
|
|
|
1453
1503
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1454
1504
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1455
1505
|
let i = n?.loading;
|
|
1456
|
-
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 >
|
|
1506
|
+
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 > Bt && this.requestTimesMs.shift());
|
|
1457
1507
|
let a = t?.frag?.url;
|
|
1458
1508
|
if (a) {
|
|
1459
|
-
let e =
|
|
1509
|
+
let e = Ge(a);
|
|
1460
1510
|
e && (this.cdnHost = e);
|
|
1461
1511
|
}
|
|
1462
1512
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1470,15 +1520,15 @@ var Rt = class {
|
|
|
1470
1520
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1471
1521
|
let t = this.prefetch;
|
|
1472
1522
|
f.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1473
|
-
let r = n?.frag, i =
|
|
1474
|
-
if (r && t.isActive(i)) for (let e of
|
|
1475
|
-
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1523
|
+
let r = n?.frag, i = lt(r?.type);
|
|
1524
|
+
if (r && t.isActive(i)) for (let e of ut(f, r)) t.prefetch(e.url, i, e.kind);
|
|
1525
|
+
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(lt(n?.frag?.type)));
|
|
1476
1526
|
}
|
|
1477
1527
|
f.on(e.Events.KEY_LOADED, () => {
|
|
1478
1528
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1479
1529
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1480
1530
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1481
|
-
},
|
|
1531
|
+
}, _t), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1482
1532
|
this.renditionSwitches += 1;
|
|
1483
1533
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1484
1534
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1542,7 +1592,7 @@ var Rt = class {
|
|
|
1542
1592
|
return;
|
|
1543
1593
|
}
|
|
1544
1594
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1545
|
-
let t = e > this.sizeCapLevel ?
|
|
1595
|
+
let t = e > this.sizeCapLevel ? Mt : Nt;
|
|
1546
1596
|
this.capTimer = setTimeout(() => {
|
|
1547
1597
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1548
1598
|
}, t);
|
|
@@ -1552,9 +1602,9 @@ var Rt = class {
|
|
|
1552
1602
|
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;
|
|
1553
1603
|
}
|
|
1554
1604
|
dropLevelsWidevineCannotPlay(e) {
|
|
1555
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1556
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1557
|
-
for (let n of t)
|
|
1605
|
+
this.removeLevelsWhere(e, (e) => Me(e) !== !0);
|
|
1606
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
|
|
1607
|
+
for (let n of t) V(n).then((t) => {
|
|
1558
1608
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1559
1609
|
});
|
|
1560
1610
|
}
|
|
@@ -1562,10 +1612,10 @@ var Rt = class {
|
|
|
1562
1612
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1563
1613
|
if (n.forEach((e, n) => {
|
|
1564
1614
|
let a = e.videoCodec;
|
|
1565
|
-
a &&
|
|
1615
|
+
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1566
1616
|
}), !r.length) return !1;
|
|
1567
1617
|
let a = [...i].join(", ");
|
|
1568
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !
|
|
1618
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Me(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1569
1619
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1570
1620
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1571
1621
|
}
|
|
@@ -1615,7 +1665,7 @@ var Rt = class {
|
|
|
1615
1665
|
e.widevine && (this.licenseUrl = e.widevine);
|
|
1616
1666
|
}
|
|
1617
1667
|
getStats() {
|
|
1618
|
-
let e = this.hls, t =
|
|
1668
|
+
let e = this.hls, t = H(this.deps.video), n = {
|
|
1619
1669
|
droppedFrames: t.dropped,
|
|
1620
1670
|
decodedFrames: t.totalFrames,
|
|
1621
1671
|
lowLatency: this.detectedLowLatency,
|
|
@@ -1663,7 +1713,7 @@ var Rt = class {
|
|
|
1663
1713
|
return;
|
|
1664
1714
|
}
|
|
1665
1715
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1666
|
-
!this.chaseSuspended && e >
|
|
1716
|
+
!this.chaseSuspended && e > vt && this.suspendChasing(), e > gt && this.emitEnded("stalled");
|
|
1667
1717
|
}
|
|
1668
1718
|
resetStarvationWindow() {
|
|
1669
1719
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1678,7 +1728,7 @@ var Rt = class {
|
|
|
1678
1728
|
this.resetStarvationWindow();
|
|
1679
1729
|
return;
|
|
1680
1730
|
}
|
|
1681
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1731
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < vt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Tt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = H(t), c = o - s, l = c !== this.starvedFrames;
|
|
1682
1732
|
if (this.starvedFrames = c, !a || l) {
|
|
1683
1733
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1684
1734
|
return;
|
|
@@ -1687,12 +1737,12 @@ var Rt = class {
|
|
|
1687
1737
|
this.resetStarvationWindow();
|
|
1688
1738
|
return;
|
|
1689
1739
|
}
|
|
1690
|
-
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 >
|
|
1740
|
+
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 > At && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= Ot && (this.clearKick(), this.starvationRebuilds < kt)) {
|
|
1691
1741
|
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");
|
|
1692
1742
|
return;
|
|
1693
1743
|
}
|
|
1694
|
-
let u = i && this.starvedTicks >=
|
|
1695
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1744
|
+
let u = i && this.starvedTicks >= Et, d = !i && this.deadTicks >= At && this.recentMainFrags.reduce((e, t) => e + t, 0) >= jt;
|
|
1745
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= Dt))) {
|
|
1696
1746
|
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");
|
|
1697
1747
|
try {
|
|
1698
1748
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1707,7 +1757,7 @@ var Rt = class {
|
|
|
1707
1757
|
let t = e.latency, n = e.targetLatency;
|
|
1708
1758
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1709
1759
|
let r = t - n;
|
|
1710
|
-
!this.catchUpEngaged && r >
|
|
1760
|
+
!this.catchUpEngaged && r > yt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= yt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1711
1761
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1712
1762
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1713
1763
|
}
|
|
@@ -1728,16 +1778,16 @@ var Rt = class {
|
|
|
1728
1778
|
this.resetFrameDropWindow();
|
|
1729
1779
|
return;
|
|
1730
1780
|
}
|
|
1731
|
-
let { totalFrames: n, dropped: r } =
|
|
1732
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
1781
|
+
let { totalFrames: n, dropped: r } = H(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
1782
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Ft || o < 0) {
|
|
1733
1783
|
this.fpsBadTicks = 0;
|
|
1734
1784
|
return;
|
|
1735
1785
|
}
|
|
1736
|
-
if (o <=
|
|
1786
|
+
if (o <= Pt * a) {
|
|
1737
1787
|
this.fpsBadTicks = 0;
|
|
1738
1788
|
return;
|
|
1739
1789
|
}
|
|
1740
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
1790
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < It) return;
|
|
1741
1791
|
this.fpsBadTicks = 0;
|
|
1742
1792
|
let s = e.levels, c = s[e.currentLevel];
|
|
1743
1793
|
if (!c) return;
|
|
@@ -1754,20 +1804,20 @@ var Rt = class {
|
|
|
1754
1804
|
return;
|
|
1755
1805
|
}
|
|
1756
1806
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
1757
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
1807
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(St, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
1758
1808
|
this.resetChaseWindow();
|
|
1759
1809
|
return;
|
|
1760
1810
|
}
|
|
1761
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
1811
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= xt) {
|
|
1762
1812
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
1763
1813
|
return;
|
|
1764
1814
|
}
|
|
1765
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
1815
|
+
if (this.chaseTicks += 1, this.chaseTicks < bt) return;
|
|
1766
1816
|
this.resetChaseWindow();
|
|
1767
1817
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
1768
1818
|
if (!(a > 1)) return;
|
|
1769
1819
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
1770
|
-
s < o +
|
|
1820
|
+
s < o + Ct || (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);
|
|
1771
1821
|
}
|
|
1772
1822
|
suspendChasing() {
|
|
1773
1823
|
let e = this.hls;
|
|
@@ -1812,7 +1862,7 @@ var Rt = class {
|
|
|
1812
1862
|
scheduleLicenseRetry(t) {
|
|
1813
1863
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1814
1864
|
let n = t.response?.code ?? 0;
|
|
1815
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1865
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= mt) return !1;
|
|
1816
1866
|
this.licenseRecoveries += 1;
|
|
1817
1867
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1818
1868
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1844,7 +1894,7 @@ var Rt = class {
|
|
|
1844
1894
|
return;
|
|
1845
1895
|
}
|
|
1846
1896
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1847
|
-
if (this.networkRecoveries <
|
|
1897
|
+
if (this.networkRecoveries < pt) {
|
|
1848
1898
|
this.networkRecoveries += 1;
|
|
1849
1899
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1850
1900
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1861,7 +1911,7 @@ var Rt = class {
|
|
|
1861
1911
|
return;
|
|
1862
1912
|
}
|
|
1863
1913
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1864
|
-
if (this.mediaRecoveries <
|
|
1914
|
+
if (this.mediaRecoveries < ft) {
|
|
1865
1915
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1866
1916
|
return;
|
|
1867
1917
|
}
|
|
@@ -1885,19 +1935,19 @@ var Rt = class {
|
|
|
1885
1935
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1886
1936
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1887
1937
|
}
|
|
1888
|
-
},
|
|
1938
|
+
}, Wt = 15e3, Gt = 6e5, Kt = 3e5, qt = 100, q = 1, Jt = 1e3, Yt = 3e4, Xt = 1e3, Zt = {
|
|
1889
1939
|
inline: "PRESENTATION_INLINE",
|
|
1890
1940
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1891
1941
|
pip: "PRESENTATION_PIP"
|
|
1892
|
-
},
|
|
1942
|
+
}, Qt = {
|
|
1893
1943
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1894
1944
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1895
1945
|
none: "KEY_SYSTEM_NONE"
|
|
1896
1946
|
};
|
|
1897
|
-
function
|
|
1947
|
+
function $t(e, t) {
|
|
1898
1948
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1899
1949
|
}
|
|
1900
|
-
var
|
|
1950
|
+
var en = /* @__PURE__ */ new Set([
|
|
1901
1951
|
"INVALID_URN",
|
|
1902
1952
|
"NOT_FOUND",
|
|
1903
1953
|
"GONE",
|
|
@@ -1917,7 +1967,7 @@ var Yt = /* @__PURE__ */ new Set([
|
|
|
1917
1967
|
ended: "PLAYER_STATE_ENDED",
|
|
1918
1968
|
error: "PLAYER_STATE_ERROR"
|
|
1919
1969
|
};
|
|
1920
|
-
function
|
|
1970
|
+
function tn(e) {
|
|
1921
1971
|
try {
|
|
1922
1972
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1923
1973
|
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);
|
|
@@ -1925,8 +1975,8 @@ function Xt(e) {
|
|
|
1925
1975
|
return;
|
|
1926
1976
|
}
|
|
1927
1977
|
}
|
|
1928
|
-
var
|
|
1929
|
-
function
|
|
1978
|
+
var nn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), rn = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), an = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
1979
|
+
function on(e) {
|
|
1930
1980
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
1931
1981
|
let t;
|
|
1932
1982
|
try {
|
|
@@ -1935,19 +1985,19 @@ function en(e) {
|
|
|
1935
1985
|
} catch {
|
|
1936
1986
|
return;
|
|
1937
1987
|
}
|
|
1938
|
-
if (
|
|
1939
|
-
Y.add(t), g(
|
|
1988
|
+
if (rn.has(t) && !Y.has(t)) {
|
|
1989
|
+
Y.add(t), g(an(new URL(t).origin));
|
|
1940
1990
|
for (let e of X) e.noteCspBlocked();
|
|
1941
1991
|
}
|
|
1942
1992
|
}
|
|
1943
|
-
function
|
|
1993
|
+
function sn(e, t) {
|
|
1944
1994
|
return g(t, e), { disabledReason: t };
|
|
1945
1995
|
}
|
|
1946
|
-
function
|
|
1947
|
-
if (n) return t && !
|
|
1996
|
+
function cn(e, t, n) {
|
|
1997
|
+
if (n) return t && !nn(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
1948
1998
|
if (t) return { endpoint: t };
|
|
1949
|
-
if (t !== void 0) return
|
|
1950
|
-
let r =
|
|
1999
|
+
if (t !== void 0) return sn("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).");
|
|
2000
|
+
let r = tn(e);
|
|
1951
2001
|
if (r) return { endpoint: r };
|
|
1952
2002
|
let i;
|
|
1953
2003
|
try {
|
|
@@ -1955,9 +2005,9 @@ function nn(e, t, n) {
|
|
|
1955
2005
|
} catch {
|
|
1956
2006
|
i = e;
|
|
1957
2007
|
}
|
|
1958
|
-
return
|
|
2008
|
+
return sn(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).`);
|
|
1959
2009
|
}
|
|
1960
|
-
var
|
|
2010
|
+
var ln = class {
|
|
1961
2011
|
opts;
|
|
1962
2012
|
url;
|
|
1963
2013
|
cspKey;
|
|
@@ -2039,8 +2089,8 @@ var rn = class {
|
|
|
2039
2089
|
constructor(e) {
|
|
2040
2090
|
this.opts = {
|
|
2041
2091
|
...e,
|
|
2042
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2043
|
-
idleMs: e.idleMs ??
|
|
2092
|
+
heartbeatMs: e.heartbeatMs ?? Wt,
|
|
2093
|
+
idleMs: e.idleMs ?? Gt
|
|
2044
2094
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2045
2095
|
try {
|
|
2046
2096
|
let e = new URL(this.url);
|
|
@@ -2057,11 +2107,11 @@ var rn = class {
|
|
|
2057
2107
|
sdkVersion: this.opts.sdkVersion,
|
|
2058
2108
|
...this.opts.environment
|
|
2059
2109
|
};
|
|
2060
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2110
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Jt), 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 && rn.add(this.cspKey), document.addEventListener("securitypolicyviolation", on), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2061
2111
|
}
|
|
2062
2112
|
checkSuspension(e) {
|
|
2063
2113
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2064
|
-
let t = Math.max(this.opts.idleMs,
|
|
2114
|
+
let t = Math.max(this.opts.idleMs, Kt);
|
|
2065
2115
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2066
2116
|
}
|
|
2067
2117
|
syncIdle(e) {
|
|
@@ -2084,12 +2134,12 @@ var rn = class {
|
|
|
2084
2134
|
let a = {
|
|
2085
2135
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2086
2136
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2087
|
-
presentation:
|
|
2137
|
+
presentation: Zt[this.presentation]
|
|
2088
2138
|
}, o = this.causeOf(e, t, i);
|
|
2089
2139
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2090
2140
|
}
|
|
2091
2141
|
seekInduced(e) {
|
|
2092
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2142
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < Xt;
|
|
2093
2143
|
}
|
|
2094
2144
|
causeOf(e, t, n) {
|
|
2095
2145
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2163,7 +2213,7 @@ var rn = class {
|
|
|
2163
2213
|
let r = n ?? "";
|
|
2164
2214
|
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";
|
|
2165
2215
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2166
|
-
if (
|
|
2216
|
+
if (en.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2167
2217
|
let i = t ?? "";
|
|
2168
2218
|
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";
|
|
2169
2219
|
}
|
|
@@ -2210,14 +2260,14 @@ var rn = class {
|
|
|
2210
2260
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2211
2261
|
o.requestCountDelta = _;
|
|
2212
2262
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2213
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2263
|
+
n.length > 0 && (o.requestTimeP50Ms = $t(n, 50), o.requestTimeP95Ms = $t(n, 95));
|
|
2214
2264
|
}
|
|
2215
2265
|
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();
|
|
2216
2266
|
}
|
|
2217
2267
|
maybeEmitMediaInfo(e) {
|
|
2218
2268
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2219
2269
|
let t = {};
|
|
2220
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2270
|
+
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);
|
|
2221
2271
|
let n = JSON.stringify(t);
|
|
2222
2272
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2223
2273
|
}
|
|
@@ -2237,7 +2287,7 @@ var rn = class {
|
|
|
2237
2287
|
let c = r?.positionMs ?? 0;
|
|
2238
2288
|
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));
|
|
2239
2289
|
let l = e !== "END_REASON_ENDED";
|
|
2240
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2290
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= Yt && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Yt && (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);
|
|
2241
2291
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2242
2292
|
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");
|
|
2243
2293
|
}
|
|
@@ -2257,13 +2307,13 @@ var rn = class {
|
|
|
2257
2307
|
};
|
|
2258
2308
|
}
|
|
2259
2309
|
noteCspBlocked() {
|
|
2260
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2310
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(an(new URL(this.url).origin)));
|
|
2261
2311
|
}
|
|
2262
2312
|
cspBlocked() {
|
|
2263
2313
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2264
2314
|
}
|
|
2265
2315
|
enqueue(e) {
|
|
2266
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2316
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > qt;) {
|
|
2267
2317
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2268
2318
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2269
2319
|
}
|
|
@@ -2290,7 +2340,7 @@ var rn = class {
|
|
|
2290
2340
|
};
|
|
2291
2341
|
//#endregion
|
|
2292
2342
|
//#region src/core/environment.ts
|
|
2293
|
-
function
|
|
2343
|
+
function un() {
|
|
2294
2344
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2295
2345
|
let e;
|
|
2296
2346
|
try {
|
|
@@ -2315,14 +2365,14 @@ function an() {
|
|
|
2315
2365
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2316
2366
|
};
|
|
2317
2367
|
}
|
|
2318
|
-
function
|
|
2368
|
+
function dn() {
|
|
2319
2369
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2320
2370
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2321
2371
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2322
2372
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2323
2373
|
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";
|
|
2324
2374
|
}
|
|
2325
|
-
function
|
|
2375
|
+
function fn() {
|
|
2326
2376
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2327
2377
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2328
2378
|
let t = {
|
|
@@ -2341,17 +2391,17 @@ function sn() {
|
|
|
2341
2391
|
}
|
|
2342
2392
|
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;
|
|
2343
2393
|
}
|
|
2344
|
-
function
|
|
2345
|
-
let t =
|
|
2346
|
-
deviceClass:
|
|
2394
|
+
function pn(e) {
|
|
2395
|
+
let t = un(), n = {
|
|
2396
|
+
deviceClass: dn(),
|
|
2347
2397
|
integration: t.integration,
|
|
2348
|
-
...
|
|
2398
|
+
...fn()
|
|
2349
2399
|
};
|
|
2350
2400
|
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);
|
|
2351
2401
|
let r = e.getBoundingClientRect?.();
|
|
2352
2402
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2353
2403
|
}
|
|
2354
|
-
async function
|
|
2404
|
+
async function mn() {
|
|
2355
2405
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2356
2406
|
if (!e?.getHighEntropyValues) return {};
|
|
2357
2407
|
try {
|
|
@@ -2363,7 +2413,7 @@ async function ln() {
|
|
|
2363
2413
|
}
|
|
2364
2414
|
//#endregion
|
|
2365
2415
|
//#region src/core/version.ts
|
|
2366
|
-
var
|
|
2416
|
+
var hn = "2.16.2", gn = {
|
|
2367
2417
|
accent: "#E1B600",
|
|
2368
2418
|
accentText: "#1B1C23",
|
|
2369
2419
|
background: "#0e0f13",
|
|
@@ -2374,7 +2424,7 @@ var un = "2.16.0", dn = {
|
|
|
2374
2424
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2375
2425
|
radius: "8px",
|
|
2376
2426
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2377
|
-
},
|
|
2427
|
+
}, _n = {
|
|
2378
2428
|
accent: "--havik-accent",
|
|
2379
2429
|
accentText: "--havik-accent-text",
|
|
2380
2430
|
background: "--havik-bg",
|
|
@@ -2386,26 +2436,26 @@ var un = "2.16.0", dn = {
|
|
|
2386
2436
|
radius: "--havik-radius",
|
|
2387
2437
|
fontFamily: "--havik-font"
|
|
2388
2438
|
};
|
|
2389
|
-
function
|
|
2439
|
+
function vn(e, t) {
|
|
2390
2440
|
let n = {
|
|
2391
|
-
...
|
|
2441
|
+
...gn,
|
|
2392
2442
|
...t
|
|
2393
2443
|
};
|
|
2394
|
-
for (let t of Object.keys(
|
|
2444
|
+
for (let t of Object.keys(_n)) e.style.setProperty(_n[t], n[t]);
|
|
2395
2445
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2396
2446
|
}
|
|
2397
2447
|
//#endregion
|
|
2398
2448
|
//#region src/ui/styles.ts
|
|
2399
|
-
var
|
|
2400
|
-
function
|
|
2401
|
-
let n = e.querySelector(`style#${
|
|
2402
|
-
if (n && (!t ||
|
|
2449
|
+
var yn = "havik-player-styles", bn = "\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", xn = /* @__PURE__ */ new WeakMap();
|
|
2450
|
+
function Sn(e = document, t) {
|
|
2451
|
+
let n = e.querySelector(`style#${yn}`);
|
|
2452
|
+
if (n && (!t || xn.get(n) === t)) return;
|
|
2403
2453
|
let r = e.createElement("style");
|
|
2404
|
-
r.id =
|
|
2454
|
+
r.id = yn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = bn, xn.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2405
2455
|
}
|
|
2406
2456
|
//#endregion
|
|
2407
2457
|
//#region src/ui/icons.ts
|
|
2408
|
-
var
|
|
2458
|
+
var Cn = {
|
|
2409
2459
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2410
2460
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2411
2461
|
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\"/>",
|
|
@@ -2418,21 +2468,21 @@ var _n = {
|
|
|
2418
2468
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
2419
2469
|
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\"/>"
|
|
2420
2470
|
};
|
|
2421
|
-
function
|
|
2422
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2471
|
+
function Z(e) {
|
|
2472
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Cn[e]}</svg>`;
|
|
2423
2473
|
}
|
|
2424
2474
|
//#endregion
|
|
2425
2475
|
//#region src/ui/controls.ts
|
|
2426
|
-
var
|
|
2476
|
+
var wn = 3e3, Tn = 250, En = /* @__PURE__ */ new Set([
|
|
2427
2477
|
"GONE",
|
|
2428
2478
|
"NOT_FOUND",
|
|
2429
2479
|
"INVALID_URN",
|
|
2430
2480
|
"UNAUTHORIZED"
|
|
2431
2481
|
]);
|
|
2432
|
-
function
|
|
2433
|
-
return new
|
|
2482
|
+
function Dn(e) {
|
|
2483
|
+
return new On(e);
|
|
2434
2484
|
}
|
|
2435
|
-
var
|
|
2485
|
+
var On = class {
|
|
2436
2486
|
root;
|
|
2437
2487
|
video;
|
|
2438
2488
|
player;
|
|
@@ -2478,7 +2528,7 @@ var Sn = class {
|
|
|
2478
2528
|
scrubbing = !1;
|
|
2479
2529
|
offFns = [];
|
|
2480
2530
|
constructor(e) {
|
|
2481
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2531
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? wn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, Sn(this.doc, 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");
|
|
2482
2532
|
let t = (e, t, n) => {
|
|
2483
2533
|
let r = this.doc.createElement(e);
|
|
2484
2534
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2489,12 +2539,12 @@ var Sn = class {
|
|
|
2489
2539
|
"aria-label": r,
|
|
2490
2540
|
title: r
|
|
2491
2541
|
});
|
|
2492
|
-
return i.innerHTML =
|
|
2542
|
+
return i.innerHTML = Z(n), i;
|
|
2493
2543
|
};
|
|
2494
2544
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
2495
2545
|
type: "button",
|
|
2496
2546
|
"aria-label": "Play"
|
|
2497
|
-
}), this.center.innerHTML =
|
|
2547
|
+
}), this.center.innerHTML = Z("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
|
|
2498
2548
|
role: "slider",
|
|
2499
2549
|
"aria-label": "Seek",
|
|
2500
2550
|
"aria-valuemin": "0",
|
|
@@ -2512,7 +2562,7 @@ var Sn = class {
|
|
|
2512
2562
|
"aria-label": "Volume"
|
|
2513
2563
|
});
|
|
2514
2564
|
let a = t("div", "havik-vol");
|
|
2515
|
-
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML =
|
|
2565
|
+
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Z("liveDot");
|
|
2516
2566
|
let o = this.doc.createElement("span");
|
|
2517
2567
|
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";
|
|
2518
2568
|
let s = t("div", "havik-spacer");
|
|
@@ -2564,7 +2614,7 @@ var Sn = class {
|
|
|
2564
2614
|
let t = this.surfaceWasHidden;
|
|
2565
2615
|
this.tapTimer = setTimeout(() => {
|
|
2566
2616
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2567
|
-
},
|
|
2617
|
+
}, Tn);
|
|
2568
2618
|
}
|
|
2569
2619
|
toggleBar(e) {
|
|
2570
2620
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2596,12 +2646,12 @@ var Sn = class {
|
|
|
2596
2646
|
}
|
|
2597
2647
|
if (e === "preplay") {
|
|
2598
2648
|
let e = this.doc.createElement("button");
|
|
2599
|
-
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML =
|
|
2649
|
+
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Z("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
|
|
2600
2650
|
} else {
|
|
2601
2651
|
let r = this.doc.createElement("div");
|
|
2602
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2652
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !En.has(this.lastError.code)) {
|
|
2603
2653
|
let e = this.doc.createElement("button");
|
|
2604
|
-
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${
|
|
2654
|
+
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Z("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
2605
2655
|
}
|
|
2606
2656
|
}
|
|
2607
2657
|
this.root.append(n), this.statusBox = n, this.show();
|
|
@@ -2640,7 +2690,7 @@ var Sn = class {
|
|
|
2640
2690
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2641
2691
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2642
2692
|
}
|
|
2643
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2693
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${kn(this.video.currentTime)} / ${kn(this.video.duration)}`);
|
|
2644
2694
|
}
|
|
2645
2695
|
syncLive() {
|
|
2646
2696
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2690,17 +2740,17 @@ var Sn = class {
|
|
|
2690
2740
|
renderQualityMenu() {
|
|
2691
2741
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2692
2742
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2693
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2743
|
+
for (let n of e) this.menu.append(this.menuItem(An(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2694
2744
|
}
|
|
2695
2745
|
renderAudioMenu() {
|
|
2696
2746
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2697
2747
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2698
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2748
|
+
for (let t of e) this.menu.append(this.menuItem(jn(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2699
2749
|
}
|
|
2700
2750
|
renderCcMenu() {
|
|
2701
2751
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2702
2752
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2703
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2753
|
+
for (let t of e) this.menu.append(this.menuItem(Mn(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2704
2754
|
}
|
|
2705
2755
|
onTracksChanged() {
|
|
2706
2756
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2720,11 +2770,11 @@ var Sn = class {
|
|
|
2720
2770
|
}
|
|
2721
2771
|
async toggleFullscreen() {
|
|
2722
2772
|
try {
|
|
2723
|
-
|
|
2773
|
+
S(this.video, this.root) ? await w(this.video, this.root) : await C(this.video, this.root);
|
|
2724
2774
|
} catch {}
|
|
2725
2775
|
}
|
|
2726
2776
|
syncFullscreen() {
|
|
2727
|
-
let e =
|
|
2777
|
+
let e = S(this.video, this.root);
|
|
2728
2778
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
2729
2779
|
}
|
|
2730
2780
|
poke() {
|
|
@@ -2784,7 +2834,7 @@ var Sn = class {
|
|
|
2784
2834
|
}
|
|
2785
2835
|
}
|
|
2786
2836
|
setIcon(e, t) {
|
|
2787
|
-
e.innerHTML =
|
|
2837
|
+
e.innerHTML = Z(t);
|
|
2788
2838
|
}
|
|
2789
2839
|
destroy() {
|
|
2790
2840
|
this.hideTimer && clearTimeout(this.hideTimer), this.tapTimer && clearTimeout(this.tapTimer);
|
|
@@ -2801,41 +2851,41 @@ var Sn = class {
|
|
|
2801
2851
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2802
2852
|
}
|
|
2803
2853
|
};
|
|
2804
|
-
function
|
|
2854
|
+
function kn(e) {
|
|
2805
2855
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2806
2856
|
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");
|
|
2807
2857
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2808
2858
|
}
|
|
2809
|
-
function
|
|
2859
|
+
function An(e) {
|
|
2810
2860
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2811
2861
|
}
|
|
2812
|
-
function
|
|
2862
|
+
function jn(e) {
|
|
2813
2863
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2814
2864
|
}
|
|
2815
|
-
function
|
|
2865
|
+
function Mn(e) {
|
|
2816
2866
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2817
2867
|
}
|
|
2818
2868
|
//#endregion
|
|
2819
2869
|
//#region src/managed/index.ts
|
|
2820
|
-
var
|
|
2821
|
-
function
|
|
2870
|
+
var Nn = 6e3, Pn = 45e3, Q = 2e3, Fn = 3, In = 2e3, Ln = 48e4;
|
|
2871
|
+
function Rn(e) {
|
|
2822
2872
|
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)})`);
|
|
2823
|
-
if (e.env !== void 0) return
|
|
2873
|
+
if (e.env !== void 0) return Ue(e.env);
|
|
2824
2874
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2825
2875
|
return e.baseUrl;
|
|
2826
2876
|
}
|
|
2827
|
-
async function
|
|
2877
|
+
async function zn(e) {
|
|
2828
2878
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2829
|
-
let t =
|
|
2879
|
+
let t = Rn(e);
|
|
2830
2880
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2831
2881
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2832
|
-
let r = new
|
|
2882
|
+
let r = new Bn({
|
|
2833
2883
|
...e,
|
|
2834
2884
|
baseUrl: t
|
|
2835
2885
|
});
|
|
2836
2886
|
return await r.start(), r;
|
|
2837
2887
|
}
|
|
2838
|
-
var
|
|
2888
|
+
var Bn = class {
|
|
2839
2889
|
opts;
|
|
2840
2890
|
abort = new AbortController();
|
|
2841
2891
|
listeners = {};
|
|
@@ -2902,7 +2952,7 @@ var Fn = class {
|
|
|
2902
2952
|
};
|
|
2903
2953
|
}
|
|
2904
2954
|
beginArming(e, t, n = !1) {
|
|
2905
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
2955
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
|
|
2906
2956
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
2907
2957
|
}
|
|
2908
2958
|
beginArmingByPolling(e) {
|
|
@@ -2923,7 +2973,7 @@ var Fn = class {
|
|
|
2923
2973
|
setTimeout(() => {
|
|
2924
2974
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
2925
2975
|
phase: i ? "unavailable" : "tooEarly",
|
|
2926
|
-
retryInMs:
|
|
2976
|
+
retryInMs: Pn,
|
|
2927
2977
|
attempt: 1,
|
|
2928
2978
|
elapsedMs: 0,
|
|
2929
2979
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -2962,13 +3012,13 @@ var Fn = class {
|
|
|
2962
3012
|
!a && !p() && h();
|
|
2963
3013
|
}, e);
|
|
2964
3014
|
};
|
|
2965
|
-
_(
|
|
3015
|
+
_(Nn), this.armingSub = T({
|
|
2966
3016
|
eventsBaseUrl: t,
|
|
2967
3017
|
matchUrn: this.opts.matchUrn,
|
|
2968
3018
|
credential: this.opts.credential,
|
|
2969
|
-
onAlive: () => _(
|
|
3019
|
+
onAlive: () => _(Pn),
|
|
2970
3020
|
onState: (e) => {
|
|
2971
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3021
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Q);
|
|
2972
3022
|
},
|
|
2973
3023
|
onError: () => h()
|
|
2974
3024
|
});
|
|
@@ -2991,7 +3041,7 @@ var Fn = class {
|
|
|
2991
3041
|
let n = await s(this.opts.credential);
|
|
2992
3042
|
if (this.destroyed || t !== this.loadGen) return;
|
|
2993
3043
|
this.setState("loading");
|
|
2994
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3044
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Je(this.opts.video, (e) => {
|
|
2995
3045
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
2996
3046
|
});
|
|
2997
3047
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3013,26 +3063,26 @@ var Fn = class {
|
|
|
3013
3063
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3014
3064
|
let i = e.analytics?.sid;
|
|
3015
3065
|
if (!i) return;
|
|
3016
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3066
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = cn(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3017
3067
|
if (!o) {
|
|
3018
3068
|
s && setTimeout(() => {
|
|
3019
3069
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3020
3070
|
}, 0);
|
|
3021
3071
|
return;
|
|
3022
3072
|
}
|
|
3023
|
-
let c = this.opts.video, l = new
|
|
3073
|
+
let c = this.opts.video, l = new ln({
|
|
3024
3074
|
endpoint: o,
|
|
3025
3075
|
sid: i,
|
|
3026
3076
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3027
|
-
sdkVersion:
|
|
3028
|
-
environment:
|
|
3077
|
+
sdkVersion: hn,
|
|
3078
|
+
environment: pn(c),
|
|
3029
3079
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3030
3080
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3031
3081
|
onBlocked: (e) => setTimeout(() => {
|
|
3032
3082
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3033
3083
|
}, 0),
|
|
3034
3084
|
sample: () => {
|
|
3035
|
-
let e = this.engine?.getStats() ??
|
|
3085
|
+
let e = this.engine?.getStats() ?? We, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3036
3086
|
return {
|
|
3037
3087
|
...e,
|
|
3038
3088
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3046,7 +3096,7 @@ var Fn = class {
|
|
|
3046
3096
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3047
3097
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3048
3098
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3049
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3099
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), mn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3050
3100
|
}
|
|
3051
3101
|
currentPresentation() {
|
|
3052
3102
|
let e = this.opts.video;
|
|
@@ -3061,7 +3111,7 @@ var Fn = class {
|
|
|
3061
3111
|
video: this.opts.video,
|
|
3062
3112
|
descriptor: e,
|
|
3063
3113
|
credential: t,
|
|
3064
|
-
deviceId:
|
|
3114
|
+
deviceId: k(),
|
|
3065
3115
|
userId: this.opts.userId,
|
|
3066
3116
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
3067
3117
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -3072,9 +3122,9 @@ var Fn = class {
|
|
|
3072
3122
|
emit: (e) => this.onEngineEvent(e)
|
|
3073
3123
|
}, o = this.opts.engine ?? "auto";
|
|
3074
3124
|
if (o === "native") return new K(a);
|
|
3075
|
-
if (o === "hls") return new
|
|
3076
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G() || !e.drmEnabled &&
|
|
3077
|
-
if (
|
|
3125
|
+
if (o === "hls") return new Ut(a);
|
|
3126
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G() || !e.drmEnabled && et() && W(this.opts.video)) return new K(a);
|
|
3127
|
+
if (dt()) return new Ut(a);
|
|
3078
3128
|
if (W(this.opts.video)) return new K(a);
|
|
3079
3129
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3080
3130
|
}
|
|
@@ -3112,11 +3162,11 @@ var Fn = class {
|
|
|
3112
3162
|
}
|
|
3113
3163
|
startLiveState(e) {
|
|
3114
3164
|
if (this.opts.liveStateEvents === !1) return;
|
|
3115
|
-
let t = this.opts.eventsBaseUrl ??
|
|
3165
|
+
let t = this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
|
|
3116
3166
|
if (!t) return;
|
|
3117
3167
|
this.closeLiveState();
|
|
3118
3168
|
let r = 0, i = !1;
|
|
3119
|
-
this.liveStateSub =
|
|
3169
|
+
this.liveStateSub = T({
|
|
3120
3170
|
eventsBaseUrl: t,
|
|
3121
3171
|
matchUrn: this.opts.matchUrn,
|
|
3122
3172
|
credential: this.opts.credential,
|
|
@@ -3127,7 +3177,7 @@ var Fn = class {
|
|
|
3127
3177
|
r = 0, i = !1;
|
|
3128
3178
|
},
|
|
3129
3179
|
onError: () => {
|
|
3130
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
3180
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Fn && (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.`))));
|
|
3131
3181
|
}
|
|
3132
3182
|
});
|
|
3133
3183
|
}
|
|
@@ -3149,7 +3199,7 @@ var Fn = class {
|
|
|
3149
3199
|
scheduleRejoin(e) {
|
|
3150
3200
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3151
3201
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3152
|
-
}, Math.random() *
|
|
3202
|
+
}, Math.random() * Q));
|
|
3153
3203
|
}
|
|
3154
3204
|
cancelRejoin() {
|
|
3155
3205
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3173,7 +3223,7 @@ var Fn = class {
|
|
|
3173
3223
|
}
|
|
3174
3224
|
t.controls = !1;
|
|
3175
3225
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3176
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3226
|
+
r && r.insertBefore(n, t), n.appendChild(t), vn(n, this.opts.theme), this.container = n, this.controlBar = Dn({
|
|
3177
3227
|
root: n,
|
|
3178
3228
|
video: t,
|
|
3179
3229
|
player: this,
|
|
@@ -3204,7 +3254,7 @@ var Fn = class {
|
|
|
3204
3254
|
}
|
|
3205
3255
|
startStats() {
|
|
3206
3256
|
this.stopStats();
|
|
3207
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3257
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? In);
|
|
3208
3258
|
this.statsTimer = setInterval(() => {
|
|
3209
3259
|
if (!this.engine) return;
|
|
3210
3260
|
let e = this.engine.getStats();
|
|
@@ -3216,7 +3266,7 @@ var Fn = class {
|
|
|
3216
3266
|
}
|
|
3217
3267
|
scheduleLicenseRefresh() {
|
|
3218
3268
|
this.stopRefresh();
|
|
3219
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3269
|
+
let e = this.opts.licenseRefreshMs ?? Ln;
|
|
3220
3270
|
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3221
3271
|
}
|
|
3222
3272
|
stopRefresh() {
|
|
@@ -3261,7 +3311,7 @@ var Fn = class {
|
|
|
3261
3311
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3262
3312
|
}
|
|
3263
3313
|
getStats() {
|
|
3264
|
-
return this.engine?.getStats() ??
|
|
3314
|
+
return this.engine?.getStats() ?? We;
|
|
3265
3315
|
}
|
|
3266
3316
|
getQualityLevels() {
|
|
3267
3317
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3300,10 +3350,10 @@ var Fn = class {
|
|
|
3300
3350
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
3301
3351
|
}
|
|
3302
3352
|
async enterFullscreen() {
|
|
3303
|
-
return !this.destroyed &&
|
|
3353
|
+
return !this.destroyed && C(this.opts.video, this.container ?? void 0);
|
|
3304
3354
|
}
|
|
3305
3355
|
async exitFullscreen() {
|
|
3306
|
-
await
|
|
3356
|
+
await w(this.opts.video, this.container ?? void 0);
|
|
3307
3357
|
}
|
|
3308
3358
|
retry() {
|
|
3309
3359
|
return this.reload();
|
|
@@ -3371,7 +3421,7 @@ function $(e) {
|
|
|
3371
3421
|
}
|
|
3372
3422
|
//#endregion
|
|
3373
3423
|
//#region src/embed/host.ts
|
|
3374
|
-
function
|
|
3424
|
+
function Vn(e) {
|
|
3375
3425
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3376
3426
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3377
3427
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3430,15 +3480,15 @@ function In(e) {
|
|
|
3430
3480
|
}
|
|
3431
3481
|
//#endregion
|
|
3432
3482
|
//#region src/embed/page.ts
|
|
3433
|
-
var
|
|
3434
|
-
function
|
|
3483
|
+
var Hn = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3484
|
+
function Un(e) {
|
|
3435
3485
|
if (typeof e == "boolean") return e;
|
|
3436
3486
|
if (typeof e == "object" && e) {
|
|
3437
3487
|
let t = e.endpoint;
|
|
3438
3488
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3439
3489
|
}
|
|
3440
3490
|
}
|
|
3441
|
-
function
|
|
3491
|
+
function Wn() {
|
|
3442
3492
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3443
3493
|
if (e) return {
|
|
3444
3494
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3448,7 +3498,7 @@ function zn() {
|
|
|
3448
3498
|
autoplay: e.autoplay ?? !0,
|
|
3449
3499
|
muted: e.muted ?? !0,
|
|
3450
3500
|
waitForLive: e.waitForLive ?? !0,
|
|
3451
|
-
analytics:
|
|
3501
|
+
analytics: Un(e.analytics)
|
|
3452
3502
|
};
|
|
3453
3503
|
let t = new URLSearchParams(location.search);
|
|
3454
3504
|
return {
|
|
@@ -3461,9 +3511,9 @@ function zn() {
|
|
|
3461
3511
|
waitForLive: !0
|
|
3462
3512
|
};
|
|
3463
3513
|
}
|
|
3464
|
-
async function
|
|
3465
|
-
let e =
|
|
3466
|
-
|
|
3514
|
+
async function Gn() {
|
|
3515
|
+
let e = Wn();
|
|
3516
|
+
qn();
|
|
3467
3517
|
let t = document.createElement("video");
|
|
3468
3518
|
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);
|
|
3469
3519
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3518,12 +3568,12 @@ async function Bn() {
|
|
|
3518
3568
|
code: e.code,
|
|
3519
3569
|
message: e.message
|
|
3520
3570
|
})), e.on("autoplayblocked", () => {
|
|
3521
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3571
|
+
i({ type: "oddin:autoplayblocked" }), Kn(t, e);
|
|
3522
3572
|
});
|
|
3523
3573
|
}, s = async (r) => {
|
|
3524
3574
|
a?.destroy(), a = null;
|
|
3525
3575
|
try {
|
|
3526
|
-
let n = await
|
|
3576
|
+
let n = await zn({
|
|
3527
3577
|
video: t,
|
|
3528
3578
|
baseUrl: e.baseUrl,
|
|
3529
3579
|
matchUrn: r,
|
|
@@ -3585,7 +3635,7 @@ async function Bn() {
|
|
|
3585
3635
|
a?.retry();
|
|
3586
3636
|
break;
|
|
3587
3637
|
case "oddin:load":
|
|
3588
|
-
typeof e.matchUrn == "string" &&
|
|
3638
|
+
typeof e.matchUrn == "string" && Hn.test(e.matchUrn) && s(e.matchUrn);
|
|
3589
3639
|
break;
|
|
3590
3640
|
case "oddin:destroy": c();
|
|
3591
3641
|
}
|
|
@@ -3597,18 +3647,18 @@ async function Bn() {
|
|
|
3597
3647
|
protocol: 1
|
|
3598
3648
|
});
|
|
3599
3649
|
}
|
|
3600
|
-
function
|
|
3650
|
+
function Kn(e, t) {
|
|
3601
3651
|
if (document.getElementById("havik-tap")) return;
|
|
3602
3652
|
let n = document.createElement("button");
|
|
3603
3653
|
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", () => {
|
|
3604
3654
|
n.remove(), t.play();
|
|
3605
3655
|
}), document.body.appendChild(n);
|
|
3606
3656
|
}
|
|
3607
|
-
function
|
|
3657
|
+
function qn() {
|
|
3608
3658
|
let e = document.createElement("style");
|
|
3609
3659
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3610
3660
|
}
|
|
3611
3661
|
//#endregion
|
|
3612
|
-
export {
|
|
3662
|
+
export { gn as ODDIN_THEME, n as PlaybackError, vn as applyTheme, Ue as baseUrlForEnv, Gn as bootEmbed, Te as clearDeviceId, zn as createPlayer, E as deriveEventsBaseUrl, ze as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, k as getDeviceId, Ve as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, Vn as mountEmbed, v as pollToLive, b as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
|
|
3613
3663
|
|
|
3614
3664
|
//# sourceMappingURL=index.js.map
|