@oddin-gg/havik-player 2.12.0 → 2.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/havik-player.global.js +18 -18
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +310 -266
- package/dist/index.js.map +1 -1
- package/docs/API.md +9 -9
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -290,32 +290,32 @@ function he(e, t) {
|
|
|
290
290
|
function ge(e) {
|
|
291
291
|
return e.ownerDocument ?? document;
|
|
292
292
|
}
|
|
293
|
-
function
|
|
293
|
+
function x(e) {
|
|
294
294
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
295
295
|
}
|
|
296
|
-
function
|
|
297
|
-
let n =
|
|
296
|
+
function S(e, t) {
|
|
297
|
+
let n = x(ge(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 = ge(e), i =
|
|
313
|
+
let r = ge(e), i = x(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 ve(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 ye(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 be(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,11 +406,16 @@ function xe(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 Se = /* @__PURE__ */ new Set([
|
|
415
|
+
"NOT_FOUND",
|
|
416
|
+
"GONE",
|
|
417
|
+
"INVALID_URN"
|
|
418
|
+
]);
|
|
414
419
|
function Ce(e) {
|
|
415
420
|
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
|
|
416
421
|
u || (a = setTimeout(m, t));
|
|
@@ -442,7 +447,10 @@ function Ce(e) {
|
|
|
442
447
|
}));
|
|
443
448
|
}
|
|
444
449
|
} catch (t) {
|
|
445
|
-
i.signal.aborted
|
|
450
|
+
if (!i.signal.aborted) {
|
|
451
|
+
let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
|
|
452
|
+
Se.has(r.code) && (u = !0), e.onError?.(r);
|
|
453
|
+
}
|
|
446
454
|
} finally {
|
|
447
455
|
f();
|
|
448
456
|
}
|
|
@@ -454,7 +462,7 @@ function Ce(e) {
|
|
|
454
462
|
//#endregion
|
|
455
463
|
//#region src/core/events.ts
|
|
456
464
|
var we = 45e3;
|
|
457
|
-
function
|
|
465
|
+
function T(e) {
|
|
458
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) => {
|
|
459
467
|
if (a.signal.aborted) return t();
|
|
460
468
|
let n = setTimeout(t, e);
|
|
@@ -536,7 +544,7 @@ function w(e) {
|
|
|
536
544
|
o || (o = !0, a.abort());
|
|
537
545
|
} };
|
|
538
546
|
}
|
|
539
|
-
function
|
|
547
|
+
function E(e) {
|
|
540
548
|
try {
|
|
541
549
|
let t = new URL(e);
|
|
542
550
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -546,24 +554,24 @@ function T(e) {
|
|
|
546
554
|
}
|
|
547
555
|
//#endregion
|
|
548
556
|
//#region src/core/drm/deviceId.ts
|
|
549
|
-
var
|
|
550
|
-
function
|
|
551
|
-
if (
|
|
557
|
+
var D = "havik.player.deviceId", O;
|
|
558
|
+
function k() {
|
|
559
|
+
if (O) return O;
|
|
552
560
|
try {
|
|
553
|
-
let e = globalThis.localStorage?.getItem(
|
|
554
|
-
if (e) return
|
|
561
|
+
let e = globalThis.localStorage?.getItem(D);
|
|
562
|
+
if (e) return O = e, e;
|
|
555
563
|
} catch {}
|
|
556
564
|
let e = Ee();
|
|
557
|
-
|
|
565
|
+
O = e;
|
|
558
566
|
try {
|
|
559
|
-
globalThis.localStorage?.setItem(
|
|
567
|
+
globalThis.localStorage?.setItem(D, e);
|
|
560
568
|
} catch {}
|
|
561
569
|
return e;
|
|
562
570
|
}
|
|
563
571
|
function Te() {
|
|
564
|
-
|
|
572
|
+
O = void 0;
|
|
565
573
|
try {
|
|
566
|
-
globalThis.localStorage?.removeItem(
|
|
574
|
+
globalThis.localStorage?.removeItem(D);
|
|
567
575
|
} catch {}
|
|
568
576
|
}
|
|
569
577
|
function Ee() {
|
|
@@ -582,17 +590,17 @@ function De(e, t, n = {}) {
|
|
|
582
590
|
let r = {
|
|
583
591
|
"x-api-key": t.apiKey,
|
|
584
592
|
"X-Match-Urn": e.matchUrn,
|
|
585
|
-
"X-Device-Id": n.deviceId ??
|
|
593
|
+
"X-Device-Id": n.deviceId ?? k(),
|
|
586
594
|
"Content-Type": "application/octet-stream"
|
|
587
595
|
};
|
|
588
596
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
589
597
|
}
|
|
590
598
|
//#endregion
|
|
591
599
|
//#region src/core/drm/cdm.ts
|
|
592
|
-
var
|
|
600
|
+
var A = /* @__PURE__ */ new WeakMap();
|
|
593
601
|
function Oe(e, t) {
|
|
594
|
-
let n =
|
|
595
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
602
|
+
let n = A.get(e);
|
|
603
|
+
n || (n = /* @__PURE__ */ new Map(), A.set(e, n));
|
|
596
604
|
let r = n.get(t.keySystem);
|
|
597
605
|
if (r) return r;
|
|
598
606
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -600,22 +608,22 @@ function Oe(e, t) {
|
|
|
600
608
|
});
|
|
601
609
|
return n.set(t.keySystem, i), i;
|
|
602
610
|
}
|
|
603
|
-
function
|
|
611
|
+
function j() {
|
|
604
612
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
605
613
|
}
|
|
606
|
-
var
|
|
614
|
+
var M = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
607
615
|
function ke(e) {
|
|
608
616
|
return e.startsWith("com.widevine");
|
|
609
617
|
}
|
|
610
|
-
function
|
|
618
|
+
function N(e, t) {
|
|
611
619
|
if (!ke(e)) return t;
|
|
612
620
|
let n = (e, t) => {
|
|
613
621
|
let n = e.videoCapabilities;
|
|
614
622
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
615
|
-
let n =
|
|
616
|
-
return n === -1 ||
|
|
623
|
+
let n = M.indexOf(e.robustness);
|
|
624
|
+
return n === -1 || M.indexOf(t) > n;
|
|
617
625
|
});
|
|
618
|
-
}, r =
|
|
626
|
+
}, r = M.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
619
627
|
...t,
|
|
620
628
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
621
629
|
...t,
|
|
@@ -624,43 +632,43 @@ function M(e, t) {
|
|
|
624
632
|
})));
|
|
625
633
|
return [...t, ...r];
|
|
626
634
|
}
|
|
627
|
-
function
|
|
628
|
-
return (t, n) =>
|
|
635
|
+
function P(e) {
|
|
636
|
+
return (t, n) => j() ? navigator.requestMediaKeySystemAccess(t, N(t, n)).then((t) => ({
|
|
629
637
|
keySystem: t.keySystem,
|
|
630
638
|
getConfiguration: () => t.getConfiguration(),
|
|
631
639
|
createMediaKeys: () => Oe(e, t)
|
|
632
640
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
633
641
|
}
|
|
634
|
-
var
|
|
642
|
+
var F = {
|
|
635
643
|
video: "SW_SECURE_DECODE",
|
|
636
644
|
audio: "SW_SECURE_CRYPTO",
|
|
637
645
|
scheme: "cbcs"
|
|
638
646
|
};
|
|
639
647
|
function Ae(e) {
|
|
640
|
-
if (!
|
|
648
|
+
if (!j()) return;
|
|
641
649
|
let t = (e, t) => ({
|
|
642
650
|
contentType: e,
|
|
643
651
|
robustness: t,
|
|
644
|
-
encryptionScheme:
|
|
652
|
+
encryptionScheme: F.scheme
|
|
645
653
|
});
|
|
646
|
-
|
|
654
|
+
P(e)("com.widevine.alpha", [{
|
|
647
655
|
initDataTypes: ["cenc"],
|
|
648
656
|
distinctiveIdentifier: "optional",
|
|
649
657
|
persistentState: "optional",
|
|
650
658
|
sessionTypes: ["temporary"],
|
|
651
|
-
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"",
|
|
652
|
-
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)]
|
|
653
661
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
654
662
|
}
|
|
655
|
-
function
|
|
656
|
-
let t =
|
|
663
|
+
function I(e) {
|
|
664
|
+
let t = L(e);
|
|
657
665
|
if (/^avc[13]/.test(t)) return "avc";
|
|
658
666
|
if (/^(hvc1|hev1)/.test(t)) return "hevc";
|
|
659
667
|
if (/^(dvh1|dvhe)/.test(t)) return "dv";
|
|
660
668
|
if (t.startsWith("av01")) return "av1";
|
|
661
669
|
if (/^vp0?9/.test(t)) return "vp9";
|
|
662
670
|
}
|
|
663
|
-
function
|
|
671
|
+
function L(e) {
|
|
664
672
|
return (e ?? "").trim().toLowerCase();
|
|
665
673
|
}
|
|
666
674
|
var je = {
|
|
@@ -668,9 +676,9 @@ var je = {
|
|
|
668
676
|
dv: "dvh1.05.06",
|
|
669
677
|
av1: "av01.0.05M.08",
|
|
670
678
|
vp9: "vp09.00.10.08"
|
|
671
|
-
}, Me = /* @__PURE__ */ new Map(),
|
|
679
|
+
}, Me = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
|
|
672
680
|
function Ne(e) {
|
|
673
|
-
let t =
|
|
681
|
+
let t = L(e), n = Me.get(t);
|
|
674
682
|
if (n) return n;
|
|
675
683
|
let r = {
|
|
676
684
|
initDataTypes: ["cenc"],
|
|
@@ -679,32 +687,32 @@ function Ne(e) {
|
|
|
679
687
|
sessionTypes: ["temporary"],
|
|
680
688
|
videoCapabilities: [{
|
|
681
689
|
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
682
|
-
robustness:
|
|
683
|
-
encryptionScheme:
|
|
690
|
+
robustness: F.video,
|
|
691
|
+
encryptionScheme: F.scheme
|
|
684
692
|
}]
|
|
685
693
|
}, i = (async () => {
|
|
686
694
|
try {
|
|
687
|
-
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha",
|
|
695
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", N("com.widevine.alpha", [r])), !0;
|
|
688
696
|
} catch {
|
|
689
697
|
return !1;
|
|
690
698
|
}
|
|
691
|
-
})().then((e) => (
|
|
699
|
+
})().then((e) => (R.set(t, e), e));
|
|
692
700
|
return Me.set(t, i), i;
|
|
693
701
|
}
|
|
694
702
|
function Pe() {
|
|
695
|
-
if (
|
|
703
|
+
if (j()) for (let e of Object.values(je)) Ne(e);
|
|
696
704
|
}
|
|
697
705
|
function Fe(e) {
|
|
698
|
-
let t =
|
|
699
|
-
if (t) return t === "avc" ? !0 :
|
|
706
|
+
let t = I(e);
|
|
707
|
+
if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(je[t]));
|
|
700
708
|
}
|
|
701
709
|
//#endregion
|
|
702
710
|
//#region src/core/drm/support.ts
|
|
703
|
-
var Ie = 5e3,
|
|
711
|
+
var Ie = 5e3, Le = "video/mp4; codecs=\"avc1.42E01E\"", Re = "audio/mp4; codecs=\"mp4a.40.2\"", ze = {
|
|
704
712
|
widevine: ["com.widevine.alpha"],
|
|
705
713
|
fairplay: ["com.apple.fps"]
|
|
706
714
|
};
|
|
707
|
-
function
|
|
715
|
+
function Be(e) {
|
|
708
716
|
return e === "fairplay" ? [{
|
|
709
717
|
initDataTypes: [
|
|
710
718
|
"sinf",
|
|
@@ -712,30 +720,30 @@ function Re(e) {
|
|
|
712
720
|
"cenc"
|
|
713
721
|
],
|
|
714
722
|
videoCapabilities: [{
|
|
715
|
-
contentType:
|
|
723
|
+
contentType: Le,
|
|
716
724
|
robustness: "",
|
|
717
725
|
encryptionScheme: "cbcs"
|
|
718
726
|
}],
|
|
719
727
|
audioCapabilities: [{
|
|
720
|
-
contentType:
|
|
728
|
+
contentType: Re,
|
|
721
729
|
robustness: "",
|
|
722
730
|
encryptionScheme: "cbcs"
|
|
723
731
|
}]
|
|
724
|
-
}] :
|
|
732
|
+
}] : N("com.widevine.alpha", [{
|
|
725
733
|
initDataTypes: ["cenc"],
|
|
726
734
|
videoCapabilities: [{
|
|
727
|
-
contentType:
|
|
728
|
-
robustness:
|
|
729
|
-
encryptionScheme:
|
|
735
|
+
contentType: Le,
|
|
736
|
+
robustness: F.video,
|
|
737
|
+
encryptionScheme: F.scheme
|
|
730
738
|
}],
|
|
731
739
|
audioCapabilities: [{
|
|
732
|
-
contentType:
|
|
733
|
-
robustness:
|
|
734
|
-
encryptionScheme:
|
|
740
|
+
contentType: Re,
|
|
741
|
+
robustness: F.audio,
|
|
742
|
+
encryptionScheme: F.scheme
|
|
735
743
|
}]
|
|
736
744
|
}]);
|
|
737
745
|
}
|
|
738
|
-
function
|
|
746
|
+
function Ve(e, t) {
|
|
739
747
|
return new Promise((n, r) => {
|
|
740
748
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
741
749
|
e.then((e) => {
|
|
@@ -745,7 +753,7 @@ function B(e, t) {
|
|
|
745
753
|
});
|
|
746
754
|
});
|
|
747
755
|
}
|
|
748
|
-
async function
|
|
756
|
+
async function He(e = {}) {
|
|
749
757
|
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ie, r = {};
|
|
750
758
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
751
759
|
verdict: "insecure-context",
|
|
@@ -758,7 +766,7 @@ async function ze(e = {}) {
|
|
|
758
766
|
};
|
|
759
767
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
760
768
|
for (let e of t) {
|
|
761
|
-
let t =
|
|
769
|
+
let t = ze[e];
|
|
762
770
|
if (!t) {
|
|
763
771
|
r[e] = "unknown system";
|
|
764
772
|
continue;
|
|
@@ -769,7 +777,7 @@ async function ze(e = {}) {
|
|
|
769
777
|
break;
|
|
770
778
|
}
|
|
771
779
|
try {
|
|
772
|
-
return await
|
|
780
|
+
return await Ve((await Ve(i(n, Be(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
773
781
|
verdict: "supported",
|
|
774
782
|
system: e,
|
|
775
783
|
detail: r
|
|
@@ -793,49 +801,49 @@ async function ze(e = {}) {
|
|
|
793
801
|
}
|
|
794
802
|
//#endregion
|
|
795
803
|
//#region src/core/manifest.ts
|
|
796
|
-
var
|
|
797
|
-
function
|
|
798
|
-
return
|
|
804
|
+
var Ue = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
805
|
+
function We(e) {
|
|
806
|
+
return Ue.test(e);
|
|
799
807
|
}
|
|
800
808
|
//#endregion
|
|
801
809
|
//#region src/core/env.ts
|
|
802
|
-
var
|
|
810
|
+
var z = {
|
|
803
811
|
integration: "https://feed-dev.oddin-video.gg",
|
|
804
812
|
production: "https://feed.oddin-video.gg"
|
|
805
813
|
};
|
|
806
|
-
function
|
|
807
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
814
|
+
function B(e) {
|
|
815
|
+
let t = Object.prototype.hasOwnProperty.call(z, e) ? z[e] : void 0;
|
|
808
816
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
809
817
|
return t;
|
|
810
818
|
}
|
|
811
819
|
//#endregion
|
|
812
820
|
//#region src/core/stats.ts
|
|
813
|
-
var
|
|
814
|
-
function
|
|
821
|
+
var V = { droppedFrames: 0 };
|
|
822
|
+
function H(e) {
|
|
815
823
|
try {
|
|
816
824
|
return new URL(e).host;
|
|
817
825
|
} catch {
|
|
818
826
|
return "";
|
|
819
827
|
}
|
|
820
828
|
}
|
|
821
|
-
var
|
|
822
|
-
function
|
|
829
|
+
var Ge = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
830
|
+
function Ke(e) {
|
|
823
831
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
824
832
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
825
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
826
|
-
let e =
|
|
833
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Ge.test(i.name)) && i.startTime >= n) {
|
|
834
|
+
let e = H(i.name);
|
|
827
835
|
e && (t = e, n = i.startTime);
|
|
828
836
|
}
|
|
829
837
|
return t;
|
|
830
838
|
}
|
|
831
|
-
function
|
|
839
|
+
function U(e) {
|
|
832
840
|
let t = e.getVideoPlaybackQuality?.();
|
|
833
841
|
return {
|
|
834
842
|
dropped: t?.droppedVideoFrames ?? 0,
|
|
835
843
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
836
844
|
};
|
|
837
845
|
}
|
|
838
|
-
function
|
|
846
|
+
function qe(e, t) {
|
|
839
847
|
let n = [
|
|
840
848
|
["playing", () => t("playing")],
|
|
841
849
|
["waiting", () => t("buffering")],
|
|
@@ -852,7 +860,7 @@ function We(e, t) {
|
|
|
852
860
|
}
|
|
853
861
|
//#endregion
|
|
854
862
|
//#region src/core/engine/native.ts
|
|
855
|
-
function
|
|
863
|
+
function Je(e) {
|
|
856
864
|
try {
|
|
857
865
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
858
866
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -860,15 +868,15 @@ function Ge(e) {
|
|
|
860
868
|
return;
|
|
861
869
|
}
|
|
862
870
|
}
|
|
863
|
-
function
|
|
871
|
+
function W(e) {
|
|
864
872
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
865
873
|
}
|
|
866
|
-
function
|
|
874
|
+
function G() {
|
|
867
875
|
if (typeof window > "u") return !1;
|
|
868
876
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
869
877
|
return e || t;
|
|
870
878
|
}
|
|
871
|
-
var
|
|
879
|
+
var K = class {
|
|
872
880
|
name = "native";
|
|
873
881
|
deps;
|
|
874
882
|
onLoaded;
|
|
@@ -904,7 +912,7 @@ var J = class {
|
|
|
904
912
|
type: "error",
|
|
905
913
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
906
914
|
fatal: !0
|
|
907
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
915
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Ye(t.manifestUrl, t.analytics?.sid), e.load();
|
|
908
916
|
}
|
|
909
917
|
startLoad() {
|
|
910
918
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -926,7 +934,7 @@ var J = class {
|
|
|
926
934
|
});
|
|
927
935
|
this.onEncrypted = (n) => {
|
|
928
936
|
let i = n;
|
|
929
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
937
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Je(i.initData), (async () => {
|
|
930
938
|
try {
|
|
931
939
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
932
940
|
initDataTypes: [i.initDataType],
|
|
@@ -1021,11 +1029,11 @@ var J = class {
|
|
|
1021
1029
|
e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
|
|
1022
1030
|
}
|
|
1023
1031
|
getStats() {
|
|
1024
|
-
let e = this.deps.video, t =
|
|
1032
|
+
let e = this.deps.video, t = U(e), n = {
|
|
1025
1033
|
droppedFrames: t.dropped,
|
|
1026
1034
|
decodedFrames: t.totalFrames
|
|
1027
1035
|
};
|
|
1028
|
-
return this.cdnHost ||=
|
|
1036
|
+
return this.cdnHost ||= Ke(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity ? (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)) : Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1), n;
|
|
1029
1037
|
}
|
|
1030
1038
|
stop() {
|
|
1031
1039
|
try {
|
|
@@ -1044,13 +1052,13 @@ var J = class {
|
|
|
1044
1052
|
} catch {}
|
|
1045
1053
|
}
|
|
1046
1054
|
};
|
|
1047
|
-
function
|
|
1055
|
+
function Ye(e, t) {
|
|
1048
1056
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1049
1057
|
}
|
|
1050
1058
|
//#endregion
|
|
1051
1059
|
//#region src/core/engine/prefetch.ts
|
|
1052
|
-
var
|
|
1053
|
-
function
|
|
1060
|
+
var Xe = 15e3, Ze = 5e3, Qe = 6;
|
|
1061
|
+
function $e(e) {
|
|
1054
1062
|
try {
|
|
1055
1063
|
let t = new URL(e);
|
|
1056
1064
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1058,7 +1066,7 @@ function Xe(e) {
|
|
|
1058
1066
|
return e;
|
|
1059
1067
|
}
|
|
1060
1068
|
}
|
|
1061
|
-
var
|
|
1069
|
+
var et = class {
|
|
1062
1070
|
cmcd;
|
|
1063
1071
|
entries = /* @__PURE__ */ new Map();
|
|
1064
1072
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1081,10 +1089,10 @@ var Ze = class {
|
|
|
1081
1089
|
}
|
|
1082
1090
|
prefetch(e, t, n) {
|
|
1083
1091
|
if (!this.isActive(t)) return;
|
|
1084
|
-
let r =
|
|
1092
|
+
let r = $e(e);
|
|
1085
1093
|
if (this.entries.has(r)) return;
|
|
1086
1094
|
let i = this.perTrack.get(t) ?? 0;
|
|
1087
|
-
if (i >=
|
|
1095
|
+
if (i >= Qe) return;
|
|
1088
1096
|
this.perTrack.set(t, i + 1);
|
|
1089
1097
|
let a = new AbortController(), o = {
|
|
1090
1098
|
started: performance.now(),
|
|
@@ -1098,10 +1106,10 @@ var Ze = class {
|
|
|
1098
1106
|
signal: a.signal
|
|
1099
1107
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1100
1108
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1101
|
-
},
|
|
1109
|
+
}, Xe);
|
|
1102
1110
|
}
|
|
1103
1111
|
take(e) {
|
|
1104
|
-
let t =
|
|
1112
|
+
let t = $e(e), n = this.entries.get(t);
|
|
1105
1113
|
return n && this.entries.delete(t), n;
|
|
1106
1114
|
}
|
|
1107
1115
|
destroy() {
|
|
@@ -1121,13 +1129,13 @@ var Ze = class {
|
|
|
1121
1129
|
}
|
|
1122
1130
|
}
|
|
1123
1131
|
};
|
|
1124
|
-
function
|
|
1132
|
+
function tt(t) {
|
|
1125
1133
|
let n = e.DefaultConfig?.loader;
|
|
1126
1134
|
if (typeof n != "function") return;
|
|
1127
1135
|
class r extends n {
|
|
1128
1136
|
served = !1;
|
|
1129
1137
|
cancelled = !1;
|
|
1130
|
-
stats =
|
|
1138
|
+
stats = nt();
|
|
1131
1139
|
load(e, n, r) {
|
|
1132
1140
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1133
1141
|
if (!i) {
|
|
@@ -1135,7 +1143,7 @@ function Qe(t) {
|
|
|
1135
1143
|
return;
|
|
1136
1144
|
}
|
|
1137
1145
|
this.served = !0;
|
|
1138
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1146
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Ze, s = setTimeout(() => {
|
|
1139
1147
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1140
1148
|
}, o);
|
|
1141
1149
|
i.bytes.then((o) => {
|
|
@@ -1162,7 +1170,7 @@ function Qe(t) {
|
|
|
1162
1170
|
}
|
|
1163
1171
|
return r;
|
|
1164
1172
|
}
|
|
1165
|
-
function
|
|
1173
|
+
function nt() {
|
|
1166
1174
|
return {
|
|
1167
1175
|
aborted: !1,
|
|
1168
1176
|
loaded: 0,
|
|
@@ -1186,10 +1194,10 @@ function $e() {
|
|
|
1186
1194
|
}
|
|
1187
1195
|
};
|
|
1188
1196
|
}
|
|
1189
|
-
function
|
|
1197
|
+
function rt(e) {
|
|
1190
1198
|
return e === "audio" ? "audio" : "main";
|
|
1191
1199
|
}
|
|
1192
|
-
function
|
|
1200
|
+
function it(e, t) {
|
|
1193
1201
|
let n = [];
|
|
1194
1202
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1195
1203
|
url: t.initSegment.url,
|
|
@@ -1208,24 +1216,24 @@ function tt(e, t) {
|
|
|
1208
1216
|
}
|
|
1209
1217
|
//#endregion
|
|
1210
1218
|
//#region src/core/engine/hls.ts
|
|
1211
|
-
function
|
|
1219
|
+
function at() {
|
|
1212
1220
|
return e.isSupported();
|
|
1213
1221
|
}
|
|
1214
|
-
var
|
|
1215
|
-
function
|
|
1222
|
+
var ot = 3, st = 5, ct = 3, lt = 3e4, ut = 12e3, dt = 3e3, ft = 6e3, pt = 5e3, mt = 4e3, ht = 2, gt = 5, _t = 2, vt = 2, yt = 4, bt = 4, xt = 2e3, St = 3e4, Ct = 2, wt = 9, Tt = .5, Et = 64;
|
|
1223
|
+
function Dt(e) {
|
|
1216
1224
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1217
1225
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1218
1226
|
return;
|
|
1219
1227
|
}
|
|
1220
|
-
e.liveSyncDuration ??=
|
|
1221
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1222
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1228
|
+
e.liveSyncDuration ??= Ct;
|
|
1229
|
+
let t = Math.max(12, e.liveSyncDuration + wt);
|
|
1230
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Ot(e, e.liveSyncDuration);
|
|
1223
1231
|
}
|
|
1224
|
-
function
|
|
1232
|
+
function Ot(e, t) {
|
|
1225
1233
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1226
1234
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1227
1235
|
}
|
|
1228
|
-
var
|
|
1236
|
+
var kt = class {
|
|
1229
1237
|
name = "hls";
|
|
1230
1238
|
hls = null;
|
|
1231
1239
|
deps;
|
|
@@ -1293,7 +1301,7 @@ var Et = class {
|
|
|
1293
1301
|
this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1294
1302
|
}
|
|
1295
1303
|
async load() {
|
|
1296
|
-
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a =
|
|
1304
|
+
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = W(r) && G(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
1297
1305
|
if (e.drmEnabled && !o) {
|
|
1298
1306
|
i({
|
|
1299
1307
|
type: "error",
|
|
@@ -1325,7 +1333,7 @@ var Et = class {
|
|
|
1325
1333
|
}
|
|
1326
1334
|
this.loadSuspended = !0;
|
|
1327
1335
|
}
|
|
1328
|
-
},
|
|
1336
|
+
}, pt));
|
|
1329
1337
|
}
|
|
1330
1338
|
resumeLoading() {
|
|
1331
1339
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1357,7 +1365,7 @@ var Et = class {
|
|
|
1357
1365
|
let t = e.liveSyncPosition;
|
|
1358
1366
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1359
1367
|
let { video: n } = this.deps;
|
|
1360
|
-
n.currentTime <= t +
|
|
1368
|
+
n.currentTime <= t + Tt || (n.currentTime = t);
|
|
1361
1369
|
}
|
|
1362
1370
|
startHls() {
|
|
1363
1371
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1376,12 +1384,12 @@ var Et = class {
|
|
|
1376
1384
|
emeEnabled: !0,
|
|
1377
1385
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1378
1386
|
drmSystemOptions: {
|
|
1379
|
-
videoRobustness:
|
|
1380
|
-
audioRobustness:
|
|
1381
|
-
videoEncryptionScheme:
|
|
1382
|
-
audioEncryptionScheme:
|
|
1387
|
+
videoRobustness: F.video,
|
|
1388
|
+
audioRobustness: F.audio,
|
|
1389
|
+
videoEncryptionScheme: F.scheme,
|
|
1390
|
+
audioEncryptionScheme: F.scheme
|
|
1383
1391
|
},
|
|
1384
|
-
...
|
|
1392
|
+
...j() ? { requestMediaKeySystemAccessFunc: P(t) } : {},
|
|
1385
1393
|
licenseXhrSetup: (e, t) => {
|
|
1386
1394
|
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;
|
|
1387
1395
|
let o = performance.now();
|
|
@@ -1398,20 +1406,20 @@ var Et = class {
|
|
|
1398
1406
|
...c
|
|
1399
1407
|
};
|
|
1400
1408
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
|
|
1401
|
-
let e = new
|
|
1409
|
+
let e = new et({
|
|
1402
1410
|
sessionId: n.analytics?.sid,
|
|
1403
1411
|
contentId: n.matchUrn
|
|
1404
|
-
}), t =
|
|
1412
|
+
}), t = tt(e);
|
|
1405
1413
|
t && (this.prefetch = e, d.fLoader = t);
|
|
1406
1414
|
}
|
|
1407
|
-
|
|
1415
|
+
Dt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
|
|
1408
1416
|
let f = new e(d);
|
|
1409
1417
|
if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1410
1418
|
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" });
|
|
1411
1419
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1412
1420
|
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(() => {
|
|
1413
1421
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1414
|
-
},
|
|
1422
|
+
}, lt)));
|
|
1415
1423
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1416
1424
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1417
1425
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1419,10 +1427,10 @@ var Et = class {
|
|
|
1419
1427
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1420
1428
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1421
1429
|
let i = n?.loading;
|
|
1422
|
-
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 >
|
|
1430
|
+
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 > Et && this.requestTimesMs.shift());
|
|
1423
1431
|
let a = t?.frag?.url;
|
|
1424
1432
|
if (a) {
|
|
1425
|
-
let e =
|
|
1433
|
+
let e = H(a);
|
|
1426
1434
|
e && (this.cdnHost = e);
|
|
1427
1435
|
}
|
|
1428
1436
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1436,15 +1444,15 @@ var Et = class {
|
|
|
1436
1444
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1437
1445
|
let t = this.prefetch;
|
|
1438
1446
|
f.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1439
|
-
let r = n?.frag, i =
|
|
1440
|
-
if (r && t.isActive(i)) for (let e of
|
|
1441
|
-
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1447
|
+
let r = n?.frag, i = rt(r?.type);
|
|
1448
|
+
if (r && t.isActive(i)) for (let e of it(f, r)) t.prefetch(e.url, i, e.kind);
|
|
1449
|
+
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(rt(n?.frag?.type)));
|
|
1442
1450
|
}
|
|
1443
1451
|
f.on(e.Events.KEY_LOADED, () => {
|
|
1444
1452
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1445
1453
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1446
1454
|
this.checkEndStale(), this.checkStarvation();
|
|
1447
|
-
},
|
|
1455
|
+
}, dt), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1448
1456
|
this.renditionSwitches += 1;
|
|
1449
1457
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1450
1458
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1508,7 +1516,7 @@ var Et = class {
|
|
|
1508
1516
|
return;
|
|
1509
1517
|
}
|
|
1510
1518
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1511
|
-
let t = e > this.sizeCapLevel ?
|
|
1519
|
+
let t = e > this.sizeCapLevel ? xt : St;
|
|
1512
1520
|
this.capTimer = setTimeout(() => {
|
|
1513
1521
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1514
1522
|
}, t);
|
|
@@ -1519,7 +1527,7 @@ var Et = class {
|
|
|
1519
1527
|
}
|
|
1520
1528
|
dropLevelsWidevineCannotPlay(e) {
|
|
1521
1529
|
this.removeLevelsWhere(e, (e) => Fe(e) !== !0);
|
|
1522
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1530
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
|
|
1523
1531
|
for (let n of t) Ne(n).then((t) => {
|
|
1524
1532
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1525
1533
|
});
|
|
@@ -1528,10 +1536,10 @@ var Et = class {
|
|
|
1528
1536
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1529
1537
|
if (n.forEach((e, n) => {
|
|
1530
1538
|
let a = e.videoCodec;
|
|
1531
|
-
a &&
|
|
1539
|
+
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1532
1540
|
}), !r.length) return !1;
|
|
1533
1541
|
let a = [...i].join(", ");
|
|
1534
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !
|
|
1542
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Fe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1535
1543
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1536
1544
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1537
1545
|
}
|
|
@@ -1577,7 +1585,7 @@ var Et = class {
|
|
|
1577
1585
|
e.widevine && (this.licenseUrl = e.widevine);
|
|
1578
1586
|
}
|
|
1579
1587
|
getStats() {
|
|
1580
|
-
let e = this.hls, t =
|
|
1588
|
+
let e = this.hls, t = U(this.deps.video), n = {
|
|
1581
1589
|
droppedFrames: t.dropped,
|
|
1582
1590
|
decodedFrames: t.totalFrames,
|
|
1583
1591
|
lowLatency: this.detectedLowLatency,
|
|
@@ -1623,7 +1631,7 @@ var Et = class {
|
|
|
1623
1631
|
return;
|
|
1624
1632
|
}
|
|
1625
1633
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1626
|
-
!this.chaseSuspended && e >
|
|
1634
|
+
!this.chaseSuspended && e > ft && this.suspendChasing(), e > ut && this.emitEnded("stalled");
|
|
1627
1635
|
}
|
|
1628
1636
|
resetStarvationWindow() {
|
|
1629
1637
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1638,7 +1646,7 @@ var Et = class {
|
|
|
1638
1646
|
this.resetStarvationWindow();
|
|
1639
1647
|
return;
|
|
1640
1648
|
}
|
|
1641
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1649
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < ft, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > mt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = U(t), c = o - s, l = c !== this.starvedFrames;
|
|
1642
1650
|
if (this.starvedFrames = c, !a || l) {
|
|
1643
1651
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1644
1652
|
return;
|
|
@@ -1647,12 +1655,12 @@ var Et = class {
|
|
|
1647
1655
|
this.resetStarvationWindow();
|
|
1648
1656
|
return;
|
|
1649
1657
|
}
|
|
1650
|
-
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 >
|
|
1658
|
+
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 > yt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= _t && (this.clearKick(), this.starvationRebuilds < vt)) {
|
|
1651
1659
|
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");
|
|
1652
1660
|
return;
|
|
1653
1661
|
}
|
|
1654
|
-
let u = i && this.starvedTicks >=
|
|
1655
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1662
|
+
let u = i && this.starvedTicks >= ht, d = !i && this.deadTicks >= yt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= bt;
|
|
1663
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= gt))) {
|
|
1656
1664
|
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");
|
|
1657
1665
|
try {
|
|
1658
1666
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1701,7 +1709,7 @@ var Et = class {
|
|
|
1701
1709
|
scheduleLicenseRetry(t) {
|
|
1702
1710
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1703
1711
|
let n = t.response?.code ?? 0;
|
|
1704
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1712
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= ct) return !1;
|
|
1705
1713
|
this.licenseRecoveries += 1;
|
|
1706
1714
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1707
1715
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1733,7 +1741,7 @@ var Et = class {
|
|
|
1733
1741
|
return;
|
|
1734
1742
|
}
|
|
1735
1743
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1736
|
-
if (this.networkRecoveries <
|
|
1744
|
+
if (this.networkRecoveries < st) {
|
|
1737
1745
|
this.networkRecoveries += 1;
|
|
1738
1746
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1739
1747
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1750,7 +1758,7 @@ var Et = class {
|
|
|
1750
1758
|
return;
|
|
1751
1759
|
}
|
|
1752
1760
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1753
|
-
if (this.mediaRecoveries <
|
|
1761
|
+
if (this.mediaRecoveries < ot) {
|
|
1754
1762
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1755
1763
|
return;
|
|
1756
1764
|
}
|
|
@@ -1774,19 +1782,19 @@ var Et = class {
|
|
|
1774
1782
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1775
1783
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1776
1784
|
}
|
|
1777
|
-
},
|
|
1785
|
+
}, At = 15e3, jt = 6e5, Mt = 3e5, Nt = 100, q = 1, Pt = 1e3, Ft = 3e4, It = 1e3, Lt = {
|
|
1778
1786
|
inline: "PRESENTATION_INLINE",
|
|
1779
1787
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1780
1788
|
pip: "PRESENTATION_PIP"
|
|
1781
|
-
},
|
|
1789
|
+
}, Rt = {
|
|
1782
1790
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1783
1791
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1784
1792
|
none: "KEY_SYSTEM_NONE"
|
|
1785
1793
|
};
|
|
1786
|
-
function
|
|
1794
|
+
function zt(e, t) {
|
|
1787
1795
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1788
1796
|
}
|
|
1789
|
-
var
|
|
1797
|
+
var Bt = /* @__PURE__ */ new Set([
|
|
1790
1798
|
"INVALID_URN",
|
|
1791
1799
|
"NOT_FOUND",
|
|
1792
1800
|
"GONE",
|
|
@@ -1796,7 +1804,7 @@ var Lt = /* @__PURE__ */ new Set([
|
|
|
1796
1804
|
"FORBIDDEN",
|
|
1797
1805
|
"RATE_LIMITED",
|
|
1798
1806
|
"TIMEOUT"
|
|
1799
|
-
]),
|
|
1807
|
+
]), J = {
|
|
1800
1808
|
idle: "PLAYER_STATE_IDLE",
|
|
1801
1809
|
waiting: "PLAYER_STATE_WAITING",
|
|
1802
1810
|
loading: "PLAYER_STATE_LOADING",
|
|
@@ -1806,7 +1814,7 @@ var Lt = /* @__PURE__ */ new Set([
|
|
|
1806
1814
|
ended: "PLAYER_STATE_ENDED",
|
|
1807
1815
|
error: "PLAYER_STATE_ERROR"
|
|
1808
1816
|
};
|
|
1809
|
-
function
|
|
1817
|
+
function Vt(e) {
|
|
1810
1818
|
try {
|
|
1811
1819
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1812
1820
|
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);
|
|
@@ -1814,15 +1822,29 @@ function Rt(e) {
|
|
|
1814
1822
|
return;
|
|
1815
1823
|
}
|
|
1816
1824
|
}
|
|
1817
|
-
var
|
|
1818
|
-
function
|
|
1825
|
+
var Ht = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Ut = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), Wt = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
1826
|
+
function Gt(e) {
|
|
1827
|
+
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
1828
|
+
let t;
|
|
1829
|
+
try {
|
|
1830
|
+
let n = new URL(e.blockedURI);
|
|
1831
|
+
t = n.origin + n.pathname;
|
|
1832
|
+
} catch {
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
if (Ut.has(t) && !Y.has(t)) {
|
|
1836
|
+
Y.add(t), g(Wt(new URL(t).origin));
|
|
1837
|
+
for (let e of X) e.noteCspBlocked();
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
function Kt(e, t) {
|
|
1819
1841
|
return g(t, e), { disabledReason: t };
|
|
1820
1842
|
}
|
|
1821
|
-
function
|
|
1822
|
-
if (n) return t && !
|
|
1843
|
+
function qt(e, t, n) {
|
|
1844
|
+
if (n) return t && !Ht(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
1823
1845
|
if (t) return { endpoint: t };
|
|
1824
|
-
if (t !== void 0) return
|
|
1825
|
-
let r =
|
|
1846
|
+
if (t !== void 0) return Kt("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).");
|
|
1847
|
+
let r = Vt(e);
|
|
1826
1848
|
if (r) return { endpoint: r };
|
|
1827
1849
|
let i;
|
|
1828
1850
|
try {
|
|
@@ -1830,11 +1852,12 @@ function Vt(e, t, n) {
|
|
|
1830
1852
|
} catch {
|
|
1831
1853
|
i = e;
|
|
1832
1854
|
}
|
|
1833
|
-
return
|
|
1855
|
+
return Kt(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).`);
|
|
1834
1856
|
}
|
|
1835
|
-
var
|
|
1857
|
+
var Jt = class {
|
|
1836
1858
|
opts;
|
|
1837
1859
|
url;
|
|
1860
|
+
cspKey;
|
|
1838
1861
|
now;
|
|
1839
1862
|
seq = 0;
|
|
1840
1863
|
pending = [];
|
|
@@ -1902,6 +1925,7 @@ var Ht = class {
|
|
|
1902
1925
|
firstPlaylistMs = 0;
|
|
1903
1926
|
drmSetupMs = 0;
|
|
1904
1927
|
onPagehide = () => this.end("END_REASON_PAGEHIDE");
|
|
1928
|
+
cspBlockedNoted = !1;
|
|
1905
1929
|
onFreeze = () => {
|
|
1906
1930
|
this.endedFlag || this.flush(!0);
|
|
1907
1931
|
};
|
|
@@ -1912,9 +1936,16 @@ var Ht = class {
|
|
|
1912
1936
|
constructor(e) {
|
|
1913
1937
|
this.opts = {
|
|
1914
1938
|
...e,
|
|
1915
|
-
heartbeatMs: e.heartbeatMs ??
|
|
1916
|
-
idleMs: e.idleMs ??
|
|
1917
|
-
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons
|
|
1939
|
+
heartbeatMs: e.heartbeatMs ?? At,
|
|
1940
|
+
idleMs: e.idleMs ?? jt
|
|
1941
|
+
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
1942
|
+
try {
|
|
1943
|
+
let e = new URL(this.url);
|
|
1944
|
+
this.cspKey = e.origin + e.pathname;
|
|
1945
|
+
} catch {
|
|
1946
|
+
this.cspKey = void 0;
|
|
1947
|
+
}
|
|
1948
|
+
this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs, this.startupAnchorMs = this.bornMs;
|
|
1918
1949
|
}
|
|
1919
1950
|
start() {
|
|
1920
1951
|
if (this.endedFlag) return;
|
|
@@ -1923,11 +1954,11 @@ var Ht = class {
|
|
|
1923
1954
|
sdkVersion: this.opts.sdkVersion,
|
|
1924
1955
|
...this.opts.environment
|
|
1925
1956
|
};
|
|
1926
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
1957
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Pt), 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 && Ut.add(this.cspKey), document.addEventListener("securitypolicyviolation", Gt), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
1927
1958
|
}
|
|
1928
1959
|
checkSuspension(e) {
|
|
1929
1960
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
1930
|
-
let t = Math.max(this.opts.idleMs,
|
|
1961
|
+
let t = Math.max(this.opts.idleMs, Mt);
|
|
1931
1962
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
1932
1963
|
}
|
|
1933
1964
|
syncIdle(e) {
|
|
@@ -1941,21 +1972,21 @@ var Ht = class {
|
|
|
1941
1972
|
noteStateChange(e, t, n, r) {
|
|
1942
1973
|
if (this.endedFlag || e === t) return;
|
|
1943
1974
|
let i = this.now();
|
|
1944
|
-
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(
|
|
1975
|
+
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(q, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(q, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
|
|
1945
1976
|
this.stallIsSeekInduced = this.seekInduced(i);
|
|
1946
1977
|
let e = !this.isHidden && !this.stallIsSeekInduced;
|
|
1947
|
-
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(
|
|
1978
|
+
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(q, Math.round(this.playingTotalMs)));
|
|
1948
1979
|
} else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
|
|
1949
1980
|
this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
|
|
1950
1981
|
let a = {
|
|
1951
|
-
fromState:
|
|
1952
|
-
toState:
|
|
1953
|
-
presentation:
|
|
1982
|
+
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1983
|
+
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1984
|
+
presentation: Lt[this.presentation]
|
|
1954
1985
|
}, o = this.causeOf(e, t, i);
|
|
1955
1986
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
1956
1987
|
}
|
|
1957
1988
|
seekInduced(e) {
|
|
1958
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
1989
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < It;
|
|
1959
1990
|
}
|
|
1960
1991
|
causeOf(e, t, n) {
|
|
1961
1992
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -1992,25 +2023,25 @@ var Ht = class {
|
|
|
1992
2023
|
}
|
|
1993
2024
|
this.muteChanges += 1;
|
|
1994
2025
|
let r = this.now();
|
|
1995
|
-
n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(
|
|
2026
|
+
n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(q, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
|
|
1996
2027
|
}
|
|
1997
2028
|
notePresentation(e) {
|
|
1998
2029
|
this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
|
|
1999
2030
|
}
|
|
2000
2031
|
notePlayIntent() {
|
|
2001
|
-
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs =
|
|
2032
|
+
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = q), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = q), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = q), this.drmSetupMs > 0 && (this.drmSetupMs = q));
|
|
2002
2033
|
}
|
|
2003
2034
|
noteReady() {
|
|
2004
|
-
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(
|
|
2035
|
+
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(q, this.now() - this.startupAnchorMs));
|
|
2005
2036
|
}
|
|
2006
2037
|
noteFirstPlaylist() {
|
|
2007
|
-
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(
|
|
2038
|
+
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(q, this.now() - this.startupAnchorMs));
|
|
2008
2039
|
}
|
|
2009
2040
|
noteDrmReady() {
|
|
2010
|
-
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(
|
|
2041
|
+
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(q, this.now() - this.startupAnchorMs));
|
|
2011
2042
|
}
|
|
2012
2043
|
noteFirstBytes() {
|
|
2013
|
-
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(
|
|
2044
|
+
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(q, this.now() - this.startupAnchorMs));
|
|
2014
2045
|
}
|
|
2015
2046
|
noteSeek() {
|
|
2016
2047
|
this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
|
|
@@ -2029,7 +2060,7 @@ var Ht = class {
|
|
|
2029
2060
|
let r = n ?? "";
|
|
2030
2061
|
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";
|
|
2031
2062
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2032
|
-
if (
|
|
2063
|
+
if (Bt.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2033
2064
|
let i = t ?? "";
|
|
2034
2065
|
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";
|
|
2035
2066
|
}
|
|
@@ -2045,7 +2076,7 @@ var Ht = class {
|
|
|
2045
2076
|
heartbeat() {
|
|
2046
2077
|
if (this.endedFlag) return;
|
|
2047
2078
|
let e = this.now();
|
|
2048
|
-
if (this.checkSuspension(e)) return;
|
|
2079
|
+
if (this.checkSuspension(e) || this.cspBlocked()) return;
|
|
2049
2080
|
let t = this.opts.sample(), n = this.playingTotalMs;
|
|
2050
2081
|
this.playingSinceMs !== null && (n += e - this.playingSinceMs);
|
|
2051
2082
|
let r = this.hiddenTotalMs;
|
|
@@ -2061,7 +2092,7 @@ var Ht = class {
|
|
|
2061
2092
|
let l = t.droppedFrames ?? 0;
|
|
2062
2093
|
l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
|
|
2063
2094
|
let u = t.renditionSwitches ?? 0;
|
|
2064
|
-
u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState =
|
|
2095
|
+
u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = J[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
|
|
2065
2096
|
let d = this.mutedTotalMs;
|
|
2066
2097
|
this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
|
|
2067
2098
|
let f = t.upshifts ?? 0;
|
|
@@ -2076,20 +2107,20 @@ var Ht = class {
|
|
|
2076
2107
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2077
2108
|
o.requestCountDelta = _;
|
|
2078
2109
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2079
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2110
|
+
n.length > 0 && (o.requestTimeP50Ms = zt(n, 50), o.requestTimeP95Ms = zt(n, 95));
|
|
2080
2111
|
}
|
|
2081
2112
|
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();
|
|
2082
2113
|
}
|
|
2083
2114
|
maybeEmitMediaInfo(e) {
|
|
2084
2115
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2085
2116
|
let t = {};
|
|
2086
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2117
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Rt[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);
|
|
2087
2118
|
let n = JSON.stringify(t);
|
|
2088
2119
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2089
2120
|
}
|
|
2090
2121
|
end(e, t) {
|
|
2091
2122
|
if (this.endedFlag) return;
|
|
2092
|
-
this.endedFlag = !0;
|
|
2123
|
+
this.endedFlag = !0, X.delete(this);
|
|
2093
2124
|
let n = t ?? this.now();
|
|
2094
2125
|
this.playingSinceMs !== null && (this.playingTotalMs += n - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += n - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += n - this.bufferingSinceMs, this.bufferingSinceMs = null), this.mutedSinceMs !== null && (this.mutedTotalMs += n - this.mutedSinceMs, this.mutedSinceMs = null), this.waitingSinceMs !== null && (this.waitingTotalMs += n - this.waitingSinceMs, this.waitingSinceMs = null), this.isPlaying = !1, this.syncActive(n), this.closePresentation(n), this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.timer &&= (clearInterval(this.timer), null), this.idleTimer &&= (clearTimeout(this.idleTimer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), document.removeEventListener("freeze", this.onFreeze), document.removeEventListener("resume", this.onResume));
|
|
2095
2126
|
let r = this.safeSample();
|
|
@@ -2103,7 +2134,7 @@ var Ht = class {
|
|
|
2103
2134
|
let c = r?.positionMs ?? 0;
|
|
2104
2135
|
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));
|
|
2105
2136
|
let l = e !== "END_REASON_ENDED";
|
|
2106
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2137
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= Ft && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Ft && (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);
|
|
2107
2138
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2108
2139
|
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");
|
|
2109
2140
|
}
|
|
@@ -2122,14 +2153,24 @@ var Ht = class {
|
|
|
2122
2153
|
...e
|
|
2123
2154
|
};
|
|
2124
2155
|
}
|
|
2156
|
+
noteCspBlocked() {
|
|
2157
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(Wt(new URL(this.url).origin)));
|
|
2158
|
+
}
|
|
2159
|
+
cspBlocked() {
|
|
2160
|
+
return !!this.cspKey && Y.has(this.cspKey);
|
|
2161
|
+
}
|
|
2125
2162
|
enqueue(e) {
|
|
2126
|
-
for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2163
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Nt;) {
|
|
2127
2164
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2128
2165
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2129
2166
|
}
|
|
2130
2167
|
}
|
|
2131
2168
|
flush(e = !1) {
|
|
2132
2169
|
if (this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.pendingStart = null, this.pending.length === 0) return;
|
|
2170
|
+
if (this.cspBlocked()) {
|
|
2171
|
+
this.pending = [];
|
|
2172
|
+
return;
|
|
2173
|
+
}
|
|
2133
2174
|
let t = JSON.stringify({ beacons: this.pending });
|
|
2134
2175
|
if (this.pending = [], e) {
|
|
2135
2176
|
let e = this.opts.sendBeacon ?? (typeof navigator < "u" && navigator.sendBeacon ? navigator.sendBeacon.bind(navigator) : void 0);
|
|
@@ -2146,7 +2187,7 @@ var Ht = class {
|
|
|
2146
2187
|
};
|
|
2147
2188
|
//#endregion
|
|
2148
2189
|
//#region src/core/environment.ts
|
|
2149
|
-
function
|
|
2190
|
+
function Yt() {
|
|
2150
2191
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2151
2192
|
let e;
|
|
2152
2193
|
try {
|
|
@@ -2171,14 +2212,14 @@ function Ut() {
|
|
|
2171
2212
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2172
2213
|
};
|
|
2173
2214
|
}
|
|
2174
|
-
function
|
|
2215
|
+
function Xt() {
|
|
2175
2216
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2176
2217
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2177
2218
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2178
2219
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2179
2220
|
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";
|
|
2180
2221
|
}
|
|
2181
|
-
function
|
|
2222
|
+
function Zt() {
|
|
2182
2223
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2183
2224
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2184
2225
|
let t = {
|
|
@@ -2197,17 +2238,17 @@ function Gt() {
|
|
|
2197
2238
|
}
|
|
2198
2239
|
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;
|
|
2199
2240
|
}
|
|
2200
|
-
function
|
|
2201
|
-
let t =
|
|
2202
|
-
deviceClass:
|
|
2241
|
+
function Qt(e) {
|
|
2242
|
+
let t = Yt(), n = {
|
|
2243
|
+
deviceClass: Xt(),
|
|
2203
2244
|
integration: t.integration,
|
|
2204
|
-
...
|
|
2245
|
+
...Zt()
|
|
2205
2246
|
};
|
|
2206
2247
|
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);
|
|
2207
2248
|
let r = e.getBoundingClientRect?.();
|
|
2208
2249
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2209
2250
|
}
|
|
2210
|
-
async function
|
|
2251
|
+
async function $t() {
|
|
2211
2252
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2212
2253
|
if (!e?.getHighEntropyValues) return {};
|
|
2213
2254
|
try {
|
|
@@ -2219,7 +2260,7 @@ async function qt() {
|
|
|
2219
2260
|
}
|
|
2220
2261
|
//#endregion
|
|
2221
2262
|
//#region src/core/version.ts
|
|
2222
|
-
var
|
|
2263
|
+
var en = "2.13.0", tn = {
|
|
2223
2264
|
accent: "#E1B600",
|
|
2224
2265
|
accentText: "#1B1C23",
|
|
2225
2266
|
background: "#0e0f13",
|
|
@@ -2230,7 +2271,7 @@ var Jt = "2.12.0", Yt = {
|
|
|
2230
2271
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2231
2272
|
radius: "8px",
|
|
2232
2273
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2233
|
-
},
|
|
2274
|
+
}, nn = {
|
|
2234
2275
|
accent: "--havik-accent",
|
|
2235
2276
|
accentText: "--havik-accent-text",
|
|
2236
2277
|
background: "--havik-bg",
|
|
@@ -2242,25 +2283,25 @@ var Jt = "2.12.0", Yt = {
|
|
|
2242
2283
|
radius: "--havik-radius",
|
|
2243
2284
|
fontFamily: "--havik-font"
|
|
2244
2285
|
};
|
|
2245
|
-
function
|
|
2286
|
+
function rn(e, t) {
|
|
2246
2287
|
let n = {
|
|
2247
|
-
...
|
|
2288
|
+
...tn,
|
|
2248
2289
|
...t
|
|
2249
2290
|
};
|
|
2250
|
-
for (let t of Object.keys(
|
|
2291
|
+
for (let t of Object.keys(nn)) e.style.setProperty(nn[t], n[t]);
|
|
2251
2292
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2252
2293
|
}
|
|
2253
2294
|
//#endregion
|
|
2254
2295
|
//#region src/ui/styles.ts
|
|
2255
|
-
var
|
|
2256
|
-
function
|
|
2257
|
-
if (e.getElementById(
|
|
2296
|
+
var an = "havik-player-styles", on = "\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.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";
|
|
2297
|
+
function sn(e = document) {
|
|
2298
|
+
if (e.getElementById(an)) return;
|
|
2258
2299
|
let t = e.createElement("style");
|
|
2259
|
-
t.id =
|
|
2300
|
+
t.id = an, t.textContent = on, e.head.appendChild(t);
|
|
2260
2301
|
}
|
|
2261
2302
|
//#endregion
|
|
2262
2303
|
//#region src/ui/icons.ts
|
|
2263
|
-
var
|
|
2304
|
+
var cn = {
|
|
2264
2305
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2265
2306
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2266
2307
|
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\"/>",
|
|
@@ -2274,20 +2315,20 @@ var tn = {
|
|
|
2274
2315
|
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\"/>"
|
|
2275
2316
|
};
|
|
2276
2317
|
function Z(e) {
|
|
2277
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2318
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${cn[e]}</svg>`;
|
|
2278
2319
|
}
|
|
2279
2320
|
//#endregion
|
|
2280
2321
|
//#region src/ui/controls.ts
|
|
2281
|
-
var
|
|
2322
|
+
var ln = 3e3, un = /* @__PURE__ */ new Set([
|
|
2282
2323
|
"GONE",
|
|
2283
2324
|
"NOT_FOUND",
|
|
2284
2325
|
"INVALID_URN",
|
|
2285
2326
|
"UNAUTHORIZED"
|
|
2286
2327
|
]);
|
|
2287
|
-
function
|
|
2288
|
-
return new
|
|
2328
|
+
function dn(e) {
|
|
2329
|
+
return new fn(e);
|
|
2289
2330
|
}
|
|
2290
|
-
var
|
|
2331
|
+
var fn = class {
|
|
2291
2332
|
root;
|
|
2292
2333
|
video;
|
|
2293
2334
|
player;
|
|
@@ -2329,7 +2370,7 @@ var on = class {
|
|
|
2329
2370
|
scrubbing = !1;
|
|
2330
2371
|
offFns = [];
|
|
2331
2372
|
constructor(e) {
|
|
2332
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2373
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? ln, 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), 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");
|
|
2333
2374
|
let t = (e, t, n) => {
|
|
2334
2375
|
let r = this.doc.createElement(e);
|
|
2335
2376
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2420,7 +2461,7 @@ var on = class {
|
|
|
2420
2461
|
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);
|
|
2421
2462
|
} else {
|
|
2422
2463
|
let r = this.doc.createElement("div");
|
|
2423
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2464
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !un.has(this.lastError.code)) {
|
|
2424
2465
|
let e = this.doc.createElement("button");
|
|
2425
2466
|
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);
|
|
2426
2467
|
}
|
|
@@ -2511,17 +2552,17 @@ var on = class {
|
|
|
2511
2552
|
renderQualityMenu() {
|
|
2512
2553
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2513
2554
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2514
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2555
|
+
for (let n of e) this.menu.append(this.menuItem(pn(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2515
2556
|
}
|
|
2516
2557
|
renderAudioMenu() {
|
|
2517
2558
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2518
2559
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2519
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2560
|
+
for (let t of e) this.menu.append(this.menuItem(mn(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2520
2561
|
}
|
|
2521
2562
|
renderCcMenu() {
|
|
2522
2563
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2523
2564
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2524
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2565
|
+
for (let t of e) this.menu.append(this.menuItem(hn(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2525
2566
|
}
|
|
2526
2567
|
onTracksChanged() {
|
|
2527
2568
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2541,11 +2582,11 @@ var on = class {
|
|
|
2541
2582
|
}
|
|
2542
2583
|
async toggleFullscreen() {
|
|
2543
2584
|
try {
|
|
2544
|
-
|
|
2585
|
+
S(this.video, this.root) ? await w(this.video, this.root) : await C(this.video, this.root);
|
|
2545
2586
|
} catch {}
|
|
2546
2587
|
}
|
|
2547
2588
|
syncFullscreen() {
|
|
2548
|
-
let e =
|
|
2589
|
+
let e = S(this.video, this.root);
|
|
2549
2590
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
2550
2591
|
}
|
|
2551
2592
|
poke() {
|
|
@@ -2626,36 +2667,36 @@ function Q(e) {
|
|
|
2626
2667
|
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");
|
|
2627
2668
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2628
2669
|
}
|
|
2629
|
-
function
|
|
2670
|
+
function pn(e) {
|
|
2630
2671
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2631
2672
|
}
|
|
2632
|
-
function
|
|
2673
|
+
function mn(e) {
|
|
2633
2674
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2634
2675
|
}
|
|
2635
|
-
function
|
|
2676
|
+
function hn(e) {
|
|
2636
2677
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2637
2678
|
}
|
|
2638
2679
|
//#endregion
|
|
2639
2680
|
//#region src/managed/index.ts
|
|
2640
|
-
var
|
|
2641
|
-
function
|
|
2681
|
+
var gn = 6e3, _n = 45e3, vn = 2e3, yn = 3, bn = 2e3, xn = 48e4;
|
|
2682
|
+
function Sn(e) {
|
|
2642
2683
|
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)})`);
|
|
2643
|
-
if (e.env !== void 0) return
|
|
2684
|
+
if (e.env !== void 0) return B(e.env);
|
|
2644
2685
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2645
2686
|
return e.baseUrl;
|
|
2646
2687
|
}
|
|
2647
|
-
async function
|
|
2688
|
+
async function Cn(e) {
|
|
2648
2689
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2649
|
-
let t =
|
|
2690
|
+
let t = Sn(e);
|
|
2650
2691
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2651
2692
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2652
|
-
let r = new
|
|
2693
|
+
let r = new wn({
|
|
2653
2694
|
...e,
|
|
2654
2695
|
baseUrl: t
|
|
2655
2696
|
});
|
|
2656
2697
|
return await r.start(), r;
|
|
2657
2698
|
}
|
|
2658
|
-
var
|
|
2699
|
+
var wn = class {
|
|
2659
2700
|
opts;
|
|
2660
2701
|
abort = new AbortController();
|
|
2661
2702
|
listeners = {};
|
|
@@ -2722,7 +2763,7 @@ var vn = class {
|
|
|
2722
2763
|
};
|
|
2723
2764
|
}
|
|
2724
2765
|
beginArming(e, t, n = !1) {
|
|
2725
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
2766
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
|
|
2726
2767
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
2727
2768
|
}
|
|
2728
2769
|
beginArmingByPolling(e) {
|
|
@@ -2743,7 +2784,7 @@ var vn = class {
|
|
|
2743
2784
|
setTimeout(() => {
|
|
2744
2785
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
2745
2786
|
phase: i ? "unavailable" : "tooEarly",
|
|
2746
|
-
retryInMs:
|
|
2787
|
+
retryInMs: _n,
|
|
2747
2788
|
attempt: 1,
|
|
2748
2789
|
elapsedMs: 0,
|
|
2749
2790
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -2782,13 +2823,13 @@ var vn = class {
|
|
|
2782
2823
|
!a && !p() && h();
|
|
2783
2824
|
}, e);
|
|
2784
2825
|
};
|
|
2785
|
-
_(
|
|
2826
|
+
_(gn), this.armingSub = T({
|
|
2786
2827
|
eventsBaseUrl: t,
|
|
2787
2828
|
matchUrn: this.opts.matchUrn,
|
|
2788
2829
|
credential: this.opts.credential,
|
|
2789
|
-
onAlive: () => _(
|
|
2830
|
+
onAlive: () => _(_n),
|
|
2790
2831
|
onState: (e) => {
|
|
2791
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
2832
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * vn);
|
|
2792
2833
|
},
|
|
2793
2834
|
onError: () => h()
|
|
2794
2835
|
});
|
|
@@ -2811,7 +2852,7 @@ var vn = class {
|
|
|
2811
2852
|
let n = await s(this.opts.credential);
|
|
2812
2853
|
if (this.destroyed || t !== this.loadGen) return;
|
|
2813
2854
|
this.setState("loading");
|
|
2814
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
2855
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = qe(this.opts.video, (e) => {
|
|
2815
2856
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
2816
2857
|
});
|
|
2817
2858
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -2833,23 +2874,26 @@ var vn = class {
|
|
|
2833
2874
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
2834
2875
|
let i = e.analytics?.sid;
|
|
2835
2876
|
if (!i) return;
|
|
2836
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
2877
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = qt(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
2837
2878
|
if (!o) {
|
|
2838
2879
|
s && setTimeout(() => {
|
|
2839
2880
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
2840
2881
|
}, 0);
|
|
2841
2882
|
return;
|
|
2842
2883
|
}
|
|
2843
|
-
let c = this.opts.video, l = new
|
|
2884
|
+
let c = this.opts.video, l = new Jt({
|
|
2844
2885
|
endpoint: o,
|
|
2845
2886
|
sid: i,
|
|
2846
2887
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
2847
|
-
sdkVersion:
|
|
2848
|
-
environment:
|
|
2888
|
+
sdkVersion: en,
|
|
2889
|
+
environment: Qt(c),
|
|
2849
2890
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
2850
2891
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
2892
|
+
onBlocked: (e) => setTimeout(() => {
|
|
2893
|
+
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
2894
|
+
}, 0),
|
|
2851
2895
|
sample: () => {
|
|
2852
|
-
let e = this.engine?.getStats() ??
|
|
2896
|
+
let e = this.engine?.getStats() ?? V, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
2853
2897
|
return {
|
|
2854
2898
|
...e,
|
|
2855
2899
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -2863,7 +2907,7 @@ var vn = class {
|
|
|
2863
2907
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
2864
2908
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
2865
2909
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
2866
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
2910
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), $t().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
2867
2911
|
}
|
|
2868
2912
|
currentPresentation() {
|
|
2869
2913
|
let e = this.opts.video;
|
|
@@ -2878,7 +2922,7 @@ var vn = class {
|
|
|
2878
2922
|
video: this.opts.video,
|
|
2879
2923
|
descriptor: e,
|
|
2880
2924
|
credential: t,
|
|
2881
|
-
deviceId:
|
|
2925
|
+
deviceId: k(),
|
|
2882
2926
|
userId: this.opts.userId,
|
|
2883
2927
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
2884
2928
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -2888,11 +2932,11 @@ var vn = class {
|
|
|
2888
2932
|
hlsConfig: i,
|
|
2889
2933
|
emit: (e) => this.onEngineEvent(e)
|
|
2890
2934
|
}, o = this.opts.engine ?? "auto";
|
|
2891
|
-
if (o === "native") return new
|
|
2892
|
-
if (o === "hls") return new
|
|
2893
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
2894
|
-
if (
|
|
2895
|
-
if (
|
|
2935
|
+
if (o === "native") return new K(a);
|
|
2936
|
+
if (o === "hls") return new kt(a);
|
|
2937
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G()) return new K(a);
|
|
2938
|
+
if (at()) return new kt(a);
|
|
2939
|
+
if (W(this.opts.video)) return new K(a);
|
|
2896
2940
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
2897
2941
|
}
|
|
2898
2942
|
onEngineEvent(e) {
|
|
@@ -2929,11 +2973,11 @@ var vn = class {
|
|
|
2929
2973
|
}
|
|
2930
2974
|
startLiveState(e) {
|
|
2931
2975
|
if (this.opts.liveStateEvents === !1) return;
|
|
2932
|
-
let t = this.opts.eventsBaseUrl ??
|
|
2976
|
+
let t = this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
|
|
2933
2977
|
if (!t) return;
|
|
2934
2978
|
this.closeLiveState();
|
|
2935
2979
|
let r = 0, i = !1;
|
|
2936
|
-
this.liveStateSub =
|
|
2980
|
+
this.liveStateSub = T({
|
|
2937
2981
|
eventsBaseUrl: t,
|
|
2938
2982
|
matchUrn: this.opts.matchUrn,
|
|
2939
2983
|
credential: this.opts.credential,
|
|
@@ -2944,7 +2988,7 @@ var vn = class {
|
|
|
2944
2988
|
r = 0, i = !1;
|
|
2945
2989
|
},
|
|
2946
2990
|
onError: () => {
|
|
2947
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
2991
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= yn && (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.`))));
|
|
2948
2992
|
}
|
|
2949
2993
|
});
|
|
2950
2994
|
}
|
|
@@ -2966,7 +3010,7 @@ var vn = class {
|
|
|
2966
3010
|
scheduleRejoin(e) {
|
|
2967
3011
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
2968
3012
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
2969
|
-
}, Math.random() *
|
|
3013
|
+
}, Math.random() * vn));
|
|
2970
3014
|
}
|
|
2971
3015
|
cancelRejoin() {
|
|
2972
3016
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -2990,7 +3034,7 @@ var vn = class {
|
|
|
2990
3034
|
}
|
|
2991
3035
|
t.controls = !1;
|
|
2992
3036
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
2993
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3037
|
+
r && r.insertBefore(n, t), n.appendChild(t), rn(n, this.opts.theme), this.container = n, this.controlBar = dn({
|
|
2994
3038
|
root: n,
|
|
2995
3039
|
video: t,
|
|
2996
3040
|
player: this,
|
|
@@ -3020,7 +3064,7 @@ var vn = class {
|
|
|
3020
3064
|
}
|
|
3021
3065
|
startStats() {
|
|
3022
3066
|
this.stopStats();
|
|
3023
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3067
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? bn);
|
|
3024
3068
|
this.statsTimer = setInterval(() => {
|
|
3025
3069
|
if (!this.engine) return;
|
|
3026
3070
|
let e = this.engine.getStats();
|
|
@@ -3032,7 +3076,7 @@ var vn = class {
|
|
|
3032
3076
|
}
|
|
3033
3077
|
scheduleLicenseRefresh() {
|
|
3034
3078
|
this.stopRefresh();
|
|
3035
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3079
|
+
let e = this.opts.licenseRefreshMs ?? xn;
|
|
3036
3080
|
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3037
3081
|
}
|
|
3038
3082
|
stopRefresh() {
|
|
@@ -3077,7 +3121,7 @@ var vn = class {
|
|
|
3077
3121
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3078
3122
|
}
|
|
3079
3123
|
getStats() {
|
|
3080
|
-
return this.engine?.getStats() ??
|
|
3124
|
+
return this.engine?.getStats() ?? V;
|
|
3081
3125
|
}
|
|
3082
3126
|
getQualityLevels() {
|
|
3083
3127
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3116,10 +3160,10 @@ var vn = class {
|
|
|
3116
3160
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
3117
3161
|
}
|
|
3118
3162
|
async enterFullscreen() {
|
|
3119
|
-
return !this.destroyed &&
|
|
3163
|
+
return !this.destroyed && C(this.opts.video, this.container ?? void 0);
|
|
3120
3164
|
}
|
|
3121
3165
|
async exitFullscreen() {
|
|
3122
|
-
await
|
|
3166
|
+
await w(this.opts.video, this.container ?? void 0);
|
|
3123
3167
|
}
|
|
3124
3168
|
retry() {
|
|
3125
3169
|
return this.reload();
|
|
@@ -3187,7 +3231,7 @@ function $(e) {
|
|
|
3187
3231
|
}
|
|
3188
3232
|
//#endregion
|
|
3189
3233
|
//#region src/embed/host.ts
|
|
3190
|
-
function
|
|
3234
|
+
function Tn(e) {
|
|
3191
3235
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3192
3236
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3193
3237
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3246,15 +3290,15 @@ function yn(e) {
|
|
|
3246
3290
|
}
|
|
3247
3291
|
//#endregion
|
|
3248
3292
|
//#region src/embed/page.ts
|
|
3249
|
-
var
|
|
3250
|
-
function
|
|
3293
|
+
var En = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3294
|
+
function Dn(e) {
|
|
3251
3295
|
if (typeof e == "boolean") return e;
|
|
3252
3296
|
if (typeof e == "object" && e) {
|
|
3253
3297
|
let t = e.endpoint;
|
|
3254
3298
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3255
3299
|
}
|
|
3256
3300
|
}
|
|
3257
|
-
function
|
|
3301
|
+
function On() {
|
|
3258
3302
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3259
3303
|
if (e) return {
|
|
3260
3304
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3264,7 +3308,7 @@ function Sn() {
|
|
|
3264
3308
|
autoplay: e.autoplay ?? !0,
|
|
3265
3309
|
muted: e.muted ?? !0,
|
|
3266
3310
|
waitForLive: e.waitForLive ?? !0,
|
|
3267
|
-
analytics:
|
|
3311
|
+
analytics: Dn(e.analytics)
|
|
3268
3312
|
};
|
|
3269
3313
|
let t = new URLSearchParams(location.search);
|
|
3270
3314
|
return {
|
|
@@ -3277,9 +3321,9 @@ function Sn() {
|
|
|
3277
3321
|
waitForLive: !0
|
|
3278
3322
|
};
|
|
3279
3323
|
}
|
|
3280
|
-
async function
|
|
3281
|
-
let e =
|
|
3282
|
-
|
|
3324
|
+
async function kn() {
|
|
3325
|
+
let e = On();
|
|
3326
|
+
jn();
|
|
3283
3327
|
let t = document.createElement("video");
|
|
3284
3328
|
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);
|
|
3285
3329
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3334,12 +3378,12 @@ async function Cn() {
|
|
|
3334
3378
|
code: e.code,
|
|
3335
3379
|
message: e.message
|
|
3336
3380
|
})), e.on("autoplayblocked", () => {
|
|
3337
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3381
|
+
i({ type: "oddin:autoplayblocked" }), An(t, e);
|
|
3338
3382
|
});
|
|
3339
3383
|
}, s = async (r) => {
|
|
3340
3384
|
a?.destroy(), a = null;
|
|
3341
3385
|
try {
|
|
3342
|
-
let n = await
|
|
3386
|
+
let n = await Cn({
|
|
3343
3387
|
video: t,
|
|
3344
3388
|
baseUrl: e.baseUrl,
|
|
3345
3389
|
matchUrn: r,
|
|
@@ -3401,7 +3445,7 @@ async function Cn() {
|
|
|
3401
3445
|
a?.retry();
|
|
3402
3446
|
break;
|
|
3403
3447
|
case "oddin:load":
|
|
3404
|
-
typeof e.matchUrn == "string" &&
|
|
3448
|
+
typeof e.matchUrn == "string" && En.test(e.matchUrn) && s(e.matchUrn);
|
|
3405
3449
|
break;
|
|
3406
3450
|
case "oddin:destroy": c();
|
|
3407
3451
|
}
|
|
@@ -3413,18 +3457,18 @@ async function Cn() {
|
|
|
3413
3457
|
protocol: 1
|
|
3414
3458
|
});
|
|
3415
3459
|
}
|
|
3416
|
-
function
|
|
3460
|
+
function An(e, t) {
|
|
3417
3461
|
if (document.getElementById("havik-tap")) return;
|
|
3418
3462
|
let n = document.createElement("button");
|
|
3419
3463
|
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", () => {
|
|
3420
3464
|
n.remove(), t.play();
|
|
3421
3465
|
}), document.body.appendChild(n);
|
|
3422
3466
|
}
|
|
3423
|
-
function
|
|
3467
|
+
function jn() {
|
|
3424
3468
|
let e = document.createElement("style");
|
|
3425
3469
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3426
3470
|
}
|
|
3427
3471
|
//#endregion
|
|
3428
|
-
export {
|
|
3472
|
+
export { tn as ODDIN_THEME, n as PlaybackError, rn as applyTheme, B as baseUrlForEnv, kn as bootEmbed, Te as clearDeviceId, Cn as createPlayer, E as deriveEventsBaseUrl, He as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, k as getDeviceId, We as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, Tn as mountEmbed, de as pollToLive, y as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
|
|
3429
3473
|
|
|
3430
3474
|
//# sourceMappingURL=index.js.map
|