@oddin-gg/havik-player 2.6.2 → 2.6.3
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 +18 -18
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -3
- package/dist/index.d.ts +14 -3
- package/dist/index.js +170 -154
- package/dist/index.js.map +1 -1
- package/docs/API.md +23 -10
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -397,14 +397,15 @@ function he(e) {
|
|
|
397
397
|
}
|
|
398
398
|
//#endregion
|
|
399
399
|
//#region src/core/events.ts
|
|
400
|
+
var ge = 45e3;
|
|
400
401
|
function E(e) {
|
|
401
|
-
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = new AbortController(),
|
|
402
|
-
if (
|
|
402
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? ge, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, l = (e) => new Promise((t) => {
|
|
403
|
+
if (a.signal.aborted) return t();
|
|
403
404
|
let n = setTimeout(t, e);
|
|
404
|
-
|
|
405
|
+
a.signal.addEventListener("abort", () => {
|
|
405
406
|
clearTimeout(n), t();
|
|
406
407
|
}, { once: !0 });
|
|
407
|
-
}),
|
|
408
|
+
}), u = (t) => {
|
|
408
409
|
e.onAlive?.();
|
|
409
410
|
let n = "message", r = [];
|
|
410
411
|
for (let e of t.split("\n")) {
|
|
@@ -417,51 +418,66 @@ function E(e) {
|
|
|
417
418
|
let t = JSON.parse(r.join("\n"));
|
|
418
419
|
t && typeof t.state == "string" && e.onState(t);
|
|
419
420
|
} catch {}
|
|
420
|
-
},
|
|
421
|
-
let
|
|
421
|
+
}, d = /\r\n\r\n|\n\n|\r\r/, f = async (e, t, n) => {
|
|
422
|
+
let r = e.getReader(), a = new TextDecoder(), s = "", c = !1, l, f = () => {
|
|
423
|
+
i && (clearTimeout(l), l = setTimeout(() => {
|
|
424
|
+
n(), r.cancel().catch(() => {});
|
|
425
|
+
}, i));
|
|
426
|
+
};
|
|
422
427
|
try {
|
|
423
|
-
for (;;) {
|
|
424
|
-
let { value: e, done:
|
|
425
|
-
if (
|
|
426
|
-
|
|
427
|
-
let
|
|
428
|
-
for (; (
|
|
429
|
-
if (
|
|
428
|
+
for (f();;) {
|
|
429
|
+
let { value: e, done: n } = await r.read();
|
|
430
|
+
if (n) return;
|
|
431
|
+
e && e.length > 0 && (f(), c || (c = !0, t())), s += a.decode(e, { stream: !0 });
|
|
432
|
+
let i;
|
|
433
|
+
for (; (i = d.exec(s)) !== null;) u(s.slice(0, i.index)), s = s.slice(i.index + i[0].length);
|
|
434
|
+
if (o) return;
|
|
430
435
|
}
|
|
431
436
|
} finally {
|
|
432
|
-
await
|
|
437
|
+
clearTimeout(l), await r.cancel().catch(() => {});
|
|
433
438
|
}
|
|
434
439
|
};
|
|
435
440
|
return (async () => {
|
|
436
|
-
let
|
|
437
|
-
for (; !
|
|
441
|
+
let r = t;
|
|
442
|
+
for (; !o;) {
|
|
443
|
+
let u = new AbortController(), d = () => u.abort();
|
|
444
|
+
a.signal.addEventListener("abort", d, { once: !0 });
|
|
445
|
+
let p = null, m, h = () => {
|
|
446
|
+
p = `no data for ${i}ms`, u.abort();
|
|
447
|
+
};
|
|
438
448
|
try {
|
|
439
449
|
let n = await s(e.credential);
|
|
440
|
-
if (
|
|
441
|
-
let a = c(e.eventsBaseUrl, `/v1/events/${encodeURIComponent(e.matchUrn)}`)
|
|
450
|
+
if (o) return;
|
|
451
|
+
let a = c(e.eventsBaseUrl, `/v1/events/${encodeURIComponent(e.matchUrn)}`);
|
|
452
|
+
i && (m = setTimeout(() => {
|
|
453
|
+
p = `no response headers within ${i}ms`, u.abort();
|
|
454
|
+
}, i));
|
|
455
|
+
let l = await fetch(a, {
|
|
442
456
|
method: "GET",
|
|
443
457
|
headers: {
|
|
444
458
|
"x-api-key": n.apiKey,
|
|
445
459
|
accept: "text/event-stream"
|
|
446
460
|
},
|
|
447
|
-
signal:
|
|
461
|
+
signal: u.signal,
|
|
448
462
|
cache: "no-store",
|
|
449
463
|
credentials: "omit",
|
|
450
464
|
mode: "cors"
|
|
451
465
|
});
|
|
452
|
-
if (
|
|
453
|
-
!l.ok || !l.body ? e.onError?.(/* @__PURE__ */ Error(`live-state subscribe failed: HTTP ${l.status}`)) : await
|
|
454
|
-
|
|
455
|
-
});
|
|
466
|
+
if (clearTimeout(m), o) return;
|
|
467
|
+
!l.ok || !l.body ? e.onError?.(/* @__PURE__ */ Error(`live-state subscribe failed: HTTP ${l.status}`)) : await f(l.body, () => {
|
|
468
|
+
r = t;
|
|
469
|
+
}, h);
|
|
456
470
|
} catch (t) {
|
|
457
|
-
if (
|
|
458
|
-
e.onError?.(t);
|
|
471
|
+
if (o || a.signal.aborted) return;
|
|
472
|
+
p || e.onError?.(t);
|
|
473
|
+
} finally {
|
|
474
|
+
clearTimeout(m), a.signal.removeEventListener("abort", d), u.abort();
|
|
459
475
|
}
|
|
460
|
-
if (
|
|
461
|
-
await
|
|
476
|
+
if (o) return;
|
|
477
|
+
p && e.onError?.(/* @__PURE__ */ Error(`live-state subscribe idle: ${p} — reconnecting`)), await l(r), r = Math.min(n, r * 2);
|
|
462
478
|
}
|
|
463
479
|
})(), { close() {
|
|
464
|
-
|
|
480
|
+
o || (o = !0, a.abort());
|
|
465
481
|
} };
|
|
466
482
|
}
|
|
467
483
|
function D(e) {
|
|
@@ -481,20 +497,20 @@ function A() {
|
|
|
481
497
|
let e = globalThis.localStorage?.getItem(O);
|
|
482
498
|
if (e) return k = e, e;
|
|
483
499
|
} catch {}
|
|
484
|
-
let e =
|
|
500
|
+
let e = ve();
|
|
485
501
|
k = e;
|
|
486
502
|
try {
|
|
487
503
|
globalThis.localStorage?.setItem(O, e);
|
|
488
504
|
} catch {}
|
|
489
505
|
return e;
|
|
490
506
|
}
|
|
491
|
-
function
|
|
507
|
+
function _e() {
|
|
492
508
|
k = void 0;
|
|
493
509
|
try {
|
|
494
510
|
globalThis.localStorage?.removeItem(O);
|
|
495
511
|
} catch {}
|
|
496
512
|
}
|
|
497
|
-
function
|
|
513
|
+
function ve() {
|
|
498
514
|
let e = globalThis.crypto;
|
|
499
515
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
500
516
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -506,7 +522,7 @@ function _e() {
|
|
|
506
522
|
}
|
|
507
523
|
//#endregion
|
|
508
524
|
//#region src/core/drm/headers.ts
|
|
509
|
-
function
|
|
525
|
+
function ye(e, t, n = {}) {
|
|
510
526
|
let r = {
|
|
511
527
|
"x-api-key": t.apiKey,
|
|
512
528
|
"X-Match-Urn": e.matchUrn,
|
|
@@ -518,7 +534,7 @@ function ve(e, t, n = {}) {
|
|
|
518
534
|
//#endregion
|
|
519
535
|
//#region src/core/drm/cdm.ts
|
|
520
536
|
var j = /* @__PURE__ */ new WeakMap();
|
|
521
|
-
function
|
|
537
|
+
function be(e, t) {
|
|
522
538
|
let n = j.get(e);
|
|
523
539
|
n || (n = /* @__PURE__ */ new Map(), j.set(e, n));
|
|
524
540
|
let r = n.get(t.keySystem);
|
|
@@ -532,11 +548,11 @@ function M() {
|
|
|
532
548
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
533
549
|
}
|
|
534
550
|
var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
535
|
-
function
|
|
551
|
+
function xe(e) {
|
|
536
552
|
return e.startsWith("com.widevine");
|
|
537
553
|
}
|
|
538
|
-
function
|
|
539
|
-
if (!
|
|
554
|
+
function Se(e, t) {
|
|
555
|
+
if (!xe(e)) return t;
|
|
540
556
|
let n = (e, t) => {
|
|
541
557
|
let n = e.videoCapabilities;
|
|
542
558
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
@@ -552,20 +568,20 @@ function xe(e, t) {
|
|
|
552
568
|
})));
|
|
553
569
|
return [...t, ...r];
|
|
554
570
|
}
|
|
555
|
-
function
|
|
556
|
-
return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t,
|
|
571
|
+
function Ce(e) {
|
|
572
|
+
return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, Se(t, n)).then((t) => ({
|
|
557
573
|
keySystem: t.keySystem,
|
|
558
574
|
getConfiguration: () => t.getConfiguration(),
|
|
559
|
-
createMediaKeys: () =>
|
|
575
|
+
createMediaKeys: () => be(e, t)
|
|
560
576
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
561
577
|
}
|
|
562
578
|
//#endregion
|
|
563
579
|
//#region src/core/drm/support.ts
|
|
564
|
-
var
|
|
580
|
+
var we = 5e3, Te = "video/mp4; codecs=\"avc1.42E01E\"", P = "audio/mp4; codecs=\"mp4a.40.2\"", Ee = {
|
|
565
581
|
widevine: ["com.widevine.alpha"],
|
|
566
582
|
fairplay: ["com.apple.fps"]
|
|
567
583
|
};
|
|
568
|
-
function
|
|
584
|
+
function De(e) {
|
|
569
585
|
return e === "fairplay" ? [{
|
|
570
586
|
initDataTypes: [
|
|
571
587
|
"sinf",
|
|
@@ -573,7 +589,7 @@ function Ee(e) {
|
|
|
573
589
|
"cenc"
|
|
574
590
|
],
|
|
575
591
|
videoCapabilities: [{
|
|
576
|
-
contentType:
|
|
592
|
+
contentType: Te,
|
|
577
593
|
robustness: "",
|
|
578
594
|
encryptionScheme: "cbcs"
|
|
579
595
|
}],
|
|
@@ -582,10 +598,10 @@ function Ee(e) {
|
|
|
582
598
|
robustness: "",
|
|
583
599
|
encryptionScheme: "cbcs"
|
|
584
600
|
}]
|
|
585
|
-
}] :
|
|
601
|
+
}] : Se("com.widevine.alpha", [{
|
|
586
602
|
initDataTypes: ["cenc"],
|
|
587
603
|
videoCapabilities: [{
|
|
588
|
-
contentType:
|
|
604
|
+
contentType: Te,
|
|
589
605
|
robustness: "SW_SECURE_DECODE",
|
|
590
606
|
encryptionScheme: "cbcs"
|
|
591
607
|
}],
|
|
@@ -606,8 +622,8 @@ function F(e, t) {
|
|
|
606
622
|
});
|
|
607
623
|
});
|
|
608
624
|
}
|
|
609
|
-
async function
|
|
610
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
625
|
+
async function Oe(e = {}) {
|
|
626
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? we, r = {};
|
|
611
627
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
612
628
|
verdict: "insecure-context",
|
|
613
629
|
detail: r
|
|
@@ -619,7 +635,7 @@ async function De(e = {}) {
|
|
|
619
635
|
};
|
|
620
636
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
621
637
|
for (let e of t) {
|
|
622
|
-
let t =
|
|
638
|
+
let t = Ee[e];
|
|
623
639
|
if (!t) {
|
|
624
640
|
r[e] = "unknown system";
|
|
625
641
|
continue;
|
|
@@ -630,7 +646,7 @@ async function De(e = {}) {
|
|
|
630
646
|
break;
|
|
631
647
|
}
|
|
632
648
|
try {
|
|
633
|
-
return await F((await F(i(n,
|
|
649
|
+
return await F((await F(i(n, De(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
634
650
|
verdict: "supported",
|
|
635
651
|
system: e,
|
|
636
652
|
detail: r
|
|
@@ -654,9 +670,9 @@ async function De(e = {}) {
|
|
|
654
670
|
}
|
|
655
671
|
//#endregion
|
|
656
672
|
//#region src/core/manifest.ts
|
|
657
|
-
var
|
|
658
|
-
function
|
|
659
|
-
return
|
|
673
|
+
var ke = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
674
|
+
function Ae(e) {
|
|
675
|
+
return ke.test(e);
|
|
660
676
|
}
|
|
661
677
|
//#endregion
|
|
662
678
|
//#region src/core/stats.ts
|
|
@@ -668,11 +684,11 @@ function L(e) {
|
|
|
668
684
|
return "";
|
|
669
685
|
}
|
|
670
686
|
}
|
|
671
|
-
var
|
|
672
|
-
function
|
|
687
|
+
var je = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
688
|
+
function Me(e) {
|
|
673
689
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
674
690
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
675
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
691
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || je.test(i.name)) && i.startTime >= n) {
|
|
676
692
|
let e = L(i.name);
|
|
677
693
|
e && (t = e, n = i.startTime);
|
|
678
694
|
}
|
|
@@ -685,7 +701,7 @@ function R(e) {
|
|
|
685
701
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
686
702
|
};
|
|
687
703
|
}
|
|
688
|
-
function
|
|
704
|
+
function Ne(e, t) {
|
|
689
705
|
let n = [
|
|
690
706
|
["playing", () => t("playing")],
|
|
691
707
|
["waiting", () => t("buffering")],
|
|
@@ -702,7 +718,7 @@ function Me(e, t) {
|
|
|
702
718
|
}
|
|
703
719
|
//#endregion
|
|
704
720
|
//#region src/core/engine/native.ts
|
|
705
|
-
function
|
|
721
|
+
function Pe(e) {
|
|
706
722
|
try {
|
|
707
723
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
708
724
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -754,7 +770,7 @@ var V = class {
|
|
|
754
770
|
type: "error",
|
|
755
771
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
756
772
|
fatal: !0
|
|
757
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
773
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Fe(t.manifestUrl, t.analytics?.sid), e.load();
|
|
758
774
|
}
|
|
759
775
|
startLoad() {
|
|
760
776
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -776,7 +792,7 @@ var V = class {
|
|
|
776
792
|
});
|
|
777
793
|
this.onEncrypted = (n) => {
|
|
778
794
|
let i = n;
|
|
779
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
795
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Pe(i.initData), (async () => {
|
|
780
796
|
try {
|
|
781
797
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
782
798
|
initDataTypes: [i.initDataType],
|
|
@@ -875,7 +891,7 @@ var V = class {
|
|
|
875
891
|
droppedFrames: t.dropped,
|
|
876
892
|
decodedFrames: t.totalFrames
|
|
877
893
|
};
|
|
878
|
-
return this.cdnHost ||=
|
|
894
|
+
return this.cdnHost ||= Me(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity && (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)), n;
|
|
879
895
|
}
|
|
880
896
|
stop() {
|
|
881
897
|
try {
|
|
@@ -894,25 +910,25 @@ var V = class {
|
|
|
894
910
|
} catch {}
|
|
895
911
|
}
|
|
896
912
|
};
|
|
897
|
-
function
|
|
913
|
+
function Fe(e, t) {
|
|
898
914
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
899
915
|
}
|
|
900
916
|
//#endregion
|
|
901
917
|
//#region src/core/engine/hls.ts
|
|
902
|
-
function
|
|
918
|
+
function Ie() {
|
|
903
919
|
return e.isSupported();
|
|
904
920
|
}
|
|
905
|
-
var
|
|
906
|
-
function
|
|
921
|
+
var Le = 3, Re = 5, ze = 3, Be = 3e4, Ve = 12e3, He = 3e3, H = 6e3, Ue = 4e3, We = 2, Ge = 5, Ke = 2, qe = 2, Je = 2e3, Ye = 3e4, Xe = 2, Ze = 9, Qe = .5, $e = 64;
|
|
922
|
+
function et(e) {
|
|
907
923
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
908
924
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
909
925
|
return;
|
|
910
926
|
}
|
|
911
|
-
e.liveSyncDuration ??=
|
|
912
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
913
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
927
|
+
e.liveSyncDuration ??= Xe;
|
|
928
|
+
let t = Math.max(12, e.liveSyncDuration + Ze);
|
|
929
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), tt(e, e.liveSyncDuration);
|
|
914
930
|
}
|
|
915
|
-
function
|
|
931
|
+
function tt(e, t) {
|
|
916
932
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
917
933
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
918
934
|
}
|
|
@@ -1010,7 +1026,7 @@ var U = class {
|
|
|
1010
1026
|
let t = e.liveSyncPosition;
|
|
1011
1027
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1012
1028
|
let { video: n } = this.deps;
|
|
1013
|
-
n.currentTime <= t +
|
|
1029
|
+
n.currentTime <= t + Qe || (n.currentTime = t);
|
|
1014
1030
|
}
|
|
1015
1031
|
startHls() {
|
|
1016
1032
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1034,7 +1050,7 @@ var U = class {
|
|
|
1034
1050
|
videoEncryptionScheme: "cbcs",
|
|
1035
1051
|
audioEncryptionScheme: "cbcs"
|
|
1036
1052
|
},
|
|
1037
|
-
...M() ? { requestMediaKeySystemAccessFunc:
|
|
1053
|
+
...M() ? { requestMediaKeySystemAccessFunc: Ce(t) } : {},
|
|
1038
1054
|
licenseXhrSetup: (e, t) => {
|
|
1039
1055
|
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;
|
|
1040
1056
|
let o = performance.now();
|
|
@@ -1050,7 +1066,7 @@ var U = class {
|
|
|
1050
1066
|
} } : {},
|
|
1051
1067
|
...c
|
|
1052
1068
|
};
|
|
1053
|
-
|
|
1069
|
+
et(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
|
|
1054
1070
|
let f = new e(d);
|
|
1055
1071
|
this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1056
1072
|
this.mediaRecoveries = 0, this.networkRecoveries = 0;
|
|
@@ -1059,14 +1075,14 @@ var U = class {
|
|
|
1059
1075
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1060
1076
|
t?.frag?.type === "main" && (this.kickPending = !1, this.kickTicks = 0, (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
1061
1077
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1062
|
-
},
|
|
1078
|
+
}, Be)));
|
|
1063
1079
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1064
1080
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1065
1081
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
1066
1082
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1067
1083
|
typeof r == "number" && (this.bytesLoaded += r);
|
|
1068
1084
|
let i = n?.loading;
|
|
1069
|
-
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length >
|
|
1085
|
+
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > $e && this.requestTimesMs.shift());
|
|
1070
1086
|
let a = t?.frag?.url;
|
|
1071
1087
|
if (a) {
|
|
1072
1088
|
let e = L(a);
|
|
@@ -1082,7 +1098,7 @@ var U = class {
|
|
|
1082
1098
|
}));
|
|
1083
1099
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1084
1100
|
this.checkEndStale(), this.checkStarvation();
|
|
1085
|
-
},
|
|
1101
|
+
}, He), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1086
1102
|
this.renditionSwitches += 1;
|
|
1087
1103
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1088
1104
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1146,7 +1162,7 @@ var U = class {
|
|
|
1146
1162
|
return;
|
|
1147
1163
|
}
|
|
1148
1164
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1149
|
-
let t = e > this.sizeCapLevel ?
|
|
1165
|
+
let t = e > this.sizeCapLevel ? Je : Ye;
|
|
1150
1166
|
this.capTimer = setTimeout(() => {
|
|
1151
1167
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1152
1168
|
}, t);
|
|
@@ -1235,7 +1251,7 @@ var U = class {
|
|
|
1235
1251
|
return;
|
|
1236
1252
|
}
|
|
1237
1253
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1238
|
-
!this.chaseSuspended && e > H && this.suspendChasing(), e >
|
|
1254
|
+
!this.chaseSuspended && e > H && this.suspendChasing(), e > Ve && this.emitEnded("stalled");
|
|
1239
1255
|
}
|
|
1240
1256
|
checkStarvation() {
|
|
1241
1257
|
let e = this.hls, { video: t } = this.deps;
|
|
@@ -1244,17 +1260,17 @@ var U = class {
|
|
|
1244
1260
|
this.starvedTicks = 0;
|
|
1245
1261
|
return;
|
|
1246
1262
|
}
|
|
1247
|
-
let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < H, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs >
|
|
1263
|
+
let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < H, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > Ue;
|
|
1248
1264
|
if (!(t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused && n && r)) {
|
|
1249
1265
|
this.starvedTicks = 0;
|
|
1250
1266
|
return;
|
|
1251
1267
|
}
|
|
1252
|
-
if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks <
|
|
1253
|
-
if (this.starvedTicks = 0, this.kickPending && this.kickTicks >=
|
|
1268
|
+
if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks < We)) {
|
|
1269
|
+
if (this.starvedTicks = 0, this.kickPending && this.kickTicks >= Ke && (this.kickPending = !1, this.kickTicks = 0, this.starvationRebuilds < qe)) {
|
|
1254
1270
|
this.starvationRebuilds += 1, 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");
|
|
1255
1271
|
return;
|
|
1256
1272
|
}
|
|
1257
|
-
if (!(this.starvationKicks >=
|
|
1273
|
+
if (!(this.starvationKicks >= Ge)) {
|
|
1258
1274
|
this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, console.warn("havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
|
|
1259
1275
|
try {
|
|
1260
1276
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1304,7 +1320,7 @@ var U = class {
|
|
|
1304
1320
|
scheduleLicenseRetry(t) {
|
|
1305
1321
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1306
1322
|
let n = t.response?.code ?? 0;
|
|
1307
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1323
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= ze) return !1;
|
|
1308
1324
|
this.licenseRecoveries += 1;
|
|
1309
1325
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1310
1326
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1336,7 +1352,7 @@ var U = class {
|
|
|
1336
1352
|
return;
|
|
1337
1353
|
}
|
|
1338
1354
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1339
|
-
if (this.networkRecoveries <
|
|
1355
|
+
if (this.networkRecoveries < Re) {
|
|
1340
1356
|
this.networkRecoveries += 1;
|
|
1341
1357
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1342
1358
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1353,7 +1369,7 @@ var U = class {
|
|
|
1353
1369
|
return;
|
|
1354
1370
|
}
|
|
1355
1371
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1356
|
-
if (this.mediaRecoveries <
|
|
1372
|
+
if (this.mediaRecoveries < Le) {
|
|
1357
1373
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1358
1374
|
return;
|
|
1359
1375
|
}
|
|
@@ -1377,11 +1393,11 @@ var U = class {
|
|
|
1377
1393
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1378
1394
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1379
1395
|
}
|
|
1380
|
-
},
|
|
1396
|
+
}, nt = 15e3, rt = 100, W = 1, it = 1e3, G = 3e4, at = 1e3, ot = {
|
|
1381
1397
|
inline: "PRESENTATION_INLINE",
|
|
1382
1398
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1383
1399
|
pip: "PRESENTATION_PIP"
|
|
1384
|
-
},
|
|
1400
|
+
}, st = {
|
|
1385
1401
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1386
1402
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1387
1403
|
none: "KEY_SYSTEM_NONE"
|
|
@@ -1389,7 +1405,7 @@ var U = class {
|
|
|
1389
1405
|
function K(e, t) {
|
|
1390
1406
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1391
1407
|
}
|
|
1392
|
-
var
|
|
1408
|
+
var ct = /* @__PURE__ */ new Set([
|
|
1393
1409
|
"INVALID_URN",
|
|
1394
1410
|
"NOT_FOUND",
|
|
1395
1411
|
"GONE",
|
|
@@ -1409,7 +1425,7 @@ var st = /* @__PURE__ */ new Set([
|
|
|
1409
1425
|
ended: "PLAYER_STATE_ENDED",
|
|
1410
1426
|
error: "PLAYER_STATE_ERROR"
|
|
1411
1427
|
};
|
|
1412
|
-
function
|
|
1428
|
+
function lt(e) {
|
|
1413
1429
|
try {
|
|
1414
1430
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1415
1431
|
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);
|
|
@@ -1417,7 +1433,7 @@ function ct(e) {
|
|
|
1417
1433
|
return;
|
|
1418
1434
|
}
|
|
1419
1435
|
}
|
|
1420
|
-
var
|
|
1436
|
+
var ut = class {
|
|
1421
1437
|
opts;
|
|
1422
1438
|
url;
|
|
1423
1439
|
now;
|
|
@@ -1489,7 +1505,7 @@ var lt = class {
|
|
|
1489
1505
|
constructor(e) {
|
|
1490
1506
|
this.opts = {
|
|
1491
1507
|
...e,
|
|
1492
|
-
heartbeatMs: e.heartbeatMs ??
|
|
1508
|
+
heartbeatMs: e.heartbeatMs ?? nt
|
|
1493
1509
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs, this.startupAnchorMs = this.bornMs;
|
|
1494
1510
|
}
|
|
1495
1511
|
start() {
|
|
@@ -1499,7 +1515,7 @@ var lt = class {
|
|
|
1499
1515
|
sdkVersion: this.opts.sdkVersion,
|
|
1500
1516
|
...this.opts.environment
|
|
1501
1517
|
};
|
|
1502
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
1518
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), it), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), this.onVisibility());
|
|
1503
1519
|
}
|
|
1504
1520
|
noteStateChange(e, t, n, r) {
|
|
1505
1521
|
if (this.endedFlag || e === t) return;
|
|
@@ -1513,12 +1529,12 @@ var lt = class {
|
|
|
1513
1529
|
let a = {
|
|
1514
1530
|
fromState: q[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1515
1531
|
toState: q[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1516
|
-
presentation:
|
|
1532
|
+
presentation: ot[this.presentation]
|
|
1517
1533
|
}, o = this.causeOf(e, t, i);
|
|
1518
1534
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
1519
1535
|
}
|
|
1520
1536
|
seekInduced(e) {
|
|
1521
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
1537
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < at;
|
|
1522
1538
|
}
|
|
1523
1539
|
causeOf(e, t, n) {
|
|
1524
1540
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -1586,7 +1602,7 @@ var lt = class {
|
|
|
1586
1602
|
let r = n ?? "";
|
|
1587
1603
|
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";
|
|
1588
1604
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
1589
|
-
if (
|
|
1605
|
+
if (ct.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
1590
1606
|
let i = t ?? "";
|
|
1591
1607
|
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";
|
|
1592
1608
|
}
|
|
@@ -1638,7 +1654,7 @@ var lt = class {
|
|
|
1638
1654
|
maybeEmitMediaInfo(e) {
|
|
1639
1655
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
1640
1656
|
let t = {};
|
|
1641
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
1657
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = st[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);
|
|
1642
1658
|
let n = JSON.stringify(t);
|
|
1643
1659
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
1644
1660
|
}
|
|
@@ -1678,7 +1694,7 @@ var lt = class {
|
|
|
1678
1694
|
};
|
|
1679
1695
|
}
|
|
1680
1696
|
enqueue(e) {
|
|
1681
|
-
for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
1697
|
+
for (this.pending.push(this.wrap(e)); this.pending.length > rt;) {
|
|
1682
1698
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
1683
1699
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
1684
1700
|
}
|
|
@@ -1701,7 +1717,7 @@ var lt = class {
|
|
|
1701
1717
|
};
|
|
1702
1718
|
//#endregion
|
|
1703
1719
|
//#region src/core/environment.ts
|
|
1704
|
-
function
|
|
1720
|
+
function dt() {
|
|
1705
1721
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
1706
1722
|
let e;
|
|
1707
1723
|
try {
|
|
@@ -1726,14 +1742,14 @@ function ut() {
|
|
|
1726
1742
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
1727
1743
|
};
|
|
1728
1744
|
}
|
|
1729
|
-
function
|
|
1745
|
+
function ft() {
|
|
1730
1746
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
1731
1747
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
1732
1748
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
1733
1749
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
1734
1750
|
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";
|
|
1735
1751
|
}
|
|
1736
|
-
function
|
|
1752
|
+
function pt() {
|
|
1737
1753
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
1738
1754
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
1739
1755
|
let t = {
|
|
@@ -1752,17 +1768,17 @@ function ft() {
|
|
|
1752
1768
|
}
|
|
1753
1769
|
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;
|
|
1754
1770
|
}
|
|
1755
|
-
function
|
|
1756
|
-
let t =
|
|
1757
|
-
deviceClass:
|
|
1771
|
+
function mt(e) {
|
|
1772
|
+
let t = dt(), n = {
|
|
1773
|
+
deviceClass: ft(),
|
|
1758
1774
|
integration: t.integration,
|
|
1759
|
-
...
|
|
1775
|
+
...pt()
|
|
1760
1776
|
};
|
|
1761
1777
|
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);
|
|
1762
1778
|
let r = e.getBoundingClientRect?.();
|
|
1763
1779
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
1764
1780
|
}
|
|
1765
|
-
async function
|
|
1781
|
+
async function ht() {
|
|
1766
1782
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
1767
1783
|
if (!e?.getHighEntropyValues) return {};
|
|
1768
1784
|
try {
|
|
@@ -1774,7 +1790,7 @@ async function mt() {
|
|
|
1774
1790
|
}
|
|
1775
1791
|
//#endregion
|
|
1776
1792
|
//#region src/core/version.ts
|
|
1777
|
-
var
|
|
1793
|
+
var gt = "2.6.3", J = {
|
|
1778
1794
|
accent: "#E1B600",
|
|
1779
1795
|
accentText: "#1B1C23",
|
|
1780
1796
|
background: "#0e0f13",
|
|
@@ -1807,15 +1823,15 @@ function X(e, t) {
|
|
|
1807
1823
|
}
|
|
1808
1824
|
//#endregion
|
|
1809
1825
|
//#region src/ui/styles.ts
|
|
1810
|
-
var Z = "havik-player-styles",
|
|
1811
|
-
function
|
|
1826
|
+
var Z = "havik-player-styles", _t = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n.havik-spinner{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";
|
|
1827
|
+
function vt(e = document) {
|
|
1812
1828
|
if (e.getElementById(Z)) return;
|
|
1813
1829
|
let t = e.createElement("style");
|
|
1814
|
-
t.id = Z, t.textContent =
|
|
1830
|
+
t.id = Z, t.textContent = _t, e.head.appendChild(t);
|
|
1815
1831
|
}
|
|
1816
1832
|
//#endregion
|
|
1817
1833
|
//#region src/ui/icons.ts
|
|
1818
|
-
var
|
|
1834
|
+
var yt = {
|
|
1819
1835
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
1820
1836
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
1821
1837
|
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\"/>",
|
|
@@ -1829,20 +1845,20 @@ var vt = {
|
|
|
1829
1845
|
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\"/>"
|
|
1830
1846
|
};
|
|
1831
1847
|
function Q(e) {
|
|
1832
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
1848
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${yt[e]}</svg>`;
|
|
1833
1849
|
}
|
|
1834
1850
|
//#endregion
|
|
1835
1851
|
//#region src/ui/controls.ts
|
|
1836
|
-
var
|
|
1852
|
+
var bt = 3e3, xt = /* @__PURE__ */ new Set([
|
|
1837
1853
|
"GONE",
|
|
1838
1854
|
"NOT_FOUND",
|
|
1839
1855
|
"INVALID_URN",
|
|
1840
1856
|
"UNAUTHORIZED"
|
|
1841
1857
|
]);
|
|
1842
|
-
function
|
|
1843
|
-
return new
|
|
1858
|
+
function St(e) {
|
|
1859
|
+
return new Ct(e);
|
|
1844
1860
|
}
|
|
1845
|
-
var
|
|
1861
|
+
var Ct = class {
|
|
1846
1862
|
root;
|
|
1847
1863
|
video;
|
|
1848
1864
|
player;
|
|
@@ -1884,7 +1900,7 @@ var St = class {
|
|
|
1884
1900
|
scrubbing = !1;
|
|
1885
1901
|
offFns = [];
|
|
1886
1902
|
constructor(e) {
|
|
1887
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
1903
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? bt, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, vt(this.doc), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
|
|
1888
1904
|
let t = (e, t, n) => {
|
|
1889
1905
|
let r = this.doc.createElement(e);
|
|
1890
1906
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -1975,7 +1991,7 @@ var St = class {
|
|
|
1975
1991
|
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);
|
|
1976
1992
|
} else {
|
|
1977
1993
|
let r = this.doc.createElement("div");
|
|
1978
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
1994
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !xt.has(this.lastError.code)) {
|
|
1979
1995
|
let e = this.doc.createElement("button");
|
|
1980
1996
|
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);
|
|
1981
1997
|
}
|
|
@@ -2016,7 +2032,7 @@ var St = class {
|
|
|
2016
2032
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2017
2033
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2018
2034
|
}
|
|
2019
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2035
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${wt(this.video.currentTime)} / ${wt(this.video.duration)}`);
|
|
2020
2036
|
}
|
|
2021
2037
|
syncLive() {
|
|
2022
2038
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2066,17 +2082,17 @@ var St = class {
|
|
|
2066
2082
|
renderQualityMenu() {
|
|
2067
2083
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2068
2084
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2069
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2085
|
+
for (let n of e) this.menu.append(this.menuItem(Tt(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2070
2086
|
}
|
|
2071
2087
|
renderAudioMenu() {
|
|
2072
2088
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2073
2089
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2074
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2090
|
+
for (let t of e) this.menu.append(this.menuItem(Et(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2075
2091
|
}
|
|
2076
2092
|
renderCcMenu() {
|
|
2077
2093
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2078
2094
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2079
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2095
|
+
for (let t of e) this.menu.append(this.menuItem(Dt(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2080
2096
|
}
|
|
2081
2097
|
onTracksChanged() {
|
|
2082
2098
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2176,32 +2192,32 @@ var St = class {
|
|
|
2176
2192
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2177
2193
|
}
|
|
2178
2194
|
};
|
|
2179
|
-
function
|
|
2195
|
+
function wt(e) {
|
|
2180
2196
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2181
2197
|
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");
|
|
2182
2198
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2183
2199
|
}
|
|
2184
|
-
function
|
|
2200
|
+
function Tt(e) {
|
|
2185
2201
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2186
2202
|
}
|
|
2187
|
-
function
|
|
2203
|
+
function Et(e) {
|
|
2188
2204
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2189
2205
|
}
|
|
2190
|
-
function
|
|
2206
|
+
function Dt(e) {
|
|
2191
2207
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2192
2208
|
}
|
|
2193
2209
|
//#endregion
|
|
2194
2210
|
//#region src/managed/index.ts
|
|
2195
|
-
var
|
|
2196
|
-
async function
|
|
2211
|
+
var Ot = 6e3, kt = 45e3, At = 2e3, jt = 3, Mt = 2e3, Nt = 48e4;
|
|
2212
|
+
async function Pt(e) {
|
|
2197
2213
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2198
2214
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: baseUrl is required");
|
|
2199
2215
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2200
2216
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2201
|
-
let t = new
|
|
2217
|
+
let t = new Ft(e);
|
|
2202
2218
|
return await t.start(), t;
|
|
2203
2219
|
}
|
|
2204
|
-
var
|
|
2220
|
+
var Ft = class {
|
|
2205
2221
|
opts;
|
|
2206
2222
|
abort = new AbortController();
|
|
2207
2223
|
listeners = {};
|
|
@@ -2288,7 +2304,7 @@ var Pt = class {
|
|
|
2288
2304
|
setTimeout(() => {
|
|
2289
2305
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
2290
2306
|
phase: i ? "unavailable" : "tooEarly",
|
|
2291
|
-
retryInMs:
|
|
2307
|
+
retryInMs: kt,
|
|
2292
2308
|
attempt: 1,
|
|
2293
2309
|
elapsedMs: 0,
|
|
2294
2310
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -2327,13 +2343,13 @@ var Pt = class {
|
|
|
2327
2343
|
!a && !p() && h();
|
|
2328
2344
|
}, e);
|
|
2329
2345
|
};
|
|
2330
|
-
_(
|
|
2346
|
+
_(Ot), this.armingSub = E({
|
|
2331
2347
|
eventsBaseUrl: t,
|
|
2332
2348
|
matchUrn: this.opts.matchUrn,
|
|
2333
2349
|
credential: this.opts.credential,
|
|
2334
|
-
onAlive: () => _(
|
|
2350
|
+
onAlive: () => _(kt),
|
|
2335
2351
|
onState: (e) => {
|
|
2336
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
2352
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * At);
|
|
2337
2353
|
},
|
|
2338
2354
|
onError: () => h()
|
|
2339
2355
|
});
|
|
@@ -2356,7 +2372,7 @@ var Pt = class {
|
|
|
2356
2372
|
let n = await s(this.opts.credential);
|
|
2357
2373
|
if (this.destroyed || t !== this.loadGen) return;
|
|
2358
2374
|
this.setState("loading");
|
|
2359
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
2375
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Ne(this.opts.video, (e) => {
|
|
2360
2376
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
2361
2377
|
});
|
|
2362
2378
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -2375,14 +2391,14 @@ var Pt = class {
|
|
|
2375
2391
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
2376
2392
|
let n = e.analytics?.sid;
|
|
2377
2393
|
if (!n) return;
|
|
2378
|
-
let r = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ??
|
|
2394
|
+
let r = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ?? lt(this.opts.baseUrl);
|
|
2379
2395
|
if (!r) return;
|
|
2380
|
-
let i = this.opts.video, a = new
|
|
2396
|
+
let i = this.opts.video, a = new ut({
|
|
2381
2397
|
endpoint: r,
|
|
2382
2398
|
sid: n,
|
|
2383
2399
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
2384
|
-
sdkVersion:
|
|
2385
|
-
environment:
|
|
2400
|
+
sdkVersion: gt,
|
|
2401
|
+
environment: mt(i),
|
|
2386
2402
|
sample: () => {
|
|
2387
2403
|
let e = this.engine?.getStats() ?? I, t = i.buffered.length ? Math.max(0, i.buffered.end(i.buffered.length - 1) - i.currentTime) : 0;
|
|
2388
2404
|
return {
|
|
@@ -2398,7 +2414,7 @@ var Pt = class {
|
|
|
2398
2414
|
let o = () => a.noteSeek(), s = () => a.noteVolume(i.muted, i.volume);
|
|
2399
2415
|
i.addEventListener("seeking", o), i.addEventListener("volumechange", s), this.detachMediaListeners = () => {
|
|
2400
2416
|
i.removeEventListener("seeking", o), i.removeEventListener("volumechange", s);
|
|
2401
|
-
}, a.start(), a.seedVolume(i.muted, i.volume), a.notePresentation(this.currentPresentation()),
|
|
2417
|
+
}, a.start(), a.seedVolume(i.muted, i.volume), a.notePresentation(this.currentPresentation()), ht().then((e) => a.noteEnvironment(e)), this.opts.autoplay === !1 && a.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
2402
2418
|
}
|
|
2403
2419
|
currentPresentation() {
|
|
2404
2420
|
let e = this.opts.video;
|
|
@@ -2425,7 +2441,7 @@ var Pt = class {
|
|
|
2425
2441
|
if (o === "native") return new V(a);
|
|
2426
2442
|
if (o === "hls") return new U(a);
|
|
2427
2443
|
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && z(this.opts.video) && B()) return new V(a);
|
|
2428
|
-
if (
|
|
2444
|
+
if (Ie()) return new U(a);
|
|
2429
2445
|
if (z(this.opts.video)) return new V(a);
|
|
2430
2446
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
2431
2447
|
}
|
|
@@ -2469,7 +2485,7 @@ var Pt = class {
|
|
|
2469
2485
|
r = 0, i = !1;
|
|
2470
2486
|
},
|
|
2471
2487
|
onError: () => {
|
|
2472
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
2488
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= jt && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
|
|
2473
2489
|
}
|
|
2474
2490
|
});
|
|
2475
2491
|
}
|
|
@@ -2491,7 +2507,7 @@ var Pt = class {
|
|
|
2491
2507
|
scheduleRejoin(e) {
|
|
2492
2508
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
2493
2509
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
2494
|
-
}, Math.random() *
|
|
2510
|
+
}, Math.random() * At));
|
|
2495
2511
|
}
|
|
2496
2512
|
cancelRejoin() {
|
|
2497
2513
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -2515,7 +2531,7 @@ var Pt = class {
|
|
|
2515
2531
|
}
|
|
2516
2532
|
t.controls = !1;
|
|
2517
2533
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
2518
|
-
r && r.insertBefore(n, t), n.appendChild(t), X(n, this.opts.theme), this.container = n, this.controlBar =
|
|
2534
|
+
r && r.insertBefore(n, t), n.appendChild(t), X(n, this.opts.theme), this.container = n, this.controlBar = St({
|
|
2519
2535
|
root: n,
|
|
2520
2536
|
video: t,
|
|
2521
2537
|
player: this,
|
|
@@ -2545,7 +2561,7 @@ var Pt = class {
|
|
|
2545
2561
|
}
|
|
2546
2562
|
startStats() {
|
|
2547
2563
|
this.stopStats();
|
|
2548
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
2564
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Mt);
|
|
2549
2565
|
this.statsTimer = setInterval(() => {
|
|
2550
2566
|
if (!this.engine) return;
|
|
2551
2567
|
let e = this.engine.getStats();
|
|
@@ -2557,7 +2573,7 @@ var Pt = class {
|
|
|
2557
2573
|
}
|
|
2558
2574
|
scheduleLicenseRefresh() {
|
|
2559
2575
|
this.stopRefresh();
|
|
2560
|
-
let e = this.opts.licenseRefreshMs ??
|
|
2576
|
+
let e = this.opts.licenseRefreshMs ?? Nt;
|
|
2561
2577
|
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
2562
2578
|
}
|
|
2563
2579
|
stopRefresh() {
|
|
@@ -2709,7 +2725,7 @@ function $(e) {
|
|
|
2709
2725
|
}
|
|
2710
2726
|
//#endregion
|
|
2711
2727
|
//#region src/embed/host.ts
|
|
2712
|
-
function
|
|
2728
|
+
function It(e) {
|
|
2713
2729
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
2714
2730
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
2715
2731
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -2768,8 +2784,8 @@ function Ft(e) {
|
|
|
2768
2784
|
}
|
|
2769
2785
|
//#endregion
|
|
2770
2786
|
//#region src/embed/page.ts
|
|
2771
|
-
var
|
|
2772
|
-
function
|
|
2787
|
+
var Lt = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
2788
|
+
function Rt() {
|
|
2773
2789
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
2774
2790
|
if (e) return {
|
|
2775
2791
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -2791,9 +2807,9 @@ function Lt() {
|
|
|
2791
2807
|
waitForLive: !0
|
|
2792
2808
|
};
|
|
2793
2809
|
}
|
|
2794
|
-
async function
|
|
2795
|
-
let e =
|
|
2796
|
-
|
|
2810
|
+
async function zt() {
|
|
2811
|
+
let e = Rt();
|
|
2812
|
+
Vt();
|
|
2797
2813
|
let t = document.createElement("video");
|
|
2798
2814
|
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);
|
|
2799
2815
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -2848,12 +2864,12 @@ async function Rt() {
|
|
|
2848
2864
|
code: e.code,
|
|
2849
2865
|
message: e.message
|
|
2850
2866
|
})), e.on("autoplayblocked", () => {
|
|
2851
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
2867
|
+
i({ type: "oddin:autoplayblocked" }), Bt(t, e);
|
|
2852
2868
|
});
|
|
2853
2869
|
}, s = async (r) => {
|
|
2854
2870
|
a?.destroy(), a = null;
|
|
2855
2871
|
try {
|
|
2856
|
-
let n = await
|
|
2872
|
+
let n = await Pt({
|
|
2857
2873
|
video: t,
|
|
2858
2874
|
baseUrl: e.baseUrl,
|
|
2859
2875
|
matchUrn: r,
|
|
@@ -2914,7 +2930,7 @@ async function Rt() {
|
|
|
2914
2930
|
a?.retry();
|
|
2915
2931
|
break;
|
|
2916
2932
|
case "oddin:load":
|
|
2917
|
-
typeof e.matchUrn == "string" &&
|
|
2933
|
+
typeof e.matchUrn == "string" && Lt.test(e.matchUrn) && s(e.matchUrn);
|
|
2918
2934
|
break;
|
|
2919
2935
|
case "oddin:destroy": c();
|
|
2920
2936
|
}
|
|
@@ -2926,18 +2942,18 @@ async function Rt() {
|
|
|
2926
2942
|
protocol: 1
|
|
2927
2943
|
});
|
|
2928
2944
|
}
|
|
2929
|
-
function
|
|
2945
|
+
function Bt(e, t) {
|
|
2930
2946
|
if (document.getElementById("havik-tap")) return;
|
|
2931
2947
|
let n = document.createElement("button");
|
|
2932
2948
|
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", () => {
|
|
2933
2949
|
n.remove(), t.play();
|
|
2934
2950
|
}), document.body.appendChild(n);
|
|
2935
2951
|
}
|
|
2936
|
-
function
|
|
2952
|
+
function Vt() {
|
|
2937
2953
|
let e = document.createElement("style");
|
|
2938
2954
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
2939
2955
|
}
|
|
2940
2956
|
//#endregion
|
|
2941
|
-
export { J as ODDIN_THEME, n as PlaybackError, X as applyTheme,
|
|
2957
|
+
export { J as ODDIN_THEME, n as PlaybackError, X as applyTheme, zt as bootEmbed, _e as clearDeviceId, Pt as createPlayer, D as deriveEventsBaseUrl, Oe as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ue as fetchCatalog, fe as fetchTournament, me as flattenMatches, A as getDeviceId, Ae as isLowLatencyManifest, $ as isOddinMessage, ye as licenseRequestHeaders, It as mountEmbed, oe as pollToLive, y as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, he as watchStatus };
|
|
2942
2958
|
|
|
2943
2959
|
//# sourceMappingURL=index.js.map
|