@oddin-gg/havik-player 2.27.1 → 2.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/havik-player.global.js +3 -3
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +424 -343
- package/dist/index.js.map +1 -1
- package/docs/API.md +48 -23
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8,8 +8,9 @@ var n = class extends Error {
|
|
|
8
8
|
serverCode;
|
|
9
9
|
liveStartsAtMs;
|
|
10
10
|
country;
|
|
11
|
+
detail;
|
|
11
12
|
constructor(e, t, n, r) {
|
|
12
|
-
super(n), this.name = "PlaybackError", this.code = e, this.httpStatus = t, this.retryAfterMs = r?.retryAfterMs, this.requestId = r?.requestId, this.serverCode = r?.serverCode, this.liveStartsAtMs = r?.liveStartsAtMs, this.country = r?.country, r?.cause !== void 0 && (this.cause = r.cause);
|
|
13
|
+
super(n), this.name = "PlaybackError", this.code = e, this.httpStatus = t, this.retryAfterMs = r?.retryAfterMs, this.requestId = r?.requestId, this.serverCode = r?.serverCode, this.liveStartsAtMs = r?.liveStartsAtMs, this.country = r?.country, this.detail = r?.detail, r?.cause !== void 0 && (this.cause = r.cause);
|
|
13
14
|
}
|
|
14
15
|
};
|
|
15
16
|
function r(e) {
|
|
@@ -315,25 +316,25 @@ function x(e) {
|
|
|
315
316
|
function _e(e) {
|
|
316
317
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
317
318
|
}
|
|
318
|
-
function
|
|
319
|
+
function S(e, t) {
|
|
319
320
|
let n = _e(x(e));
|
|
320
321
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
321
322
|
}
|
|
322
|
-
function
|
|
323
|
+
function C(e, t) {
|
|
323
324
|
let n = t ?? e, r = x(e);
|
|
324
325
|
if (typeof n.requestFullscreen == "function") return r.fullscreenEnabled !== !1;
|
|
325
326
|
if (typeof n.webkitRequestFullscreen == "function") return r.webkitFullscreenEnabled !== !1;
|
|
326
327
|
let i = e;
|
|
327
328
|
return i.webkitSupportsFullscreen === !0 && typeof i.webkitEnterFullscreen == "function" || e.readyState < 1;
|
|
328
329
|
}
|
|
329
|
-
async function
|
|
330
|
+
async function w(e, t) {
|
|
330
331
|
let n = t ?? e;
|
|
331
332
|
if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
|
|
332
333
|
if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
|
|
333
334
|
let r = e;
|
|
334
335
|
return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
|
|
335
336
|
}
|
|
336
|
-
async function
|
|
337
|
+
async function T(e, t) {
|
|
337
338
|
let n = e;
|
|
338
339
|
if (n.webkitDisplayingFullscreen) {
|
|
339
340
|
n.webkitExitFullscreen?.();
|
|
@@ -344,7 +345,7 @@ async function w(e, t) {
|
|
|
344
345
|
}
|
|
345
346
|
//#endregion
|
|
346
347
|
//#region src/core/catalog.ts
|
|
347
|
-
async function
|
|
348
|
+
async function ve(e) {
|
|
348
349
|
let t = new URLSearchParams();
|
|
349
350
|
e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
|
|
350
351
|
let i = t.toString(), a = f(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
|
|
@@ -362,12 +363,12 @@ async function ye(e) {
|
|
|
362
363
|
};
|
|
363
364
|
if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
|
|
364
365
|
return {
|
|
365
|
-
tournaments:
|
|
366
|
+
tournaments: ye(await s.json()),
|
|
366
367
|
etag: s.headers.get("etag") ?? void 0,
|
|
367
368
|
notModified: !1
|
|
368
369
|
};
|
|
369
370
|
}
|
|
370
|
-
function
|
|
371
|
+
function ye(e) {
|
|
371
372
|
return (e.tournaments ?? []).map((e) => {
|
|
372
373
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
373
374
|
return {
|
|
@@ -389,7 +390,7 @@ function be(e) {
|
|
|
389
390
|
};
|
|
390
391
|
});
|
|
391
392
|
}
|
|
392
|
-
async function
|
|
393
|
+
async function be(e) {
|
|
393
394
|
let t = f(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
394
395
|
e.etag && i.set("If-None-Match", e.etag);
|
|
395
396
|
let a = await m(t, {
|
|
@@ -409,13 +410,13 @@ async function xe(e) {
|
|
|
409
410
|
};
|
|
410
411
|
if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
411
412
|
return {
|
|
412
|
-
tournament:
|
|
413
|
+
tournament: xe(await a.json()),
|
|
413
414
|
etag: a.headers.get("etag") ?? void 0,
|
|
414
415
|
notModified: !1,
|
|
415
416
|
notFound: !1
|
|
416
417
|
};
|
|
417
418
|
}
|
|
418
|
-
function
|
|
419
|
+
function xe(e) {
|
|
419
420
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
420
421
|
return {
|
|
421
422
|
urn: t,
|
|
@@ -435,18 +436,18 @@ function Se(e) {
|
|
|
435
436
|
}))
|
|
436
437
|
};
|
|
437
438
|
}
|
|
438
|
-
function
|
|
439
|
+
function Se(e) {
|
|
439
440
|
return e.tournaments.flatMap((e) => e.matches);
|
|
440
441
|
}
|
|
441
442
|
//#endregion
|
|
442
443
|
//#region src/core/poll.ts
|
|
443
|
-
var
|
|
444
|
+
var Ce = /* @__PURE__ */ new Set([
|
|
444
445
|
"NOT_FOUND",
|
|
445
446
|
"GEO_DENIED",
|
|
446
447
|
"GONE",
|
|
447
448
|
"INVALID_URN"
|
|
448
449
|
]);
|
|
449
|
-
function
|
|
450
|
+
function we(e) {
|
|
450
451
|
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, c = !1, d = () => {
|
|
451
452
|
c || (a = setTimeout(p, t));
|
|
452
453
|
}, p = async () => {
|
|
@@ -479,7 +480,7 @@ function Te(e) {
|
|
|
479
480
|
} catch (t) {
|
|
480
481
|
if (!i.signal.aborted) {
|
|
481
482
|
let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
|
|
482
|
-
|
|
483
|
+
Ce.has(r.code) && (c = !0), e.onError?.(r);
|
|
483
484
|
}
|
|
484
485
|
} finally {
|
|
485
486
|
d();
|
|
@@ -491,16 +492,16 @@ function Te(e) {
|
|
|
491
492
|
}
|
|
492
493
|
//#endregion
|
|
493
494
|
//#region src/core/events.ts
|
|
494
|
-
var
|
|
495
|
+
var Te = 45e3, E = class extends Error {
|
|
495
496
|
status;
|
|
496
497
|
terminal;
|
|
497
498
|
constructor(e) {
|
|
498
499
|
let t = e === 410;
|
|
499
500
|
super(t ? `live-state subscribe failed: HTTP ${e} — match is gone, not retrying` : e === 404 ? `live-state subscribe failed: HTTP ${e} — match not in the catalog, retrying slowly` : `live-state subscribe failed: HTTP ${e}`), this.name = "LiveStateHttpError", this.status = e, this.terminal = t;
|
|
500
501
|
}
|
|
501
|
-
},
|
|
502
|
-
function
|
|
503
|
-
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = Math.max(t, e.notFoundRetryMs ??
|
|
502
|
+
}, Ee = 3e5;
|
|
503
|
+
function D(e) {
|
|
504
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = Math.max(t, e.notFoundRetryMs ?? Ee), i = e.idleTimeoutMs ?? Te, a = Number.isFinite(i) && i > 0 ? i : 0, o = new AbortController(), s = !1, l = (e) => new Promise((t) => {
|
|
504
505
|
if (o.signal.aborted) return t();
|
|
505
506
|
let n = setTimeout(t, e);
|
|
506
507
|
o.signal.addEventListener("abort", () => {
|
|
@@ -567,7 +568,7 @@ function E(e) {
|
|
|
567
568
|
});
|
|
568
569
|
if (clearTimeout(_), s) return;
|
|
569
570
|
if (!o.ok || !o.body) {
|
|
570
|
-
let t = new
|
|
571
|
+
let t = new E(o.status);
|
|
571
572
|
h = t.terminal, g = o.status === 404, e.onError?.(t);
|
|
572
573
|
} else await p(o.body, () => {
|
|
573
574
|
i = t;
|
|
@@ -585,7 +586,7 @@ function E(e) {
|
|
|
585
586
|
s || (s = !0, o.abort());
|
|
586
587
|
} };
|
|
587
588
|
}
|
|
588
|
-
function
|
|
589
|
+
function O(e) {
|
|
589
590
|
try {
|
|
590
591
|
let t = new URL(e);
|
|
591
592
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -595,27 +596,27 @@ function D(e) {
|
|
|
595
596
|
}
|
|
596
597
|
//#endregion
|
|
597
598
|
//#region src/core/drm/deviceId.ts
|
|
598
|
-
var
|
|
599
|
-
function
|
|
599
|
+
var De = "havik.player.deviceId", k;
|
|
600
|
+
function Oe() {
|
|
600
601
|
if (k) return k;
|
|
601
602
|
try {
|
|
602
|
-
let e = globalThis.localStorage?.getItem(
|
|
603
|
+
let e = globalThis.localStorage?.getItem(De);
|
|
603
604
|
if (e) return k = e, e;
|
|
604
605
|
} catch {}
|
|
605
|
-
let e =
|
|
606
|
+
let e = Ae();
|
|
606
607
|
k = e;
|
|
607
608
|
try {
|
|
608
|
-
globalThis.localStorage?.setItem(
|
|
609
|
+
globalThis.localStorage?.setItem(De, e);
|
|
609
610
|
} catch {}
|
|
610
611
|
return e;
|
|
611
612
|
}
|
|
612
|
-
function
|
|
613
|
+
function ke() {
|
|
613
614
|
k = void 0;
|
|
614
615
|
try {
|
|
615
|
-
globalThis.localStorage?.removeItem(
|
|
616
|
+
globalThis.localStorage?.removeItem(De);
|
|
616
617
|
} catch {}
|
|
617
618
|
}
|
|
618
|
-
function
|
|
619
|
+
function Ae() {
|
|
619
620
|
let e = globalThis.crypto;
|
|
620
621
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
621
622
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -627,32 +628,32 @@ function ke() {
|
|
|
627
628
|
}
|
|
628
629
|
//#endregion
|
|
629
630
|
//#region src/core/drm/headers.ts
|
|
630
|
-
function
|
|
631
|
+
function je(e, t, n = {}) {
|
|
631
632
|
let r = {
|
|
632
633
|
"x-api-key": t.apiKey,
|
|
633
634
|
"X-Match-Urn": e.matchUrn,
|
|
634
|
-
"X-Device-Id": n.deviceId ??
|
|
635
|
+
"X-Device-Id": n.deviceId ?? Oe(),
|
|
635
636
|
"Content-Type": "application/octet-stream"
|
|
636
637
|
};
|
|
637
638
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
638
639
|
}
|
|
639
640
|
//#endregion
|
|
640
641
|
//#region src/core/bandwidthMemory.ts
|
|
641
|
-
var
|
|
642
|
-
function
|
|
642
|
+
var Me = "havik.player.bandwidth", Ne = .8, Pe = 2e7, Fe = 3e5;
|
|
643
|
+
function Ie() {
|
|
643
644
|
return globalThis.navigator?.connection;
|
|
644
645
|
}
|
|
645
|
-
function
|
|
646
|
-
let e =
|
|
646
|
+
function Le() {
|
|
647
|
+
let e = Ie()?.type;
|
|
647
648
|
return typeof e == "string" && e !== "" && e !== "unknown" ? e : "any";
|
|
648
649
|
}
|
|
649
|
-
function
|
|
650
|
-
let e =
|
|
650
|
+
function Re() {
|
|
651
|
+
let e = Ie()?.downlink;
|
|
651
652
|
return typeof e == "number" && Number.isFinite(e) && e > 0 ? e * 1e6 : void 0;
|
|
652
653
|
}
|
|
653
|
-
function
|
|
654
|
+
function ze() {
|
|
654
655
|
try {
|
|
655
|
-
let e = globalThis.localStorage?.getItem(
|
|
656
|
+
let e = globalThis.localStorage?.getItem(Me);
|
|
656
657
|
if (!e) return {};
|
|
657
658
|
let t = JSON.parse(e);
|
|
658
659
|
return t && typeof t == "object" && !Array.isArray(t) ? t : {};
|
|
@@ -660,36 +661,36 @@ function Le() {
|
|
|
660
661
|
return {};
|
|
661
662
|
}
|
|
662
663
|
}
|
|
663
|
-
function
|
|
664
|
-
let t =
|
|
664
|
+
function Be(e = Date.now()) {
|
|
665
|
+
let t = ze()[Le()];
|
|
665
666
|
if (!t || typeof t.bps != "number" || typeof t.at != "number" || !Number.isFinite(t.bps) || t.bps <= 0) return;
|
|
666
667
|
let n = e - t.at;
|
|
667
668
|
if (n < 0 || n > 2592e5) return;
|
|
668
|
-
let r =
|
|
669
|
-
return Math.round(Math.min(
|
|
669
|
+
let r = Re(), i = r === void 0 ? t.bps : Math.min(t.bps, r);
|
|
670
|
+
return Math.round(Math.min(Pe, Math.max(Fe, i * Ne)));
|
|
670
671
|
}
|
|
671
|
-
function
|
|
672
|
+
function Ve(e, t = Date.now()) {
|
|
672
673
|
if (!Number.isFinite(e) || e <= 0) return;
|
|
673
|
-
let n =
|
|
674
|
-
n[
|
|
674
|
+
let n = ze();
|
|
675
|
+
n[Le()] = {
|
|
675
676
|
bps: Math.round(e),
|
|
676
677
|
at: t
|
|
677
678
|
};
|
|
678
679
|
try {
|
|
679
|
-
globalThis.localStorage?.setItem(
|
|
680
|
+
globalThis.localStorage?.setItem(Me, JSON.stringify(n));
|
|
680
681
|
} catch {}
|
|
681
682
|
}
|
|
682
|
-
function
|
|
683
|
+
function He() {
|
|
683
684
|
try {
|
|
684
|
-
globalThis.localStorage?.removeItem(
|
|
685
|
+
globalThis.localStorage?.removeItem(Me);
|
|
685
686
|
} catch {}
|
|
686
687
|
}
|
|
687
688
|
//#endregion
|
|
688
689
|
//#region src/core/drm/cdm.ts
|
|
689
|
-
var
|
|
690
|
-
function
|
|
691
|
-
let n =
|
|
692
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
690
|
+
var Ue = /* @__PURE__ */ new WeakMap();
|
|
691
|
+
function We(e, t) {
|
|
692
|
+
let n = Ue.get(e);
|
|
693
|
+
n || (n = /* @__PURE__ */ new Map(), Ue.set(e, n));
|
|
693
694
|
let r = n.get(t.keySystem);
|
|
694
695
|
if (r) return r;
|
|
695
696
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -697,22 +698,22 @@ function He(e, t) {
|
|
|
697
698
|
});
|
|
698
699
|
return n.set(t.keySystem, i), i;
|
|
699
700
|
}
|
|
700
|
-
function
|
|
701
|
+
function A() {
|
|
701
702
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
702
703
|
}
|
|
703
|
-
var
|
|
704
|
-
function
|
|
704
|
+
var j = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
705
|
+
function Ge(e) {
|
|
705
706
|
return e.startsWith("com.widevine");
|
|
706
707
|
}
|
|
707
|
-
function
|
|
708
|
-
if (!
|
|
708
|
+
function M(e, t) {
|
|
709
|
+
if (!Ge(e)) return t;
|
|
709
710
|
let n = (e, t) => {
|
|
710
711
|
let n = e.videoCapabilities;
|
|
711
712
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
712
|
-
let n =
|
|
713
|
-
return n === -1 ||
|
|
713
|
+
let n = j.indexOf(e.robustness);
|
|
714
|
+
return n === -1 || j.indexOf(t) > n;
|
|
714
715
|
});
|
|
715
|
-
}, r =
|
|
716
|
+
}, r = j.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
716
717
|
...t,
|
|
717
718
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
718
719
|
...t,
|
|
@@ -722,10 +723,10 @@ function Ge(e, t) {
|
|
|
722
723
|
return [...t, ...r];
|
|
723
724
|
}
|
|
724
725
|
function Ke(e) {
|
|
725
|
-
return (t, n) =>
|
|
726
|
+
return (t, n) => A() ? navigator.requestMediaKeySystemAccess(t, M(t, n)).then((t) => ({
|
|
726
727
|
keySystem: t.keySystem,
|
|
727
728
|
getConfiguration: () => t.getConfiguration(),
|
|
728
|
-
createMediaKeys: () =>
|
|
729
|
+
createMediaKeys: () => We(e, t)
|
|
729
730
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
730
731
|
}
|
|
731
732
|
var N = {
|
|
@@ -734,7 +735,7 @@ var N = {
|
|
|
734
735
|
scheme: "cbcs"
|
|
735
736
|
};
|
|
736
737
|
function qe(e) {
|
|
737
|
-
if (!
|
|
738
|
+
if (!A()) return;
|
|
738
739
|
let t = (e, t) => ({
|
|
739
740
|
contentType: e,
|
|
740
741
|
robustness: t,
|
|
@@ -781,7 +782,7 @@ function Xe(e) {
|
|
|
781
782
|
}]
|
|
782
783
|
}, i = (async () => {
|
|
783
784
|
try {
|
|
784
|
-
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha",
|
|
785
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", M("com.widevine.alpha", [r])), !0;
|
|
785
786
|
} catch {
|
|
786
787
|
return !1;
|
|
787
788
|
}
|
|
@@ -789,7 +790,7 @@ function Xe(e) {
|
|
|
789
790
|
return Ye.set(t, i), i;
|
|
790
791
|
}
|
|
791
792
|
function Ze() {
|
|
792
|
-
if (
|
|
793
|
+
if (A()) for (let e of Object.values(Je)) Xe(e);
|
|
793
794
|
}
|
|
794
795
|
function Qe(e) {
|
|
795
796
|
let t = P(e);
|
|
@@ -818,7 +819,7 @@ function rt(e) {
|
|
|
818
819
|
robustness: "",
|
|
819
820
|
encryptionScheme: "cbcs"
|
|
820
821
|
}]
|
|
821
|
-
}] :
|
|
822
|
+
}] : M("com.widevine.alpha", [{
|
|
822
823
|
initDataTypes: ["cenc"],
|
|
823
824
|
videoCapabilities: [{
|
|
824
825
|
contentType: et,
|
|
@@ -975,36 +976,43 @@ var ht = class {
|
|
|
975
976
|
this.video.removeEventListener("timeupdate", e), this.video.removeEventListener("seeking", e);
|
|
976
977
|
};
|
|
977
978
|
}
|
|
978
|
-
}, gt = .25;
|
|
979
|
-
function
|
|
979
|
+
}, gt = .25, _t = 1e3;
|
|
980
|
+
function vt(e, t) {
|
|
980
981
|
let n = null, r = (r) => {
|
|
981
982
|
n = r === "buffering" ? e.currentTime : null, t(r);
|
|
982
|
-
}, i =
|
|
983
|
-
|
|
983
|
+
}, i = () => typeof performance < "u" ? performance.now() : Date.now(), a = i(), o = e.currentTime, s = () => {
|
|
984
|
+
let t = e.currentTime;
|
|
985
|
+
t > o && !e.seeking && !e.paused && (a = i()), o = t;
|
|
986
|
+
}, c = [
|
|
987
|
+
["playing", () => {
|
|
988
|
+
a = i(), o = e.currentTime, r("playing");
|
|
989
|
+
}],
|
|
984
990
|
["waiting", () => r("buffering")],
|
|
985
991
|
["stalled", () => {
|
|
986
|
-
|
|
992
|
+
if (e.paused) return;
|
|
993
|
+
let t = e.readyState < HTMLMediaElement.HAVE_FUTURE_DATA, n = i() - a >= _t;
|
|
994
|
+
(t || n) && r("buffering");
|
|
987
995
|
}],
|
|
988
996
|
["seeked", () => {
|
|
989
|
-
n !== null && (n = e.currentTime);
|
|
997
|
+
o = e.currentTime, n !== null && (n = e.currentTime);
|
|
990
998
|
}],
|
|
991
999
|
["timeupdate", () => {
|
|
992
|
-
n !== null && !e.paused && !e.seeking && e.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA && e.currentTime - n >= gt && r("playing");
|
|
1000
|
+
s(), n !== null && !e.paused && !e.seeking && e.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA && e.currentTime - n >= gt && r("playing");
|
|
993
1001
|
}],
|
|
994
1002
|
["pause", () => {
|
|
995
1003
|
e.ended || r("paused");
|
|
996
1004
|
}],
|
|
997
1005
|
["ended", () => r("ended")]
|
|
998
1006
|
];
|
|
999
|
-
for (let [t, n] of
|
|
1007
|
+
for (let [t, n] of c) e.addEventListener(t, n);
|
|
1000
1008
|
return () => {
|
|
1001
|
-
for (let [t, n] of
|
|
1009
|
+
for (let [t, n] of c) e.removeEventListener(t, n);
|
|
1002
1010
|
};
|
|
1003
1011
|
}
|
|
1004
1012
|
//#endregion
|
|
1005
1013
|
//#region src/core/engine/native.ts
|
|
1006
|
-
var
|
|
1007
|
-
function
|
|
1014
|
+
var yt = 2e3, bt = 3, z = 500, xt = 6e3, St = .25, Ct = 250, wt = .05, Tt = 4, Et = 12e3, Dt = .25, Ot = 1e3, kt = 8e3, At = .05, jt = 2, Mt = 3e4;
|
|
1015
|
+
function Nt(e) {
|
|
1008
1016
|
try {
|
|
1009
1017
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
1010
1018
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -1020,7 +1028,7 @@ function V() {
|
|
|
1020
1028
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
1021
1029
|
return e || t;
|
|
1022
1030
|
}
|
|
1023
|
-
function
|
|
1031
|
+
function Pt() {
|
|
1024
1032
|
if (typeof navigator > "u" || !V()) return !1;
|
|
1025
1033
|
let e = navigator.userAgent ?? "";
|
|
1026
1034
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
@@ -1046,6 +1054,11 @@ var H = class {
|
|
|
1046
1054
|
edgeStampedAt = null;
|
|
1047
1055
|
lastTickAt = null;
|
|
1048
1056
|
endedEmitted = !1;
|
|
1057
|
+
lastPlayhead = null;
|
|
1058
|
+
playheadStampedAt = null;
|
|
1059
|
+
movingSince = null;
|
|
1060
|
+
stuckReloads = 0;
|
|
1061
|
+
stuckReloadsTotal = 0;
|
|
1049
1062
|
fairplayKeyIV;
|
|
1050
1063
|
loadStarted;
|
|
1051
1064
|
preloadTouched = !1;
|
|
@@ -1076,7 +1089,7 @@ var H = class {
|
|
|
1076
1089
|
type: "error",
|
|
1077
1090
|
error: L() ? new n("INTERNAL", 0, "native HLS playback error") : new n("NETWORK", 0, "native HLS playback error while offline"),
|
|
1078
1091
|
fatal: !0
|
|
1079
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
1092
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = It(t.manifestUrl, t.analytics?.sid), e.load();
|
|
1080
1093
|
}
|
|
1081
1094
|
startLoad() {
|
|
1082
1095
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -1104,7 +1117,7 @@ var H = class {
|
|
|
1104
1117
|
};
|
|
1105
1118
|
this.onEncrypted = (n) => {
|
|
1106
1119
|
let a = n;
|
|
1107
|
-
a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
1120
|
+
a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Nt(a.initData), (async () => {
|
|
1108
1121
|
try {
|
|
1109
1122
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
1110
1123
|
initDataTypes: [a.initDataType],
|
|
@@ -1204,10 +1217,10 @@ var H = class {
|
|
|
1204
1217
|
droppedFrames: t.dropped,
|
|
1205
1218
|
decodedFrames: t.totalFrames
|
|
1206
1219
|
};
|
|
1207
|
-
if (this.cdnHost ||= mt(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1220
|
+
if (this.cdnHost ||= mt(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), n.stuckReloads = this.stuckReloadsTotal, e.duration === Infinity) {
|
|
1208
1221
|
n.isLive = !0;
|
|
1209
1222
|
let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
|
|
1210
|
-
Number.isFinite(r) && (n.atLiveEdge = r <=
|
|
1223
|
+
Number.isFinite(r) && (n.atLiveEdge = r <= Tt, !e.paused && r >= 0 && (n.latencySeconds = r));
|
|
1211
1224
|
} else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
|
|
1212
1225
|
return n;
|
|
1213
1226
|
}
|
|
@@ -1225,7 +1238,7 @@ var H = class {
|
|
|
1225
1238
|
return;
|
|
1226
1239
|
}
|
|
1227
1240
|
let t = this.hiddenSince;
|
|
1228
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1241
|
+
this.hiddenSince = null, t != null && e - t >= yt && this.armRefocus();
|
|
1229
1242
|
}, this.onPageShow = (e) => {
|
|
1230
1243
|
e.persisted && this.armRefocus();
|
|
1231
1244
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
@@ -1235,7 +1248,7 @@ var H = class {
|
|
|
1235
1248
|
let e = this.liveEnd(), t = U, n = t(), r = 0, i = () => {
|
|
1236
1249
|
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1237
1250
|
r += z;
|
|
1238
|
-
let a = this.liveEnd(), o = a != null && (e == null || a >= e +
|
|
1251
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + St), s = Math.max(r, t() - n) >= xt;
|
|
1239
1252
|
if (o || s && a != null) {
|
|
1240
1253
|
this.snapToLive();
|
|
1241
1254
|
return;
|
|
@@ -1251,28 +1264,27 @@ var H = class {
|
|
|
1251
1264
|
if (this.edgeTimer != null) return;
|
|
1252
1265
|
let { video: e } = this.deps;
|
|
1253
1266
|
this.onEdgeReset = (e) => {
|
|
1254
|
-
this.lastBufferedEnd = null, this.bufferedAdvancedAt = null, e.type === "emptied" && this.resetEndStale();
|
|
1267
|
+
this.lastBufferedEnd = null, this.bufferedAdvancedAt = null, this.resetStuck(), e.type === "emptied" && this.resetEndStale();
|
|
1255
1268
|
}, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
|
|
1256
1269
|
if (e.duration !== Infinity) return;
|
|
1257
|
-
this.
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1270
|
+
let t = U(), n = this.lastTickAt == null ? 0 : t - this.lastTickAt;
|
|
1271
|
+
this.lastTickAt = t;
|
|
1272
|
+
let r = Ft(e, e.currentTime);
|
|
1273
|
+
r != null && ((this.lastBufferedEnd == null || Math.abs(r - this.lastBufferedEnd) >= wt) && (this.bufferedAdvancedAt = t), this.lastBufferedEnd = r), this.checkEndStale(t, n), this.checkStuck(t, n);
|
|
1274
|
+
}, Ct);
|
|
1261
1275
|
}
|
|
1262
|
-
checkEndStale() {
|
|
1276
|
+
checkEndStale(e, t) {
|
|
1263
1277
|
if (this.endedEmitted) return;
|
|
1264
|
-
let e = U(), t = this.lastTickAt == null ? 0 : e - this.lastTickAt;
|
|
1265
|
-
this.lastTickAt = e;
|
|
1266
1278
|
let n = this.liveEnd();
|
|
1267
1279
|
if (n == null) return;
|
|
1268
|
-
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >=
|
|
1280
|
+
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= Dt;
|
|
1269
1281
|
this.lastSeekableEnd = n;
|
|
1270
1282
|
let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
|
|
1271
|
-
if (r || t >
|
|
1283
|
+
if (r || t > Ot || a || i.paused) {
|
|
1272
1284
|
this.edgeStampedAt = e;
|
|
1273
1285
|
return;
|
|
1274
1286
|
}
|
|
1275
|
-
e - (this.edgeStampedAt ?? e) >
|
|
1287
|
+
e - (this.edgeStampedAt ?? e) > Et && (this.endedEmitted = !0, this.deps.emit({
|
|
1276
1288
|
type: "ended",
|
|
1277
1289
|
reason: "stalled"
|
|
1278
1290
|
}));
|
|
@@ -1280,13 +1292,44 @@ var H = class {
|
|
|
1280
1292
|
resetEndStale() {
|
|
1281
1293
|
this.lastSeekableEnd = null, this.edgeStampedAt = null, this.lastTickAt = null;
|
|
1282
1294
|
}
|
|
1295
|
+
checkStuck(e, t) {
|
|
1296
|
+
if (this.deps.stuckReload === !1 || this.endedEmitted) return;
|
|
1297
|
+
let n = this.deps.video, r = n.currentTime, i = this.lastPlayhead == null || !Number.isFinite(r) || Math.abs(r - this.lastPlayhead) >= At;
|
|
1298
|
+
this.lastPlayhead = Number.isFinite(r) ? r : null;
|
|
1299
|
+
let a = typeof document < "u" && document.visibilityState === "hidden", o = t > Ot || a || n.paused || n.seeking || n.readyState < HTMLMediaElement.HAVE_CURRENT_DATA || !L();
|
|
1300
|
+
if (i || o) {
|
|
1301
|
+
this.playheadStampedAt = e, i && !o ? (this.movingSince ??= e, this.stuckReloads > 0 && e - this.movingSince >= Mt && (this.stuckReloads = 0)) : this.movingSince = null;
|
|
1302
|
+
return;
|
|
1303
|
+
}
|
|
1304
|
+
this.movingSince = null;
|
|
1305
|
+
let s = e - (this.playheadStampedAt ?? e), c = this.bufferedAdvancedAt == null ? Infinity : e - this.bufferedAdvancedAt;
|
|
1306
|
+
s <= kt || c <= kt || (this.playheadStampedAt = e, !(this.stuckReloads >= jt) && this.reloadStuck());
|
|
1307
|
+
}
|
|
1308
|
+
resetStuck() {
|
|
1309
|
+
this.lastPlayhead = null, this.playheadStampedAt = null, this.movingSince = null;
|
|
1310
|
+
}
|
|
1311
|
+
reloadStuck() {
|
|
1312
|
+
let { video: e, descriptor: t } = this.deps;
|
|
1313
|
+
this.stuckReloads += 1, this.stuckReloadsTotal += 1;
|
|
1314
|
+
let n = !e.paused;
|
|
1315
|
+
console.warn("havik-player: native playback frozen, buffer not growing: reloading at live");
|
|
1316
|
+
try {
|
|
1317
|
+
e.src = It(t.manifestUrl, t.analytics?.sid), e.load();
|
|
1318
|
+
} catch (e) {
|
|
1319
|
+
console.warn("havik-player: reload failed", e);
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
n && Promise.resolve(e.play()).catch((e) => {
|
|
1323
|
+
console.warn("havik-player: play() after the reload was refused", e);
|
|
1324
|
+
});
|
|
1325
|
+
}
|
|
1283
1326
|
unwatchBufferedEnd() {
|
|
1284
|
-
this.edgeTimer != null && clearInterval(this.edgeTimer), this.edgeTimer = null, this.onEdgeReset &&= (this.deps.video.removeEventListener("seeking", this.onEdgeReset), this.deps.video.removeEventListener("emptied", this.onEdgeReset), null), this.resetEndStale(), this.lastBufferedEnd = null, this.bufferedAdvancedAt = null;
|
|
1327
|
+
this.edgeTimer != null && clearInterval(this.edgeTimer), this.edgeTimer = null, this.onEdgeReset &&= (this.deps.video.removeEventListener("seeking", this.onEdgeReset), this.deps.video.removeEventListener("emptied", this.onEdgeReset), null), this.resetEndStale(), this.resetStuck(), this.lastBufferedEnd = null, this.bufferedAdvancedAt = null;
|
|
1285
1328
|
}
|
|
1286
1329
|
liveEdgeEstimate() {
|
|
1287
1330
|
let e = this.deps.video;
|
|
1288
1331
|
if (e.duration !== Infinity) return null;
|
|
1289
|
-
let t = this.liveEnd(), n =
|
|
1332
|
+
let t = this.liveEnd(), n = Ft(e, e.currentTime) ?? this.lastBufferedEnd;
|
|
1290
1333
|
if (n != null) {
|
|
1291
1334
|
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (U() - e) / 1e3));
|
|
1292
1335
|
(t == null || r > t) && (t = r);
|
|
@@ -1302,7 +1345,7 @@ var H = class {
|
|
|
1302
1345
|
snapToLive() {
|
|
1303
1346
|
let e = this.deps.video, t = this.liveEnd();
|
|
1304
1347
|
if (t == null) return;
|
|
1305
|
-
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t -
|
|
1348
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - bt, r);
|
|
1306
1349
|
try {
|
|
1307
1350
|
e.currentTime = i;
|
|
1308
1351
|
} catch {}
|
|
@@ -1323,7 +1366,7 @@ var H = class {
|
|
|
1323
1366
|
function U() {
|
|
1324
1367
|
return typeof performance < "u" ? performance.now() : Date.now();
|
|
1325
1368
|
}
|
|
1326
|
-
function
|
|
1369
|
+
function Ft(e, t) {
|
|
1327
1370
|
let n = e.buffered;
|
|
1328
1371
|
if (!n || !Number.isFinite(t)) return null;
|
|
1329
1372
|
for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
|
|
@@ -1332,7 +1375,7 @@ function At(e, t) {
|
|
|
1332
1375
|
}
|
|
1333
1376
|
return null;
|
|
1334
1377
|
}
|
|
1335
|
-
function
|
|
1378
|
+
function It(e, t) {
|
|
1336
1379
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1337
1380
|
}
|
|
1338
1381
|
//#endregion
|
|
@@ -1349,13 +1392,13 @@ function W(e, t = Date.now()) {
|
|
|
1349
1392
|
}
|
|
1350
1393
|
//#endregion
|
|
1351
1394
|
//#region src/core/drm/xhrBody.ts
|
|
1352
|
-
var
|
|
1353
|
-
function
|
|
1395
|
+
var Lt = 4096;
|
|
1396
|
+
function Rt(e) {
|
|
1354
1397
|
if (!e || typeof e != "object") return;
|
|
1355
1398
|
let { response: t } = e;
|
|
1356
1399
|
if (typeof t == "string") return t;
|
|
1357
1400
|
let n;
|
|
1358
|
-
if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength >
|
|
1401
|
+
if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength > Lt)) try {
|
|
1359
1402
|
return new TextDecoder().decode(n);
|
|
1360
1403
|
} catch {
|
|
1361
1404
|
return;
|
|
@@ -1363,7 +1406,7 @@ function Nt(e) {
|
|
|
1363
1406
|
}
|
|
1364
1407
|
//#endregion
|
|
1365
1408
|
//#region src/core/engine/prefetch.ts
|
|
1366
|
-
var
|
|
1409
|
+
var zt = 15e3, Bt = 5e3, Vt = 6, Ht = 4e3, Ut = 2;
|
|
1367
1410
|
function G(e) {
|
|
1368
1411
|
try {
|
|
1369
1412
|
let t = new URL(e);
|
|
@@ -1372,7 +1415,7 @@ function G(e) {
|
|
|
1372
1415
|
return e;
|
|
1373
1416
|
}
|
|
1374
1417
|
}
|
|
1375
|
-
var
|
|
1418
|
+
var Wt = class {
|
|
1376
1419
|
cmcd;
|
|
1377
1420
|
entries = /* @__PURE__ */ new Map();
|
|
1378
1421
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1404,17 +1447,17 @@ var zt = class {
|
|
|
1404
1447
|
let r = G(e);
|
|
1405
1448
|
if (this.entries.has(r)) return;
|
|
1406
1449
|
let i = this.perTrack.get(t) ?? 0;
|
|
1407
|
-
i >=
|
|
1450
|
+
i >= Vt || (this.perTrack.set(t, i + 1), this.start(r, this.withCmcd(e, t, n), !1, zt), this.stats.started += 1);
|
|
1408
1451
|
}
|
|
1409
1452
|
prefetchHint(e, t) {
|
|
1410
1453
|
let n = G(e);
|
|
1411
1454
|
if (this.entries.has(n)) return;
|
|
1412
1455
|
let r = this.hints.get(t) ?? [];
|
|
1413
|
-
for (; r.length >=
|
|
1456
|
+
for (; r.length >= Ut;) {
|
|
1414
1457
|
let e = r.shift();
|
|
1415
1458
|
e !== void 0 && this.drop(e) && (this.stats.hintDropped += 1);
|
|
1416
1459
|
}
|
|
1417
|
-
r.push(n), this.hints.set(t, r), this.start(n, this.withCmcd(e, t, "media"), !0,
|
|
1460
|
+
r.push(n), this.hints.set(t, r), this.start(n, this.withCmcd(e, t, "media"), !0, Ht), this.stats.hintStarted += 1;
|
|
1418
1461
|
}
|
|
1419
1462
|
dropHints(e) {
|
|
1420
1463
|
for (let t of this.hints.get(e) ?? []) this.drop(t) && (this.stats.hintDropped += 1);
|
|
@@ -1467,14 +1510,14 @@ var zt = class {
|
|
|
1467
1510
|
}
|
|
1468
1511
|
}
|
|
1469
1512
|
};
|
|
1470
|
-
function
|
|
1513
|
+
function Gt(t, n) {
|
|
1471
1514
|
let r = typeof n == "function" ? n : e.DefaultConfig?.loader;
|
|
1472
1515
|
if (typeof r != "function") return;
|
|
1473
1516
|
class i extends r {
|
|
1474
1517
|
served = !1;
|
|
1475
1518
|
cancelled = !1;
|
|
1476
1519
|
entry;
|
|
1477
|
-
stats =
|
|
1520
|
+
stats = Kt();
|
|
1478
1521
|
load(e, n, r) {
|
|
1479
1522
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1480
1523
|
if (!i) {
|
|
@@ -1486,7 +1529,7 @@ function Bt(t, n) {
|
|
|
1486
1529
|
i.hint ? t.stats.hintFailed += 1 : t.stats.failed += 1;
|
|
1487
1530
|
}, s = () => {
|
|
1488
1531
|
!this.cancelled && this.served && (i.abort.abort(), o(), this.served = !1, this.entry = void 0, super.load(e, n, r));
|
|
1489
|
-
}, c = n?.loadPolicy, l = c?.maxTimeToFirstByteMs ||
|
|
1532
|
+
}, c = n?.loadPolicy, l = c?.maxTimeToFirstByteMs || Bt, u = setTimeout(s, l);
|
|
1490
1533
|
i.headers.then(() => {
|
|
1491
1534
|
clearTimeout(u);
|
|
1492
1535
|
let e = c?.maxLoadTimeMs;
|
|
@@ -1519,7 +1562,7 @@ function Bt(t, n) {
|
|
|
1519
1562
|
}
|
|
1520
1563
|
return i;
|
|
1521
1564
|
}
|
|
1522
|
-
function
|
|
1565
|
+
function Kt() {
|
|
1523
1566
|
return {
|
|
1524
1567
|
aborted: !1,
|
|
1525
1568
|
loaded: 0,
|
|
@@ -1543,10 +1586,10 @@ function Vt() {
|
|
|
1543
1586
|
}
|
|
1544
1587
|
};
|
|
1545
1588
|
}
|
|
1546
|
-
function
|
|
1589
|
+
function qt(e) {
|
|
1547
1590
|
return e === "audio" ? "audio" : "main";
|
|
1548
1591
|
}
|
|
1549
|
-
function
|
|
1592
|
+
function Jt(e, t) {
|
|
1550
1593
|
let n = [];
|
|
1551
1594
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1552
1595
|
url: t.initSegment.url,
|
|
@@ -1563,7 +1606,7 @@ function Ut(e, t) {
|
|
|
1563
1606
|
});
|
|
1564
1607
|
return n;
|
|
1565
1608
|
}
|
|
1566
|
-
function
|
|
1609
|
+
function Yt(e) {
|
|
1567
1610
|
let t = e, n = t?.preloadHint;
|
|
1568
1611
|
if (!n || !t?.url || n.TYPE !== "PART" || n["BYTERANGE-START"] !== void 0 || n["BYTERANGE-LENGTH"] !== void 0) return null;
|
|
1569
1612
|
let r = n.URI;
|
|
@@ -1581,15 +1624,15 @@ function K(e, t) {
|
|
|
1581
1624
|
}
|
|
1582
1625
|
//#endregion
|
|
1583
1626
|
//#region src/core/engine/hls.ts
|
|
1584
|
-
function
|
|
1627
|
+
function Xt() {
|
|
1585
1628
|
return e.isSupported();
|
|
1586
1629
|
}
|
|
1587
|
-
var
|
|
1588
|
-
function
|
|
1630
|
+
var Zt = 3, Qt = 1e6, $t = 20, en = 1e4, tn = 3, nn = 5, rn = 3, an = 1e4, on = 3e4, sn = 12e3, cn = 3e3, ln = .02, un = 6e3, dn = .5, fn = 3, pn = .5, mn = 1.1, hn = .25, gn = 5e3, _n = 4e3, vn = 2, yn = 5, bn = 2, xn = 2, Sn = 4, Cn = 4, wn = 2e3, Tn = 3e4, En = 1, Dn = 2, On = .5, kn = .6, An = 2, jn = 1.5, Mn = 1e4, Nn = 18e4, Pn = .5, Fn = 2;
|
|
1631
|
+
function In(e) {
|
|
1589
1632
|
let t = e.config ?? {};
|
|
1590
1633
|
return t.capLevelToPlayerSize === !0 || t.capLevelOnFPSDrop === !0;
|
|
1591
1634
|
}
|
|
1592
|
-
var q = 8,
|
|
1635
|
+
var q = 8, Ln = 12e4, Rn = 6e4;
|
|
1593
1636
|
function J(e, t, n) {
|
|
1594
1637
|
if (n <= 0 || t < 0 || t >= e.length) return t;
|
|
1595
1638
|
let r = (t, n) => e[t].width === e[n].width && e[t].height === e[n].height, i = (t) => {
|
|
@@ -1602,11 +1645,11 @@ function J(e, t, n) {
|
|
|
1602
1645
|
function Y() {
|
|
1603
1646
|
return typeof self < "u" && self.devicePixelRatio > 0 ? self.devicePixelRatio : 1;
|
|
1604
1647
|
}
|
|
1605
|
-
var
|
|
1606
|
-
function
|
|
1648
|
+
var zn = .2, Bn = 30, Vn = 2, Hn = 2, Un = 2, Wn = 9, Gn = .5, Kn = 64, qn = 1e4, Jn = 8, Yn = .6, Xn = .4, Zn = .4, Qn = 2, $n = 6e4, X = .5, er = 3.5, tr = 300;
|
|
1649
|
+
function nr(e) {
|
|
1607
1650
|
return (e?.part ?? e?.frag)?.stats;
|
|
1608
1651
|
}
|
|
1609
|
-
function
|
|
1652
|
+
function rr() {
|
|
1610
1653
|
if (typeof navigator > "u") return 0;
|
|
1611
1654
|
try {
|
|
1612
1655
|
let e = navigator.connection?.rtt;
|
|
@@ -1615,20 +1658,20 @@ function Zn() {
|
|
|
1615
1658
|
return 0;
|
|
1616
1659
|
}
|
|
1617
1660
|
}
|
|
1618
|
-
function
|
|
1661
|
+
function ir(e) {
|
|
1619
1662
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1620
1663
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1621
1664
|
return;
|
|
1622
1665
|
}
|
|
1623
|
-
e.liveSyncDuration ??=
|
|
1624
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1625
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1666
|
+
e.liveSyncDuration ??= Un;
|
|
1667
|
+
let t = Math.max(12, e.liveSyncDuration + Wn);
|
|
1668
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), ar(e, e.liveSyncDuration);
|
|
1626
1669
|
}
|
|
1627
|
-
function
|
|
1670
|
+
function ar(e, t) {
|
|
1628
1671
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1629
1672
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1630
1673
|
}
|
|
1631
|
-
var
|
|
1674
|
+
var or = class {
|
|
1632
1675
|
name = "hls";
|
|
1633
1676
|
hls = null;
|
|
1634
1677
|
deps;
|
|
@@ -1781,7 +1824,7 @@ var er = class {
|
|
|
1781
1824
|
}
|
|
1782
1825
|
this.loadSuspended = !0;
|
|
1783
1826
|
}
|
|
1784
|
-
},
|
|
1827
|
+
}, gn));
|
|
1785
1828
|
}
|
|
1786
1829
|
resumeLoading() {
|
|
1787
1830
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1813,7 +1856,7 @@ var er = class {
|
|
|
1813
1856
|
let t = e.liveSyncPosition;
|
|
1814
1857
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1815
1858
|
let { video: n } = this.deps;
|
|
1816
|
-
n.currentTime <= t +
|
|
1859
|
+
n.currentTime <= t + Gn || (n.currentTime = t);
|
|
1817
1860
|
}
|
|
1818
1861
|
reanchorPartTimeline(e, t) {
|
|
1819
1862
|
let { frag: n, part: r } = t;
|
|
@@ -1825,7 +1868,7 @@ var er = class {
|
|
|
1825
1868
|
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1826
1869
|
if (!s) return;
|
|
1827
1870
|
let c = a.startPTS - s.start;
|
|
1828
|
-
if (!(!Number.isFinite(c) || Math.abs(c) <
|
|
1871
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < ln)) {
|
|
1829
1872
|
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1830
1873
|
i.fragmentHint?.setStart(i.fragmentHint.start + c), this.deps.debug === !0 && console.info(`havik-player: LL-HLS timeline re-anchored by ${c >= 0 ? "+" : ""}${c.toFixed(3)}s at sn ${n.sn} (level ${n.level})`);
|
|
1831
1874
|
}
|
|
@@ -1853,7 +1896,7 @@ var er = class {
|
|
|
1853
1896
|
videoEncryptionScheme: N.scheme,
|
|
1854
1897
|
audioEncryptionScheme: N.scheme
|
|
1855
1898
|
},
|
|
1856
|
-
...
|
|
1899
|
+
...A() ? { requestMediaKeySystemAccessFunc: Ke(t) } : {},
|
|
1857
1900
|
licenseXhrSetup: (e, t) => {
|
|
1858
1901
|
let o = performance.now(), s = () => {
|
|
1859
1902
|
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, e.addEventListener("loadend", () => {
|
|
@@ -1865,7 +1908,7 @@ var er = class {
|
|
|
1865
1908
|
return;
|
|
1866
1909
|
}
|
|
1867
1910
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1868
|
-
u = setTimeout(() => e(void 0),
|
|
1911
|
+
u = setTimeout(() => e(void 0), an);
|
|
1869
1912
|
});
|
|
1870
1913
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1871
1914
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1883,28 +1926,28 @@ var er = class {
|
|
|
1883
1926
|
this.prefetch?.destroy(), this.prefetch = null;
|
|
1884
1927
|
let p = !1, m = !1, h = u && this.deps.mediaDuringKey !== !1, g = this.deps.preloadHints !== !1;
|
|
1885
1928
|
if ((h || g) && !f.fLoader) {
|
|
1886
|
-
let e = new
|
|
1929
|
+
let e = new Wt({
|
|
1887
1930
|
sessionId: n.analytics?.sid,
|
|
1888
1931
|
contentId: n.matchUrn
|
|
1889
|
-
}), t =
|
|
1932
|
+
}), t = Gt(e, f.loader);
|
|
1890
1933
|
t && (this.prefetch = e, p = h, m = g, f.fLoader = t);
|
|
1891
1934
|
}
|
|
1892
|
-
|
|
1935
|
+
ir(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
|
|
1893
1936
|
let _ = new e(f);
|
|
1894
1937
|
if (this.hls = _, this.armHoldBack(_, f), _.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(_, t)), _.on(e.Events.MANIFEST_PARSED, () => {
|
|
1895
1938
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(_), this.measureLadder(_), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1896
1939
|
}), _.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1897
1940
|
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(() => {
|
|
1898
1941
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1899
|
-
},
|
|
1942
|
+
}, on)));
|
|
1900
1943
|
}), _.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1901
1944
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1902
1945
|
}), _.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
1903
1946
|
t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
|
|
1904
|
-
let n = t?.frag, r =
|
|
1947
|
+
let n = t?.frag, r = nr(t), i = r?.loaded;
|
|
1905
1948
|
typeof i == "number" && (this.bytesLoaded += i), !this.reportedFirstBytes && typeof i == "number" && i > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1906
1949
|
let a = r?.loading;
|
|
1907
|
-
a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length >
|
|
1950
|
+
a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length > Kn && this.requestTimesMs.shift()), this.sampleHoldBack(t), this.sampleHeadroom(t);
|
|
1908
1951
|
let o = n?.url;
|
|
1909
1952
|
if (o) {
|
|
1910
1953
|
let e = ft(o);
|
|
@@ -1924,8 +1967,8 @@ var er = class {
|
|
|
1924
1967
|
let i = e;
|
|
1925
1968
|
if (!i?.live || !i.partList?.length || typeof i.edge != "number") return;
|
|
1926
1969
|
let a = n.buffered, o = a.length ? a.end(a.length - 1) : 0;
|
|
1927
|
-
if (i.edge - o >
|
|
1928
|
-
let s =
|
|
1970
|
+
if (i.edge - o > Zt * (i.partTarget || .5)) return;
|
|
1971
|
+
let s = Yt(e);
|
|
1929
1972
|
s && t.prefetchHint(s, r);
|
|
1930
1973
|
};
|
|
1931
1974
|
_.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1937,15 +1980,15 @@ var er = class {
|
|
|
1937
1980
|
if (this.prefetch && p) {
|
|
1938
1981
|
let t = this.prefetch;
|
|
1939
1982
|
_.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1940
|
-
let r = n?.frag, i =
|
|
1941
|
-
if (r && t.isActive(i)) for (let e of
|
|
1942
|
-
}), _.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1983
|
+
let r = n?.frag, i = qt(r?.type);
|
|
1984
|
+
if (r && t.isActive(i)) for (let e of Jt(_, r)) t.prefetch(e.url, i, e.kind);
|
|
1985
|
+
}), _.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(qt(n?.frag?.type)));
|
|
1943
1986
|
}
|
|
1944
1987
|
_.on(e.Events.KEY_LOADED, () => {
|
|
1945
1988
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1946
1989
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1947
1990
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.adaptHoldBack(), this.reviewSizeCapHeadroom(), this.releaseStallCap(), this.checkFrameDrops();
|
|
1948
|
-
},
|
|
1991
|
+
}, cn), _.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1949
1992
|
this.renditionSwitches += 1;
|
|
1950
1993
|
let n = this.lastLevelIndex >= 0 ? _.levels[this.lastLevelIndex] : void 0, r = _.levels[t.level];
|
|
1951
1994
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, this.armFrameDropGrace(), l({
|
|
@@ -2006,8 +2049,8 @@ var er = class {
|
|
|
2006
2049
|
let e = this.hls, t = this.sizeCapCover();
|
|
2007
2050
|
if (!e || !t) return null;
|
|
2008
2051
|
let { cover: n, deviceRatio: r } = t, i = this.deps.sizeCapHeadroom, a = i == null || Number.isNaN(i);
|
|
2009
|
-
if (a && r >=
|
|
2010
|
-
if (a) return this.headroomUngated || this.headroomGranted ? J(e.levels, n,
|
|
2052
|
+
if (a && r >= Dn) return n;
|
|
2053
|
+
if (a) return this.headroomUngated || this.headroomGranted ? J(e.levels, n, En) : n;
|
|
2011
2054
|
let o = i === Infinity ? e.levels.length : Math.max(0, Math.floor(i));
|
|
2012
2055
|
return J(e.levels, n, o);
|
|
2013
2056
|
}
|
|
@@ -2024,11 +2067,11 @@ var er = class {
|
|
|
2024
2067
|
return;
|
|
2025
2068
|
}
|
|
2026
2069
|
this.capTimer && clearTimeout(this.capTimer);
|
|
2027
|
-
let t = e > this.sizeCapLevel ?
|
|
2070
|
+
let t = e > this.sizeCapLevel ? wn : Tn;
|
|
2028
2071
|
this.capTimer = setTimeout(() => {
|
|
2029
2072
|
this.capTimer = null;
|
|
2030
2073
|
let n = this.computeSizeCapTarget();
|
|
2031
|
-
n === e || t ===
|
|
2074
|
+
n === e || t === Tn && n != null && n < e ? this.applySizeCap() : this.onMediaResize();
|
|
2032
2075
|
}, t);
|
|
2033
2076
|
}
|
|
2034
2077
|
measureLadder(e) {
|
|
@@ -2055,7 +2098,7 @@ var er = class {
|
|
|
2055
2098
|
}
|
|
2056
2099
|
defaultHeadroomApplies() {
|
|
2057
2100
|
let e = this.deps.sizeCapHeadroom;
|
|
2058
|
-
return e != null && !Number.isNaN(e) || this.headroomUngated ? !1 : Y() <
|
|
2101
|
+
return e != null && !Number.isNaN(e) || this.headroomUngated ? !1 : Y() < Dn;
|
|
2059
2102
|
}
|
|
2060
2103
|
applySizeCapUnlessPending() {
|
|
2061
2104
|
this.capTimer || this.applySizeCap();
|
|
@@ -2064,7 +2107,7 @@ var er = class {
|
|
|
2064
2107
|
if (!this.sizeCapManaged || !this.defaultHeadroomApplies() || e.frag?.type !== "main" || typeof e.frag.level != "number" || typeof document < "u" && document.hidden) return;
|
|
2065
2108
|
let t = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag.duration;
|
|
2066
2109
|
if (typeof t != "number" || !(t > 0)) return;
|
|
2067
|
-
let n =
|
|
2110
|
+
let n = nr(e)?.loading;
|
|
2068
2111
|
if (!n || !(n.start > 0) || !(n.end >= n.start)) return;
|
|
2069
2112
|
let r = this.hls?.levels?.[e.frag.level]?.bitrate;
|
|
2070
2113
|
if (!(typeof r == "number" && r > 0)) return;
|
|
@@ -2077,7 +2120,7 @@ var er = class {
|
|
|
2077
2120
|
}
|
|
2078
2121
|
onPlaybackStall(e) {
|
|
2079
2122
|
let t = Date.now();
|
|
2080
|
-
this.deps.video.seeking || !this.playingSince || t - this.playingSince <
|
|
2123
|
+
this.deps.video.seeking || !this.playingSince || t - this.playingSince < Mn || (this.lastStallAt = t, this.stepStallCapDown(t, e), this.headroomGranted && (this.headroomGranted = !1, this.applySizeCapUnlessPending()));
|
|
2081
2124
|
}
|
|
2082
2125
|
stallCapLevel(e) {
|
|
2083
2126
|
if (this.stallCapBitrate == null) return -1;
|
|
@@ -2088,7 +2131,7 @@ var er = class {
|
|
|
2088
2131
|
}
|
|
2089
2132
|
stepStallCapDown(e, t) {
|
|
2090
2133
|
let n = this.hls;
|
|
2091
|
-
if (!n || !this.stallCapEnabled ||
|
|
2134
|
+
if (!n || !this.stallCapEnabled || In(n) || !n.autoLevelEnabled || typeof t == "number" && t >= Pn || this.isLiveEdgeWait(n, t ?? 0)) return;
|
|
2092
2135
|
this.stallCapBitrate != null && (this.stallCapSince = e);
|
|
2093
2136
|
let r = Math.max(n.levels[n.currentLevel]?.bitrate ?? 0, n.levels[n.loadLevel]?.bitrate ?? 0);
|
|
2094
2137
|
if (!(r > 0)) return;
|
|
@@ -2099,7 +2142,7 @@ var er = class {
|
|
|
2099
2142
|
let n = e.latestLevelDetails;
|
|
2100
2143
|
if (!n?.live) return !1;
|
|
2101
2144
|
let r = n.partTarget || n.targetduration;
|
|
2102
|
-
return !(r > 0) || !(n.edge > 0) ? !1 : n.edge - (this.deps.video.currentTime + t) <
|
|
2145
|
+
return !(r > 0) || !(n.edge > 0) ? !1 : n.edge - (this.deps.video.currentTime + t) < Fn * r;
|
|
2103
2146
|
}
|
|
2104
2147
|
releaseStallCap() {
|
|
2105
2148
|
let e = this.hls, t = Date.now(), n = this.stallCapTickAt;
|
|
@@ -2108,7 +2151,7 @@ var er = class {
|
|
|
2108
2151
|
n && (this.stallCapSince += t - Math.max(n, this.stallCapSince));
|
|
2109
2152
|
return;
|
|
2110
2153
|
}
|
|
2111
|
-
if (t - this.stallCapSince <
|
|
2154
|
+
if (t - this.stallCapSince < Nn) return;
|
|
2112
2155
|
let r = this.stallCapBitrate, i = e.levels.map((e) => e.bitrate).filter((e) => e > r).sort((e, t) => e - t)[0];
|
|
2113
2156
|
this.stallCapBitrate = i ?? null, this.stallCapSince = t, this.pushCap();
|
|
2114
2157
|
}
|
|
@@ -2121,26 +2164,26 @@ var er = class {
|
|
|
2121
2164
|
this.headroomGranted = !1, this.headroomSamples = [];
|
|
2122
2165
|
return;
|
|
2123
2166
|
}
|
|
2124
|
-
this.headroomSamples = this.headroomSamples.filter((t) => t.t >= e -
|
|
2167
|
+
this.headroomSamples = this.headroomSamples.filter((t) => t.t >= e - qn);
|
|
2125
2168
|
let r = this.headroomEarned(n, e);
|
|
2126
|
-
r !== this.headroomGranted && (r || (this.headroomRegrantAt = e +
|
|
2169
|
+
r !== this.headroomGranted && (r || (this.headroomRegrantAt = e + Rn), this.headroomGranted = r, this.applySizeCapUnlessPending());
|
|
2127
2170
|
}
|
|
2128
2171
|
headroomEarned(e, t) {
|
|
2129
|
-
if (t - this.lastStallAt <
|
|
2172
|
+
if (t - this.lastStallAt < Ln || !this.headroomGranted && t < this.headroomRegrantAt || !this.headroomGranted && this.headroomSamples.length < q) return !1;
|
|
2130
2173
|
let n = e.levels, r = this.sizeCapCoverLevel();
|
|
2131
2174
|
if (r == null) return this.headroomGranted;
|
|
2132
|
-
let i = J(n, r,
|
|
2175
|
+
let i = J(n, r, En);
|
|
2133
2176
|
if (i === r) return this.headroomGranted;
|
|
2134
|
-
let a = n[i]?.bitrate, o = e.bandwidthEstimate, s = this.headroomGranted ?
|
|
2177
|
+
let a = n[i]?.bitrate, o = e.bandwidthEstimate, s = this.headroomGranted ? jn : An;
|
|
2135
2178
|
if (!(a > 0) || !(o >= s * a)) return !1;
|
|
2136
2179
|
let c = (e) => K([...e].sort((e, t) => e - t), 90);
|
|
2137
2180
|
if (this.headroomGranted) {
|
|
2138
2181
|
let e = this.headroomSamples.filter((e) => e.bitrate >= a).map((e) => e.ratio);
|
|
2139
|
-
return e.length < q || c(e) <=
|
|
2182
|
+
return e.length < q || c(e) <= kn;
|
|
2140
2183
|
}
|
|
2141
2184
|
let l = [];
|
|
2142
2185
|
for (let e of this.headroomSamples) e.bitrate < a && l.push(e.ratio * (a / e.bitrate));
|
|
2143
|
-
return l.length >= q && c(l) <=
|
|
2186
|
+
return l.length >= q && c(l) <= On;
|
|
2144
2187
|
}
|
|
2145
2188
|
applySizeCap() {
|
|
2146
2189
|
if (!this.sizeCapManaged) return;
|
|
@@ -2215,7 +2258,7 @@ var er = class {
|
|
|
2215
2258
|
let t = e.currentLevel >= 0 ? e.levels[e.currentLevel] : void 0;
|
|
2216
2259
|
t && (n.levelHeight = t.height);
|
|
2217
2260
|
let r = e.autoLevelCapping, i = r >= 0 ? e.levels[r] : void 0;
|
|
2218
|
-
i && i.height > 0 && (n.maxLevelHeight = i.height, !
|
|
2261
|
+
i && i.height > 0 && (n.maxLevelHeight = i.height, !In(e) && r === this.pushedCapLevel && this.pushedCapReason && (n.capReason = this.pushedCapReason)), t?.videoCodec && (n.videoCodec = t.videoCodec), t?.audioCodec && (n.audioCodec = t.audioCodec), t && typeof t.bitrate == "number" && (n.renditionBitrateKbps = Math.round(t.bitrate / 1e3)), typeof t?.details?.live == "boolean" && (n.isLive = t.details.live, typeof e.liveSyncPosition == "number" && (n.atLiveEdge = this.deps.video.currentTime >= e.liveSyncPosition - 1.5));
|
|
2219
2262
|
}
|
|
2220
2263
|
return n;
|
|
2221
2264
|
}
|
|
@@ -2243,7 +2286,7 @@ var er = class {
|
|
|
2243
2286
|
return;
|
|
2244
2287
|
}
|
|
2245
2288
|
let e = Date.now() - this.lastAdvanceMs;
|
|
2246
|
-
!this.chaseSuspended && e >
|
|
2289
|
+
!this.chaseSuspended && e > un && this.suspendChasing(), e > sn && this.emitEnded("stalled");
|
|
2247
2290
|
}
|
|
2248
2291
|
resetStarvationWindow() {
|
|
2249
2292
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -2258,7 +2301,7 @@ var er = class {
|
|
|
2258
2301
|
this.resetStarvationWindow();
|
|
2259
2302
|
return;
|
|
2260
2303
|
}
|
|
2261
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
2304
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < un, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > _n, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = R(t), c = o - s, l = c !== this.starvedFrames;
|
|
2262
2305
|
if (this.starvedFrames = c, !a || l) {
|
|
2263
2306
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
2264
2307
|
return;
|
|
@@ -2267,12 +2310,12 @@ var er = class {
|
|
|
2267
2310
|
this.resetStarvationWindow();
|
|
2268
2311
|
return;
|
|
2269
2312
|
}
|
|
2270
|
-
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 >
|
|
2313
|
+
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 > Sn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= bn && (this.clearKick(), this.starvationRebuilds < xn)) {
|
|
2271
2314
|
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");
|
|
2272
2315
|
return;
|
|
2273
2316
|
}
|
|
2274
|
-
let u = i && this.starvedTicks >=
|
|
2275
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
2317
|
+
let u = i && this.starvedTicks >= vn, d = !i && this.deadTicks >= Sn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Cn;
|
|
2318
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= yn))) {
|
|
2276
2319
|
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");
|
|
2277
2320
|
try {
|
|
2278
2321
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -2287,7 +2330,7 @@ var er = class {
|
|
|
2287
2330
|
let t = e.latency, n = e.targetLatency;
|
|
2288
2331
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
2289
2332
|
let r = t - n;
|
|
2290
|
-
!this.catchUpEngaged && r >
|
|
2333
|
+
!this.catchUpEngaged && r > dn ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= dn && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
2291
2334
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
2292
2335
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
2293
2336
|
}
|
|
@@ -2300,7 +2343,7 @@ var er = class {
|
|
|
2300
2343
|
}), n < 0 ? 0 : n;
|
|
2301
2344
|
}
|
|
2302
2345
|
armFrameDropGrace() {
|
|
2303
|
-
this.fpsGraceTicks > 0 || (this.fpsGraceTicks =
|
|
2346
|
+
this.fpsGraceTicks > 0 || (this.fpsGraceTicks = Hn, this.fpsBadTicks = 0);
|
|
2304
2347
|
}
|
|
2305
2348
|
resetFrameDropWindow() {
|
|
2306
2349
|
this.fpsLastFrames = -1, this.fpsLastDropped = -1, this.fpsBadTicks = 0;
|
|
@@ -2312,7 +2355,7 @@ var er = class {
|
|
|
2312
2355
|
return;
|
|
2313
2356
|
}
|
|
2314
2357
|
let { totalFrames: n, dropped: r } = R(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
2315
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
2358
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Bn || o < 0) {
|
|
2316
2359
|
this.fpsBadTicks = 0;
|
|
2317
2360
|
return;
|
|
2318
2361
|
}
|
|
@@ -2320,11 +2363,11 @@ var er = class {
|
|
|
2320
2363
|
--this.fpsGraceTicks, this.fpsBadTicks = 0;
|
|
2321
2364
|
return;
|
|
2322
2365
|
}
|
|
2323
|
-
if (o <=
|
|
2366
|
+
if (o <= zn * a) {
|
|
2324
2367
|
this.fpsBadTicks = 0;
|
|
2325
2368
|
return;
|
|
2326
2369
|
}
|
|
2327
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
2370
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < Vn) return;
|
|
2328
2371
|
this.fpsBadTicks = 0;
|
|
2329
2372
|
let s = e.levels, c = s[e.currentLevel];
|
|
2330
2373
|
if (!c) return;
|
|
@@ -2341,22 +2384,22 @@ var er = class {
|
|
|
2341
2384
|
return;
|
|
2342
2385
|
}
|
|
2343
2386
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
2344
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
2387
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(mn, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
2345
2388
|
this.resetChaseWindow();
|
|
2346
2389
|
return;
|
|
2347
2390
|
}
|
|
2348
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
2391
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= pn) {
|
|
2349
2392
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
2350
2393
|
return;
|
|
2351
2394
|
}
|
|
2352
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
2395
|
+
if (this.chaseTicks += 1, this.chaseTicks < fn) return;
|
|
2353
2396
|
this.resetChaseWindow();
|
|
2354
2397
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2355
2398
|
if (!(a > 1)) return;
|
|
2356
2399
|
let o = e.targetLatency;
|
|
2357
2400
|
if (typeof o != "number" || !(o > 0)) return;
|
|
2358
2401
|
let s = Math.min(n, a - 1);
|
|
2359
|
-
s < o +
|
|
2402
|
+
s < o + hn || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s, this.deps.emit({
|
|
2360
2403
|
type: "livetargetchange",
|
|
2361
2404
|
change: {
|
|
2362
2405
|
targetSeconds: s,
|
|
@@ -2373,13 +2416,13 @@ var er = class {
|
|
|
2373
2416
|
if (!this.holdBackEnabled || this.holdBackPriorChecked || !e || (this.holdBackPriorChecked = !0, this.holdBackApplied > 0 || this.holdBackStepCount > 0)) return;
|
|
2374
2417
|
let t = e.targetLatency;
|
|
2375
2418
|
if (this.holdBackBase < 0 && typeof t == "number" && t > 0 && (this.holdBackBase = t), this.holdBackBase < 0) return;
|
|
2376
|
-
let n =
|
|
2377
|
-
if (!(n >=
|
|
2419
|
+
let n = rr();
|
|
2420
|
+
if (!(n >= tr)) return;
|
|
2378
2421
|
let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase + X);
|
|
2379
2422
|
i > r && (this.holdBackStepCount = 1, this.moveHoldBack(e, r, i, "connection-rtt", `connection rtt ${n} ms`));
|
|
2380
2423
|
}
|
|
2381
2424
|
holdBackCeiling(e) {
|
|
2382
|
-
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t :
|
|
2425
|
+
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t : er, r = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2383
2426
|
return r > 1 ? Math.min(n, r - 1) : n;
|
|
2384
2427
|
}
|
|
2385
2428
|
sampleHoldBack(e) {
|
|
@@ -2388,7 +2431,7 @@ var er = class {
|
|
|
2388
2431
|
if (t !== "main" && t !== "audio") return;
|
|
2389
2432
|
let n = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag?.duration;
|
|
2390
2433
|
if (typeof n != "number" || !(n > 0)) return;
|
|
2391
|
-
let r =
|
|
2434
|
+
let r = nr(e)?.loading;
|
|
2392
2435
|
if (!r || !(r.start > 0) || !(r.end > 0)) return;
|
|
2393
2436
|
let i = r.first > r.start ? r.first : r.end, a = Math.max(0, i - r.start) / (n * 1e3);
|
|
2394
2437
|
this.holdBackSamples.push({
|
|
@@ -2403,20 +2446,20 @@ var er = class {
|
|
|
2403
2446
|
this.holdBackSlowTicks = 0, this.holdBackFastSince = 0, this.holdBackSamples = [];
|
|
2404
2447
|
return;
|
|
2405
2448
|
}
|
|
2406
|
-
let t = Date.now(), n = t -
|
|
2449
|
+
let t = Date.now(), n = t - qn, r = this.holdBackSamples, i = 0;
|
|
2407
2450
|
for (; i < r.length && r[i].t < n;) i += 1;
|
|
2408
2451
|
i > 0 && r.splice(0, i);
|
|
2409
2452
|
let a = e.targetLatency;
|
|
2410
2453
|
if (typeof a != "number" || !(a > 0)) return;
|
|
2411
2454
|
this.holdBackBase < 0 && (this.holdBackBase = a);
|
|
2412
2455
|
let o = this.holdBackBase, s = this.holdBackCeiling(e);
|
|
2413
|
-
if (r.length <
|
|
2456
|
+
if (r.length < Jn) {
|
|
2414
2457
|
this.holdBackSlowTicks = 0;
|
|
2415
2458
|
return;
|
|
2416
2459
|
}
|
|
2417
2460
|
let c = r.map((e) => e.ratio).sort((e, t) => e - t), l = K(c, 95), u = K(c, 50), d = Math.round(l * 1e3);
|
|
2418
|
-
if (l >=
|
|
2419
|
-
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks <
|
|
2461
|
+
if (l >= Yn && u >= Xn) {
|
|
2462
|
+
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks < Qn) return;
|
|
2420
2463
|
this.holdBackSlowTicks = 0;
|
|
2421
2464
|
let t = Math.ceil((s - o) / X), n = Math.ceil((a - o) / X - 1e-9);
|
|
2422
2465
|
if (n > this.holdBackStepCount && (this.holdBackStepCount = n), this.holdBackStepCount >= t) return;
|
|
@@ -2426,7 +2469,7 @@ var er = class {
|
|
|
2426
2469
|
this.moveHoldBack(e, a, r, "slow-fetches", `part fetches slow (first byte p50 ${Math.round(u * 1e3)} / p95 ${d} ms per 1 s of media)`);
|
|
2427
2470
|
return;
|
|
2428
2471
|
}
|
|
2429
|
-
if (this.holdBackSlowTicks = 0, l >=
|
|
2472
|
+
if (this.holdBackSlowTicks = 0, l >= Zn) {
|
|
2430
2473
|
this.holdBackFastSince = 0;
|
|
2431
2474
|
return;
|
|
2432
2475
|
}
|
|
@@ -2434,7 +2477,7 @@ var er = class {
|
|
|
2434
2477
|
this.holdBackFastSince = t;
|
|
2435
2478
|
return;
|
|
2436
2479
|
}
|
|
2437
|
-
if (t - this.holdBackFastSince <
|
|
2480
|
+
if (t - this.holdBackFastSince < $n || (this.holdBackFastSince = t, this.holdBackStepCount === 0 || a !== this.holdBackApplied)) return;
|
|
2438
2481
|
--this.holdBackStepCount;
|
|
2439
2482
|
let f = Math.max(o, o + this.holdBackStepCount * X);
|
|
2440
2483
|
f >= a || this.moveHoldBack(e, a, f, "fast-fetches", `part fetches fast again (p95 first byte ${d} ms per 1 s of media)`);
|
|
@@ -2477,14 +2520,14 @@ var er = class {
|
|
|
2477
2520
|
} catch {}
|
|
2478
2521
|
}
|
|
2479
2522
|
startEstimate() {
|
|
2480
|
-
return this.deps.rememberBandwidth === !1 ?
|
|
2523
|
+
return this.deps.rememberBandwidth === !1 ? Qt : Be() ?? Qt;
|
|
2481
2524
|
}
|
|
2482
2525
|
maybeRememberBandwidth(e) {
|
|
2483
|
-
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded <
|
|
2526
|
+
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < $t) return;
|
|
2484
2527
|
let t = Date.now();
|
|
2485
|
-
if (!e && t - this.bwSavedAt <
|
|
2528
|
+
if (!e && t - this.bwSavedAt < en) return;
|
|
2486
2529
|
let n = this.hls?.bandwidthEstimate;
|
|
2487
|
-
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t,
|
|
2530
|
+
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Ve(n));
|
|
2488
2531
|
}
|
|
2489
2532
|
destroy() {
|
|
2490
2533
|
if (this.maybeRememberBandwidth(!0), this.detachFrames?.(), this.detachFrames = null, this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onOffline && typeof window < "u" && (window.removeEventListener("offline", this.onOffline), this.onOffline = null), this.onOnline && typeof window < "u" && (window.removeEventListener("online", this.onOnline), this.onOnline = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
|
|
@@ -2502,7 +2545,7 @@ var er = class {
|
|
|
2502
2545
|
scheduleLicenseRetry(t) {
|
|
2503
2546
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
2504
2547
|
let n = t.response?.code ?? 0;
|
|
2505
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
2548
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= rn) return !1;
|
|
2506
2549
|
this.licenseRecoveries += 1;
|
|
2507
2550
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
2508
2551
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -2538,7 +2581,7 @@ var er = class {
|
|
|
2538
2581
|
this.offlineHold = !0, this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null);
|
|
2539
2582
|
return;
|
|
2540
2583
|
}
|
|
2541
|
-
if (this.networkRecoveries <
|
|
2584
|
+
if (this.networkRecoveries < nn) {
|
|
2542
2585
|
this.networkRecoveries += 1;
|
|
2543
2586
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
2544
2587
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -2555,7 +2598,7 @@ var er = class {
|
|
|
2555
2598
|
return;
|
|
2556
2599
|
}
|
|
2557
2600
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
2558
|
-
if (this.mediaRecoveries <
|
|
2601
|
+
if (this.mediaRecoveries < tn) {
|
|
2559
2602
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
2560
2603
|
return;
|
|
2561
2604
|
}
|
|
@@ -2576,18 +2619,21 @@ var er = class {
|
|
|
2576
2619
|
}
|
|
2577
2620
|
}
|
|
2578
2621
|
toError(t, r = "PLAYBACK") {
|
|
2579
|
-
let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(
|
|
2580
|
-
return new n(r === "DRM" ? a(o, l) : r === "NETWORK" && o === 0 ? "NETWORK" : o === 401 ? "UNAUTHORIZED" : o === 403 ? "FORBIDDEN" : "INTERNAL", o, `${r} error: ${s}${c ? ` (${c})` : ""}`,
|
|
2622
|
+
let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(Rt(t.networkDetails)) : void 0;
|
|
2623
|
+
return new n(r === "DRM" ? a(o, l) : r === "NETWORK" && o === 0 ? "NETWORK" : o === 401 ? "UNAUTHORIZED" : o === 403 ? "FORBIDDEN" : "INTERNAL", o, `${r} error: ${s}${c ? ` (${c})` : ""}`, {
|
|
2624
|
+
detail: s,
|
|
2625
|
+
...l ? { serverCode: l } : {}
|
|
2626
|
+
});
|
|
2581
2627
|
}
|
|
2582
|
-
},
|
|
2628
|
+
}, sr = 15e3, cr = 6e5, lr = 3e5, ur = 100, Z = 1, dr = 1e3, fr = 3e4, pr = 1e3, mr = {
|
|
2583
2629
|
inline: "PRESENTATION_INLINE",
|
|
2584
2630
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2585
2631
|
pip: "PRESENTATION_PIP"
|
|
2586
|
-
},
|
|
2632
|
+
}, hr = {
|
|
2587
2633
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2588
2634
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2589
2635
|
none: "KEY_SYSTEM_NONE"
|
|
2590
|
-
},
|
|
2636
|
+
}, gr = /* @__PURE__ */ new Set([
|
|
2591
2637
|
"INVALID_URN",
|
|
2592
2638
|
"NOT_FOUND",
|
|
2593
2639
|
"GEO_DENIED",
|
|
@@ -2598,7 +2644,7 @@ var er = class {
|
|
|
2598
2644
|
"FORBIDDEN",
|
|
2599
2645
|
"RATE_LIMITED",
|
|
2600
2646
|
"TIMEOUT"
|
|
2601
|
-
]),
|
|
2647
|
+
]), _r = {
|
|
2602
2648
|
idle: "PLAYER_STATE_IDLE",
|
|
2603
2649
|
waiting: "PLAYER_STATE_WAITING",
|
|
2604
2650
|
loading: "PLAYER_STATE_LOADING",
|
|
@@ -2608,7 +2654,7 @@ var er = class {
|
|
|
2608
2654
|
ended: "PLAYER_STATE_ENDED",
|
|
2609
2655
|
error: "PLAYER_STATE_ERROR"
|
|
2610
2656
|
};
|
|
2611
|
-
function
|
|
2657
|
+
function vr(e) {
|
|
2612
2658
|
try {
|
|
2613
2659
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2614
2660
|
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);
|
|
@@ -2616,8 +2662,8 @@ function fr(e) {
|
|
|
2616
2662
|
return;
|
|
2617
2663
|
}
|
|
2618
2664
|
}
|
|
2619
|
-
var
|
|
2620
|
-
function
|
|
2665
|
+
var yr = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), br = /* @__PURE__ */ new Set(), xr = /* @__PURE__ */ new Set(), Sr = /* @__PURE__ */ new Set(), Cr = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2666
|
+
function wr(e) {
|
|
2621
2667
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2622
2668
|
let t;
|
|
2623
2669
|
try {
|
|
@@ -2626,19 +2672,19 @@ function vr(e) {
|
|
|
2626
2672
|
} catch {
|
|
2627
2673
|
return;
|
|
2628
2674
|
}
|
|
2629
|
-
if (
|
|
2630
|
-
|
|
2631
|
-
for (let e of
|
|
2675
|
+
if (br.has(t) && !xr.has(t)) {
|
|
2676
|
+
xr.add(t), _(Cr(new URL(t).origin));
|
|
2677
|
+
for (let e of Sr) e.noteCspBlocked();
|
|
2632
2678
|
}
|
|
2633
2679
|
}
|
|
2634
|
-
function
|
|
2680
|
+
function Tr(e, t) {
|
|
2635
2681
|
return _(t, e), { disabledReason: t };
|
|
2636
2682
|
}
|
|
2637
|
-
function
|
|
2638
|
-
if (n) return t && !
|
|
2683
|
+
function Er(e, t, n) {
|
|
2684
|
+
if (n) return t && !yr(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2639
2685
|
if (t) return { endpoint: t };
|
|
2640
|
-
if (t !== void 0) return
|
|
2641
|
-
let r =
|
|
2686
|
+
if (t !== void 0) return Tr("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).");
|
|
2687
|
+
let r = vr(e);
|
|
2642
2688
|
if (r) return { endpoint: r };
|
|
2643
2689
|
let i;
|
|
2644
2690
|
try {
|
|
@@ -2646,9 +2692,9 @@ function br(e, t, n) {
|
|
|
2646
2692
|
} catch {
|
|
2647
2693
|
i = e;
|
|
2648
2694
|
}
|
|
2649
|
-
return
|
|
2695
|
+
return Tr(i, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${i}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
|
|
2650
2696
|
}
|
|
2651
|
-
var
|
|
2697
|
+
var Dr = class {
|
|
2652
2698
|
opts;
|
|
2653
2699
|
url;
|
|
2654
2700
|
cspKey;
|
|
@@ -2730,8 +2776,8 @@ var xr = class {
|
|
|
2730
2776
|
constructor(e) {
|
|
2731
2777
|
this.opts = {
|
|
2732
2778
|
...e,
|
|
2733
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2734
|
-
idleMs: e.idleMs ??
|
|
2779
|
+
heartbeatMs: e.heartbeatMs ?? sr,
|
|
2780
|
+
idleMs: e.idleMs ?? cr
|
|
2735
2781
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2736
2782
|
try {
|
|
2737
2783
|
let e = new URL(this.url);
|
|
@@ -2748,11 +2794,11 @@ var xr = class {
|
|
|
2748
2794
|
sdkVersion: this.opts.sdkVersion,
|
|
2749
2795
|
...this.opts.environment
|
|
2750
2796
|
};
|
|
2751
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2797
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), dr), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.cspKey && br.add(this.cspKey), document.addEventListener("securitypolicyviolation", wr), Sr.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2752
2798
|
}
|
|
2753
2799
|
checkSuspension(e) {
|
|
2754
2800
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2755
|
-
let t = Math.max(this.opts.idleMs,
|
|
2801
|
+
let t = Math.max(this.opts.idleMs, lr);
|
|
2756
2802
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2757
2803
|
}
|
|
2758
2804
|
syncIdle(e) {
|
|
@@ -2766,21 +2812,21 @@ var xr = class {
|
|
|
2766
2812
|
noteStateChange(e, t, n, r) {
|
|
2767
2813
|
if (this.endedFlag || e === t) return;
|
|
2768
2814
|
let i = this.now();
|
|
2769
|
-
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(
|
|
2815
|
+
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(Z, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(Z, 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") {
|
|
2770
2816
|
this.stallIsSeekInduced = this.seekInduced(i);
|
|
2771
2817
|
let e = !this.isHidden && !this.stallIsSeekInduced;
|
|
2772
|
-
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(
|
|
2818
|
+
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(Z, Math.round(this.playingTotalMs)));
|
|
2773
2819
|
} else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
|
|
2774
2820
|
this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
|
|
2775
2821
|
let a = {
|
|
2776
|
-
fromState:
|
|
2777
|
-
toState:
|
|
2778
|
-
presentation:
|
|
2822
|
+
fromState: _r[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2823
|
+
toState: _r[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2824
|
+
presentation: mr[this.presentation]
|
|
2779
2825
|
}, o = this.causeOf(e, t, i);
|
|
2780
2826
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2781
2827
|
}
|
|
2782
2828
|
seekInduced(e) {
|
|
2783
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2829
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < pr;
|
|
2784
2830
|
}
|
|
2785
2831
|
causeOf(e, t, n) {
|
|
2786
2832
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2817,25 +2863,25 @@ var xr = class {
|
|
|
2817
2863
|
}
|
|
2818
2864
|
this.muteChanges += 1;
|
|
2819
2865
|
let r = this.now();
|
|
2820
|
-
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(
|
|
2866
|
+
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(Z, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
|
|
2821
2867
|
}
|
|
2822
2868
|
notePresentation(e) {
|
|
2823
2869
|
this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
|
|
2824
2870
|
}
|
|
2825
2871
|
notePlayIntent() {
|
|
2826
|
-
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs =
|
|
2872
|
+
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = Z), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = Z), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = Z), this.drmSetupMs > 0 && (this.drmSetupMs = Z));
|
|
2827
2873
|
}
|
|
2828
2874
|
noteReady() {
|
|
2829
|
-
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(
|
|
2875
|
+
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(Z, this.now() - this.startupAnchorMs));
|
|
2830
2876
|
}
|
|
2831
2877
|
noteFirstPlaylist() {
|
|
2832
|
-
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(
|
|
2878
|
+
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(Z, this.now() - this.startupAnchorMs));
|
|
2833
2879
|
}
|
|
2834
2880
|
noteDrmReady() {
|
|
2835
|
-
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(
|
|
2881
|
+
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(Z, this.now() - this.startupAnchorMs));
|
|
2836
2882
|
}
|
|
2837
2883
|
noteFirstBytes() {
|
|
2838
|
-
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(
|
|
2884
|
+
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(Z, this.now() - this.startupAnchorMs));
|
|
2839
2885
|
}
|
|
2840
2886
|
noteSeek() {
|
|
2841
2887
|
this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
|
|
@@ -2854,7 +2900,7 @@ var xr = class {
|
|
|
2854
2900
|
let r = n ?? "";
|
|
2855
2901
|
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";
|
|
2856
2902
|
if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
|
|
2857
|
-
if (
|
|
2903
|
+
if (gr.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2858
2904
|
let i = t ?? "";
|
|
2859
2905
|
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";
|
|
2860
2906
|
}
|
|
@@ -2886,7 +2932,7 @@ var xr = class {
|
|
|
2886
2932
|
let l = t.droppedFrames ?? 0;
|
|
2887
2933
|
l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
|
|
2888
2934
|
let u = t.renditionSwitches ?? 0;
|
|
2889
|
-
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 =
|
|
2935
|
+
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 = _r[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
|
|
2890
2936
|
let d = this.mutedTotalMs;
|
|
2891
2937
|
this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
|
|
2892
2938
|
let f = t.upshifts ?? 0;
|
|
@@ -2908,13 +2954,13 @@ var xr = class {
|
|
|
2908
2954
|
maybeEmitMediaInfo(e) {
|
|
2909
2955
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2910
2956
|
let t = {};
|
|
2911
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2957
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = hr[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);
|
|
2912
2958
|
let n = JSON.stringify(t);
|
|
2913
2959
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2914
2960
|
}
|
|
2915
2961
|
end(e, t) {
|
|
2916
2962
|
if (this.endedFlag) return;
|
|
2917
|
-
this.endedFlag = !0,
|
|
2963
|
+
this.endedFlag = !0, Sr.delete(this);
|
|
2918
2964
|
let n = t ?? this.now();
|
|
2919
2965
|
this.playingSinceMs !== null && (this.playingTotalMs += n - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += n - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += n - this.bufferingSinceMs, this.bufferingSinceMs = null), this.mutedSinceMs !== null && (this.mutedTotalMs += n - this.mutedSinceMs, this.mutedSinceMs = null), this.waitingSinceMs !== null && (this.waitingTotalMs += n - this.waitingSinceMs, this.waitingSinceMs = null), this.isPlaying = !1, this.syncActive(n), this.closePresentation(n), this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.timer &&= (clearInterval(this.timer), null), this.idleTimer &&= (clearTimeout(this.idleTimer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), document.removeEventListener("freeze", this.onFreeze), document.removeEventListener("resume", this.onResume));
|
|
2920
2966
|
let r = this.safeSample();
|
|
@@ -2928,7 +2974,7 @@ var xr = class {
|
|
|
2928
2974
|
let c = r?.positionMs ?? 0;
|
|
2929
2975
|
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));
|
|
2930
2976
|
let l = e !== "END_REASON_ENDED";
|
|
2931
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2977
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= fr && (i.abandonAfterStallMs = Math.max(Z, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= fr && (i.abandonAfterErrorMs = Math.max(Z, 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);
|
|
2932
2978
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2933
2979
|
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");
|
|
2934
2980
|
}
|
|
@@ -2948,13 +2994,13 @@ var xr = class {
|
|
|
2948
2994
|
};
|
|
2949
2995
|
}
|
|
2950
2996
|
noteCspBlocked() {
|
|
2951
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2997
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(Cr(new URL(this.url).origin)));
|
|
2952
2998
|
}
|
|
2953
2999
|
cspBlocked() {
|
|
2954
|
-
return !!this.cspKey &&
|
|
3000
|
+
return !!this.cspKey && xr.has(this.cspKey);
|
|
2955
3001
|
}
|
|
2956
3002
|
enqueue(e) {
|
|
2957
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
3003
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > ur;) {
|
|
2958
3004
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2959
3005
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2960
3006
|
}
|
|
@@ -2981,7 +3027,7 @@ var xr = class {
|
|
|
2981
3027
|
};
|
|
2982
3028
|
//#endregion
|
|
2983
3029
|
//#region src/core/environment.ts
|
|
2984
|
-
function
|
|
3030
|
+
function Or() {
|
|
2985
3031
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2986
3032
|
let e;
|
|
2987
3033
|
try {
|
|
@@ -3006,14 +3052,14 @@ function Sr() {
|
|
|
3006
3052
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
3007
3053
|
};
|
|
3008
3054
|
}
|
|
3009
|
-
function
|
|
3055
|
+
function kr() {
|
|
3010
3056
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
3011
3057
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
3012
3058
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
3013
3059
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
3014
3060
|
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";
|
|
3015
3061
|
}
|
|
3016
|
-
function
|
|
3062
|
+
function Ar() {
|
|
3017
3063
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
3018
3064
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
3019
3065
|
let t = {
|
|
@@ -3032,17 +3078,17 @@ function wr() {
|
|
|
3032
3078
|
}
|
|
3033
3079
|
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;
|
|
3034
3080
|
}
|
|
3035
|
-
function
|
|
3036
|
-
let t =
|
|
3037
|
-
deviceClass:
|
|
3081
|
+
function jr(e) {
|
|
3082
|
+
let t = Or(), n = {
|
|
3083
|
+
deviceClass: kr(),
|
|
3038
3084
|
integration: t.integration,
|
|
3039
|
-
...
|
|
3085
|
+
...Ar()
|
|
3040
3086
|
};
|
|
3041
3087
|
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);
|
|
3042
3088
|
let r = e.getBoundingClientRect?.();
|
|
3043
3089
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
3044
3090
|
}
|
|
3045
|
-
async function
|
|
3091
|
+
async function Mr() {
|
|
3046
3092
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
3047
3093
|
if (!e?.getHighEntropyValues) return {};
|
|
3048
3094
|
try {
|
|
@@ -3054,7 +3100,7 @@ async function Er() {
|
|
|
3054
3100
|
}
|
|
3055
3101
|
//#endregion
|
|
3056
3102
|
//#region src/core/version.ts
|
|
3057
|
-
var
|
|
3103
|
+
var Nr = "2.28.0", Pr = {
|
|
3058
3104
|
accent: "#E1B600",
|
|
3059
3105
|
accentText: "#1B1C23",
|
|
3060
3106
|
background: "#0e0f13",
|
|
@@ -3065,7 +3111,7 @@ var Dr = "2.27.1", Or = {
|
|
|
3065
3111
|
border: "rgba(255, 255, 255, 0.1)",
|
|
3066
3112
|
radius: "8px",
|
|
3067
3113
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
3068
|
-
},
|
|
3114
|
+
}, Fr = {
|
|
3069
3115
|
accent: "--havik-accent",
|
|
3070
3116
|
accentText: "--havik-accent-text",
|
|
3071
3117
|
background: "--havik-bg",
|
|
@@ -3077,26 +3123,26 @@ var Dr = "2.27.1", Or = {
|
|
|
3077
3123
|
radius: "--havik-radius",
|
|
3078
3124
|
fontFamily: "--havik-font"
|
|
3079
3125
|
};
|
|
3080
|
-
function
|
|
3126
|
+
function Ir(e, t) {
|
|
3081
3127
|
let n = {
|
|
3082
|
-
...
|
|
3128
|
+
...Pr,
|
|
3083
3129
|
...t
|
|
3084
3130
|
};
|
|
3085
|
-
for (let t of Object.keys(
|
|
3131
|
+
for (let t of Object.keys(Fr)) e.style.setProperty(Fr[t], n[t]);
|
|
3086
3132
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
3087
3133
|
}
|
|
3088
3134
|
//#endregion
|
|
3089
3135
|
//#region src/ui/styles.ts
|
|
3090
|
-
var
|
|
3091
|
-
function
|
|
3092
|
-
let n = e.querySelector(`style#${
|
|
3093
|
-
if (n && (!t ||
|
|
3136
|
+
var Lr = "havik-player-styles", Rr = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", zr = /* @__PURE__ */ new WeakMap();
|
|
3137
|
+
function Br(e = document, t) {
|
|
3138
|
+
let n = e.querySelector(`style#${Lr}`);
|
|
3139
|
+
if (n && (!t || zr.get(n) === t)) return;
|
|
3094
3140
|
let r = e.createElement("style");
|
|
3095
|
-
r.id =
|
|
3141
|
+
r.id = Lr, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Rr, zr.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
3096
3142
|
}
|
|
3097
3143
|
//#endregion
|
|
3098
3144
|
//#region src/ui/icons.ts
|
|
3099
|
-
var
|
|
3145
|
+
var Vr = {
|
|
3100
3146
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
3101
3147
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
3102
3148
|
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\"/>",
|
|
@@ -3109,12 +3155,12 @@ var Fr = {
|
|
|
3109
3155
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
3110
3156
|
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\"/>"
|
|
3111
3157
|
};
|
|
3112
|
-
function
|
|
3113
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
3158
|
+
function Q(e) {
|
|
3159
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Vr[e]}</svg>`;
|
|
3114
3160
|
}
|
|
3115
3161
|
//#endregion
|
|
3116
3162
|
//#region src/ui/controls.ts
|
|
3117
|
-
var
|
|
3163
|
+
var Hr = 3e3, Ur = 250, Wr = /* @__PURE__ */ new Set([
|
|
3118
3164
|
"GONE",
|
|
3119
3165
|
"NOT_FOUND",
|
|
3120
3166
|
"GEO_DENIED",
|
|
@@ -3122,15 +3168,19 @@ var Ir = 3e3, Lr = 250, Rr = /* @__PURE__ */ new Set([
|
|
|
3122
3168
|
"UNAUTHORIZED",
|
|
3123
3169
|
"DRM_DEVICE_REVOKED"
|
|
3124
3170
|
]);
|
|
3125
|
-
function
|
|
3171
|
+
function Gr(e) {
|
|
3126
3172
|
let t = "This match isn't available in your country";
|
|
3127
3173
|
return e ? `${t} (${e})` : t;
|
|
3128
3174
|
}
|
|
3129
|
-
var
|
|
3130
|
-
function
|
|
3131
|
-
return
|
|
3175
|
+
var Kr = "This device can't play protected video";
|
|
3176
|
+
function qr(e) {
|
|
3177
|
+
return `This browser can't play protected video. Allow protected content in its site settings, or use ${e ? "Chrome, Edge or Safari" : "Chrome or Edge"} (Firefox asks when you retry)`;
|
|
3178
|
+
}
|
|
3179
|
+
var Jr = "Protected video can't be shown on this display. Use the built-in screen, or an HDCP-capable monitor and cable";
|
|
3180
|
+
function Yr(e) {
|
|
3181
|
+
return new Xr(e);
|
|
3132
3182
|
}
|
|
3133
|
-
var
|
|
3183
|
+
var Xr = class {
|
|
3134
3184
|
root;
|
|
3135
3185
|
video;
|
|
3136
3186
|
player;
|
|
@@ -3179,7 +3229,7 @@ var Hr = class {
|
|
|
3179
3229
|
scrubbing = !1;
|
|
3180
3230
|
offFns = [];
|
|
3181
3231
|
constructor(e) {
|
|
3182
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
3232
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Hr, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, this.offlineMessage = e.offlineMessage ?? "No internet connection — waiting to reconnect", Br(this.doc, e.cspNonce), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
|
|
3183
3233
|
let t = (e, t, n) => {
|
|
3184
3234
|
let r = this.doc.createElement(e);
|
|
3185
3235
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -3190,12 +3240,12 @@ var Hr = class {
|
|
|
3190
3240
|
"aria-label": r,
|
|
3191
3241
|
title: r
|
|
3192
3242
|
});
|
|
3193
|
-
return i.innerHTML =
|
|
3243
|
+
return i.innerHTML = Q(n), i;
|
|
3194
3244
|
};
|
|
3195
3245
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
3196
3246
|
type: "button",
|
|
3197
3247
|
"aria-label": "Play"
|
|
3198
|
-
}), this.center.innerHTML =
|
|
3248
|
+
}), this.center.innerHTML = Q("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
|
|
3199
3249
|
role: "slider",
|
|
3200
3250
|
"aria-label": "Seek",
|
|
3201
3251
|
"aria-valuemin": "0",
|
|
@@ -3213,7 +3263,7 @@ var Hr = class {
|
|
|
3213
3263
|
"aria-label": "Volume"
|
|
3214
3264
|
});
|
|
3215
3265
|
let a = t("div", "havik-vol");
|
|
3216
|
-
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML =
|
|
3266
|
+
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Q("liveDot");
|
|
3217
3267
|
let o = this.doc.createElement("span");
|
|
3218
3268
|
o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
|
|
3219
3269
|
let s = t("div", "havik-spacer");
|
|
@@ -3265,7 +3315,7 @@ var Hr = class {
|
|
|
3265
3315
|
let t = this.surfaceWasHidden;
|
|
3266
3316
|
this.tapTimer = setTimeout(() => {
|
|
3267
3317
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
3268
|
-
},
|
|
3318
|
+
}, Ur);
|
|
3269
3319
|
}
|
|
3270
3320
|
toggleBar(e) {
|
|
3271
3321
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -3292,7 +3342,20 @@ var Hr = class {
|
|
|
3292
3342
|
this.renderStatus(t);
|
|
3293
3343
|
}
|
|
3294
3344
|
statusMessageFor(e) {
|
|
3295
|
-
|
|
3345
|
+
if (e === "ended") return this.isGone() ? this.endedMessage : this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage;
|
|
3346
|
+
if (e === "offline") return this.offlineMessage;
|
|
3347
|
+
if (e === "waiting") return this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…";
|
|
3348
|
+
if (e === "error") {
|
|
3349
|
+
if (this.errorMessage !== void 0) return this.errorMessage;
|
|
3350
|
+
if (this.lastError?.code === "GEO_DENIED") return Gr(this.lastError.country);
|
|
3351
|
+
if (this.lastError?.code === "DRM_DEVICE_REVOKED") return Kr;
|
|
3352
|
+
if (this.lastError?.code === "DRM_CLIENT") {
|
|
3353
|
+
if (this.lastError.detail === "keySystemNoAccess") return qr(!!this.player.descriptor?.drm?.fairplay?.licenseUrl);
|
|
3354
|
+
if (this.lastError.detail === "keySystemStatusOutputRestricted") return Jr;
|
|
3355
|
+
}
|
|
3356
|
+
return this.lastError?.message ?? "Playback unavailable";
|
|
3357
|
+
}
|
|
3358
|
+
return null;
|
|
3296
3359
|
}
|
|
3297
3360
|
renderStatus(e) {
|
|
3298
3361
|
let t = this.statusMessageFor(e);
|
|
@@ -3304,12 +3367,12 @@ var Hr = class {
|
|
|
3304
3367
|
}
|
|
3305
3368
|
if (e === "preplay") {
|
|
3306
3369
|
let e = this.doc.createElement("button");
|
|
3307
|
-
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML =
|
|
3370
|
+
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);
|
|
3308
3371
|
} else {
|
|
3309
3372
|
let r = this.doc.createElement("div");
|
|
3310
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
3373
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Wr.has(this.lastError.code)) {
|
|
3311
3374
|
let e = this.doc.createElement("button");
|
|
3312
|
-
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${
|
|
3375
|
+
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);
|
|
3313
3376
|
}
|
|
3314
3377
|
}
|
|
3315
3378
|
this.root.append(n), this.statusBox = n, this.show();
|
|
@@ -3348,7 +3411,7 @@ var Hr = class {
|
|
|
3348
3411
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
3349
3412
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
3350
3413
|
}
|
|
3351
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
3414
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Zr(this.video.currentTime)} / ${Zr(this.video.duration)}`);
|
|
3352
3415
|
}
|
|
3353
3416
|
syncLive() {
|
|
3354
3417
|
let e = this.player.getStats(), t = e.isLive !== !1, n = this.isGone(), r = this.player.state === "ended" || n, i = !t && !this.streamEnded() && !n;
|
|
@@ -3398,17 +3461,17 @@ var Hr = class {
|
|
|
3398
3461
|
renderQualityMenu() {
|
|
3399
3462
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
3400
3463
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
3401
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
3464
|
+
for (let n of e) this.menu.append(this.menuItem(Qr(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
3402
3465
|
}
|
|
3403
3466
|
renderAudioMenu() {
|
|
3404
3467
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
3405
3468
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
3406
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3469
|
+
for (let t of e) this.menu.append(this.menuItem($r(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
3407
3470
|
}
|
|
3408
3471
|
renderCcMenu() {
|
|
3409
3472
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
3410
3473
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
3411
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3474
|
+
for (let t of e) this.menu.append(this.menuItem(ei(t), !1, () => this.player.setTextTrack(t.id)));
|
|
3412
3475
|
}
|
|
3413
3476
|
onTracksChanged() {
|
|
3414
3477
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -3428,14 +3491,14 @@ var Hr = class {
|
|
|
3428
3491
|
}
|
|
3429
3492
|
async toggleFullscreen() {
|
|
3430
3493
|
try {
|
|
3431
|
-
|
|
3494
|
+
S(this.video, this.root) ? await T(this.video, this.root) : await w(this.video, this.root);
|
|
3432
3495
|
} catch {}
|
|
3433
3496
|
}
|
|
3434
3497
|
syncFullscreenSupport() {
|
|
3435
|
-
this.fsSupported =
|
|
3498
|
+
this.fsSupported = C(this.video, this.root), this.fsBtn.style.display = this.fsSupported ? "" : "none";
|
|
3436
3499
|
}
|
|
3437
3500
|
syncFullscreen() {
|
|
3438
|
-
let e =
|
|
3501
|
+
let e = S(this.video, this.root);
|
|
3439
3502
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
3440
3503
|
}
|
|
3441
3504
|
poke() {
|
|
@@ -3496,7 +3559,7 @@ var Hr = class {
|
|
|
3496
3559
|
}
|
|
3497
3560
|
}
|
|
3498
3561
|
setIcon(e, t) {
|
|
3499
|
-
e.innerHTML =
|
|
3562
|
+
e.innerHTML = Q(t);
|
|
3500
3563
|
}
|
|
3501
3564
|
destroy() {
|
|
3502
3565
|
this.hideTimer && clearTimeout(this.hideTimer), this.tapTimer && clearTimeout(this.tapTimer);
|
|
@@ -3513,23 +3576,23 @@ var Hr = class {
|
|
|
3513
3576
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
3514
3577
|
}
|
|
3515
3578
|
};
|
|
3516
|
-
function
|
|
3579
|
+
function Zr(e) {
|
|
3517
3580
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
3518
3581
|
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");
|
|
3519
3582
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
3520
3583
|
}
|
|
3521
|
-
function
|
|
3584
|
+
function Qr(e) {
|
|
3522
3585
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
3523
3586
|
}
|
|
3524
|
-
function
|
|
3587
|
+
function $r(e) {
|
|
3525
3588
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3526
3589
|
}
|
|
3527
|
-
function
|
|
3590
|
+
function ei(e) {
|
|
3528
3591
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3529
3592
|
}
|
|
3530
3593
|
//#endregion
|
|
3531
3594
|
//#region src/managed/index.ts
|
|
3532
|
-
var
|
|
3595
|
+
var ti = 6e3, ni = 45e3, ri = 2e3, ii = 3, ai = 6e4, oi = 2, si = 6e5, ci = 5e3, li = 2e3, ui = 48e4, di = "keySystemLicenseRequestFailed", fi = /* @__PURE__ */ new Set([
|
|
3533
3596
|
"GONE",
|
|
3534
3597
|
"NOT_FOUND",
|
|
3535
3598
|
"INVALID_URN",
|
|
@@ -3537,27 +3600,27 @@ var qr = 6e3, Jr = 45e3, Yr = 2e3, Xr = 3, Zr = 5e3, Qr = 2e3, $r = 48e4, ei = "
|
|
|
3537
3600
|
"GEO_DENIED",
|
|
3538
3601
|
"DRM_DEVICE_REVOKED"
|
|
3539
3602
|
]);
|
|
3540
|
-
function
|
|
3541
|
-
return !
|
|
3603
|
+
function pi(e) {
|
|
3604
|
+
return !fi.has(e);
|
|
3542
3605
|
}
|
|
3543
|
-
function
|
|
3606
|
+
function mi(e) {
|
|
3544
3607
|
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)})`);
|
|
3545
3608
|
if (e.env !== void 0) return lt(e.env);
|
|
3546
3609
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
3547
3610
|
return e.baseUrl;
|
|
3548
3611
|
}
|
|
3549
|
-
async function
|
|
3612
|
+
async function hi(e) {
|
|
3550
3613
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
3551
|
-
let t =
|
|
3614
|
+
let t = mi(e);
|
|
3552
3615
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
3553
3616
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
3554
|
-
let r = new
|
|
3617
|
+
let r = new gi({
|
|
3555
3618
|
...e,
|
|
3556
3619
|
baseUrl: t
|
|
3557
3620
|
});
|
|
3558
3621
|
return await r.start(), r;
|
|
3559
3622
|
}
|
|
3560
|
-
var
|
|
3623
|
+
var gi = class {
|
|
3561
3624
|
opts;
|
|
3562
3625
|
abort = new AbortController();
|
|
3563
3626
|
listeners = {};
|
|
@@ -3580,6 +3643,10 @@ var ai = class {
|
|
|
3580
3643
|
destroyed = !1;
|
|
3581
3644
|
loadGen = 0;
|
|
3582
3645
|
liveStateSub = null;
|
|
3646
|
+
liveStateLast = null;
|
|
3647
|
+
liveStateAliveAt = 0;
|
|
3648
|
+
staleEndReloads = 0;
|
|
3649
|
+
staleEndWindowAt = 0;
|
|
3583
3650
|
endedHandled = !1;
|
|
3584
3651
|
_endedReason = null;
|
|
3585
3652
|
rejoinTimer = null;
|
|
@@ -3636,7 +3703,7 @@ var ai = class {
|
|
|
3636
3703
|
};
|
|
3637
3704
|
}
|
|
3638
3705
|
beginArming(e, t, n = !1) {
|
|
3639
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
3706
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
|
|
3640
3707
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
3641
3708
|
}
|
|
3642
3709
|
beginArmingByPolling(e) {
|
|
@@ -3657,7 +3724,7 @@ var ai = class {
|
|
|
3657
3724
|
setTimeout(() => {
|
|
3658
3725
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3659
3726
|
phase: i ? "unavailable" : "tooEarly",
|
|
3660
|
-
retryInMs:
|
|
3727
|
+
retryInMs: ni,
|
|
3661
3728
|
attempt: 1,
|
|
3662
3729
|
elapsedMs: 0,
|
|
3663
3730
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3696,13 +3763,13 @@ var ai = class {
|
|
|
3696
3763
|
!a && !p() && h();
|
|
3697
3764
|
}, e);
|
|
3698
3765
|
};
|
|
3699
|
-
_(
|
|
3766
|
+
_(ti), this.armingSub = D({
|
|
3700
3767
|
eventsBaseUrl: t,
|
|
3701
3768
|
matchUrn: this.opts.matchUrn,
|
|
3702
3769
|
credential: this.opts.credential,
|
|
3703
|
-
onAlive: () => _(
|
|
3770
|
+
onAlive: () => _(ni),
|
|
3704
3771
|
onState: (e) => {
|
|
3705
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3772
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * ri);
|
|
3706
3773
|
},
|
|
3707
3774
|
onError: () => h()
|
|
3708
3775
|
});
|
|
@@ -3725,7 +3792,7 @@ var ai = class {
|
|
|
3725
3792
|
let n = await c(this.opts.credential);
|
|
3726
3793
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3727
3794
|
this.setState("loading");
|
|
3728
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3795
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = vt(this.opts.video, (e) => {
|
|
3729
3796
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3730
3797
|
});
|
|
3731
3798
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3747,19 +3814,19 @@ var ai = class {
|
|
|
3747
3814
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3748
3815
|
let i = e.analytics?.sid;
|
|
3749
3816
|
if (!i) return;
|
|
3750
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3817
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Er(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3751
3818
|
if (!o) {
|
|
3752
3819
|
s && setTimeout(() => {
|
|
3753
3820
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3754
3821
|
}, 0);
|
|
3755
3822
|
return;
|
|
3756
3823
|
}
|
|
3757
|
-
let c = this.opts.video, l = new
|
|
3824
|
+
let c = this.opts.video, l = new Dr({
|
|
3758
3825
|
endpoint: o,
|
|
3759
3826
|
sid: i,
|
|
3760
3827
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3761
|
-
sdkVersion:
|
|
3762
|
-
environment:
|
|
3828
|
+
sdkVersion: Nr,
|
|
3829
|
+
environment: jr(c),
|
|
3763
3830
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3764
3831
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3765
3832
|
onBlocked: (e) => setTimeout(() => {
|
|
@@ -3780,7 +3847,7 @@ var ai = class {
|
|
|
3780
3847
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3781
3848
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3782
3849
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3783
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3850
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Mr().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3784
3851
|
}
|
|
3785
3852
|
currentPresentation() {
|
|
3786
3853
|
let e = this.opts.video;
|
|
@@ -3795,7 +3862,7 @@ var ai = class {
|
|
|
3795
3862
|
video: this.opts.video,
|
|
3796
3863
|
descriptor: e,
|
|
3797
3864
|
credential: t,
|
|
3798
|
-
deviceId:
|
|
3865
|
+
deviceId: Oe(),
|
|
3799
3866
|
userId: this.opts.userId,
|
|
3800
3867
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
3801
3868
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -3804,6 +3871,7 @@ var ai = class {
|
|
|
3804
3871
|
adaptiveHoldBack: this.opts.adaptiveHoldBack,
|
|
3805
3872
|
adaptiveHoldBackCeiling: this.opts.adaptiveHoldBackCeiling,
|
|
3806
3873
|
stallCap: this.opts.stallCap,
|
|
3874
|
+
stuckReload: this.opts.stuckReload,
|
|
3807
3875
|
mediaDuringKey: this.opts.mediaDuringKey,
|
|
3808
3876
|
preloadHints: this.opts.preloadHints,
|
|
3809
3877
|
debug: this.opts.debug,
|
|
@@ -3813,9 +3881,9 @@ var ai = class {
|
|
|
3813
3881
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3814
3882
|
}, o = this.opts.engine ?? "auto";
|
|
3815
3883
|
if (o === "native") return new H(a);
|
|
3816
|
-
if (o === "hls") return new
|
|
3817
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && B(this.opts.video) && V() || !e.drmEnabled &&
|
|
3818
|
-
if (
|
|
3884
|
+
if (o === "hls") return new or(a);
|
|
3885
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && B(this.opts.video) && V() || !e.drmEnabled && Pt() && B(this.opts.video)) return new H(a);
|
|
3886
|
+
if (Xt()) return new or(a);
|
|
3819
3887
|
if (B(this.opts.video)) return new H(a);
|
|
3820
3888
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3821
3889
|
}
|
|
@@ -3849,6 +3917,7 @@ var ai = class {
|
|
|
3849
3917
|
this.emit("texttrackchange", e.id);
|
|
3850
3918
|
break;
|
|
3851
3919
|
case "ended":
|
|
3920
|
+
if (e.reason === "stalled" && this.reloadStaleEnd()) break;
|
|
3852
3921
|
this.onStreamEnded();
|
|
3853
3922
|
break;
|
|
3854
3923
|
case "error": {
|
|
@@ -3866,27 +3935,27 @@ var ai = class {
|
|
|
3866
3935
|
}
|
|
3867
3936
|
startLiveState(e) {
|
|
3868
3937
|
if (this.opts.liveStateEvents === !1) return;
|
|
3869
|
-
let t = this.opts.eventsBaseUrl ??
|
|
3938
|
+
let t = this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
|
|
3870
3939
|
if (!t) return;
|
|
3871
|
-
this.closeLiveState();
|
|
3940
|
+
this.closeLiveState(), this.liveStateLast = null, this.liveStateAliveAt = 0;
|
|
3872
3941
|
let i = 0, a = !1;
|
|
3873
|
-
this.liveStateSub =
|
|
3942
|
+
this.liveStateSub = D({
|
|
3874
3943
|
eventsBaseUrl: t,
|
|
3875
3944
|
matchUrn: this.opts.matchUrn,
|
|
3876
3945
|
credential: this.opts.credential,
|
|
3877
3946
|
onState: (t) => {
|
|
3878
|
-
this.destroyed || e !== this.loadGen || (t.state === "gone" ? this.onStreamEnded(!0, t.reason ?? "match_ended") : t.state === "ended" ? this.onStreamEnded(!1, t.reason) : t.state === "live" && this.endedHandled && this.scheduleRejoin(e));
|
|
3947
|
+
this.destroyed || e !== this.loadGen || (this.liveStateLast = t.state, this.liveStateAliveAt = Date.now(), t.state === "gone" ? this.onStreamEnded(!0, t.reason ?? "match_ended") : t.state === "ended" ? this.onStreamEnded(!1, t.reason) : t.state === "live" && this.endedHandled && this.scheduleRejoin(e));
|
|
3879
3948
|
},
|
|
3880
3949
|
onAlive: () => {
|
|
3881
|
-
i = 0, a = !1;
|
|
3950
|
+
i = 0, a = !1, !this.destroyed && e === this.loadGen && (this.liveStateAliveAt = Date.now());
|
|
3882
3951
|
},
|
|
3883
3952
|
onError: (o) => {
|
|
3884
3953
|
if (!(this.destroyed || e !== this.loadGen || a) && !this.endedHandled) {
|
|
3885
|
-
if (o instanceof
|
|
3954
|
+
if (o instanceof E && (o.terminal || o.status === 404)) {
|
|
3886
3955
|
a = !0, this.emit("warning", new n(r(o.status), o.status, `live-state events answered HTTP ${o.status} for ${this.opts.matchUrn}: the match is ` + (o.terminal ? "gone, so the subscription stopped" : "not in the catalog (ended and dropped, or not listed yet), so it retries every 5 min") + " — end-of-stream detection falls back to the HLS staleness watchdog."));
|
|
3887
3956
|
return;
|
|
3888
3957
|
}
|
|
3889
|
-
i += 1, i >=
|
|
3958
|
+
i += 1, i >= ii && (a = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${i} 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.`)));
|
|
3890
3959
|
}
|
|
3891
3960
|
}
|
|
3892
3961
|
});
|
|
@@ -3894,6 +3963,18 @@ var ai = class {
|
|
|
3894
3963
|
closeLiveState() {
|
|
3895
3964
|
this.liveStateSub?.close(), this.liveStateSub = null;
|
|
3896
3965
|
}
|
|
3966
|
+
reloadStaleEnd() {
|
|
3967
|
+
if (this.destroyed || this.endedHandled || this._state === "error" || this._state === "ended") return !1;
|
|
3968
|
+
let e = Date.now();
|
|
3969
|
+
if (this.liveStateLast !== "live" || e - this.liveStateAliveAt > ai || (e - this.staleEndWindowAt > si && (this.staleEndReloads = 0, this.staleEndWindowAt = e), this.staleEndReloads >= oi)) return !1;
|
|
3970
|
+
this.staleEndReloads += 1;
|
|
3971
|
+
let t = new n("UNAVAILABLE", 0, `live playlist stopped advancing for 12 s while the match is live (live-state push heard ${Math.round((e - this.liveStateAliveAt) / 1e3)} s ago): reloading instead of ending (${this.staleEndReloads} of ${oi} this window)`);
|
|
3972
|
+
this.analyticsSession?.noteError(t.code, t.message, !1, 0, Math.round(this.opts.video.currentTime * 1e3), "staleEndReload");
|
|
3973
|
+
let r = this.loadGen;
|
|
3974
|
+
return this.emit("warning", t), Promise.resolve().then(() => {
|
|
3975
|
+
if (!(this.destroyed || r !== this.loadGen) && this._state !== "error" && this._state !== "ended") return this.reload().catch(() => void 0);
|
|
3976
|
+
}), !0;
|
|
3977
|
+
}
|
|
3897
3978
|
watchConnectivity() {
|
|
3898
3979
|
this.connectivity || (this.connectivity = ut(), this.connectivity.onChange((e) => {
|
|
3899
3980
|
if (this.destroyed) return;
|
|
@@ -3903,7 +3984,7 @@ var ai = class {
|
|
|
3903
3984
|
}
|
|
3904
3985
|
if (this.emit("online"), this._state !== "error" || !this._lastError) return;
|
|
3905
3986
|
let t = this._lastError.code;
|
|
3906
|
-
|
|
3987
|
+
pi(t) && (t === "NETWORK" || this.failedWhileOffline) && this.retry().catch(() => void 0);
|
|
3907
3988
|
}));
|
|
3908
3989
|
}
|
|
3909
3990
|
watchReturn() {
|
|
@@ -3913,7 +3994,7 @@ var ai = class {
|
|
|
3913
3994
|
return;
|
|
3914
3995
|
}
|
|
3915
3996
|
let e = this.hiddenAtMs;
|
|
3916
|
-
this.hiddenAtMs = null, e != null && Date.now() - e >=
|
|
3997
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= ci && this.resyncLiveState();
|
|
3917
3998
|
}, this.onReturnPageShow = (e) => {
|
|
3918
3999
|
e.persisted && this.resyncLiveState();
|
|
3919
4000
|
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
@@ -3945,7 +4026,7 @@ var ai = class {
|
|
|
3945
4026
|
scheduleRejoin(e) {
|
|
3946
4027
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3947
4028
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3948
|
-
}, Math.random() *
|
|
4029
|
+
}, Math.random() * ri));
|
|
3949
4030
|
}
|
|
3950
4031
|
cancelRejoin() {
|
|
3951
4032
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3969,7 +4050,7 @@ var ai = class {
|
|
|
3969
4050
|
}
|
|
3970
4051
|
t.controls = !1;
|
|
3971
4052
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3972
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
4053
|
+
r && r.insertBefore(n, t), n.appendChild(t), Ir(n, this.opts.theme), this.container = n, this.controlBar = Yr({
|
|
3973
4054
|
root: n,
|
|
3974
4055
|
video: t,
|
|
3975
4056
|
player: this,
|
|
@@ -4008,7 +4089,7 @@ var ai = class {
|
|
|
4008
4089
|
}
|
|
4009
4090
|
startStats() {
|
|
4010
4091
|
this.stopStats();
|
|
4011
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
4092
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? li);
|
|
4012
4093
|
this.statsTimer = setInterval(() => {
|
|
4013
4094
|
if (!this.engine) return;
|
|
4014
4095
|
let e = this.engine.getStats();
|
|
@@ -4019,14 +4100,14 @@ var ai = class {
|
|
|
4019
4100
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
4020
4101
|
}
|
|
4021
4102
|
isStaleLicenseDenial(e) {
|
|
4022
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
4103
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== di || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : W(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
4023
4104
|
}
|
|
4024
4105
|
scheduleLicenseRefresh() {
|
|
4025
4106
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
4026
4107
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
4027
4108
|
document.visibilityState !== "visible" || this.destroyed || W(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
4028
4109
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
4029
|
-
let e = this.opts.licenseRefreshMs ??
|
|
4110
|
+
let e = this.opts.licenseRefreshMs ?? ui;
|
|
4030
4111
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
4031
4112
|
}
|
|
4032
4113
|
stopRefresh() {
|
|
@@ -4122,13 +4203,13 @@ var ai = class {
|
|
|
4122
4203
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
4123
4204
|
}
|
|
4124
4205
|
async enterFullscreen() {
|
|
4125
|
-
return !this.destroyed &&
|
|
4206
|
+
return !this.destroyed && w(this.opts.video, this.container ?? void 0);
|
|
4126
4207
|
}
|
|
4127
4208
|
async exitFullscreen() {
|
|
4128
|
-
await
|
|
4209
|
+
await T(this.opts.video, this.container ?? void 0);
|
|
4129
4210
|
}
|
|
4130
4211
|
fullscreenSupported() {
|
|
4131
|
-
return !this.destroyed &&
|
|
4212
|
+
return !this.destroyed && C(this.opts.video, this.container ?? void 0);
|
|
4132
4213
|
}
|
|
4133
4214
|
retry() {
|
|
4134
4215
|
return this.reload();
|
|
@@ -4191,12 +4272,12 @@ var ai = class {
|
|
|
4191
4272
|
};
|
|
4192
4273
|
//#endregion
|
|
4193
4274
|
//#region src/embed/protocol.ts
|
|
4194
|
-
function
|
|
4275
|
+
function $(e) {
|
|
4195
4276
|
return !!e && typeof e == "object" && typeof e.type == "string" && e.type.startsWith("oddin:");
|
|
4196
4277
|
}
|
|
4197
4278
|
//#endregion
|
|
4198
4279
|
//#region src/embed/host.ts
|
|
4199
|
-
function
|
|
4280
|
+
function _i(e) {
|
|
4200
4281
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
4201
4282
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
4202
4283
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -4205,7 +4286,7 @@ function si(e) {
|
|
|
4205
4286
|
let r = document.createElement("iframe");
|
|
4206
4287
|
r.src = t.toString(), r.allow = "autoplay; encrypted-media; fullscreen", r.setAttribute("allowfullscreen", ""), r.referrerPolicy = "no-referrer", r.setAttribute("sandbox", e.sandbox ?? "allow-scripts allow-same-origin allow-presentation"), r.style.cssText = "border:0;width:100%;height:100%;display:block", e.container.appendChild(r);
|
|
4207
4288
|
let i = /* @__PURE__ */ new Set(), a = (t) => {
|
|
4208
|
-
if (t.source !== r.contentWindow || t.origin !== n ||
|
|
4289
|
+
if (t.source !== r.contentWindow || t.origin !== n || !$(t.data)) return;
|
|
4209
4290
|
let a = t.data;
|
|
4210
4291
|
a.type === "oddin:ready" && a.protocol !== 1 && console.warn(`havik-player: embed protocol v${a.protocol} != host v1. Pin the embed page version to the SDK version to avoid skew.`), e.onEvent?.(a), i.forEach((e) => e(a));
|
|
4211
4292
|
};
|
|
@@ -4255,15 +4336,15 @@ function si(e) {
|
|
|
4255
4336
|
}
|
|
4256
4337
|
//#endregion
|
|
4257
4338
|
//#region src/embed/page.ts
|
|
4258
|
-
var
|
|
4259
|
-
function
|
|
4339
|
+
var vi = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
4340
|
+
function yi(e) {
|
|
4260
4341
|
if (typeof e == "boolean") return e;
|
|
4261
4342
|
if (typeof e == "object" && e) {
|
|
4262
4343
|
let t = e.endpoint;
|
|
4263
4344
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
4264
4345
|
}
|
|
4265
4346
|
}
|
|
4266
|
-
function
|
|
4347
|
+
function bi() {
|
|
4267
4348
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
4268
4349
|
if (e) return {
|
|
4269
4350
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -4273,7 +4354,7 @@ function ui() {
|
|
|
4273
4354
|
autoplay: e.autoplay ?? !0,
|
|
4274
4355
|
muted: e.muted ?? !0,
|
|
4275
4356
|
waitForLive: e.waitForLive ?? !0,
|
|
4276
|
-
analytics:
|
|
4357
|
+
analytics: yi(e.analytics)
|
|
4277
4358
|
};
|
|
4278
4359
|
let t = new URLSearchParams(location.search);
|
|
4279
4360
|
return {
|
|
@@ -4286,9 +4367,9 @@ function ui() {
|
|
|
4286
4367
|
waitForLive: !0
|
|
4287
4368
|
};
|
|
4288
4369
|
}
|
|
4289
|
-
async function
|
|
4290
|
-
let e =
|
|
4291
|
-
|
|
4370
|
+
async function xi() {
|
|
4371
|
+
let e = bi();
|
|
4372
|
+
Ci();
|
|
4292
4373
|
let t = document.createElement("video");
|
|
4293
4374
|
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);
|
|
4294
4375
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -4344,12 +4425,12 @@ async function di() {
|
|
|
4344
4425
|
message: e.message,
|
|
4345
4426
|
...e.country === void 0 ? {} : { country: e.country }
|
|
4346
4427
|
})), e.on("autoplayblocked", () => {
|
|
4347
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
4428
|
+
i({ type: "oddin:autoplayblocked" }), Si(t, e);
|
|
4348
4429
|
});
|
|
4349
4430
|
}, s = async (r) => {
|
|
4350
4431
|
a?.destroy(), a = null;
|
|
4351
4432
|
try {
|
|
4352
|
-
let n = await
|
|
4433
|
+
let n = await hi({
|
|
4353
4434
|
video: t,
|
|
4354
4435
|
baseUrl: e.baseUrl,
|
|
4355
4436
|
matchUrn: r,
|
|
@@ -4412,30 +4493,30 @@ async function di() {
|
|
|
4412
4493
|
a?.retry();
|
|
4413
4494
|
break;
|
|
4414
4495
|
case "oddin:load":
|
|
4415
|
-
typeof e.matchUrn == "string" &&
|
|
4496
|
+
typeof e.matchUrn == "string" && vi.test(e.matchUrn) && s(e.matchUrn);
|
|
4416
4497
|
break;
|
|
4417
4498
|
case "oddin:destroy": c();
|
|
4418
4499
|
}
|
|
4419
4500
|
}, u = (e) => {
|
|
4420
|
-
r && e.origin === r &&
|
|
4501
|
+
r && e.origin === r && $(e.data) && l(e.data);
|
|
4421
4502
|
};
|
|
4422
4503
|
r && window.addEventListener("message", u), window.addEventListener("pagehide", c, { once: !0 }), await s(e.matchUrn), i({
|
|
4423
4504
|
type: "oddin:ready",
|
|
4424
4505
|
protocol: 1
|
|
4425
4506
|
});
|
|
4426
4507
|
}
|
|
4427
|
-
function
|
|
4508
|
+
function Si(e, t) {
|
|
4428
4509
|
if (document.getElementById("havik-tap")) return;
|
|
4429
4510
|
let n = document.createElement("button");
|
|
4430
4511
|
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", () => {
|
|
4431
4512
|
n.remove(), t.play();
|
|
4432
4513
|
}), document.body.appendChild(n);
|
|
4433
4514
|
}
|
|
4434
|
-
function
|
|
4515
|
+
function Ci() {
|
|
4435
4516
|
let e = document.createElement("style");
|
|
4436
4517
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
4437
4518
|
}
|
|
4438
4519
|
//#endregion
|
|
4439
|
-
export {
|
|
4520
|
+
export { E as LiveStateHttpError, Pr as ODDIN_THEME, n as PlaybackError, Ir as applyTheme, lt as baseUrlForEnv, xi as bootEmbed, ke as clearDeviceId, He as clearRememberedBandwidth, hi as createPlayer, O as deriveEventsBaseUrl, at as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, Oe as getDeviceId, st as isLowLatencyManifest, $ as isOddinMessage, je as licenseRequestHeaders, _i as mountEmbed, fe as pollToLive, y as resolveStream, D as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
|
|
4440
4521
|
|
|
4441
4522
|
//# sourceMappingURL=index.js.map
|