@oddin-gg/havik-player 2.16.1 → 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 +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +325 -303
- 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,8 +860,8 @@ function qe(e, t) {
|
|
|
860
860
|
}
|
|
861
861
|
//#endregion
|
|
862
862
|
//#region src/core/engine/native.ts
|
|
863
|
-
var
|
|
864
|
-
function
|
|
863
|
+
var Ye = 2e3, Xe = 3, U = 500, Ze = 6e3, Qe = .25;
|
|
864
|
+
function $e(e) {
|
|
865
865
|
try {
|
|
866
866
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
867
867
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -877,7 +877,7 @@ function G() {
|
|
|
877
877
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
878
878
|
return e || t;
|
|
879
879
|
}
|
|
880
|
-
function
|
|
880
|
+
function et() {
|
|
881
881
|
if (typeof navigator > "u" || !G()) return !1;
|
|
882
882
|
let e = navigator.userAgent ?? "";
|
|
883
883
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
@@ -894,6 +894,7 @@ var K = class {
|
|
|
894
894
|
onVisibility = null;
|
|
895
895
|
onPageShow = null;
|
|
896
896
|
hiddenSince = null;
|
|
897
|
+
refocusTimer = null;
|
|
897
898
|
fairplayKeyIV;
|
|
898
899
|
loadStarted;
|
|
899
900
|
preloadTouched = !1;
|
|
@@ -921,7 +922,7 @@ var K = class {
|
|
|
921
922
|
type: "error",
|
|
922
923
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
923
924
|
fatal: !0
|
|
924
|
-
}), 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();
|
|
925
926
|
}
|
|
926
927
|
startLoad() {
|
|
927
928
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -943,7 +944,7 @@ var K = class {
|
|
|
943
944
|
});
|
|
944
945
|
this.onEncrypted = (n) => {
|
|
945
946
|
let i = n;
|
|
946
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
947
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = $e(i.initData), (async () => {
|
|
947
948
|
try {
|
|
948
949
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
949
950
|
initDataTypes: [i.initDataType],
|
|
@@ -1038,11 +1039,11 @@ var K = class {
|
|
|
1038
1039
|
e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
|
|
1039
1040
|
}
|
|
1040
1041
|
getStats() {
|
|
1041
|
-
let e = this.deps.video, t =
|
|
1042
|
+
let e = this.deps.video, t = H(e), n = {
|
|
1042
1043
|
droppedFrames: t.dropped,
|
|
1043
1044
|
decodedFrames: t.totalFrames
|
|
1044
1045
|
};
|
|
1045
|
-
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) {
|
|
1046
1047
|
if (n.isLive = !0, e.seekable.length > 0) {
|
|
1047
1048
|
let t = e.seekable.end(e.seekable.length - 1);
|
|
1048
1049
|
n.atLiveEdge = e.currentTime >= t - 2;
|
|
@@ -1061,27 +1062,48 @@ var K = class {
|
|
|
1061
1062
|
this.deps.snapToLiveOnRefocus === !1 || typeof document > "u" || this.onVisibility || (this.onVisibility = () => {
|
|
1062
1063
|
let e = typeof performance < "u" ? performance.now() : Date.now();
|
|
1063
1064
|
if (document.visibilityState === "hidden") {
|
|
1064
|
-
this.hiddenSince = e;
|
|
1065
|
+
this.hiddenSince = e, this.cancelRefocus();
|
|
1065
1066
|
return;
|
|
1066
1067
|
}
|
|
1067
1068
|
let t = this.hiddenSince;
|
|
1068
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1069
|
+
this.hiddenSince = null, t != null && e - t >= Ye && this.armRefocus();
|
|
1069
1070
|
}, this.onPageShow = (e) => {
|
|
1070
|
-
e.persisted && this.
|
|
1071
|
+
e.persisted && this.armRefocus();
|
|
1071
1072
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
1072
1073
|
}
|
|
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() {
|
|
1074
1092
|
let e = this.deps.video;
|
|
1075
|
-
if (e.duration !== Infinity || e.seekable.length === 0) return;
|
|
1076
|
-
let t = e.seekable.
|
|
1077
|
-
|
|
1078
|
-
|
|
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);
|
|
1079
1101
|
try {
|
|
1080
|
-
e.currentTime =
|
|
1102
|
+
e.currentTime = i;
|
|
1081
1103
|
} catch {}
|
|
1082
1104
|
}
|
|
1083
1105
|
destroy() {
|
|
1084
|
-
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);
|
|
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);
|
|
1085
1107
|
let { video: e } = this.deps;
|
|
1086
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;
|
|
1087
1109
|
try {
|
|
@@ -1093,13 +1115,13 @@ var K = class {
|
|
|
1093
1115
|
} catch {}
|
|
1094
1116
|
}
|
|
1095
1117
|
};
|
|
1096
|
-
function
|
|
1118
|
+
function tt(e, t) {
|
|
1097
1119
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1098
1120
|
}
|
|
1099
1121
|
//#endregion
|
|
1100
1122
|
//#region src/core/engine/prefetch.ts
|
|
1101
|
-
var
|
|
1102
|
-
function
|
|
1123
|
+
var nt = 15e3, rt = 5e3, it = 6;
|
|
1124
|
+
function at(e) {
|
|
1103
1125
|
try {
|
|
1104
1126
|
let t = new URL(e);
|
|
1105
1127
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1107,7 +1129,7 @@ function nt(e) {
|
|
|
1107
1129
|
return e;
|
|
1108
1130
|
}
|
|
1109
1131
|
}
|
|
1110
|
-
var
|
|
1132
|
+
var ot = class {
|
|
1111
1133
|
cmcd;
|
|
1112
1134
|
entries = /* @__PURE__ */ new Map();
|
|
1113
1135
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1130,10 +1152,10 @@ var rt = class {
|
|
|
1130
1152
|
}
|
|
1131
1153
|
prefetch(e, t, n) {
|
|
1132
1154
|
if (!this.isActive(t)) return;
|
|
1133
|
-
let r =
|
|
1155
|
+
let r = at(e);
|
|
1134
1156
|
if (this.entries.has(r)) return;
|
|
1135
1157
|
let i = this.perTrack.get(t) ?? 0;
|
|
1136
|
-
if (i >=
|
|
1158
|
+
if (i >= it) return;
|
|
1137
1159
|
this.perTrack.set(t, i + 1);
|
|
1138
1160
|
let a = new AbortController(), o = {
|
|
1139
1161
|
started: performance.now(),
|
|
@@ -1147,10 +1169,10 @@ var rt = class {
|
|
|
1147
1169
|
signal: a.signal
|
|
1148
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(() => {
|
|
1149
1171
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1150
|
-
},
|
|
1172
|
+
}, nt);
|
|
1151
1173
|
}
|
|
1152
1174
|
take(e) {
|
|
1153
|
-
let t =
|
|
1175
|
+
let t = at(e), n = this.entries.get(t);
|
|
1154
1176
|
return n && this.entries.delete(t), n;
|
|
1155
1177
|
}
|
|
1156
1178
|
destroy() {
|
|
@@ -1170,13 +1192,13 @@ var rt = class {
|
|
|
1170
1192
|
}
|
|
1171
1193
|
}
|
|
1172
1194
|
};
|
|
1173
|
-
function
|
|
1195
|
+
function st(t) {
|
|
1174
1196
|
let n = e.DefaultConfig?.loader;
|
|
1175
1197
|
if (typeof n != "function") return;
|
|
1176
1198
|
class r extends n {
|
|
1177
1199
|
served = !1;
|
|
1178
1200
|
cancelled = !1;
|
|
1179
|
-
stats =
|
|
1201
|
+
stats = ct();
|
|
1180
1202
|
load(e, n, r) {
|
|
1181
1203
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1182
1204
|
if (!i) {
|
|
@@ -1184,7 +1206,7 @@ function it(t) {
|
|
|
1184
1206
|
return;
|
|
1185
1207
|
}
|
|
1186
1208
|
this.served = !0;
|
|
1187
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1209
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || rt, s = setTimeout(() => {
|
|
1188
1210
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1189
1211
|
}, o);
|
|
1190
1212
|
i.bytes.then((o) => {
|
|
@@ -1211,7 +1233,7 @@ function it(t) {
|
|
|
1211
1233
|
}
|
|
1212
1234
|
return r;
|
|
1213
1235
|
}
|
|
1214
|
-
function
|
|
1236
|
+
function ct() {
|
|
1215
1237
|
return {
|
|
1216
1238
|
aborted: !1,
|
|
1217
1239
|
loaded: 0,
|
|
@@ -1235,10 +1257,10 @@ function at() {
|
|
|
1235
1257
|
}
|
|
1236
1258
|
};
|
|
1237
1259
|
}
|
|
1238
|
-
function
|
|
1260
|
+
function lt(e) {
|
|
1239
1261
|
return e === "audio" ? "audio" : "main";
|
|
1240
1262
|
}
|
|
1241
|
-
function
|
|
1263
|
+
function ut(e, t) {
|
|
1242
1264
|
let n = [];
|
|
1243
1265
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1244
1266
|
url: t.initSegment.url,
|
|
@@ -1257,24 +1279,24 @@ function st(e, t) {
|
|
|
1257
1279
|
}
|
|
1258
1280
|
//#endregion
|
|
1259
1281
|
//#region src/core/engine/hls.ts
|
|
1260
|
-
function
|
|
1282
|
+
function dt() {
|
|
1261
1283
|
return e.isSupported();
|
|
1262
1284
|
}
|
|
1263
|
-
var
|
|
1264
|
-
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) {
|
|
1265
1287
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1266
1288
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1267
1289
|
return;
|
|
1268
1290
|
}
|
|
1269
|
-
e.liveSyncDuration ??=
|
|
1270
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1271
|
-
(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);
|
|
1272
1294
|
}
|
|
1273
|
-
function
|
|
1295
|
+
function Ht(e, t) {
|
|
1274
1296
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1275
1297
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1276
1298
|
}
|
|
1277
|
-
var
|
|
1299
|
+
var Ut = class {
|
|
1278
1300
|
name = "hls";
|
|
1279
1301
|
hls = null;
|
|
1280
1302
|
deps;
|
|
@@ -1364,7 +1386,7 @@ var Bt = class {
|
|
|
1364
1386
|
});
|
|
1365
1387
|
return;
|
|
1366
1388
|
}
|
|
1367
|
-
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 = () => {
|
|
1368
1390
|
let e = this.hls;
|
|
1369
1391
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1370
1392
|
let t = e.liveSyncPosition;
|
|
@@ -1387,7 +1409,7 @@ var Bt = class {
|
|
|
1387
1409
|
}
|
|
1388
1410
|
this.loadSuspended = !0;
|
|
1389
1411
|
}
|
|
1390
|
-
},
|
|
1412
|
+
}, wt));
|
|
1391
1413
|
}
|
|
1392
1414
|
resumeLoading() {
|
|
1393
1415
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1419,7 +1441,7 @@ var Bt = class {
|
|
|
1419
1441
|
let t = e.liveSyncPosition;
|
|
1420
1442
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1421
1443
|
let { video: n } = this.deps;
|
|
1422
|
-
n.currentTime <= t +
|
|
1444
|
+
n.currentTime <= t + zt || (n.currentTime = t);
|
|
1423
1445
|
}
|
|
1424
1446
|
startHls() {
|
|
1425
1447
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1438,12 +1460,12 @@ var Bt = class {
|
|
|
1438
1460
|
emeEnabled: !0,
|
|
1439
1461
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1440
1462
|
drmSystemOptions: {
|
|
1441
|
-
videoRobustness:
|
|
1442
|
-
audioRobustness:
|
|
1443
|
-
videoEncryptionScheme:
|
|
1444
|
-
audioEncryptionScheme:
|
|
1463
|
+
videoRobustness: F.video,
|
|
1464
|
+
audioRobustness: F.audio,
|
|
1465
|
+
videoEncryptionScheme: F.scheme,
|
|
1466
|
+
audioEncryptionScheme: F.scheme
|
|
1445
1467
|
},
|
|
1446
|
-
...
|
|
1468
|
+
...j() ? { requestMediaKeySystemAccessFunc: P(t) } : {},
|
|
1447
1469
|
licenseXhrSetup: (e, t) => {
|
|
1448
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;
|
|
1449
1471
|
let o = performance.now();
|
|
@@ -1460,20 +1482,20 @@ var Bt = class {
|
|
|
1460
1482
|
...c
|
|
1461
1483
|
};
|
|
1462
1484
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
|
|
1463
|
-
let e = new
|
|
1485
|
+
let e = new ot({
|
|
1464
1486
|
sessionId: n.analytics?.sid,
|
|
1465
1487
|
contentId: n.matchUrn
|
|
1466
|
-
}), t =
|
|
1488
|
+
}), t = st(e);
|
|
1467
1489
|
t && (this.prefetch = e, d.fLoader = t);
|
|
1468
1490
|
}
|
|
1469
|
-
|
|
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;
|
|
1470
1492
|
let f = new e(d);
|
|
1471
1493
|
if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1472
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" });
|
|
1473
1495
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1474
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(() => {
|
|
1475
1497
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1476
|
-
},
|
|
1498
|
+
}, ht)));
|
|
1477
1499
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1478
1500
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1479
1501
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1481,10 +1503,10 @@ var Bt = class {
|
|
|
1481
1503
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1482
1504
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1483
1505
|
let i = n?.loading;
|
|
1484
|
-
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());
|
|
1485
1507
|
let a = t?.frag?.url;
|
|
1486
1508
|
if (a) {
|
|
1487
|
-
let e =
|
|
1509
|
+
let e = Ge(a);
|
|
1488
1510
|
e && (this.cdnHost = e);
|
|
1489
1511
|
}
|
|
1490
1512
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1498,15 +1520,15 @@ var Bt = class {
|
|
|
1498
1520
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1499
1521
|
let t = this.prefetch;
|
|
1500
1522
|
f.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1501
|
-
let r = n?.frag, i =
|
|
1502
|
-
if (r && t.isActive(i)) for (let e of
|
|
1503
|
-
}), 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)));
|
|
1504
1526
|
}
|
|
1505
1527
|
f.on(e.Events.KEY_LOADED, () => {
|
|
1506
1528
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1507
1529
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1508
1530
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1509
|
-
},
|
|
1531
|
+
}, _t), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1510
1532
|
this.renditionSwitches += 1;
|
|
1511
1533
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1512
1534
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1570,7 +1592,7 @@ var Bt = class {
|
|
|
1570
1592
|
return;
|
|
1571
1593
|
}
|
|
1572
1594
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1573
|
-
let t = e > this.sizeCapLevel ?
|
|
1595
|
+
let t = e > this.sizeCapLevel ? Mt : Nt;
|
|
1574
1596
|
this.capTimer = setTimeout(() => {
|
|
1575
1597
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1576
1598
|
}, t);
|
|
@@ -1580,9 +1602,9 @@ var Bt = class {
|
|
|
1580
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;
|
|
1581
1603
|
}
|
|
1582
1604
|
dropLevelsWidevineCannotPlay(e) {
|
|
1583
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1584
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1585
|
-
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) => {
|
|
1586
1608
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1587
1609
|
});
|
|
1588
1610
|
}
|
|
@@ -1590,10 +1612,10 @@ var Bt = class {
|
|
|
1590
1612
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1591
1613
|
if (n.forEach((e, n) => {
|
|
1592
1614
|
let a = e.videoCodec;
|
|
1593
|
-
a &&
|
|
1615
|
+
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1594
1616
|
}), !r.length) return !1;
|
|
1595
1617
|
let a = [...i].join(", ");
|
|
1596
|
-
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;
|
|
1597
1619
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1598
1620
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1599
1621
|
}
|
|
@@ -1643,7 +1665,7 @@ var Bt = class {
|
|
|
1643
1665
|
e.widevine && (this.licenseUrl = e.widevine);
|
|
1644
1666
|
}
|
|
1645
1667
|
getStats() {
|
|
1646
|
-
let e = this.hls, t =
|
|
1668
|
+
let e = this.hls, t = H(this.deps.video), n = {
|
|
1647
1669
|
droppedFrames: t.dropped,
|
|
1648
1670
|
decodedFrames: t.totalFrames,
|
|
1649
1671
|
lowLatency: this.detectedLowLatency,
|
|
@@ -1691,7 +1713,7 @@ var Bt = class {
|
|
|
1691
1713
|
return;
|
|
1692
1714
|
}
|
|
1693
1715
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1694
|
-
!this.chaseSuspended && e >
|
|
1716
|
+
!this.chaseSuspended && e > vt && this.suspendChasing(), e > gt && this.emitEnded("stalled");
|
|
1695
1717
|
}
|
|
1696
1718
|
resetStarvationWindow() {
|
|
1697
1719
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1706,7 +1728,7 @@ var Bt = class {
|
|
|
1706
1728
|
this.resetStarvationWindow();
|
|
1707
1729
|
return;
|
|
1708
1730
|
}
|
|
1709
|
-
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;
|
|
1710
1732
|
if (this.starvedFrames = c, !a || l) {
|
|
1711
1733
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1712
1734
|
return;
|
|
@@ -1715,12 +1737,12 @@ var Bt = class {
|
|
|
1715
1737
|
this.resetStarvationWindow();
|
|
1716
1738
|
return;
|
|
1717
1739
|
}
|
|
1718
|
-
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)) {
|
|
1719
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");
|
|
1720
1742
|
return;
|
|
1721
1743
|
}
|
|
1722
|
-
let u = i && this.starvedTicks >=
|
|
1723
|
-
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))) {
|
|
1724
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");
|
|
1725
1747
|
try {
|
|
1726
1748
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1735,7 +1757,7 @@ var Bt = class {
|
|
|
1735
1757
|
let t = e.latency, n = e.targetLatency;
|
|
1736
1758
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1737
1759
|
let r = t - n;
|
|
1738
|
-
!this.catchUpEngaged && r >
|
|
1760
|
+
!this.catchUpEngaged && r > yt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= yt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1739
1761
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1740
1762
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1741
1763
|
}
|
|
@@ -1756,16 +1778,16 @@ var Bt = class {
|
|
|
1756
1778
|
this.resetFrameDropWindow();
|
|
1757
1779
|
return;
|
|
1758
1780
|
}
|
|
1759
|
-
let { totalFrames: n, dropped: r } =
|
|
1760
|
-
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) {
|
|
1761
1783
|
this.fpsBadTicks = 0;
|
|
1762
1784
|
return;
|
|
1763
1785
|
}
|
|
1764
|
-
if (o <=
|
|
1786
|
+
if (o <= Pt * a) {
|
|
1765
1787
|
this.fpsBadTicks = 0;
|
|
1766
1788
|
return;
|
|
1767
1789
|
}
|
|
1768
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
1790
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < It) return;
|
|
1769
1791
|
this.fpsBadTicks = 0;
|
|
1770
1792
|
let s = e.levels, c = s[e.currentLevel];
|
|
1771
1793
|
if (!c) return;
|
|
@@ -1782,20 +1804,20 @@ var Bt = class {
|
|
|
1782
1804
|
return;
|
|
1783
1805
|
}
|
|
1784
1806
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
1785
|
-
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))) {
|
|
1786
1808
|
this.resetChaseWindow();
|
|
1787
1809
|
return;
|
|
1788
1810
|
}
|
|
1789
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
1811
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= xt) {
|
|
1790
1812
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
1791
1813
|
return;
|
|
1792
1814
|
}
|
|
1793
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
1815
|
+
if (this.chaseTicks += 1, this.chaseTicks < bt) return;
|
|
1794
1816
|
this.resetChaseWindow();
|
|
1795
1817
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
1796
1818
|
if (!(a > 1)) return;
|
|
1797
1819
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
1798
|
-
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);
|
|
1799
1821
|
}
|
|
1800
1822
|
suspendChasing() {
|
|
1801
1823
|
let e = this.hls;
|
|
@@ -1840,7 +1862,7 @@ var Bt = class {
|
|
|
1840
1862
|
scheduleLicenseRetry(t) {
|
|
1841
1863
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1842
1864
|
let n = t.response?.code ?? 0;
|
|
1843
|
-
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;
|
|
1844
1866
|
this.licenseRecoveries += 1;
|
|
1845
1867
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1846
1868
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1872,7 +1894,7 @@ var Bt = class {
|
|
|
1872
1894
|
return;
|
|
1873
1895
|
}
|
|
1874
1896
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1875
|
-
if (this.networkRecoveries <
|
|
1897
|
+
if (this.networkRecoveries < pt) {
|
|
1876
1898
|
this.networkRecoveries += 1;
|
|
1877
1899
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1878
1900
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1889,7 +1911,7 @@ var Bt = class {
|
|
|
1889
1911
|
return;
|
|
1890
1912
|
}
|
|
1891
1913
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1892
|
-
if (this.mediaRecoveries <
|
|
1914
|
+
if (this.mediaRecoveries < ft) {
|
|
1893
1915
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1894
1916
|
return;
|
|
1895
1917
|
}
|
|
@@ -1913,19 +1935,19 @@ var Bt = class {
|
|
|
1913
1935
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1914
1936
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1915
1937
|
}
|
|
1916
|
-
},
|
|
1938
|
+
}, Wt = 15e3, Gt = 6e5, Kt = 3e5, qt = 100, q = 1, Jt = 1e3, Yt = 3e4, Xt = 1e3, Zt = {
|
|
1917
1939
|
inline: "PRESENTATION_INLINE",
|
|
1918
1940
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1919
1941
|
pip: "PRESENTATION_PIP"
|
|
1920
|
-
},
|
|
1942
|
+
}, Qt = {
|
|
1921
1943
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1922
1944
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1923
1945
|
none: "KEY_SYSTEM_NONE"
|
|
1924
1946
|
};
|
|
1925
|
-
function
|
|
1947
|
+
function $t(e, t) {
|
|
1926
1948
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1927
1949
|
}
|
|
1928
|
-
var
|
|
1950
|
+
var en = /* @__PURE__ */ new Set([
|
|
1929
1951
|
"INVALID_URN",
|
|
1930
1952
|
"NOT_FOUND",
|
|
1931
1953
|
"GONE",
|
|
@@ -1945,7 +1967,7 @@ var Zt = /* @__PURE__ */ new Set([
|
|
|
1945
1967
|
ended: "PLAYER_STATE_ENDED",
|
|
1946
1968
|
error: "PLAYER_STATE_ERROR"
|
|
1947
1969
|
};
|
|
1948
|
-
function
|
|
1970
|
+
function tn(e) {
|
|
1949
1971
|
try {
|
|
1950
1972
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1951
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);
|
|
@@ -1953,8 +1975,8 @@ function Qt(e) {
|
|
|
1953
1975
|
return;
|
|
1954
1976
|
}
|
|
1955
1977
|
}
|
|
1956
|
-
var
|
|
1957
|
-
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) {
|
|
1958
1980
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
1959
1981
|
let t;
|
|
1960
1982
|
try {
|
|
@@ -1963,19 +1985,19 @@ function nn(e) {
|
|
|
1963
1985
|
} catch {
|
|
1964
1986
|
return;
|
|
1965
1987
|
}
|
|
1966
|
-
if (
|
|
1967
|
-
Y.add(t), g(
|
|
1988
|
+
if (rn.has(t) && !Y.has(t)) {
|
|
1989
|
+
Y.add(t), g(an(new URL(t).origin));
|
|
1968
1990
|
for (let e of X) e.noteCspBlocked();
|
|
1969
1991
|
}
|
|
1970
1992
|
}
|
|
1971
|
-
function
|
|
1993
|
+
function sn(e, t) {
|
|
1972
1994
|
return g(t, e), { disabledReason: t };
|
|
1973
1995
|
}
|
|
1974
|
-
function
|
|
1975
|
-
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 };
|
|
1976
1998
|
if (t) return { endpoint: t };
|
|
1977
|
-
if (t !== void 0) return
|
|
1978
|
-
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);
|
|
1979
2001
|
if (r) return { endpoint: r };
|
|
1980
2002
|
let i;
|
|
1981
2003
|
try {
|
|
@@ -1983,9 +2005,9 @@ function an(e, t, n) {
|
|
|
1983
2005
|
} catch {
|
|
1984
2006
|
i = e;
|
|
1985
2007
|
}
|
|
1986
|
-
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).`);
|
|
1987
2009
|
}
|
|
1988
|
-
var
|
|
2010
|
+
var ln = class {
|
|
1989
2011
|
opts;
|
|
1990
2012
|
url;
|
|
1991
2013
|
cspKey;
|
|
@@ -2067,8 +2089,8 @@ var on = class {
|
|
|
2067
2089
|
constructor(e) {
|
|
2068
2090
|
this.opts = {
|
|
2069
2091
|
...e,
|
|
2070
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2071
|
-
idleMs: e.idleMs ??
|
|
2092
|
+
heartbeatMs: e.heartbeatMs ?? Wt,
|
|
2093
|
+
idleMs: e.idleMs ?? Gt
|
|
2072
2094
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2073
2095
|
try {
|
|
2074
2096
|
let e = new URL(this.url);
|
|
@@ -2085,11 +2107,11 @@ var on = class {
|
|
|
2085
2107
|
sdkVersion: this.opts.sdkVersion,
|
|
2086
2108
|
...this.opts.environment
|
|
2087
2109
|
};
|
|
2088
|
-
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());
|
|
2089
2111
|
}
|
|
2090
2112
|
checkSuspension(e) {
|
|
2091
2113
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2092
|
-
let t = Math.max(this.opts.idleMs,
|
|
2114
|
+
let t = Math.max(this.opts.idleMs, Kt);
|
|
2093
2115
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2094
2116
|
}
|
|
2095
2117
|
syncIdle(e) {
|
|
@@ -2112,12 +2134,12 @@ var on = class {
|
|
|
2112
2134
|
let a = {
|
|
2113
2135
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2114
2136
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2115
|
-
presentation:
|
|
2137
|
+
presentation: Zt[this.presentation]
|
|
2116
2138
|
}, o = this.causeOf(e, t, i);
|
|
2117
2139
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2118
2140
|
}
|
|
2119
2141
|
seekInduced(e) {
|
|
2120
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2142
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < Xt;
|
|
2121
2143
|
}
|
|
2122
2144
|
causeOf(e, t, n) {
|
|
2123
2145
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2191,7 +2213,7 @@ var on = class {
|
|
|
2191
2213
|
let r = n ?? "";
|
|
2192
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";
|
|
2193
2215
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2194
|
-
if (
|
|
2216
|
+
if (en.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2195
2217
|
let i = t ?? "";
|
|
2196
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";
|
|
2197
2219
|
}
|
|
@@ -2238,14 +2260,14 @@ var on = class {
|
|
|
2238
2260
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2239
2261
|
o.requestCountDelta = _;
|
|
2240
2262
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2241
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2263
|
+
n.length > 0 && (o.requestTimeP50Ms = $t(n, 50), o.requestTimeP95Ms = $t(n, 95));
|
|
2242
2264
|
}
|
|
2243
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();
|
|
2244
2266
|
}
|
|
2245
2267
|
maybeEmitMediaInfo(e) {
|
|
2246
2268
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2247
2269
|
let t = {};
|
|
2248
|
-
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);
|
|
2249
2271
|
let n = JSON.stringify(t);
|
|
2250
2272
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2251
2273
|
}
|
|
@@ -2265,7 +2287,7 @@ var on = class {
|
|
|
2265
2287
|
let c = r?.positionMs ?? 0;
|
|
2266
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));
|
|
2267
2289
|
let l = e !== "END_REASON_ENDED";
|
|
2268
|
-
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);
|
|
2269
2291
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2270
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");
|
|
2271
2293
|
}
|
|
@@ -2285,13 +2307,13 @@ var on = class {
|
|
|
2285
2307
|
};
|
|
2286
2308
|
}
|
|
2287
2309
|
noteCspBlocked() {
|
|
2288
|
-
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)));
|
|
2289
2311
|
}
|
|
2290
2312
|
cspBlocked() {
|
|
2291
2313
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2292
2314
|
}
|
|
2293
2315
|
enqueue(e) {
|
|
2294
|
-
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;) {
|
|
2295
2317
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2296
2318
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2297
2319
|
}
|
|
@@ -2318,7 +2340,7 @@ var on = class {
|
|
|
2318
2340
|
};
|
|
2319
2341
|
//#endregion
|
|
2320
2342
|
//#region src/core/environment.ts
|
|
2321
|
-
function
|
|
2343
|
+
function un() {
|
|
2322
2344
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2323
2345
|
let e;
|
|
2324
2346
|
try {
|
|
@@ -2343,14 +2365,14 @@ function sn() {
|
|
|
2343
2365
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2344
2366
|
};
|
|
2345
2367
|
}
|
|
2346
|
-
function
|
|
2368
|
+
function dn() {
|
|
2347
2369
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2348
2370
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2349
2371
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2350
2372
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2351
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";
|
|
2352
2374
|
}
|
|
2353
|
-
function
|
|
2375
|
+
function fn() {
|
|
2354
2376
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2355
2377
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2356
2378
|
let t = {
|
|
@@ -2369,17 +2391,17 @@ function ln() {
|
|
|
2369
2391
|
}
|
|
2370
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;
|
|
2371
2393
|
}
|
|
2372
|
-
function
|
|
2373
|
-
let t =
|
|
2374
|
-
deviceClass:
|
|
2394
|
+
function pn(e) {
|
|
2395
|
+
let t = un(), n = {
|
|
2396
|
+
deviceClass: dn(),
|
|
2375
2397
|
integration: t.integration,
|
|
2376
|
-
...
|
|
2398
|
+
...fn()
|
|
2377
2399
|
};
|
|
2378
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);
|
|
2379
2401
|
let r = e.getBoundingClientRect?.();
|
|
2380
2402
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2381
2403
|
}
|
|
2382
|
-
async function
|
|
2404
|
+
async function mn() {
|
|
2383
2405
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2384
2406
|
if (!e?.getHighEntropyValues) return {};
|
|
2385
2407
|
try {
|
|
@@ -2391,7 +2413,7 @@ async function dn() {
|
|
|
2391
2413
|
}
|
|
2392
2414
|
//#endregion
|
|
2393
2415
|
//#region src/core/version.ts
|
|
2394
|
-
var
|
|
2416
|
+
var hn = "2.16.2", gn = {
|
|
2395
2417
|
accent: "#E1B600",
|
|
2396
2418
|
accentText: "#1B1C23",
|
|
2397
2419
|
background: "#0e0f13",
|
|
@@ -2402,7 +2424,7 @@ var fn = "2.16.1", pn = {
|
|
|
2402
2424
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2403
2425
|
radius: "8px",
|
|
2404
2426
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2405
|
-
},
|
|
2427
|
+
}, _n = {
|
|
2406
2428
|
accent: "--havik-accent",
|
|
2407
2429
|
accentText: "--havik-accent-text",
|
|
2408
2430
|
background: "--havik-bg",
|
|
@@ -2414,26 +2436,26 @@ var fn = "2.16.1", pn = {
|
|
|
2414
2436
|
radius: "--havik-radius",
|
|
2415
2437
|
fontFamily: "--havik-font"
|
|
2416
2438
|
};
|
|
2417
|
-
function
|
|
2439
|
+
function vn(e, t) {
|
|
2418
2440
|
let n = {
|
|
2419
|
-
...
|
|
2441
|
+
...gn,
|
|
2420
2442
|
...t
|
|
2421
2443
|
};
|
|
2422
|
-
for (let t of Object.keys(
|
|
2444
|
+
for (let t of Object.keys(_n)) e.style.setProperty(_n[t], n[t]);
|
|
2423
2445
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2424
2446
|
}
|
|
2425
2447
|
//#endregion
|
|
2426
2448
|
//#region src/ui/styles.ts
|
|
2427
|
-
var
|
|
2428
|
-
function
|
|
2429
|
-
let n = e.querySelector(`style#${
|
|
2430
|
-
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;
|
|
2431
2453
|
let r = e.createElement("style");
|
|
2432
|
-
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);
|
|
2433
2455
|
}
|
|
2434
2456
|
//#endregion
|
|
2435
2457
|
//#region src/ui/icons.ts
|
|
2436
|
-
var
|
|
2458
|
+
var Cn = {
|
|
2437
2459
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2438
2460
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2439
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\"/>",
|
|
@@ -2446,21 +2468,21 @@ var yn = {
|
|
|
2446
2468
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
2447
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\"/>"
|
|
2448
2470
|
};
|
|
2449
|
-
function
|
|
2450
|
-
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>`;
|
|
2451
2473
|
}
|
|
2452
2474
|
//#endregion
|
|
2453
2475
|
//#region src/ui/controls.ts
|
|
2454
|
-
var
|
|
2476
|
+
var wn = 3e3, Tn = 250, En = /* @__PURE__ */ new Set([
|
|
2455
2477
|
"GONE",
|
|
2456
2478
|
"NOT_FOUND",
|
|
2457
2479
|
"INVALID_URN",
|
|
2458
2480
|
"UNAUTHORIZED"
|
|
2459
2481
|
]);
|
|
2460
|
-
function
|
|
2461
|
-
return new
|
|
2482
|
+
function Dn(e) {
|
|
2483
|
+
return new On(e);
|
|
2462
2484
|
}
|
|
2463
|
-
var
|
|
2485
|
+
var On = class {
|
|
2464
2486
|
root;
|
|
2465
2487
|
video;
|
|
2466
2488
|
player;
|
|
@@ -2506,7 +2528,7 @@ var wn = class {
|
|
|
2506
2528
|
scrubbing = !1;
|
|
2507
2529
|
offFns = [];
|
|
2508
2530
|
constructor(e) {
|
|
2509
|
-
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");
|
|
2510
2532
|
let t = (e, t, n) => {
|
|
2511
2533
|
let r = this.doc.createElement(e);
|
|
2512
2534
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2517,12 +2539,12 @@ var wn = class {
|
|
|
2517
2539
|
"aria-label": r,
|
|
2518
2540
|
title: r
|
|
2519
2541
|
});
|
|
2520
|
-
return i.innerHTML =
|
|
2542
|
+
return i.innerHTML = Z(n), i;
|
|
2521
2543
|
};
|
|
2522
2544
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
2523
2545
|
type: "button",
|
|
2524
2546
|
"aria-label": "Play"
|
|
2525
|
-
}), 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", {
|
|
2526
2548
|
role: "slider",
|
|
2527
2549
|
"aria-label": "Seek",
|
|
2528
2550
|
"aria-valuemin": "0",
|
|
@@ -2540,7 +2562,7 @@ var wn = class {
|
|
|
2540
2562
|
"aria-label": "Volume"
|
|
2541
2563
|
});
|
|
2542
2564
|
let a = t("div", "havik-vol");
|
|
2543
|
-
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");
|
|
2544
2566
|
let o = this.doc.createElement("span");
|
|
2545
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";
|
|
2546
2568
|
let s = t("div", "havik-spacer");
|
|
@@ -2592,7 +2614,7 @@ var wn = class {
|
|
|
2592
2614
|
let t = this.surfaceWasHidden;
|
|
2593
2615
|
this.tapTimer = setTimeout(() => {
|
|
2594
2616
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2595
|
-
},
|
|
2617
|
+
}, Tn);
|
|
2596
2618
|
}
|
|
2597
2619
|
toggleBar(e) {
|
|
2598
2620
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2624,12 +2646,12 @@ var wn = class {
|
|
|
2624
2646
|
}
|
|
2625
2647
|
if (e === "preplay") {
|
|
2626
2648
|
let e = this.doc.createElement("button");
|
|
2627
|
-
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);
|
|
2628
2650
|
} else {
|
|
2629
2651
|
let r = this.doc.createElement("div");
|
|
2630
|
-
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)) {
|
|
2631
2653
|
let e = this.doc.createElement("button");
|
|
2632
|
-
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);
|
|
2633
2655
|
}
|
|
2634
2656
|
}
|
|
2635
2657
|
this.root.append(n), this.statusBox = n, this.show();
|
|
@@ -2668,7 +2690,7 @@ var wn = class {
|
|
|
2668
2690
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2669
2691
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2670
2692
|
}
|
|
2671
|
-
!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)}`);
|
|
2672
2694
|
}
|
|
2673
2695
|
syncLive() {
|
|
2674
2696
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2718,17 +2740,17 @@ var wn = class {
|
|
|
2718
2740
|
renderQualityMenu() {
|
|
2719
2741
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2720
2742
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2721
|
-
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)));
|
|
2722
2744
|
}
|
|
2723
2745
|
renderAudioMenu() {
|
|
2724
2746
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2725
2747
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2726
|
-
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)));
|
|
2727
2749
|
}
|
|
2728
2750
|
renderCcMenu() {
|
|
2729
2751
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2730
2752
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2731
|
-
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)));
|
|
2732
2754
|
}
|
|
2733
2755
|
onTracksChanged() {
|
|
2734
2756
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2748,11 +2770,11 @@ var wn = class {
|
|
|
2748
2770
|
}
|
|
2749
2771
|
async toggleFullscreen() {
|
|
2750
2772
|
try {
|
|
2751
|
-
|
|
2773
|
+
S(this.video, this.root) ? await w(this.video, this.root) : await C(this.video, this.root);
|
|
2752
2774
|
} catch {}
|
|
2753
2775
|
}
|
|
2754
2776
|
syncFullscreen() {
|
|
2755
|
-
let e =
|
|
2777
|
+
let e = S(this.video, this.root);
|
|
2756
2778
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
2757
2779
|
}
|
|
2758
2780
|
poke() {
|
|
@@ -2812,7 +2834,7 @@ var wn = class {
|
|
|
2812
2834
|
}
|
|
2813
2835
|
}
|
|
2814
2836
|
setIcon(e, t) {
|
|
2815
|
-
e.innerHTML =
|
|
2837
|
+
e.innerHTML = Z(t);
|
|
2816
2838
|
}
|
|
2817
2839
|
destroy() {
|
|
2818
2840
|
this.hideTimer && clearTimeout(this.hideTimer), this.tapTimer && clearTimeout(this.tapTimer);
|
|
@@ -2829,41 +2851,41 @@ var wn = class {
|
|
|
2829
2851
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2830
2852
|
}
|
|
2831
2853
|
};
|
|
2832
|
-
function
|
|
2854
|
+
function kn(e) {
|
|
2833
2855
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2834
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");
|
|
2835
2857
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2836
2858
|
}
|
|
2837
|
-
function
|
|
2859
|
+
function An(e) {
|
|
2838
2860
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2839
2861
|
}
|
|
2840
|
-
function
|
|
2862
|
+
function jn(e) {
|
|
2841
2863
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2842
2864
|
}
|
|
2843
|
-
function
|
|
2865
|
+
function Mn(e) {
|
|
2844
2866
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2845
2867
|
}
|
|
2846
2868
|
//#endregion
|
|
2847
2869
|
//#region src/managed/index.ts
|
|
2848
|
-
var
|
|
2849
|
-
function
|
|
2870
|
+
var Nn = 6e3, Pn = 45e3, Q = 2e3, Fn = 3, In = 2e3, Ln = 48e4;
|
|
2871
|
+
function Rn(e) {
|
|
2850
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)})`);
|
|
2851
|
-
if (e.env !== void 0) return
|
|
2873
|
+
if (e.env !== void 0) return Ue(e.env);
|
|
2852
2874
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2853
2875
|
return e.baseUrl;
|
|
2854
2876
|
}
|
|
2855
|
-
async function
|
|
2877
|
+
async function zn(e) {
|
|
2856
2878
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2857
|
-
let t =
|
|
2879
|
+
let t = Rn(e);
|
|
2858
2880
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2859
2881
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2860
|
-
let r = new
|
|
2882
|
+
let r = new Bn({
|
|
2861
2883
|
...e,
|
|
2862
2884
|
baseUrl: t
|
|
2863
2885
|
});
|
|
2864
2886
|
return await r.start(), r;
|
|
2865
2887
|
}
|
|
2866
|
-
var
|
|
2888
|
+
var Bn = class {
|
|
2867
2889
|
opts;
|
|
2868
2890
|
abort = new AbortController();
|
|
2869
2891
|
listeners = {};
|
|
@@ -2930,7 +2952,7 @@ var Ln = class {
|
|
|
2930
2952
|
};
|
|
2931
2953
|
}
|
|
2932
2954
|
beginArming(e, t, n = !1) {
|
|
2933
|
-
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);
|
|
2934
2956
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
2935
2957
|
}
|
|
2936
2958
|
beginArmingByPolling(e) {
|
|
@@ -2951,7 +2973,7 @@ var Ln = class {
|
|
|
2951
2973
|
setTimeout(() => {
|
|
2952
2974
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
2953
2975
|
phase: i ? "unavailable" : "tooEarly",
|
|
2954
|
-
retryInMs:
|
|
2976
|
+
retryInMs: Pn,
|
|
2955
2977
|
attempt: 1,
|
|
2956
2978
|
elapsedMs: 0,
|
|
2957
2979
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -2990,13 +3012,13 @@ var Ln = class {
|
|
|
2990
3012
|
!a && !p() && h();
|
|
2991
3013
|
}, e);
|
|
2992
3014
|
};
|
|
2993
|
-
_(
|
|
3015
|
+
_(Nn), this.armingSub = T({
|
|
2994
3016
|
eventsBaseUrl: t,
|
|
2995
3017
|
matchUrn: this.opts.matchUrn,
|
|
2996
3018
|
credential: this.opts.credential,
|
|
2997
|
-
onAlive: () => _(
|
|
3019
|
+
onAlive: () => _(Pn),
|
|
2998
3020
|
onState: (e) => {
|
|
2999
|
-
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);
|
|
3000
3022
|
},
|
|
3001
3023
|
onError: () => h()
|
|
3002
3024
|
});
|
|
@@ -3019,7 +3041,7 @@ var Ln = class {
|
|
|
3019
3041
|
let n = await s(this.opts.credential);
|
|
3020
3042
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3021
3043
|
this.setState("loading");
|
|
3022
|
-
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) => {
|
|
3023
3045
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3024
3046
|
});
|
|
3025
3047
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3041,26 +3063,26 @@ var Ln = class {
|
|
|
3041
3063
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3042
3064
|
let i = e.analytics?.sid;
|
|
3043
3065
|
if (!i) return;
|
|
3044
|
-
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);
|
|
3045
3067
|
if (!o) {
|
|
3046
3068
|
s && setTimeout(() => {
|
|
3047
3069
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3048
3070
|
}, 0);
|
|
3049
3071
|
return;
|
|
3050
3072
|
}
|
|
3051
|
-
let c = this.opts.video, l = new
|
|
3073
|
+
let c = this.opts.video, l = new ln({
|
|
3052
3074
|
endpoint: o,
|
|
3053
3075
|
sid: i,
|
|
3054
3076
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3055
|
-
sdkVersion:
|
|
3056
|
-
environment:
|
|
3077
|
+
sdkVersion: hn,
|
|
3078
|
+
environment: pn(c),
|
|
3057
3079
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3058
3080
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3059
3081
|
onBlocked: (e) => setTimeout(() => {
|
|
3060
3082
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3061
3083
|
}, 0),
|
|
3062
3084
|
sample: () => {
|
|
3063
|
-
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;
|
|
3064
3086
|
return {
|
|
3065
3087
|
...e,
|
|
3066
3088
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3074,7 +3096,7 @@ var Ln = class {
|
|
|
3074
3096
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3075
3097
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3076
3098
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3077
|
-
}, 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");
|
|
3078
3100
|
}
|
|
3079
3101
|
currentPresentation() {
|
|
3080
3102
|
let e = this.opts.video;
|
|
@@ -3089,7 +3111,7 @@ var Ln = class {
|
|
|
3089
3111
|
video: this.opts.video,
|
|
3090
3112
|
descriptor: e,
|
|
3091
3113
|
credential: t,
|
|
3092
|
-
deviceId:
|
|
3114
|
+
deviceId: k(),
|
|
3093
3115
|
userId: this.opts.userId,
|
|
3094
3116
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
3095
3117
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -3100,9 +3122,9 @@ var Ln = class {
|
|
|
3100
3122
|
emit: (e) => this.onEngineEvent(e)
|
|
3101
3123
|
}, o = this.opts.engine ?? "auto";
|
|
3102
3124
|
if (o === "native") return new K(a);
|
|
3103
|
-
if (o === "hls") return new
|
|
3104
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G() || !e.drmEnabled &&
|
|
3105
|
-
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);
|
|
3106
3128
|
if (W(this.opts.video)) return new K(a);
|
|
3107
3129
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3108
3130
|
}
|
|
@@ -3140,11 +3162,11 @@ var Ln = class {
|
|
|
3140
3162
|
}
|
|
3141
3163
|
startLiveState(e) {
|
|
3142
3164
|
if (this.opts.liveStateEvents === !1) return;
|
|
3143
|
-
let t = this.opts.eventsBaseUrl ??
|
|
3165
|
+
let t = this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
|
|
3144
3166
|
if (!t) return;
|
|
3145
3167
|
this.closeLiveState();
|
|
3146
3168
|
let r = 0, i = !1;
|
|
3147
|
-
this.liveStateSub =
|
|
3169
|
+
this.liveStateSub = T({
|
|
3148
3170
|
eventsBaseUrl: t,
|
|
3149
3171
|
matchUrn: this.opts.matchUrn,
|
|
3150
3172
|
credential: this.opts.credential,
|
|
@@ -3155,7 +3177,7 @@ var Ln = class {
|
|
|
3155
3177
|
r = 0, i = !1;
|
|
3156
3178
|
},
|
|
3157
3179
|
onError: () => {
|
|
3158
|
-
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.`))));
|
|
3159
3181
|
}
|
|
3160
3182
|
});
|
|
3161
3183
|
}
|
|
@@ -3177,7 +3199,7 @@ var Ln = class {
|
|
|
3177
3199
|
scheduleRejoin(e) {
|
|
3178
3200
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3179
3201
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3180
|
-
}, Math.random() *
|
|
3202
|
+
}, Math.random() * Q));
|
|
3181
3203
|
}
|
|
3182
3204
|
cancelRejoin() {
|
|
3183
3205
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3201,7 +3223,7 @@ var Ln = class {
|
|
|
3201
3223
|
}
|
|
3202
3224
|
t.controls = !1;
|
|
3203
3225
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3204
|
-
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({
|
|
3205
3227
|
root: n,
|
|
3206
3228
|
video: t,
|
|
3207
3229
|
player: this,
|
|
@@ -3232,7 +3254,7 @@ var Ln = class {
|
|
|
3232
3254
|
}
|
|
3233
3255
|
startStats() {
|
|
3234
3256
|
this.stopStats();
|
|
3235
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3257
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? In);
|
|
3236
3258
|
this.statsTimer = setInterval(() => {
|
|
3237
3259
|
if (!this.engine) return;
|
|
3238
3260
|
let e = this.engine.getStats();
|
|
@@ -3244,7 +3266,7 @@ var Ln = class {
|
|
|
3244
3266
|
}
|
|
3245
3267
|
scheduleLicenseRefresh() {
|
|
3246
3268
|
this.stopRefresh();
|
|
3247
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3269
|
+
let e = this.opts.licenseRefreshMs ?? Ln;
|
|
3248
3270
|
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3249
3271
|
}
|
|
3250
3272
|
stopRefresh() {
|
|
@@ -3289,7 +3311,7 @@ var Ln = class {
|
|
|
3289
3311
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3290
3312
|
}
|
|
3291
3313
|
getStats() {
|
|
3292
|
-
return this.engine?.getStats() ??
|
|
3314
|
+
return this.engine?.getStats() ?? We;
|
|
3293
3315
|
}
|
|
3294
3316
|
getQualityLevels() {
|
|
3295
3317
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3328,10 +3350,10 @@ var Ln = class {
|
|
|
3328
3350
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
3329
3351
|
}
|
|
3330
3352
|
async enterFullscreen() {
|
|
3331
|
-
return !this.destroyed &&
|
|
3353
|
+
return !this.destroyed && C(this.opts.video, this.container ?? void 0);
|
|
3332
3354
|
}
|
|
3333
3355
|
async exitFullscreen() {
|
|
3334
|
-
await
|
|
3356
|
+
await w(this.opts.video, this.container ?? void 0);
|
|
3335
3357
|
}
|
|
3336
3358
|
retry() {
|
|
3337
3359
|
return this.reload();
|
|
@@ -3399,7 +3421,7 @@ function $(e) {
|
|
|
3399
3421
|
}
|
|
3400
3422
|
//#endregion
|
|
3401
3423
|
//#region src/embed/host.ts
|
|
3402
|
-
function
|
|
3424
|
+
function Vn(e) {
|
|
3403
3425
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3404
3426
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3405
3427
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3458,15 +3480,15 @@ function Rn(e) {
|
|
|
3458
3480
|
}
|
|
3459
3481
|
//#endregion
|
|
3460
3482
|
//#region src/embed/page.ts
|
|
3461
|
-
var
|
|
3462
|
-
function
|
|
3483
|
+
var Hn = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3484
|
+
function Un(e) {
|
|
3463
3485
|
if (typeof e == "boolean") return e;
|
|
3464
3486
|
if (typeof e == "object" && e) {
|
|
3465
3487
|
let t = e.endpoint;
|
|
3466
3488
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3467
3489
|
}
|
|
3468
3490
|
}
|
|
3469
|
-
function
|
|
3491
|
+
function Wn() {
|
|
3470
3492
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3471
3493
|
if (e) return {
|
|
3472
3494
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3476,7 +3498,7 @@ function Vn() {
|
|
|
3476
3498
|
autoplay: e.autoplay ?? !0,
|
|
3477
3499
|
muted: e.muted ?? !0,
|
|
3478
3500
|
waitForLive: e.waitForLive ?? !0,
|
|
3479
|
-
analytics:
|
|
3501
|
+
analytics: Un(e.analytics)
|
|
3480
3502
|
};
|
|
3481
3503
|
let t = new URLSearchParams(location.search);
|
|
3482
3504
|
return {
|
|
@@ -3489,9 +3511,9 @@ function Vn() {
|
|
|
3489
3511
|
waitForLive: !0
|
|
3490
3512
|
};
|
|
3491
3513
|
}
|
|
3492
|
-
async function
|
|
3493
|
-
let e =
|
|
3494
|
-
|
|
3514
|
+
async function Gn() {
|
|
3515
|
+
let e = Wn();
|
|
3516
|
+
qn();
|
|
3495
3517
|
let t = document.createElement("video");
|
|
3496
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);
|
|
3497
3519
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3546,12 +3568,12 @@ async function Hn() {
|
|
|
3546
3568
|
code: e.code,
|
|
3547
3569
|
message: e.message
|
|
3548
3570
|
})), e.on("autoplayblocked", () => {
|
|
3549
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3571
|
+
i({ type: "oddin:autoplayblocked" }), Kn(t, e);
|
|
3550
3572
|
});
|
|
3551
3573
|
}, s = async (r) => {
|
|
3552
3574
|
a?.destroy(), a = null;
|
|
3553
3575
|
try {
|
|
3554
|
-
let n = await
|
|
3576
|
+
let n = await zn({
|
|
3555
3577
|
video: t,
|
|
3556
3578
|
baseUrl: e.baseUrl,
|
|
3557
3579
|
matchUrn: r,
|
|
@@ -3613,7 +3635,7 @@ async function Hn() {
|
|
|
3613
3635
|
a?.retry();
|
|
3614
3636
|
break;
|
|
3615
3637
|
case "oddin:load":
|
|
3616
|
-
typeof e.matchUrn == "string" &&
|
|
3638
|
+
typeof e.matchUrn == "string" && Hn.test(e.matchUrn) && s(e.matchUrn);
|
|
3617
3639
|
break;
|
|
3618
3640
|
case "oddin:destroy": c();
|
|
3619
3641
|
}
|
|
@@ -3625,18 +3647,18 @@ async function Hn() {
|
|
|
3625
3647
|
protocol: 1
|
|
3626
3648
|
});
|
|
3627
3649
|
}
|
|
3628
|
-
function
|
|
3650
|
+
function Kn(e, t) {
|
|
3629
3651
|
if (document.getElementById("havik-tap")) return;
|
|
3630
3652
|
let n = document.createElement("button");
|
|
3631
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", () => {
|
|
3632
3654
|
n.remove(), t.play();
|
|
3633
3655
|
}), document.body.appendChild(n);
|
|
3634
3656
|
}
|
|
3635
|
-
function
|
|
3657
|
+
function qn() {
|
|
3636
3658
|
let e = document.createElement("style");
|
|
3637
3659
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3638
3660
|
}
|
|
3639
3661
|
//#endregion
|
|
3640
|
-
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 };
|
|
3641
3663
|
|
|
3642
3664
|
//# sourceMappingURL=index.js.map
|