@oddin-gg/havik-player 2.11.0 → 2.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/havik-player.global.js +17 -17
- 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.js +333 -267
- package/dist/index.js.map +1 -1
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -267,35 +267,35 @@ function de(e, t) {
|
|
|
267
267
|
}
|
|
268
268
|
//#endregion
|
|
269
269
|
//#region src/core/fullscreen.ts
|
|
270
|
-
function
|
|
270
|
+
function S(e) {
|
|
271
271
|
return e.ownerDocument ?? document;
|
|
272
272
|
}
|
|
273
|
-
function
|
|
273
|
+
function C(e) {
|
|
274
274
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
275
275
|
}
|
|
276
|
-
function
|
|
277
|
-
let n = S(
|
|
276
|
+
function w(e, t) {
|
|
277
|
+
let n = C(S(e));
|
|
278
278
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
279
279
|
}
|
|
280
|
-
async function
|
|
280
|
+
async function T(e, t) {
|
|
281
281
|
let n = t ?? e;
|
|
282
282
|
if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
|
|
283
283
|
if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
|
|
284
284
|
let r = e;
|
|
285
285
|
return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
|
|
286
286
|
}
|
|
287
|
-
async function
|
|
287
|
+
async function E(e, t) {
|
|
288
288
|
let n = e;
|
|
289
289
|
if (n.webkitDisplayingFullscreen) {
|
|
290
290
|
n.webkitExitFullscreen?.();
|
|
291
291
|
return;
|
|
292
292
|
}
|
|
293
|
-
let r =
|
|
293
|
+
let r = S(e), i = C(r);
|
|
294
294
|
i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
|
|
295
295
|
}
|
|
296
296
|
//#endregion
|
|
297
297
|
//#region src/core/catalog.ts
|
|
298
|
-
async function
|
|
298
|
+
async function fe(e) {
|
|
299
299
|
let t = new URLSearchParams();
|
|
300
300
|
e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
|
|
301
301
|
let i = t.toString(), a = d(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
|
|
@@ -313,12 +313,12 @@ async function pe(e) {
|
|
|
313
313
|
};
|
|
314
314
|
if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
|
|
315
315
|
return {
|
|
316
|
-
tournaments:
|
|
316
|
+
tournaments: pe(await s.json()),
|
|
317
317
|
etag: s.headers.get("etag") ?? void 0,
|
|
318
318
|
notModified: !1
|
|
319
319
|
};
|
|
320
320
|
}
|
|
321
|
-
function
|
|
321
|
+
function pe(e) {
|
|
322
322
|
return (e.tournaments ?? []).map((e) => {
|
|
323
323
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
324
324
|
return {
|
|
@@ -340,7 +340,7 @@ function me(e) {
|
|
|
340
340
|
};
|
|
341
341
|
});
|
|
342
342
|
}
|
|
343
|
-
async function
|
|
343
|
+
async function me(e) {
|
|
344
344
|
let t = d(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
345
345
|
e.etag && i.set("If-None-Match", e.etag);
|
|
346
346
|
let a = await p(t, {
|
|
@@ -360,13 +360,13 @@ async function he(e) {
|
|
|
360
360
|
};
|
|
361
361
|
if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
362
362
|
return {
|
|
363
|
-
tournament:
|
|
363
|
+
tournament: he(await a.json()),
|
|
364
364
|
etag: a.headers.get("etag") ?? void 0,
|
|
365
365
|
notModified: !1,
|
|
366
366
|
notFound: !1
|
|
367
367
|
};
|
|
368
368
|
}
|
|
369
|
-
function
|
|
369
|
+
function he(e) {
|
|
370
370
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
371
371
|
return {
|
|
372
372
|
urn: t,
|
|
@@ -386,12 +386,12 @@ function ge(e) {
|
|
|
386
386
|
}))
|
|
387
387
|
};
|
|
388
388
|
}
|
|
389
|
-
function
|
|
389
|
+
function ge(e) {
|
|
390
390
|
return e.tournaments.flatMap((e) => e.matches);
|
|
391
391
|
}
|
|
392
392
|
//#endregion
|
|
393
393
|
//#region src/core/poll.ts
|
|
394
|
-
function
|
|
394
|
+
function _e(e) {
|
|
395
395
|
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
|
|
396
396
|
u || (a = setTimeout(m, t));
|
|
397
397
|
}, m = async () => {
|
|
@@ -433,9 +433,9 @@ function ve(e) {
|
|
|
433
433
|
}
|
|
434
434
|
//#endregion
|
|
435
435
|
//#region src/core/events.ts
|
|
436
|
-
var
|
|
437
|
-
function
|
|
438
|
-
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ??
|
|
436
|
+
var ve = 45e3;
|
|
437
|
+
function D(e) {
|
|
438
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? ve, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
|
|
439
439
|
if (a.signal.aborted) return t();
|
|
440
440
|
let n = setTimeout(t, e);
|
|
441
441
|
a.signal.addEventListener("abort", () => {
|
|
@@ -516,7 +516,7 @@ function E(e) {
|
|
|
516
516
|
o || (o = !0, a.abort());
|
|
517
517
|
} };
|
|
518
518
|
}
|
|
519
|
-
function
|
|
519
|
+
function O(e) {
|
|
520
520
|
try {
|
|
521
521
|
let t = new URL(e);
|
|
522
522
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -526,27 +526,27 @@ function D(e) {
|
|
|
526
526
|
}
|
|
527
527
|
//#endregion
|
|
528
528
|
//#region src/core/drm/deviceId.ts
|
|
529
|
-
var
|
|
530
|
-
function
|
|
531
|
-
if (
|
|
529
|
+
var k = "havik.player.deviceId", A;
|
|
530
|
+
function j() {
|
|
531
|
+
if (A) return A;
|
|
532
532
|
try {
|
|
533
|
-
let e = globalThis.localStorage?.getItem(
|
|
534
|
-
if (e) return
|
|
533
|
+
let e = globalThis.localStorage?.getItem(k);
|
|
534
|
+
if (e) return A = e, e;
|
|
535
535
|
} catch {}
|
|
536
|
-
let e =
|
|
537
|
-
|
|
536
|
+
let e = be();
|
|
537
|
+
A = e;
|
|
538
538
|
try {
|
|
539
|
-
globalThis.localStorage?.setItem(
|
|
539
|
+
globalThis.localStorage?.setItem(k, e);
|
|
540
540
|
} catch {}
|
|
541
541
|
return e;
|
|
542
542
|
}
|
|
543
|
-
function
|
|
544
|
-
|
|
543
|
+
function ye() {
|
|
544
|
+
A = void 0;
|
|
545
545
|
try {
|
|
546
|
-
globalThis.localStorage?.removeItem(
|
|
546
|
+
globalThis.localStorage?.removeItem(k);
|
|
547
547
|
} catch {}
|
|
548
548
|
}
|
|
549
|
-
function
|
|
549
|
+
function be() {
|
|
550
550
|
let e = globalThis.crypto;
|
|
551
551
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
552
552
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -558,21 +558,21 @@ function xe() {
|
|
|
558
558
|
}
|
|
559
559
|
//#endregion
|
|
560
560
|
//#region src/core/drm/headers.ts
|
|
561
|
-
function
|
|
561
|
+
function xe(e, t, n = {}) {
|
|
562
562
|
let r = {
|
|
563
563
|
"x-api-key": t.apiKey,
|
|
564
564
|
"X-Match-Urn": e.matchUrn,
|
|
565
|
-
"X-Device-Id": n.deviceId ??
|
|
565
|
+
"X-Device-Id": n.deviceId ?? j(),
|
|
566
566
|
"Content-Type": "application/octet-stream"
|
|
567
567
|
};
|
|
568
568
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
569
569
|
}
|
|
570
570
|
//#endregion
|
|
571
571
|
//#region src/core/drm/cdm.ts
|
|
572
|
-
var
|
|
573
|
-
function
|
|
574
|
-
let n =
|
|
575
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
572
|
+
var M = /* @__PURE__ */ new WeakMap();
|
|
573
|
+
function Se(e, t) {
|
|
574
|
+
let n = M.get(e);
|
|
575
|
+
n || (n = /* @__PURE__ */ new Map(), M.set(e, n));
|
|
576
576
|
let r = n.get(t.keySystem);
|
|
577
577
|
if (r) return r;
|
|
578
578
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -580,22 +580,22 @@ function Ce(e, t) {
|
|
|
580
580
|
});
|
|
581
581
|
return n.set(t.keySystem, i), i;
|
|
582
582
|
}
|
|
583
|
-
function
|
|
583
|
+
function N() {
|
|
584
584
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
585
585
|
}
|
|
586
|
-
var
|
|
587
|
-
function
|
|
586
|
+
var P = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
587
|
+
function Ce(e) {
|
|
588
588
|
return e.startsWith("com.widevine");
|
|
589
589
|
}
|
|
590
|
-
function
|
|
591
|
-
if (!
|
|
590
|
+
function F(e, t) {
|
|
591
|
+
if (!Ce(e)) return t;
|
|
592
592
|
let n = (e, t) => {
|
|
593
593
|
let n = e.videoCapabilities;
|
|
594
594
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
595
|
-
let n =
|
|
596
|
-
return n === -1 ||
|
|
595
|
+
let n = P.indexOf(e.robustness);
|
|
596
|
+
return n === -1 || P.indexOf(t) > n;
|
|
597
597
|
});
|
|
598
|
-
}, r =
|
|
598
|
+
}, r = P.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
599
599
|
...t,
|
|
600
600
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
601
601
|
...t,
|
|
@@ -604,41 +604,87 @@ function P(e, t) {
|
|
|
604
604
|
})));
|
|
605
605
|
return [...t, ...r];
|
|
606
606
|
}
|
|
607
|
-
function
|
|
608
|
-
return (t, n) =>
|
|
607
|
+
function we(e) {
|
|
608
|
+
return (t, n) => N() ? navigator.requestMediaKeySystemAccess(t, F(t, n)).then((t) => ({
|
|
609
609
|
keySystem: t.keySystem,
|
|
610
610
|
getConfiguration: () => t.getConfiguration(),
|
|
611
|
-
createMediaKeys: () =>
|
|
611
|
+
createMediaKeys: () => Se(e, t)
|
|
612
612
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
613
613
|
}
|
|
614
|
-
var
|
|
614
|
+
var I = {
|
|
615
615
|
video: "SW_SECURE_DECODE",
|
|
616
616
|
audio: "SW_SECURE_CRYPTO",
|
|
617
617
|
scheme: "cbcs"
|
|
618
618
|
};
|
|
619
|
-
function
|
|
620
|
-
if (!
|
|
619
|
+
function Te(e) {
|
|
620
|
+
if (!N()) return;
|
|
621
621
|
let t = (e, t) => ({
|
|
622
622
|
contentType: e,
|
|
623
623
|
robustness: t,
|
|
624
|
-
encryptionScheme:
|
|
624
|
+
encryptionScheme: I.scheme
|
|
625
625
|
});
|
|
626
|
-
|
|
626
|
+
we(e)("com.widevine.alpha", [{
|
|
627
627
|
initDataTypes: ["cenc"],
|
|
628
628
|
distinctiveIdentifier: "optional",
|
|
629
629
|
persistentState: "optional",
|
|
630
630
|
sessionTypes: ["temporary"],
|
|
631
|
-
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"",
|
|
632
|
-
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"",
|
|
631
|
+
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", I.audio)],
|
|
632
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", I.video)]
|
|
633
633
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
634
634
|
}
|
|
635
|
+
function L(e) {
|
|
636
|
+
let t = R(e);
|
|
637
|
+
if (/^avc[13]/.test(t)) return "avc";
|
|
638
|
+
if (/^(hvc1|hev1)/.test(t)) return "hevc";
|
|
639
|
+
if (/^(dvh1|dvhe)/.test(t)) return "dv";
|
|
640
|
+
if (t.startsWith("av01")) return "av1";
|
|
641
|
+
if (/^vp0?9/.test(t)) return "vp9";
|
|
642
|
+
}
|
|
643
|
+
function R(e) {
|
|
644
|
+
return (e ?? "").trim().toLowerCase();
|
|
645
|
+
}
|
|
646
|
+
var Ee = {
|
|
647
|
+
hevc: "hvc1.1.6.L93.90",
|
|
648
|
+
dv: "dvh1.05.06",
|
|
649
|
+
av1: "av01.0.05M.08",
|
|
650
|
+
vp9: "vp09.00.10.08"
|
|
651
|
+
}, De = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Map();
|
|
652
|
+
function Oe(e) {
|
|
653
|
+
let t = R(e), n = De.get(t);
|
|
654
|
+
if (n) return n;
|
|
655
|
+
let r = {
|
|
656
|
+
initDataTypes: ["cenc"],
|
|
657
|
+
distinctiveIdentifier: "optional",
|
|
658
|
+
persistentState: "optional",
|
|
659
|
+
sessionTypes: ["temporary"],
|
|
660
|
+
videoCapabilities: [{
|
|
661
|
+
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
662
|
+
robustness: I.video,
|
|
663
|
+
encryptionScheme: I.scheme
|
|
664
|
+
}]
|
|
665
|
+
}, i = (async () => {
|
|
666
|
+
try {
|
|
667
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", F("com.widevine.alpha", [r])), !0;
|
|
668
|
+
} catch {
|
|
669
|
+
return !1;
|
|
670
|
+
}
|
|
671
|
+
})().then((e) => (z.set(t, e), e));
|
|
672
|
+
return De.set(t, i), i;
|
|
673
|
+
}
|
|
674
|
+
function ke() {
|
|
675
|
+
if (N()) for (let e of Object.values(Ee)) Oe(e);
|
|
676
|
+
}
|
|
677
|
+
function Ae(e) {
|
|
678
|
+
let t = L(e);
|
|
679
|
+
if (t) return t === "avc" ? !0 : z.get(R(e)) ?? z.get(R(Ee[t]));
|
|
680
|
+
}
|
|
635
681
|
//#endregion
|
|
636
682
|
//#region src/core/drm/support.ts
|
|
637
|
-
var
|
|
683
|
+
var je = 5e3, Me = "video/mp4; codecs=\"avc1.42E01E\"", B = "audio/mp4; codecs=\"mp4a.40.2\"", Ne = {
|
|
638
684
|
widevine: ["com.widevine.alpha"],
|
|
639
685
|
fairplay: ["com.apple.fps"]
|
|
640
686
|
};
|
|
641
|
-
function
|
|
687
|
+
function Pe(e) {
|
|
642
688
|
return e === "fairplay" ? [{
|
|
643
689
|
initDataTypes: [
|
|
644
690
|
"sinf",
|
|
@@ -646,30 +692,30 @@ function je(e) {
|
|
|
646
692
|
"cenc"
|
|
647
693
|
],
|
|
648
694
|
videoCapabilities: [{
|
|
649
|
-
contentType:
|
|
695
|
+
contentType: Me,
|
|
650
696
|
robustness: "",
|
|
651
697
|
encryptionScheme: "cbcs"
|
|
652
698
|
}],
|
|
653
699
|
audioCapabilities: [{
|
|
654
|
-
contentType:
|
|
700
|
+
contentType: B,
|
|
655
701
|
robustness: "",
|
|
656
702
|
encryptionScheme: "cbcs"
|
|
657
703
|
}]
|
|
658
|
-
}] :
|
|
704
|
+
}] : F("com.widevine.alpha", [{
|
|
659
705
|
initDataTypes: ["cenc"],
|
|
660
706
|
videoCapabilities: [{
|
|
661
|
-
contentType:
|
|
662
|
-
robustness:
|
|
663
|
-
encryptionScheme:
|
|
707
|
+
contentType: Me,
|
|
708
|
+
robustness: I.video,
|
|
709
|
+
encryptionScheme: I.scheme
|
|
664
710
|
}],
|
|
665
711
|
audioCapabilities: [{
|
|
666
|
-
contentType:
|
|
667
|
-
robustness:
|
|
668
|
-
encryptionScheme:
|
|
712
|
+
contentType: B,
|
|
713
|
+
robustness: I.audio,
|
|
714
|
+
encryptionScheme: I.scheme
|
|
669
715
|
}]
|
|
670
716
|
}]);
|
|
671
717
|
}
|
|
672
|
-
function
|
|
718
|
+
function V(e, t) {
|
|
673
719
|
return new Promise((n, r) => {
|
|
674
720
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
675
721
|
e.then((e) => {
|
|
@@ -679,8 +725,8 @@ function Me(e, t) {
|
|
|
679
725
|
});
|
|
680
726
|
});
|
|
681
727
|
}
|
|
682
|
-
async function
|
|
683
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
728
|
+
async function Fe(e = {}) {
|
|
729
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? je, r = {};
|
|
684
730
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
685
731
|
verdict: "insecure-context",
|
|
686
732
|
detail: r
|
|
@@ -692,7 +738,7 @@ async function Ne(e = {}) {
|
|
|
692
738
|
};
|
|
693
739
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
694
740
|
for (let e of t) {
|
|
695
|
-
let t =
|
|
741
|
+
let t = Ne[e];
|
|
696
742
|
if (!t) {
|
|
697
743
|
r[e] = "unknown system";
|
|
698
744
|
continue;
|
|
@@ -703,7 +749,7 @@ async function Ne(e = {}) {
|
|
|
703
749
|
break;
|
|
704
750
|
}
|
|
705
751
|
try {
|
|
706
|
-
return await
|
|
752
|
+
return await V((await V(i(n, Pe(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
707
753
|
verdict: "supported",
|
|
708
754
|
system: e,
|
|
709
755
|
detail: r
|
|
@@ -727,49 +773,49 @@ async function Ne(e = {}) {
|
|
|
727
773
|
}
|
|
728
774
|
//#endregion
|
|
729
775
|
//#region src/core/manifest.ts
|
|
730
|
-
var
|
|
731
|
-
function
|
|
732
|
-
return
|
|
776
|
+
var Ie = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
777
|
+
function Le(e) {
|
|
778
|
+
return Ie.test(e);
|
|
733
779
|
}
|
|
734
780
|
//#endregion
|
|
735
781
|
//#region src/core/env.ts
|
|
736
|
-
var
|
|
782
|
+
var H = {
|
|
737
783
|
integration: "https://feed-dev.oddin-video.gg",
|
|
738
784
|
production: "https://feed.oddin-video.gg"
|
|
739
785
|
};
|
|
740
|
-
function
|
|
741
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
786
|
+
function U(e) {
|
|
787
|
+
let t = Object.prototype.hasOwnProperty.call(H, e) ? H[e] : void 0;
|
|
742
788
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
743
789
|
return t;
|
|
744
790
|
}
|
|
745
791
|
//#endregion
|
|
746
792
|
//#region src/core/stats.ts
|
|
747
|
-
var
|
|
748
|
-
function
|
|
793
|
+
var W = { droppedFrames: 0 };
|
|
794
|
+
function G(e) {
|
|
749
795
|
try {
|
|
750
796
|
return new URL(e).host;
|
|
751
797
|
} catch {
|
|
752
798
|
return "";
|
|
753
799
|
}
|
|
754
800
|
}
|
|
755
|
-
var
|
|
756
|
-
function
|
|
801
|
+
var Re = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
802
|
+
function ze(e) {
|
|
757
803
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
758
804
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
759
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
760
|
-
let e =
|
|
805
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Re.test(i.name)) && i.startTime >= n) {
|
|
806
|
+
let e = G(i.name);
|
|
761
807
|
e && (t = e, n = i.startTime);
|
|
762
808
|
}
|
|
763
809
|
return t;
|
|
764
810
|
}
|
|
765
|
-
function
|
|
811
|
+
function K(e) {
|
|
766
812
|
let t = e.getVideoPlaybackQuality?.();
|
|
767
813
|
return {
|
|
768
814
|
dropped: t?.droppedVideoFrames ?? 0,
|
|
769
815
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
770
816
|
};
|
|
771
817
|
}
|
|
772
|
-
function
|
|
818
|
+
function Be(e, t) {
|
|
773
819
|
let n = [
|
|
774
820
|
["playing", () => t("playing")],
|
|
775
821
|
["waiting", () => t("buffering")],
|
|
@@ -786,7 +832,7 @@ function Re(e, t) {
|
|
|
786
832
|
}
|
|
787
833
|
//#endregion
|
|
788
834
|
//#region src/core/engine/native.ts
|
|
789
|
-
function
|
|
835
|
+
function Ve(e) {
|
|
790
836
|
try {
|
|
791
837
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
792
838
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -794,15 +840,15 @@ function ze(e) {
|
|
|
794
840
|
return;
|
|
795
841
|
}
|
|
796
842
|
}
|
|
797
|
-
function
|
|
843
|
+
function q(e) {
|
|
798
844
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
799
845
|
}
|
|
800
|
-
function
|
|
846
|
+
function J() {
|
|
801
847
|
if (typeof window > "u") return !1;
|
|
802
848
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
803
849
|
return e || t;
|
|
804
850
|
}
|
|
805
|
-
var
|
|
851
|
+
var Y = class {
|
|
806
852
|
name = "native";
|
|
807
853
|
deps;
|
|
808
854
|
onLoaded;
|
|
@@ -838,7 +884,7 @@ var U = class {
|
|
|
838
884
|
type: "error",
|
|
839
885
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
840
886
|
fatal: !0
|
|
841
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
887
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = He(t.manifestUrl, t.analytics?.sid), e.load();
|
|
842
888
|
}
|
|
843
889
|
startLoad() {
|
|
844
890
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -860,7 +906,7 @@ var U = class {
|
|
|
860
906
|
});
|
|
861
907
|
this.onEncrypted = (n) => {
|
|
862
908
|
let i = n;
|
|
863
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
909
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Ve(i.initData), (async () => {
|
|
864
910
|
try {
|
|
865
911
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
866
912
|
initDataTypes: [i.initDataType],
|
|
@@ -955,11 +1001,11 @@ var U = class {
|
|
|
955
1001
|
e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
|
|
956
1002
|
}
|
|
957
1003
|
getStats() {
|
|
958
|
-
let e = this.deps.video, t =
|
|
1004
|
+
let e = this.deps.video, t = K(e), n = {
|
|
959
1005
|
droppedFrames: t.dropped,
|
|
960
1006
|
decodedFrames: t.totalFrames
|
|
961
1007
|
};
|
|
962
|
-
return this.cdnHost ||=
|
|
1008
|
+
return this.cdnHost ||= ze(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;
|
|
963
1009
|
}
|
|
964
1010
|
stop() {
|
|
965
1011
|
try {
|
|
@@ -978,13 +1024,13 @@ var U = class {
|
|
|
978
1024
|
} catch {}
|
|
979
1025
|
}
|
|
980
1026
|
};
|
|
981
|
-
function
|
|
1027
|
+
function He(e, t) {
|
|
982
1028
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
983
1029
|
}
|
|
984
1030
|
//#endregion
|
|
985
1031
|
//#region src/core/engine/prefetch.ts
|
|
986
|
-
var
|
|
987
|
-
function
|
|
1032
|
+
var Ue = 15e3, We = 5e3, Ge = 6;
|
|
1033
|
+
function Ke(e) {
|
|
988
1034
|
try {
|
|
989
1035
|
let t = new URL(e);
|
|
990
1036
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -992,7 +1038,7 @@ function W(e) {
|
|
|
992
1038
|
return e;
|
|
993
1039
|
}
|
|
994
1040
|
}
|
|
995
|
-
var
|
|
1041
|
+
var qe = class {
|
|
996
1042
|
cmcd;
|
|
997
1043
|
entries = /* @__PURE__ */ new Map();
|
|
998
1044
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1015,10 +1061,10 @@ var We = class {
|
|
|
1015
1061
|
}
|
|
1016
1062
|
prefetch(e, t, n) {
|
|
1017
1063
|
if (!this.isActive(t)) return;
|
|
1018
|
-
let r =
|
|
1064
|
+
let r = Ke(e);
|
|
1019
1065
|
if (this.entries.has(r)) return;
|
|
1020
1066
|
let i = this.perTrack.get(t) ?? 0;
|
|
1021
|
-
if (i >=
|
|
1067
|
+
if (i >= Ge) return;
|
|
1022
1068
|
this.perTrack.set(t, i + 1);
|
|
1023
1069
|
let a = new AbortController(), o = {
|
|
1024
1070
|
started: performance.now(),
|
|
@@ -1032,10 +1078,10 @@ var We = class {
|
|
|
1032
1078
|
signal: a.signal
|
|
1033
1079
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1034
1080
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1035
|
-
},
|
|
1081
|
+
}, Ue);
|
|
1036
1082
|
}
|
|
1037
1083
|
take(e) {
|
|
1038
|
-
let t =
|
|
1084
|
+
let t = Ke(e), n = this.entries.get(t);
|
|
1039
1085
|
return n && this.entries.delete(t), n;
|
|
1040
1086
|
}
|
|
1041
1087
|
destroy() {
|
|
@@ -1055,13 +1101,13 @@ var We = class {
|
|
|
1055
1101
|
}
|
|
1056
1102
|
}
|
|
1057
1103
|
};
|
|
1058
|
-
function
|
|
1104
|
+
function Je(t) {
|
|
1059
1105
|
let n = e.DefaultConfig?.loader;
|
|
1060
1106
|
if (typeof n != "function") return;
|
|
1061
1107
|
class r extends n {
|
|
1062
1108
|
served = !1;
|
|
1063
1109
|
cancelled = !1;
|
|
1064
|
-
stats =
|
|
1110
|
+
stats = Ye();
|
|
1065
1111
|
load(e, n, r) {
|
|
1066
1112
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1067
1113
|
if (!i) {
|
|
@@ -1069,7 +1115,7 @@ function Ge(t) {
|
|
|
1069
1115
|
return;
|
|
1070
1116
|
}
|
|
1071
1117
|
this.served = !0;
|
|
1072
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1118
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || We, s = setTimeout(() => {
|
|
1073
1119
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1074
1120
|
}, o);
|
|
1075
1121
|
i.bytes.then((o) => {
|
|
@@ -1096,7 +1142,7 @@ function Ge(t) {
|
|
|
1096
1142
|
}
|
|
1097
1143
|
return r;
|
|
1098
1144
|
}
|
|
1099
|
-
function
|
|
1145
|
+
function Ye() {
|
|
1100
1146
|
return {
|
|
1101
1147
|
aborted: !1,
|
|
1102
1148
|
loaded: 0,
|
|
@@ -1120,10 +1166,10 @@ function Ke() {
|
|
|
1120
1166
|
}
|
|
1121
1167
|
};
|
|
1122
1168
|
}
|
|
1123
|
-
function
|
|
1169
|
+
function Xe(e) {
|
|
1124
1170
|
return e === "audio" ? "audio" : "main";
|
|
1125
1171
|
}
|
|
1126
|
-
function
|
|
1172
|
+
function Ze(e, t) {
|
|
1127
1173
|
let n = [];
|
|
1128
1174
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1129
1175
|
url: t.initSegment.url,
|
|
@@ -1142,24 +1188,24 @@ function qe(e, t) {
|
|
|
1142
1188
|
}
|
|
1143
1189
|
//#endregion
|
|
1144
1190
|
//#region src/core/engine/hls.ts
|
|
1145
|
-
function
|
|
1191
|
+
function Qe() {
|
|
1146
1192
|
return e.isSupported();
|
|
1147
1193
|
}
|
|
1148
|
-
var
|
|
1149
|
-
function
|
|
1194
|
+
var $e = 3, et = 5, tt = 3, nt = 3e4, rt = 12e3, it = 3e3, at = 6e3, ot = 5e3, st = 4e3, ct = 2, lt = 5, ut = 2, dt = 2, ft = 4, pt = 4, mt = 2e3, ht = 3e4, gt = 2, _t = 9, vt = .5, yt = 64;
|
|
1195
|
+
function bt(e) {
|
|
1150
1196
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1151
1197
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1152
1198
|
return;
|
|
1153
1199
|
}
|
|
1154
|
-
e.liveSyncDuration ??=
|
|
1155
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1156
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1200
|
+
e.liveSyncDuration ??= gt;
|
|
1201
|
+
let t = Math.max(12, e.liveSyncDuration + _t);
|
|
1202
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), xt(e, e.liveSyncDuration);
|
|
1157
1203
|
}
|
|
1158
|
-
function
|
|
1204
|
+
function xt(e, t) {
|
|
1159
1205
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1160
1206
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1161
1207
|
}
|
|
1162
|
-
var
|
|
1208
|
+
var St = class {
|
|
1163
1209
|
name = "hls";
|
|
1164
1210
|
hls = null;
|
|
1165
1211
|
deps;
|
|
@@ -1227,7 +1273,7 @@ var J = class {
|
|
|
1227
1273
|
this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1228
1274
|
}
|
|
1229
1275
|
async load() {
|
|
1230
|
-
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a =
|
|
1276
|
+
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = q(r) && J(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
1231
1277
|
if (e.drmEnabled && !o) {
|
|
1232
1278
|
i({
|
|
1233
1279
|
type: "error",
|
|
@@ -1236,7 +1282,7 @@ var J = class {
|
|
|
1236
1282
|
});
|
|
1237
1283
|
return;
|
|
1238
1284
|
}
|
|
1239
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc &&
|
|
1285
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Te(r), ke()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1240
1286
|
let e = this.hls;
|
|
1241
1287
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1242
1288
|
let t = e.liveSyncPosition;
|
|
@@ -1259,7 +1305,7 @@ var J = class {
|
|
|
1259
1305
|
}
|
|
1260
1306
|
this.loadSuspended = !0;
|
|
1261
1307
|
}
|
|
1262
|
-
},
|
|
1308
|
+
}, ot));
|
|
1263
1309
|
}
|
|
1264
1310
|
resumeLoading() {
|
|
1265
1311
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1291,7 +1337,7 @@ var J = class {
|
|
|
1291
1337
|
let t = e.liveSyncPosition;
|
|
1292
1338
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1293
1339
|
let { video: n } = this.deps;
|
|
1294
|
-
n.currentTime <= t +
|
|
1340
|
+
n.currentTime <= t + vt || (n.currentTime = t);
|
|
1295
1341
|
}
|
|
1296
1342
|
startHls() {
|
|
1297
1343
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1310,12 +1356,12 @@ var J = class {
|
|
|
1310
1356
|
emeEnabled: !0,
|
|
1311
1357
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1312
1358
|
drmSystemOptions: {
|
|
1313
|
-
videoRobustness:
|
|
1314
|
-
audioRobustness:
|
|
1315
|
-
videoEncryptionScheme:
|
|
1316
|
-
audioEncryptionScheme:
|
|
1359
|
+
videoRobustness: I.video,
|
|
1360
|
+
audioRobustness: I.audio,
|
|
1361
|
+
videoEncryptionScheme: I.scheme,
|
|
1362
|
+
audioEncryptionScheme: I.scheme
|
|
1317
1363
|
},
|
|
1318
|
-
...
|
|
1364
|
+
...N() ? { requestMediaKeySystemAccessFunc: we(t) } : {},
|
|
1319
1365
|
licenseXhrSetup: (e, t) => {
|
|
1320
1366
|
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;
|
|
1321
1367
|
let o = performance.now();
|
|
@@ -1332,22 +1378,20 @@ var J = class {
|
|
|
1332
1378
|
...c
|
|
1333
1379
|
};
|
|
1334
1380
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
|
|
1335
|
-
let e = new
|
|
1381
|
+
let e = new qe({
|
|
1336
1382
|
sessionId: n.analytics?.sid,
|
|
1337
1383
|
contentId: n.matchUrn
|
|
1338
|
-
}), t =
|
|
1384
|
+
}), t = Je(e);
|
|
1339
1385
|
t && (this.prefetch = e, d.fLoader = t);
|
|
1340
1386
|
}
|
|
1341
|
-
|
|
1387
|
+
bt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
|
|
1342
1388
|
let f = new e(d);
|
|
1343
1389
|
if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1344
|
-
this.mediaRecoveries = 0, this.networkRecoveries = 0;
|
|
1345
|
-
let e = f.levels.map((e) => e.height).filter((e) => !!e);
|
|
1346
|
-
this.ladderHeights = e.length ? [...new Set(e)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = f.levels.length ? Math.round(Math.max(...f.levels.map((e) => e.bitrate)) / 1e3) : 0, this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1390
|
+
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" });
|
|
1347
1391
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1348
1392
|
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(() => {
|
|
1349
1393
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1350
|
-
},
|
|
1394
|
+
}, nt)));
|
|
1351
1395
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1352
1396
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1353
1397
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1355,10 +1399,10 @@ var J = class {
|
|
|
1355
1399
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1356
1400
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1357
1401
|
let i = n?.loading;
|
|
1358
|
-
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 >
|
|
1402
|
+
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 > yt && this.requestTimesMs.shift());
|
|
1359
1403
|
let a = t?.frag?.url;
|
|
1360
1404
|
if (a) {
|
|
1361
|
-
let e =
|
|
1405
|
+
let e = G(a);
|
|
1362
1406
|
e && (this.cdnHost = e);
|
|
1363
1407
|
}
|
|
1364
1408
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1372,15 +1416,15 @@ var J = class {
|
|
|
1372
1416
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1373
1417
|
let t = this.prefetch;
|
|
1374
1418
|
f.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1375
|
-
let r = n?.frag, i =
|
|
1376
|
-
if (r && t.isActive(i)) for (let e of
|
|
1377
|
-
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1419
|
+
let r = n?.frag, i = Xe(r?.type);
|
|
1420
|
+
if (r && t.isActive(i)) for (let e of Ze(f, r)) t.prefetch(e.url, i, e.kind);
|
|
1421
|
+
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Xe(n?.frag?.type)));
|
|
1378
1422
|
}
|
|
1379
1423
|
f.on(e.Events.KEY_LOADED, () => {
|
|
1380
1424
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1381
1425
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1382
1426
|
this.checkEndStale(), this.checkStarvation();
|
|
1383
|
-
},
|
|
1427
|
+
}, it), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1384
1428
|
this.renditionSwitches += 1;
|
|
1385
1429
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1386
1430
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1444,11 +1488,33 @@ var J = class {
|
|
|
1444
1488
|
return;
|
|
1445
1489
|
}
|
|
1446
1490
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1447
|
-
let t = e > this.sizeCapLevel ?
|
|
1491
|
+
let t = e > this.sizeCapLevel ? mt : ht;
|
|
1448
1492
|
this.capTimer = setTimeout(() => {
|
|
1449
1493
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1450
1494
|
}, t);
|
|
1451
1495
|
}
|
|
1496
|
+
measureLadder(e) {
|
|
1497
|
+
let t = e.levels.map((e) => e.height).filter((e) => !!e);
|
|
1498
|
+
this.ladderHeights = t.length ? [...new Set(t)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = e.levels.length ? Math.round(Math.max(...e.levels.map((e) => e.bitrate)) / 1e3) : 0;
|
|
1499
|
+
}
|
|
1500
|
+
dropLevelsWidevineCannotPlay(e) {
|
|
1501
|
+
this.removeLevelsWhere(e, (e) => Ae(e) !== !0);
|
|
1502
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && L(e) !== "avc" && !!L(e)));
|
|
1503
|
+
for (let n of t) Oe(n).then((t) => {
|
|
1504
|
+
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
removeLevelsWhere(e, t) {
|
|
1508
|
+
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1509
|
+
if (n.forEach((e, n) => {
|
|
1510
|
+
let a = e.videoCodec;
|
|
1511
|
+
a && L(a) && t(a) && (r.push(n), i.add(a));
|
|
1512
|
+
}), !r.length) return !1;
|
|
1513
|
+
let a = [...i].join(", ");
|
|
1514
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !L(e.videoCodec) || Ae(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1515
|
+
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1516
|
+
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1517
|
+
}
|
|
1452
1518
|
applySizeCap() {
|
|
1453
1519
|
if (!this.sizeCapManaged) return;
|
|
1454
1520
|
this.capTimer &&= (clearTimeout(this.capTimer), null);
|
|
@@ -1491,7 +1557,7 @@ var J = class {
|
|
|
1491
1557
|
e.widevine && (this.licenseUrl = e.widevine);
|
|
1492
1558
|
}
|
|
1493
1559
|
getStats() {
|
|
1494
|
-
let e = this.hls, t =
|
|
1560
|
+
let e = this.hls, t = K(this.deps.video), n = {
|
|
1495
1561
|
droppedFrames: t.dropped,
|
|
1496
1562
|
decodedFrames: t.totalFrames,
|
|
1497
1563
|
lowLatency: this.detectedLowLatency,
|
|
@@ -1537,7 +1603,7 @@ var J = class {
|
|
|
1537
1603
|
return;
|
|
1538
1604
|
}
|
|
1539
1605
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1540
|
-
!this.chaseSuspended && e >
|
|
1606
|
+
!this.chaseSuspended && e > at && this.suspendChasing(), e > rt && this.emitEnded("stalled");
|
|
1541
1607
|
}
|
|
1542
1608
|
resetStarvationWindow() {
|
|
1543
1609
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1552,7 +1618,7 @@ var J = class {
|
|
|
1552
1618
|
this.resetStarvationWindow();
|
|
1553
1619
|
return;
|
|
1554
1620
|
}
|
|
1555
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1621
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < at, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > st, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = K(t), c = o - s, l = c !== this.starvedFrames;
|
|
1556
1622
|
if (this.starvedFrames = c, !a || l) {
|
|
1557
1623
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1558
1624
|
return;
|
|
@@ -1561,12 +1627,12 @@ var J = class {
|
|
|
1561
1627
|
this.resetStarvationWindow();
|
|
1562
1628
|
return;
|
|
1563
1629
|
}
|
|
1564
|
-
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 >
|
|
1630
|
+
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 > ft && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= ut && (this.clearKick(), this.starvationRebuilds < dt)) {
|
|
1565
1631
|
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");
|
|
1566
1632
|
return;
|
|
1567
1633
|
}
|
|
1568
|
-
let u = i && this.starvedTicks >=
|
|
1569
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1634
|
+
let u = i && this.starvedTicks >= ct, d = !i && this.deadTicks >= ft && this.recentMainFrags.reduce((e, t) => e + t, 0) >= pt;
|
|
1635
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= lt))) {
|
|
1570
1636
|
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");
|
|
1571
1637
|
try {
|
|
1572
1638
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1615,7 +1681,7 @@ var J = class {
|
|
|
1615
1681
|
scheduleLicenseRetry(t) {
|
|
1616
1682
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1617
1683
|
let n = t.response?.code ?? 0;
|
|
1618
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1684
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= tt) return !1;
|
|
1619
1685
|
this.licenseRecoveries += 1;
|
|
1620
1686
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1621
1687
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1647,7 +1713,7 @@ var J = class {
|
|
|
1647
1713
|
return;
|
|
1648
1714
|
}
|
|
1649
1715
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1650
|
-
if (this.networkRecoveries <
|
|
1716
|
+
if (this.networkRecoveries < et) {
|
|
1651
1717
|
this.networkRecoveries += 1;
|
|
1652
1718
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1653
1719
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1664,7 +1730,7 @@ var J = class {
|
|
|
1664
1730
|
return;
|
|
1665
1731
|
}
|
|
1666
1732
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1667
|
-
if (this.mediaRecoveries <
|
|
1733
|
+
if (this.mediaRecoveries < $e) {
|
|
1668
1734
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1669
1735
|
return;
|
|
1670
1736
|
}
|
|
@@ -1688,19 +1754,19 @@ var J = class {
|
|
|
1688
1754
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1689
1755
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1690
1756
|
}
|
|
1691
|
-
},
|
|
1757
|
+
}, Ct = 15e3, wt = 6e5, Tt = 3e5, Et = 100, X = 1, Dt = 1e3, Ot = 3e4, kt = 1e3, At = {
|
|
1692
1758
|
inline: "PRESENTATION_INLINE",
|
|
1693
1759
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1694
1760
|
pip: "PRESENTATION_PIP"
|
|
1695
|
-
},
|
|
1761
|
+
}, jt = {
|
|
1696
1762
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1697
1763
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1698
1764
|
none: "KEY_SYSTEM_NONE"
|
|
1699
1765
|
};
|
|
1700
|
-
function
|
|
1766
|
+
function Mt(e, t) {
|
|
1701
1767
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1702
1768
|
}
|
|
1703
|
-
var
|
|
1769
|
+
var Nt = /* @__PURE__ */ new Set([
|
|
1704
1770
|
"INVALID_URN",
|
|
1705
1771
|
"NOT_FOUND",
|
|
1706
1772
|
"GONE",
|
|
@@ -1710,7 +1776,7 @@ var Et = /* @__PURE__ */ new Set([
|
|
|
1710
1776
|
"FORBIDDEN",
|
|
1711
1777
|
"RATE_LIMITED",
|
|
1712
1778
|
"TIMEOUT"
|
|
1713
|
-
]),
|
|
1779
|
+
]), Z = {
|
|
1714
1780
|
idle: "PLAYER_STATE_IDLE",
|
|
1715
1781
|
waiting: "PLAYER_STATE_WAITING",
|
|
1716
1782
|
loading: "PLAYER_STATE_LOADING",
|
|
@@ -1720,7 +1786,7 @@ var Et = /* @__PURE__ */ new Set([
|
|
|
1720
1786
|
ended: "PLAYER_STATE_ENDED",
|
|
1721
1787
|
error: "PLAYER_STATE_ERROR"
|
|
1722
1788
|
};
|
|
1723
|
-
function
|
|
1789
|
+
function Pt(e) {
|
|
1724
1790
|
try {
|
|
1725
1791
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1726
1792
|
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);
|
|
@@ -1728,14 +1794,14 @@ function Dt(e) {
|
|
|
1728
1794
|
return;
|
|
1729
1795
|
}
|
|
1730
1796
|
}
|
|
1731
|
-
var
|
|
1732
|
-
function
|
|
1733
|
-
return
|
|
1797
|
+
var Ft = /* @__PURE__ */ new Set();
|
|
1798
|
+
function It(e, t) {
|
|
1799
|
+
return Ft.has(e) || (Ft.add(e), console.warn(`havik-player: ${t}`)), { disabledReason: t };
|
|
1734
1800
|
}
|
|
1735
|
-
function
|
|
1801
|
+
function Lt(e, t) {
|
|
1736
1802
|
if (t) return { endpoint: t };
|
|
1737
|
-
if (t !== void 0) return
|
|
1738
|
-
let n =
|
|
1803
|
+
if (t !== void 0) return It("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).");
|
|
1804
|
+
let n = Pt(e);
|
|
1739
1805
|
if (n) return { endpoint: n };
|
|
1740
1806
|
let r;
|
|
1741
1807
|
try {
|
|
@@ -1743,9 +1809,9 @@ function At(e, t) {
|
|
|
1743
1809
|
} catch {
|
|
1744
1810
|
r = e;
|
|
1745
1811
|
}
|
|
1746
|
-
return
|
|
1812
|
+
return It(r, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${r}" — 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).`);
|
|
1747
1813
|
}
|
|
1748
|
-
var
|
|
1814
|
+
var Rt = class {
|
|
1749
1815
|
opts;
|
|
1750
1816
|
url;
|
|
1751
1817
|
now;
|
|
@@ -1825,8 +1891,8 @@ var jt = class {
|
|
|
1825
1891
|
constructor(e) {
|
|
1826
1892
|
this.opts = {
|
|
1827
1893
|
...e,
|
|
1828
|
-
heartbeatMs: e.heartbeatMs ??
|
|
1829
|
-
idleMs: e.idleMs ??
|
|
1894
|
+
heartbeatMs: e.heartbeatMs ?? Ct,
|
|
1895
|
+
idleMs: e.idleMs ?? wt
|
|
1830
1896
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs, this.startupAnchorMs = this.bornMs;
|
|
1831
1897
|
}
|
|
1832
1898
|
start() {
|
|
@@ -1836,11 +1902,11 @@ var jt = class {
|
|
|
1836
1902
|
sdkVersion: this.opts.sdkVersion,
|
|
1837
1903
|
...this.opts.environment
|
|
1838
1904
|
};
|
|
1839
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
1905
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Dt), 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.onVisibility());
|
|
1840
1906
|
}
|
|
1841
1907
|
checkSuspension(e) {
|
|
1842
1908
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
1843
|
-
let t = Math.max(this.opts.idleMs,
|
|
1909
|
+
let t = Math.max(this.opts.idleMs, Tt);
|
|
1844
1910
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
1845
1911
|
}
|
|
1846
1912
|
syncIdle(e) {
|
|
@@ -1854,21 +1920,21 @@ var jt = class {
|
|
|
1854
1920
|
noteStateChange(e, t, n, r) {
|
|
1855
1921
|
if (this.endedFlag || e === t) return;
|
|
1856
1922
|
let i = this.now();
|
|
1857
|
-
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(
|
|
1923
|
+
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(X, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(X, 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") {
|
|
1858
1924
|
this.stallIsSeekInduced = this.seekInduced(i);
|
|
1859
1925
|
let e = !this.isHidden && !this.stallIsSeekInduced;
|
|
1860
|
-
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(
|
|
1926
|
+
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(X, Math.round(this.playingTotalMs)));
|
|
1861
1927
|
} else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
|
|
1862
1928
|
this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
|
|
1863
1929
|
let a = {
|
|
1864
|
-
fromState:
|
|
1865
|
-
toState:
|
|
1866
|
-
presentation:
|
|
1930
|
+
fromState: Z[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1931
|
+
toState: Z[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1932
|
+
presentation: At[this.presentation]
|
|
1867
1933
|
}, o = this.causeOf(e, t, i);
|
|
1868
1934
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
1869
1935
|
}
|
|
1870
1936
|
seekInduced(e) {
|
|
1871
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
1937
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < kt;
|
|
1872
1938
|
}
|
|
1873
1939
|
causeOf(e, t, n) {
|
|
1874
1940
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -1905,25 +1971,25 @@ var jt = class {
|
|
|
1905
1971
|
}
|
|
1906
1972
|
this.muteChanges += 1;
|
|
1907
1973
|
let r = this.now();
|
|
1908
|
-
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(
|
|
1974
|
+
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(X, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
|
|
1909
1975
|
}
|
|
1910
1976
|
notePresentation(e) {
|
|
1911
1977
|
this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
|
|
1912
1978
|
}
|
|
1913
1979
|
notePlayIntent() {
|
|
1914
|
-
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs =
|
|
1980
|
+
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = X), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = X), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = X), this.drmSetupMs > 0 && (this.drmSetupMs = X));
|
|
1915
1981
|
}
|
|
1916
1982
|
noteReady() {
|
|
1917
|
-
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(
|
|
1983
|
+
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(X, this.now() - this.startupAnchorMs));
|
|
1918
1984
|
}
|
|
1919
1985
|
noteFirstPlaylist() {
|
|
1920
|
-
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(
|
|
1986
|
+
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(X, this.now() - this.startupAnchorMs));
|
|
1921
1987
|
}
|
|
1922
1988
|
noteDrmReady() {
|
|
1923
|
-
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(
|
|
1989
|
+
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(X, this.now() - this.startupAnchorMs));
|
|
1924
1990
|
}
|
|
1925
1991
|
noteFirstBytes() {
|
|
1926
|
-
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(
|
|
1992
|
+
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(X, this.now() - this.startupAnchorMs));
|
|
1927
1993
|
}
|
|
1928
1994
|
noteSeek() {
|
|
1929
1995
|
this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
|
|
@@ -1942,7 +2008,7 @@ var jt = class {
|
|
|
1942
2008
|
let r = n ?? "";
|
|
1943
2009
|
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";
|
|
1944
2010
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
1945
|
-
if (
|
|
2011
|
+
if (Nt.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
1946
2012
|
let i = t ?? "";
|
|
1947
2013
|
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";
|
|
1948
2014
|
}
|
|
@@ -1974,7 +2040,7 @@ var jt = class {
|
|
|
1974
2040
|
let l = t.droppedFrames ?? 0;
|
|
1975
2041
|
l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
|
|
1976
2042
|
let u = t.renditionSwitches ?? 0;
|
|
1977
|
-
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 =
|
|
2043
|
+
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 = Z[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
|
|
1978
2044
|
let d = this.mutedTotalMs;
|
|
1979
2045
|
this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
|
|
1980
2046
|
let f = t.upshifts ?? 0;
|
|
@@ -1989,14 +2055,14 @@ var jt = class {
|
|
|
1989
2055
|
if (this.lastRequestCount = g, _ > 0) {
|
|
1990
2056
|
o.requestCountDelta = _;
|
|
1991
2057
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
1992
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2058
|
+
n.length > 0 && (o.requestTimeP50Ms = Mt(n, 50), o.requestTimeP95Ms = Mt(n, 95));
|
|
1993
2059
|
}
|
|
1994
2060
|
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();
|
|
1995
2061
|
}
|
|
1996
2062
|
maybeEmitMediaInfo(e) {
|
|
1997
2063
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
1998
2064
|
let t = {};
|
|
1999
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2065
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = jt[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);
|
|
2000
2066
|
let n = JSON.stringify(t);
|
|
2001
2067
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2002
2068
|
}
|
|
@@ -2016,7 +2082,7 @@ var jt = class {
|
|
|
2016
2082
|
let c = r?.positionMs ?? 0;
|
|
2017
2083
|
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));
|
|
2018
2084
|
let l = e !== "END_REASON_ENDED";
|
|
2019
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2085
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= Ot && (i.abandonAfterStallMs = Math.max(X, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Ot && (i.abandonAfterErrorMs = Math.max(X, 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);
|
|
2020
2086
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2021
2087
|
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");
|
|
2022
2088
|
}
|
|
@@ -2036,7 +2102,7 @@ var jt = class {
|
|
|
2036
2102
|
};
|
|
2037
2103
|
}
|
|
2038
2104
|
enqueue(e) {
|
|
2039
|
-
for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2105
|
+
for (this.pending.push(this.wrap(e)); this.pending.length > Et;) {
|
|
2040
2106
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2041
2107
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2042
2108
|
}
|
|
@@ -2059,7 +2125,7 @@ var jt = class {
|
|
|
2059
2125
|
};
|
|
2060
2126
|
//#endregion
|
|
2061
2127
|
//#region src/core/environment.ts
|
|
2062
|
-
function
|
|
2128
|
+
function zt() {
|
|
2063
2129
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2064
2130
|
let e;
|
|
2065
2131
|
try {
|
|
@@ -2084,14 +2150,14 @@ function Mt() {
|
|
|
2084
2150
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2085
2151
|
};
|
|
2086
2152
|
}
|
|
2087
|
-
function
|
|
2153
|
+
function Bt() {
|
|
2088
2154
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2089
2155
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2090
2156
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2091
2157
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2092
2158
|
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";
|
|
2093
2159
|
}
|
|
2094
|
-
function
|
|
2160
|
+
function Vt() {
|
|
2095
2161
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2096
2162
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2097
2163
|
let t = {
|
|
@@ -2110,17 +2176,17 @@ function Pt() {
|
|
|
2110
2176
|
}
|
|
2111
2177
|
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;
|
|
2112
2178
|
}
|
|
2113
|
-
function
|
|
2114
|
-
let t =
|
|
2115
|
-
deviceClass:
|
|
2179
|
+
function Ht(e) {
|
|
2180
|
+
let t = zt(), n = {
|
|
2181
|
+
deviceClass: Bt(),
|
|
2116
2182
|
integration: t.integration,
|
|
2117
|
-
...
|
|
2183
|
+
...Vt()
|
|
2118
2184
|
};
|
|
2119
2185
|
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);
|
|
2120
2186
|
let r = e.getBoundingClientRect?.();
|
|
2121
2187
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2122
2188
|
}
|
|
2123
|
-
async function
|
|
2189
|
+
async function Ut() {
|
|
2124
2190
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2125
2191
|
if (!e?.getHighEntropyValues) return {};
|
|
2126
2192
|
try {
|
|
@@ -2132,7 +2198,7 @@ async function It() {
|
|
|
2132
2198
|
}
|
|
2133
2199
|
//#endregion
|
|
2134
2200
|
//#region src/core/version.ts
|
|
2135
|
-
var
|
|
2201
|
+
var Wt = "2.11.1", Gt = {
|
|
2136
2202
|
accent: "#E1B600",
|
|
2137
2203
|
accentText: "#1B1C23",
|
|
2138
2204
|
background: "#0e0f13",
|
|
@@ -2143,7 +2209,7 @@ var Lt = "2.11.0", Rt = {
|
|
|
2143
2209
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2144
2210
|
radius: "8px",
|
|
2145
2211
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2146
|
-
},
|
|
2212
|
+
}, Kt = {
|
|
2147
2213
|
accent: "--havik-accent",
|
|
2148
2214
|
accentText: "--havik-accent-text",
|
|
2149
2215
|
background: "--havik-bg",
|
|
@@ -2155,25 +2221,25 @@ var Lt = "2.11.0", Rt = {
|
|
|
2155
2221
|
radius: "--havik-radius",
|
|
2156
2222
|
fontFamily: "--havik-font"
|
|
2157
2223
|
};
|
|
2158
|
-
function
|
|
2224
|
+
function qt(e, t) {
|
|
2159
2225
|
let n = {
|
|
2160
|
-
...
|
|
2226
|
+
...Gt,
|
|
2161
2227
|
...t
|
|
2162
2228
|
};
|
|
2163
|
-
for (let t of Object.keys(
|
|
2229
|
+
for (let t of Object.keys(Kt)) e.style.setProperty(Kt[t], n[t]);
|
|
2164
2230
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2165
2231
|
}
|
|
2166
2232
|
//#endregion
|
|
2167
2233
|
//#region src/ui/styles.ts
|
|
2168
|
-
var
|
|
2169
|
-
function
|
|
2170
|
-
if (e.getElementById(
|
|
2234
|
+
var Jt = "havik-player-styles", Yt = "\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";
|
|
2235
|
+
function Xt(e = document) {
|
|
2236
|
+
if (e.getElementById(Jt)) return;
|
|
2171
2237
|
let t = e.createElement("style");
|
|
2172
|
-
t.id =
|
|
2238
|
+
t.id = Jt, t.textContent = Yt, e.head.appendChild(t);
|
|
2173
2239
|
}
|
|
2174
2240
|
//#endregion
|
|
2175
2241
|
//#region src/ui/icons.ts
|
|
2176
|
-
var
|
|
2242
|
+
var Zt = {
|
|
2177
2243
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2178
2244
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2179
2245
|
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\"/>",
|
|
@@ -2187,20 +2253,20 @@ var Ut = {
|
|
|
2187
2253
|
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\"/>"
|
|
2188
2254
|
};
|
|
2189
2255
|
function Q(e) {
|
|
2190
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2256
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Zt[e]}</svg>`;
|
|
2191
2257
|
}
|
|
2192
2258
|
//#endregion
|
|
2193
2259
|
//#region src/ui/controls.ts
|
|
2194
|
-
var
|
|
2260
|
+
var Qt = 3e3, $t = /* @__PURE__ */ new Set([
|
|
2195
2261
|
"GONE",
|
|
2196
2262
|
"NOT_FOUND",
|
|
2197
2263
|
"INVALID_URN",
|
|
2198
2264
|
"UNAUTHORIZED"
|
|
2199
2265
|
]);
|
|
2200
|
-
function
|
|
2201
|
-
return new
|
|
2266
|
+
function en(e) {
|
|
2267
|
+
return new tn(e);
|
|
2202
2268
|
}
|
|
2203
|
-
var
|
|
2269
|
+
var tn = class {
|
|
2204
2270
|
root;
|
|
2205
2271
|
video;
|
|
2206
2272
|
player;
|
|
@@ -2242,7 +2308,7 @@ var qt = class {
|
|
|
2242
2308
|
scrubbing = !1;
|
|
2243
2309
|
offFns = [];
|
|
2244
2310
|
constructor(e) {
|
|
2245
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2311
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Qt, 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, Xt(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");
|
|
2246
2312
|
let t = (e, t, n) => {
|
|
2247
2313
|
let r = this.doc.createElement(e);
|
|
2248
2314
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2333,7 +2399,7 @@ var qt = class {
|
|
|
2333
2399
|
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Q("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
|
|
2334
2400
|
} else {
|
|
2335
2401
|
let r = this.doc.createElement("div");
|
|
2336
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError &&
|
|
2402
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !$t.has(this.lastError.code)) {
|
|
2337
2403
|
let e = this.doc.createElement("button");
|
|
2338
2404
|
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Q("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
2339
2405
|
}
|
|
@@ -2374,7 +2440,7 @@ var qt = class {
|
|
|
2374
2440
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2375
2441
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2376
2442
|
}
|
|
2377
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2443
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${nn(this.video.currentTime)} / ${nn(this.video.duration)}`);
|
|
2378
2444
|
}
|
|
2379
2445
|
syncLive() {
|
|
2380
2446
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2424,17 +2490,17 @@ var qt = class {
|
|
|
2424
2490
|
renderQualityMenu() {
|
|
2425
2491
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2426
2492
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2427
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2493
|
+
for (let n of e) this.menu.append(this.menuItem(rn(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2428
2494
|
}
|
|
2429
2495
|
renderAudioMenu() {
|
|
2430
2496
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2431
2497
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2432
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2498
|
+
for (let t of e) this.menu.append(this.menuItem(an(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2433
2499
|
}
|
|
2434
2500
|
renderCcMenu() {
|
|
2435
2501
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2436
2502
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2437
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2503
|
+
for (let t of e) this.menu.append(this.menuItem(on(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2438
2504
|
}
|
|
2439
2505
|
onTracksChanged() {
|
|
2440
2506
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2454,11 +2520,11 @@ var qt = class {
|
|
|
2454
2520
|
}
|
|
2455
2521
|
async toggleFullscreen() {
|
|
2456
2522
|
try {
|
|
2457
|
-
|
|
2523
|
+
w(this.video, this.root) ? await E(this.video, this.root) : await T(this.video, this.root);
|
|
2458
2524
|
} catch {}
|
|
2459
2525
|
}
|
|
2460
2526
|
syncFullscreen() {
|
|
2461
|
-
let e =
|
|
2527
|
+
let e = w(this.video, this.root);
|
|
2462
2528
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
2463
2529
|
}
|
|
2464
2530
|
poke() {
|
|
@@ -2534,41 +2600,41 @@ var qt = class {
|
|
|
2534
2600
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2535
2601
|
}
|
|
2536
2602
|
};
|
|
2537
|
-
function
|
|
2603
|
+
function nn(e) {
|
|
2538
2604
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2539
2605
|
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");
|
|
2540
2606
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2541
2607
|
}
|
|
2542
|
-
function
|
|
2608
|
+
function rn(e) {
|
|
2543
2609
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2544
2610
|
}
|
|
2545
|
-
function
|
|
2611
|
+
function an(e) {
|
|
2546
2612
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2547
2613
|
}
|
|
2548
|
-
function
|
|
2614
|
+
function on(e) {
|
|
2549
2615
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2550
2616
|
}
|
|
2551
2617
|
//#endregion
|
|
2552
2618
|
//#region src/managed/index.ts
|
|
2553
|
-
var
|
|
2554
|
-
function
|
|
2619
|
+
var sn = 6e3, cn = 45e3, ln = 2e3, un = 3, dn = 2e3, fn = 48e4;
|
|
2620
|
+
function pn(e) {
|
|
2555
2621
|
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)})`);
|
|
2556
|
-
if (e.env !== void 0) return
|
|
2622
|
+
if (e.env !== void 0) return U(e.env);
|
|
2557
2623
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2558
2624
|
return e.baseUrl;
|
|
2559
2625
|
}
|
|
2560
|
-
async function
|
|
2626
|
+
async function mn(e) {
|
|
2561
2627
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2562
|
-
let t =
|
|
2628
|
+
let t = pn(e);
|
|
2563
2629
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2564
2630
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2565
|
-
let r = new
|
|
2631
|
+
let r = new hn({
|
|
2566
2632
|
...e,
|
|
2567
2633
|
baseUrl: t
|
|
2568
2634
|
});
|
|
2569
2635
|
return await r.start(), r;
|
|
2570
2636
|
}
|
|
2571
|
-
var
|
|
2637
|
+
var hn = class {
|
|
2572
2638
|
opts;
|
|
2573
2639
|
abort = new AbortController();
|
|
2574
2640
|
listeners = {};
|
|
@@ -2635,7 +2701,7 @@ var sn = class {
|
|
|
2635
2701
|
};
|
|
2636
2702
|
}
|
|
2637
2703
|
beginArming(e, t, n = !1) {
|
|
2638
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
2704
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
|
|
2639
2705
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
2640
2706
|
}
|
|
2641
2707
|
beginArmingByPolling(e) {
|
|
@@ -2656,7 +2722,7 @@ var sn = class {
|
|
|
2656
2722
|
setTimeout(() => {
|
|
2657
2723
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
2658
2724
|
phase: i ? "unavailable" : "tooEarly",
|
|
2659
|
-
retryInMs:
|
|
2725
|
+
retryInMs: cn,
|
|
2660
2726
|
attempt: 1,
|
|
2661
2727
|
elapsedMs: 0,
|
|
2662
2728
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -2695,13 +2761,13 @@ var sn = class {
|
|
|
2695
2761
|
!a && !p() && h();
|
|
2696
2762
|
}, e);
|
|
2697
2763
|
};
|
|
2698
|
-
_(
|
|
2764
|
+
_(sn), this.armingSub = D({
|
|
2699
2765
|
eventsBaseUrl: t,
|
|
2700
2766
|
matchUrn: this.opts.matchUrn,
|
|
2701
2767
|
credential: this.opts.credential,
|
|
2702
|
-
onAlive: () => _(
|
|
2768
|
+
onAlive: () => _(cn),
|
|
2703
2769
|
onState: (e) => {
|
|
2704
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
2770
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * ln);
|
|
2705
2771
|
},
|
|
2706
2772
|
onError: () => h()
|
|
2707
2773
|
});
|
|
@@ -2724,7 +2790,7 @@ var sn = class {
|
|
|
2724
2790
|
let n = await s(this.opts.credential);
|
|
2725
2791
|
if (this.destroyed || t !== this.loadGen) return;
|
|
2726
2792
|
this.setState("loading");
|
|
2727
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
2793
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Be(this.opts.video, (e) => {
|
|
2728
2794
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
2729
2795
|
});
|
|
2730
2796
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -2746,23 +2812,23 @@ var sn = class {
|
|
|
2746
2812
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
2747
2813
|
let i = e.analytics?.sid;
|
|
2748
2814
|
if (!i) return;
|
|
2749
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
2815
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Lt(this.opts.baseUrl, a);
|
|
2750
2816
|
if (!o) {
|
|
2751
2817
|
s && setTimeout(() => {
|
|
2752
2818
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
2753
2819
|
}, 0);
|
|
2754
2820
|
return;
|
|
2755
2821
|
}
|
|
2756
|
-
let c = this.opts.video, l = new
|
|
2822
|
+
let c = this.opts.video, l = new Rt({
|
|
2757
2823
|
endpoint: o,
|
|
2758
2824
|
sid: i,
|
|
2759
2825
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
2760
|
-
sdkVersion:
|
|
2761
|
-
environment:
|
|
2826
|
+
sdkVersion: Wt,
|
|
2827
|
+
environment: Ht(c),
|
|
2762
2828
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
2763
2829
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
2764
2830
|
sample: () => {
|
|
2765
|
-
let e = this.engine?.getStats() ??
|
|
2831
|
+
let e = this.engine?.getStats() ?? W, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
2766
2832
|
return {
|
|
2767
2833
|
...e,
|
|
2768
2834
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -2776,7 +2842,7 @@ var sn = class {
|
|
|
2776
2842
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
2777
2843
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
2778
2844
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
2779
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
2845
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Ut().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
2780
2846
|
}
|
|
2781
2847
|
currentPresentation() {
|
|
2782
2848
|
let e = this.opts.video;
|
|
@@ -2791,7 +2857,7 @@ var sn = class {
|
|
|
2791
2857
|
video: this.opts.video,
|
|
2792
2858
|
descriptor: e,
|
|
2793
2859
|
credential: t,
|
|
2794
|
-
deviceId:
|
|
2860
|
+
deviceId: j(),
|
|
2795
2861
|
userId: this.opts.userId,
|
|
2796
2862
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
2797
2863
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -2801,11 +2867,11 @@ var sn = class {
|
|
|
2801
2867
|
hlsConfig: i,
|
|
2802
2868
|
emit: (e) => this.onEngineEvent(e)
|
|
2803
2869
|
}, o = this.opts.engine ?? "auto";
|
|
2804
|
-
if (o === "native") return new
|
|
2805
|
-
if (o === "hls") return new
|
|
2806
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
2807
|
-
if (
|
|
2808
|
-
if (
|
|
2870
|
+
if (o === "native") return new Y(a);
|
|
2871
|
+
if (o === "hls") return new St(a);
|
|
2872
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && q(this.opts.video) && J()) return new Y(a);
|
|
2873
|
+
if (Qe()) return new St(a);
|
|
2874
|
+
if (q(this.opts.video)) return new Y(a);
|
|
2809
2875
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
2810
2876
|
}
|
|
2811
2877
|
onEngineEvent(e) {
|
|
@@ -2842,11 +2908,11 @@ var sn = class {
|
|
|
2842
2908
|
}
|
|
2843
2909
|
startLiveState(e) {
|
|
2844
2910
|
if (this.opts.liveStateEvents === !1) return;
|
|
2845
|
-
let t = this.opts.eventsBaseUrl ??
|
|
2911
|
+
let t = this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
|
|
2846
2912
|
if (!t) return;
|
|
2847
2913
|
this.closeLiveState();
|
|
2848
2914
|
let r = 0, i = !1;
|
|
2849
|
-
this.liveStateSub =
|
|
2915
|
+
this.liveStateSub = D({
|
|
2850
2916
|
eventsBaseUrl: t,
|
|
2851
2917
|
matchUrn: this.opts.matchUrn,
|
|
2852
2918
|
credential: this.opts.credential,
|
|
@@ -2857,7 +2923,7 @@ var sn = class {
|
|
|
2857
2923
|
r = 0, i = !1;
|
|
2858
2924
|
},
|
|
2859
2925
|
onError: () => {
|
|
2860
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
2926
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= un && (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.`))));
|
|
2861
2927
|
}
|
|
2862
2928
|
});
|
|
2863
2929
|
}
|
|
@@ -2879,7 +2945,7 @@ var sn = class {
|
|
|
2879
2945
|
scheduleRejoin(e) {
|
|
2880
2946
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
2881
2947
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
2882
|
-
}, Math.random() *
|
|
2948
|
+
}, Math.random() * ln));
|
|
2883
2949
|
}
|
|
2884
2950
|
cancelRejoin() {
|
|
2885
2951
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -2903,7 +2969,7 @@ var sn = class {
|
|
|
2903
2969
|
}
|
|
2904
2970
|
t.controls = !1;
|
|
2905
2971
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
2906
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
2972
|
+
r && r.insertBefore(n, t), n.appendChild(t), qt(n, this.opts.theme), this.container = n, this.controlBar = en({
|
|
2907
2973
|
root: n,
|
|
2908
2974
|
video: t,
|
|
2909
2975
|
player: this,
|
|
@@ -2933,7 +2999,7 @@ var sn = class {
|
|
|
2933
2999
|
}
|
|
2934
3000
|
startStats() {
|
|
2935
3001
|
this.stopStats();
|
|
2936
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3002
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? dn);
|
|
2937
3003
|
this.statsTimer = setInterval(() => {
|
|
2938
3004
|
if (!this.engine) return;
|
|
2939
3005
|
let e = this.engine.getStats();
|
|
@@ -2945,7 +3011,7 @@ var sn = class {
|
|
|
2945
3011
|
}
|
|
2946
3012
|
scheduleLicenseRefresh() {
|
|
2947
3013
|
this.stopRefresh();
|
|
2948
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3014
|
+
let e = this.opts.licenseRefreshMs ?? fn;
|
|
2949
3015
|
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
2950
3016
|
}
|
|
2951
3017
|
stopRefresh() {
|
|
@@ -2990,7 +3056,7 @@ var sn = class {
|
|
|
2990
3056
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
2991
3057
|
}
|
|
2992
3058
|
getStats() {
|
|
2993
|
-
return this.engine?.getStats() ??
|
|
3059
|
+
return this.engine?.getStats() ?? W;
|
|
2994
3060
|
}
|
|
2995
3061
|
getQualityLevels() {
|
|
2996
3062
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3029,10 +3095,10 @@ var sn = class {
|
|
|
3029
3095
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
3030
3096
|
}
|
|
3031
3097
|
async enterFullscreen() {
|
|
3032
|
-
return !this.destroyed &&
|
|
3098
|
+
return !this.destroyed && T(this.opts.video, this.container ?? void 0);
|
|
3033
3099
|
}
|
|
3034
3100
|
async exitFullscreen() {
|
|
3035
|
-
await
|
|
3101
|
+
await E(this.opts.video, this.container ?? void 0);
|
|
3036
3102
|
}
|
|
3037
3103
|
retry() {
|
|
3038
3104
|
return this.reload();
|
|
@@ -3100,7 +3166,7 @@ function $(e) {
|
|
|
3100
3166
|
}
|
|
3101
3167
|
//#endregion
|
|
3102
3168
|
//#region src/embed/host.ts
|
|
3103
|
-
function
|
|
3169
|
+
function gn(e) {
|
|
3104
3170
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3105
3171
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3106
3172
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3159,15 +3225,15 @@ function cn(e) {
|
|
|
3159
3225
|
}
|
|
3160
3226
|
//#endregion
|
|
3161
3227
|
//#region src/embed/page.ts
|
|
3162
|
-
var
|
|
3163
|
-
function
|
|
3228
|
+
var _n = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3229
|
+
function vn(e) {
|
|
3164
3230
|
if (typeof e == "boolean") return e;
|
|
3165
3231
|
if (typeof e == "object" && e) {
|
|
3166
3232
|
let t = e.endpoint;
|
|
3167
3233
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3168
3234
|
}
|
|
3169
3235
|
}
|
|
3170
|
-
function
|
|
3236
|
+
function yn() {
|
|
3171
3237
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3172
3238
|
if (e) return {
|
|
3173
3239
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3177,7 +3243,7 @@ function dn() {
|
|
|
3177
3243
|
autoplay: e.autoplay ?? !0,
|
|
3178
3244
|
muted: e.muted ?? !0,
|
|
3179
3245
|
waitForLive: e.waitForLive ?? !0,
|
|
3180
|
-
analytics:
|
|
3246
|
+
analytics: vn(e.analytics)
|
|
3181
3247
|
};
|
|
3182
3248
|
let t = new URLSearchParams(location.search);
|
|
3183
3249
|
return {
|
|
@@ -3190,9 +3256,9 @@ function dn() {
|
|
|
3190
3256
|
waitForLive: !0
|
|
3191
3257
|
};
|
|
3192
3258
|
}
|
|
3193
|
-
async function
|
|
3194
|
-
let e =
|
|
3195
|
-
|
|
3259
|
+
async function bn() {
|
|
3260
|
+
let e = yn();
|
|
3261
|
+
Sn();
|
|
3196
3262
|
let t = document.createElement("video");
|
|
3197
3263
|
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);
|
|
3198
3264
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3247,12 +3313,12 @@ async function fn() {
|
|
|
3247
3313
|
code: e.code,
|
|
3248
3314
|
message: e.message
|
|
3249
3315
|
})), e.on("autoplayblocked", () => {
|
|
3250
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3316
|
+
i({ type: "oddin:autoplayblocked" }), xn(t, e);
|
|
3251
3317
|
});
|
|
3252
3318
|
}, s = async (r) => {
|
|
3253
3319
|
a?.destroy(), a = null;
|
|
3254
3320
|
try {
|
|
3255
|
-
let n = await
|
|
3321
|
+
let n = await mn({
|
|
3256
3322
|
video: t,
|
|
3257
3323
|
baseUrl: e.baseUrl,
|
|
3258
3324
|
matchUrn: r,
|
|
@@ -3314,7 +3380,7 @@ async function fn() {
|
|
|
3314
3380
|
a?.retry();
|
|
3315
3381
|
break;
|
|
3316
3382
|
case "oddin:load":
|
|
3317
|
-
typeof e.matchUrn == "string" &&
|
|
3383
|
+
typeof e.matchUrn == "string" && _n.test(e.matchUrn) && s(e.matchUrn);
|
|
3318
3384
|
break;
|
|
3319
3385
|
case "oddin:destroy": c();
|
|
3320
3386
|
}
|
|
@@ -3326,18 +3392,18 @@ async function fn() {
|
|
|
3326
3392
|
protocol: 1
|
|
3327
3393
|
});
|
|
3328
3394
|
}
|
|
3329
|
-
function
|
|
3395
|
+
function xn(e, t) {
|
|
3330
3396
|
if (document.getElementById("havik-tap")) return;
|
|
3331
3397
|
let n = document.createElement("button");
|
|
3332
3398
|
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", () => {
|
|
3333
3399
|
n.remove(), t.play();
|
|
3334
3400
|
}), document.body.appendChild(n);
|
|
3335
3401
|
}
|
|
3336
|
-
function
|
|
3402
|
+
function Sn() {
|
|
3337
3403
|
let e = document.createElement("style");
|
|
3338
3404
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3339
3405
|
}
|
|
3340
3406
|
//#endregion
|
|
3341
|
-
export {
|
|
3407
|
+
export { Gt as ODDIN_THEME, n as PlaybackError, qt as applyTheme, U as baseUrlForEnv, bn as bootEmbed, ye as clearDeviceId, mn as createPlayer, O as deriveEventsBaseUrl, Fe as detectDrmSupport, T as enterVideoFullscreen, E as exitVideoFullscreen, fe as fetchCatalog, me as fetchTournament, ge as flattenMatches, j as getDeviceId, Le as isLowLatencyManifest, $ as isOddinMessage, xe as licenseRequestHeaders, gn as mountEmbed, v as pollToLive, b as resolveStream, D as subscribeLiveState, w as videoFullscreenActive, _e as watchStatus };
|
|
3342
3408
|
|
|
3343
3409
|
//# sourceMappingURL=index.js.map
|