@oddin-gg/havik-player 2.6.2 → 2.6.4
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 +209 -160
- 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 = 5e3, We = 4e3, Ge = 2, Ke = 5, qe = 2, Je = 2, Ye = 2e3, Xe = 3e4, Ze = 2, Qe = 9, $e = .5, et = 64;
|
|
922
|
+
function tt(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 ??= Ze;
|
|
928
|
+
let t = Math.max(12, e.liveSyncDuration + Qe);
|
|
929
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), nt(e, e.liveSyncDuration);
|
|
914
930
|
}
|
|
915
|
-
function
|
|
931
|
+
function nt(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
|
}
|
|
@@ -944,6 +960,11 @@ var U = class {
|
|
|
944
960
|
licenseRetryTimer = null;
|
|
945
961
|
onVisibility = null;
|
|
946
962
|
onSeeking = null;
|
|
963
|
+
onPause = null;
|
|
964
|
+
onPlay = null;
|
|
965
|
+
pauseSuspendTimer = null;
|
|
966
|
+
loadSuspended = !1;
|
|
967
|
+
stopped = !1;
|
|
947
968
|
sawLive = !1;
|
|
948
969
|
lastEndSN = -1;
|
|
949
970
|
lastAdvanceMs = 0;
|
|
@@ -986,10 +1007,34 @@ var U = class {
|
|
|
986
1007
|
if (typeof t != "number") return;
|
|
987
1008
|
let n = typeof e.targetLatency == "number" && e.targetLatency > 0 ? e.targetLatency : 3;
|
|
988
1009
|
t - r.currentTime > Math.max(n * 3, 8) && (r.currentTime = t);
|
|
989
|
-
}, document.addEventListener("visibilitychange", this.onVisibility)), this.onSeeking = () =>
|
|
1010
|
+
}, document.addEventListener("visibilitychange", this.onVisibility)), this.onSeeking = () => {
|
|
1011
|
+
this.clampOverSeek(), this.loadSuspended && (this.resumeLoading(), this.schedulePauseSuspend());
|
|
1012
|
+
}, r.addEventListener("seeking", this.onSeeking), this.onPause = () => this.schedulePauseSuspend(), this.onPlay = () => this.resumeLoading(), r.addEventListener("pause", this.onPause), r.addEventListener("play", this.onPlay), this.sizeCapManaged && typeof ResizeObserver < "u" && (this.capObserver = new ResizeObserver(() => this.onMediaResize()), this.capObserver.observe(r), this.watchDprChanges());
|
|
1013
|
+
}
|
|
1014
|
+
schedulePauseSuspend() {
|
|
1015
|
+
this.pauseSuspendTimer || this.loadSuspended || this.stopped || !this.loadStarted || (this.pauseSuspendTimer = setTimeout(() => {
|
|
1016
|
+
this.pauseSuspendTimer = null;
|
|
1017
|
+
let { video: e } = this.deps;
|
|
1018
|
+
if (e.paused && !e.ended && !this.stopped && this.hls) {
|
|
1019
|
+
try {
|
|
1020
|
+
this.hls.stopLoad();
|
|
1021
|
+
} catch {
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
this.loadSuspended = !0;
|
|
1025
|
+
}
|
|
1026
|
+
}, Ue));
|
|
1027
|
+
}
|
|
1028
|
+
resumeLoading() {
|
|
1029
|
+
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
1030
|
+
this.lastAdvanceMs = Date.now(), this.lastFragLoadingMs = 0, this.starvedTicks = 0, this.kickPending = !1, this.kickTicks = 0;
|
|
1031
|
+
try {
|
|
1032
|
+
this.hls.startLoad(-1);
|
|
1033
|
+
} catch {}
|
|
1034
|
+
}
|
|
990
1035
|
}
|
|
991
1036
|
startLoad() {
|
|
992
|
-
this.loadStarted || (this.loadStarted = !0, this.hls?.startLoad(-1));
|
|
1037
|
+
this.loadStarted || (this.loadStarted = !0, this.deps.video.paused && this.schedulePauseSuspend(), this.hls?.startLoad(-1));
|
|
993
1038
|
}
|
|
994
1039
|
watchDprChanges() {
|
|
995
1040
|
if (typeof matchMedia != "function") return;
|
|
@@ -1010,7 +1055,7 @@ var U = class {
|
|
|
1010
1055
|
let t = e.liveSyncPosition;
|
|
1011
1056
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1012
1057
|
let { video: n } = this.deps;
|
|
1013
|
-
n.currentTime <= t +
|
|
1058
|
+
n.currentTime <= t + $e || (n.currentTime = t);
|
|
1014
1059
|
}
|
|
1015
1060
|
startHls() {
|
|
1016
1061
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1034,7 +1079,7 @@ var U = class {
|
|
|
1034
1079
|
videoEncryptionScheme: "cbcs",
|
|
1035
1080
|
audioEncryptionScheme: "cbcs"
|
|
1036
1081
|
},
|
|
1037
|
-
...M() ? { requestMediaKeySystemAccessFunc:
|
|
1082
|
+
...M() ? { requestMediaKeySystemAccessFunc: Ce(t) } : {},
|
|
1038
1083
|
licenseXhrSetup: (e, t) => {
|
|
1039
1084
|
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
1085
|
let o = performance.now();
|
|
@@ -1050,23 +1095,23 @@ var U = class {
|
|
|
1050
1095
|
} } : {},
|
|
1051
1096
|
...c
|
|
1052
1097
|
};
|
|
1053
|
-
|
|
1098
|
+
tt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
|
|
1054
1099
|
let f = new e(d);
|
|
1055
1100
|
this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1056
1101
|
this.mediaRecoveries = 0, this.networkRecoveries = 0;
|
|
1057
1102
|
let e = f.levels.map((e) => e.height).filter((e) => !!e);
|
|
1058
|
-
this.ladderHeights = e.length ? [...new Set(e)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = f.levels.length ? Math.round(Math.max(...f.levels.map((e) => e.bitrate)) / 1e3) : 0, this.applySizeCap(), l({ type: "ready" });
|
|
1103
|
+
this.ladderHeights = e.length ? [...new Set(e)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = f.levels.length ? Math.round(Math.max(...f.levels.map((e) => e.bitrate)) / 1e3) : 0, this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1059
1104
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1060
1105
|
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
1106
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1062
|
-
},
|
|
1107
|
+
}, Be)));
|
|
1063
1108
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1064
1109
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1065
1110
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
1066
1111
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1067
1112
|
typeof r == "number" && (this.bytesLoaded += r);
|
|
1068
1113
|
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 >
|
|
1114
|
+
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > et && this.requestTimesMs.shift());
|
|
1070
1115
|
let a = t?.frag?.url;
|
|
1071
1116
|
if (a) {
|
|
1072
1117
|
let e = L(a);
|
|
@@ -1082,7 +1127,7 @@ var U = class {
|
|
|
1082
1127
|
}));
|
|
1083
1128
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1084
1129
|
this.checkEndStale(), this.checkStarvation();
|
|
1085
|
-
},
|
|
1130
|
+
}, He), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1086
1131
|
this.renditionSwitches += 1;
|
|
1087
1132
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1088
1133
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1146,7 +1191,7 @@ var U = class {
|
|
|
1146
1191
|
return;
|
|
1147
1192
|
}
|
|
1148
1193
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1149
|
-
let t = e > this.sizeCapLevel ?
|
|
1194
|
+
let t = e > this.sizeCapLevel ? Ye : Xe;
|
|
1150
1195
|
this.capTimer = setTimeout(() => {
|
|
1151
1196
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1152
1197
|
}, t);
|
|
@@ -1234,27 +1279,31 @@ var U = class {
|
|
|
1234
1279
|
this.lastAdvanceMs = Date.now();
|
|
1235
1280
|
return;
|
|
1236
1281
|
}
|
|
1282
|
+
if (this.loadSuspended) {
|
|
1283
|
+
this.lastAdvanceMs = Date.now();
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1237
1286
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1238
|
-
!this.chaseSuspended && e > H && this.suspendChasing(), e >
|
|
1287
|
+
!this.chaseSuspended && e > H && this.suspendChasing(), e > Ve && this.emitEnded("stalled");
|
|
1239
1288
|
}
|
|
1240
1289
|
checkStarvation() {
|
|
1241
1290
|
let e = this.hls, { video: t } = this.deps;
|
|
1242
1291
|
if (!e || this.endedEmitted || !this.sawLive || this.chaseSuspended) return;
|
|
1243
|
-
if (typeof document < "u" && document.hidden) {
|
|
1292
|
+
if (typeof document < "u" && document.hidden || this.loadSuspended) {
|
|
1244
1293
|
this.starvedTicks = 0;
|
|
1245
1294
|
return;
|
|
1246
1295
|
}
|
|
1247
|
-
let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < H, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs >
|
|
1296
|
+
let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < H, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > We;
|
|
1248
1297
|
if (!(t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused && n && r)) {
|
|
1249
1298
|
this.starvedTicks = 0;
|
|
1250
1299
|
return;
|
|
1251
1300
|
}
|
|
1252
|
-
if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks <
|
|
1253
|
-
if (this.starvedTicks = 0, this.kickPending && this.kickTicks >=
|
|
1301
|
+
if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks < Ge)) {
|
|
1302
|
+
if (this.starvedTicks = 0, this.kickPending && this.kickTicks >= qe && (this.kickPending = !1, this.kickTicks = 0, this.starvationRebuilds < Je)) {
|
|
1254
1303
|
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
1304
|
return;
|
|
1256
1305
|
}
|
|
1257
|
-
if (!(this.starvationKicks >=
|
|
1306
|
+
if (!(this.starvationKicks >= Ke)) {
|
|
1258
1307
|
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
1308
|
try {
|
|
1260
1309
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1280,7 +1329,7 @@ var U = class {
|
|
|
1280
1329
|
}));
|
|
1281
1330
|
}
|
|
1282
1331
|
stop() {
|
|
1283
|
-
this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.kickPending = !1, this.kickTicks = 0;
|
|
1332
|
+
this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.kickPending = !1, this.kickTicks = 0, this.stopped = !0, this.loadSuspended = !1, this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null);
|
|
1284
1333
|
try {
|
|
1285
1334
|
this.hls?.stopLoad();
|
|
1286
1335
|
} catch {}
|
|
@@ -1289,7 +1338,7 @@ var U = class {
|
|
|
1289
1338
|
} catch {}
|
|
1290
1339
|
}
|
|
1291
1340
|
destroy() {
|
|
1292
|
-
if (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.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
|
|
1341
|
+
if (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.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), 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) {
|
|
1293
1342
|
try {
|
|
1294
1343
|
this.hls.destroy();
|
|
1295
1344
|
} catch (e) {
|
|
@@ -1304,7 +1353,7 @@ var U = class {
|
|
|
1304
1353
|
scheduleLicenseRetry(t) {
|
|
1305
1354
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1306
1355
|
let n = t.response?.code ?? 0;
|
|
1307
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1356
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= ze) return !1;
|
|
1308
1357
|
this.licenseRecoveries += 1;
|
|
1309
1358
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1310
1359
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1336,7 +1385,7 @@ var U = class {
|
|
|
1336
1385
|
return;
|
|
1337
1386
|
}
|
|
1338
1387
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1339
|
-
if (this.networkRecoveries <
|
|
1388
|
+
if (this.networkRecoveries < Re) {
|
|
1340
1389
|
this.networkRecoveries += 1;
|
|
1341
1390
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1342
1391
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1353,7 +1402,7 @@ var U = class {
|
|
|
1353
1402
|
return;
|
|
1354
1403
|
}
|
|
1355
1404
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1356
|
-
if (this.mediaRecoveries <
|
|
1405
|
+
if (this.mediaRecoveries < Le) {
|
|
1357
1406
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1358
1407
|
return;
|
|
1359
1408
|
}
|
|
@@ -1377,11 +1426,11 @@ var U = class {
|
|
|
1377
1426
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1378
1427
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1379
1428
|
}
|
|
1380
|
-
},
|
|
1429
|
+
}, rt = 15e3, it = 100, W = 1, at = 1e3, G = 3e4, ot = 1e3, st = {
|
|
1381
1430
|
inline: "PRESENTATION_INLINE",
|
|
1382
1431
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1383
1432
|
pip: "PRESENTATION_PIP"
|
|
1384
|
-
},
|
|
1433
|
+
}, ct = {
|
|
1385
1434
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1386
1435
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1387
1436
|
none: "KEY_SYSTEM_NONE"
|
|
@@ -1389,7 +1438,7 @@ var U = class {
|
|
|
1389
1438
|
function K(e, t) {
|
|
1390
1439
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1391
1440
|
}
|
|
1392
|
-
var
|
|
1441
|
+
var lt = /* @__PURE__ */ new Set([
|
|
1393
1442
|
"INVALID_URN",
|
|
1394
1443
|
"NOT_FOUND",
|
|
1395
1444
|
"GONE",
|
|
@@ -1409,7 +1458,7 @@ var st = /* @__PURE__ */ new Set([
|
|
|
1409
1458
|
ended: "PLAYER_STATE_ENDED",
|
|
1410
1459
|
error: "PLAYER_STATE_ERROR"
|
|
1411
1460
|
};
|
|
1412
|
-
function
|
|
1461
|
+
function ut(e) {
|
|
1413
1462
|
try {
|
|
1414
1463
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1415
1464
|
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 +1466,7 @@ function ct(e) {
|
|
|
1417
1466
|
return;
|
|
1418
1467
|
}
|
|
1419
1468
|
}
|
|
1420
|
-
var
|
|
1469
|
+
var dt = class {
|
|
1421
1470
|
opts;
|
|
1422
1471
|
url;
|
|
1423
1472
|
now;
|
|
@@ -1489,7 +1538,7 @@ var lt = class {
|
|
|
1489
1538
|
constructor(e) {
|
|
1490
1539
|
this.opts = {
|
|
1491
1540
|
...e,
|
|
1492
|
-
heartbeatMs: e.heartbeatMs ??
|
|
1541
|
+
heartbeatMs: e.heartbeatMs ?? rt
|
|
1493
1542
|
}, 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
1543
|
}
|
|
1495
1544
|
start() {
|
|
@@ -1499,7 +1548,7 @@ var lt = class {
|
|
|
1499
1548
|
sdkVersion: this.opts.sdkVersion,
|
|
1500
1549
|
...this.opts.environment
|
|
1501
1550
|
};
|
|
1502
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
1551
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), at), 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
1552
|
}
|
|
1504
1553
|
noteStateChange(e, t, n, r) {
|
|
1505
1554
|
if (this.endedFlag || e === t) return;
|
|
@@ -1513,12 +1562,12 @@ var lt = class {
|
|
|
1513
1562
|
let a = {
|
|
1514
1563
|
fromState: q[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1515
1564
|
toState: q[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1516
|
-
presentation:
|
|
1565
|
+
presentation: st[this.presentation]
|
|
1517
1566
|
}, o = this.causeOf(e, t, i);
|
|
1518
1567
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
1519
1568
|
}
|
|
1520
1569
|
seekInduced(e) {
|
|
1521
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
1570
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < ot;
|
|
1522
1571
|
}
|
|
1523
1572
|
causeOf(e, t, n) {
|
|
1524
1573
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -1586,7 +1635,7 @@ var lt = class {
|
|
|
1586
1635
|
let r = n ?? "";
|
|
1587
1636
|
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
1637
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
1589
|
-
if (
|
|
1638
|
+
if (lt.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
1590
1639
|
let i = t ?? "";
|
|
1591
1640
|
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
1641
|
}
|
|
@@ -1638,7 +1687,7 @@ var lt = class {
|
|
|
1638
1687
|
maybeEmitMediaInfo(e) {
|
|
1639
1688
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
1640
1689
|
let t = {};
|
|
1641
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
1690
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = ct[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
1691
|
let n = JSON.stringify(t);
|
|
1643
1692
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
1644
1693
|
}
|
|
@@ -1678,7 +1727,7 @@ var lt = class {
|
|
|
1678
1727
|
};
|
|
1679
1728
|
}
|
|
1680
1729
|
enqueue(e) {
|
|
1681
|
-
for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
1730
|
+
for (this.pending.push(this.wrap(e)); this.pending.length > it;) {
|
|
1682
1731
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
1683
1732
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
1684
1733
|
}
|
|
@@ -1701,7 +1750,7 @@ var lt = class {
|
|
|
1701
1750
|
};
|
|
1702
1751
|
//#endregion
|
|
1703
1752
|
//#region src/core/environment.ts
|
|
1704
|
-
function
|
|
1753
|
+
function ft() {
|
|
1705
1754
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
1706
1755
|
let e;
|
|
1707
1756
|
try {
|
|
@@ -1726,14 +1775,14 @@ function ut() {
|
|
|
1726
1775
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
1727
1776
|
};
|
|
1728
1777
|
}
|
|
1729
|
-
function
|
|
1778
|
+
function pt() {
|
|
1730
1779
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
1731
1780
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
1732
1781
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
1733
1782
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
1734
1783
|
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
1784
|
}
|
|
1736
|
-
function
|
|
1785
|
+
function mt() {
|
|
1737
1786
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
1738
1787
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
1739
1788
|
let t = {
|
|
@@ -1752,17 +1801,17 @@ function ft() {
|
|
|
1752
1801
|
}
|
|
1753
1802
|
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
1803
|
}
|
|
1755
|
-
function
|
|
1756
|
-
let t =
|
|
1757
|
-
deviceClass:
|
|
1804
|
+
function ht(e) {
|
|
1805
|
+
let t = ft(), n = {
|
|
1806
|
+
deviceClass: pt(),
|
|
1758
1807
|
integration: t.integration,
|
|
1759
|
-
...
|
|
1808
|
+
...mt()
|
|
1760
1809
|
};
|
|
1761
1810
|
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
1811
|
let r = e.getBoundingClientRect?.();
|
|
1763
1812
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
1764
1813
|
}
|
|
1765
|
-
async function
|
|
1814
|
+
async function gt() {
|
|
1766
1815
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
1767
1816
|
if (!e?.getHighEntropyValues) return {};
|
|
1768
1817
|
try {
|
|
@@ -1774,7 +1823,7 @@ async function mt() {
|
|
|
1774
1823
|
}
|
|
1775
1824
|
//#endregion
|
|
1776
1825
|
//#region src/core/version.ts
|
|
1777
|
-
var
|
|
1826
|
+
var _t = "2.6.4", J = {
|
|
1778
1827
|
accent: "#E1B600",
|
|
1779
1828
|
accentText: "#1B1C23",
|
|
1780
1829
|
background: "#0e0f13",
|
|
@@ -1807,15 +1856,15 @@ function X(e, t) {
|
|
|
1807
1856
|
}
|
|
1808
1857
|
//#endregion
|
|
1809
1858
|
//#region src/ui/styles.ts
|
|
1810
|
-
var Z = "havik-player-styles",
|
|
1811
|
-
function
|
|
1859
|
+
var Z = "havik-player-styles", vt = "\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";
|
|
1860
|
+
function yt(e = document) {
|
|
1812
1861
|
if (e.getElementById(Z)) return;
|
|
1813
1862
|
let t = e.createElement("style");
|
|
1814
|
-
t.id = Z, t.textContent =
|
|
1863
|
+
t.id = Z, t.textContent = vt, e.head.appendChild(t);
|
|
1815
1864
|
}
|
|
1816
1865
|
//#endregion
|
|
1817
1866
|
//#region src/ui/icons.ts
|
|
1818
|
-
var
|
|
1867
|
+
var bt = {
|
|
1819
1868
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
1820
1869
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
1821
1870
|
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 +1878,20 @@ var vt = {
|
|
|
1829
1878
|
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
1879
|
};
|
|
1831
1880
|
function Q(e) {
|
|
1832
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
1881
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${bt[e]}</svg>`;
|
|
1833
1882
|
}
|
|
1834
1883
|
//#endregion
|
|
1835
1884
|
//#region src/ui/controls.ts
|
|
1836
|
-
var
|
|
1885
|
+
var xt = 3e3, St = /* @__PURE__ */ new Set([
|
|
1837
1886
|
"GONE",
|
|
1838
1887
|
"NOT_FOUND",
|
|
1839
1888
|
"INVALID_URN",
|
|
1840
1889
|
"UNAUTHORIZED"
|
|
1841
1890
|
]);
|
|
1842
|
-
function
|
|
1843
|
-
return new
|
|
1891
|
+
function Ct(e) {
|
|
1892
|
+
return new wt(e);
|
|
1844
1893
|
}
|
|
1845
|
-
var
|
|
1894
|
+
var wt = class {
|
|
1846
1895
|
root;
|
|
1847
1896
|
video;
|
|
1848
1897
|
player;
|
|
@@ -1884,7 +1933,7 @@ var St = class {
|
|
|
1884
1933
|
scrubbing = !1;
|
|
1885
1934
|
offFns = [];
|
|
1886
1935
|
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 ??
|
|
1936
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? xt, 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, yt(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
1937
|
let t = (e, t, n) => {
|
|
1889
1938
|
let r = this.doc.createElement(e);
|
|
1890
1939
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -1975,7 +2024,7 @@ var St = class {
|
|
|
1975
2024
|
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
2025
|
} else {
|
|
1977
2026
|
let r = this.doc.createElement("div");
|
|
1978
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2027
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !St.has(this.lastError.code)) {
|
|
1979
2028
|
let e = this.doc.createElement("button");
|
|
1980
2029
|
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
2030
|
}
|
|
@@ -2016,7 +2065,7 @@ var St = class {
|
|
|
2016
2065
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2017
2066
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2018
2067
|
}
|
|
2019
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2068
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Tt(this.video.currentTime)} / ${Tt(this.video.duration)}`);
|
|
2020
2069
|
}
|
|
2021
2070
|
syncLive() {
|
|
2022
2071
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2066,17 +2115,17 @@ var St = class {
|
|
|
2066
2115
|
renderQualityMenu() {
|
|
2067
2116
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2068
2117
|
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(
|
|
2118
|
+
for (let n of e) this.menu.append(this.menuItem(Et(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2070
2119
|
}
|
|
2071
2120
|
renderAudioMenu() {
|
|
2072
2121
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2073
2122
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2074
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2123
|
+
for (let t of e) this.menu.append(this.menuItem(Dt(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2075
2124
|
}
|
|
2076
2125
|
renderCcMenu() {
|
|
2077
2126
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2078
2127
|
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(
|
|
2128
|
+
for (let t of e) this.menu.append(this.menuItem(Ot(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2080
2129
|
}
|
|
2081
2130
|
onTracksChanged() {
|
|
2082
2131
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2176,32 +2225,32 @@ var St = class {
|
|
|
2176
2225
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2177
2226
|
}
|
|
2178
2227
|
};
|
|
2179
|
-
function
|
|
2228
|
+
function Tt(e) {
|
|
2180
2229
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2181
2230
|
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
2231
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2183
2232
|
}
|
|
2184
|
-
function
|
|
2233
|
+
function Et(e) {
|
|
2185
2234
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2186
2235
|
}
|
|
2187
|
-
function
|
|
2236
|
+
function Dt(e) {
|
|
2188
2237
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2189
2238
|
}
|
|
2190
|
-
function
|
|
2239
|
+
function Ot(e) {
|
|
2191
2240
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2192
2241
|
}
|
|
2193
2242
|
//#endregion
|
|
2194
2243
|
//#region src/managed/index.ts
|
|
2195
|
-
var
|
|
2196
|
-
async function
|
|
2244
|
+
var kt = 6e3, At = 45e3, jt = 2e3, Mt = 3, Nt = 2e3, Pt = 48e4;
|
|
2245
|
+
async function Ft(e) {
|
|
2197
2246
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2198
2247
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: baseUrl is required");
|
|
2199
2248
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2200
2249
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2201
|
-
let t = new
|
|
2250
|
+
let t = new It(e);
|
|
2202
2251
|
return await t.start(), t;
|
|
2203
2252
|
}
|
|
2204
|
-
var
|
|
2253
|
+
var It = class {
|
|
2205
2254
|
opts;
|
|
2206
2255
|
abort = new AbortController();
|
|
2207
2256
|
listeners = {};
|
|
@@ -2288,7 +2337,7 @@ var Pt = class {
|
|
|
2288
2337
|
setTimeout(() => {
|
|
2289
2338
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
2290
2339
|
phase: i ? "unavailable" : "tooEarly",
|
|
2291
|
-
retryInMs:
|
|
2340
|
+
retryInMs: At,
|
|
2292
2341
|
attempt: 1,
|
|
2293
2342
|
elapsedMs: 0,
|
|
2294
2343
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -2327,13 +2376,13 @@ var Pt = class {
|
|
|
2327
2376
|
!a && !p() && h();
|
|
2328
2377
|
}, e);
|
|
2329
2378
|
};
|
|
2330
|
-
_(
|
|
2379
|
+
_(kt), this.armingSub = E({
|
|
2331
2380
|
eventsBaseUrl: t,
|
|
2332
2381
|
matchUrn: this.opts.matchUrn,
|
|
2333
2382
|
credential: this.opts.credential,
|
|
2334
|
-
onAlive: () => _(
|
|
2383
|
+
onAlive: () => _(At),
|
|
2335
2384
|
onState: (e) => {
|
|
2336
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
2385
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * jt);
|
|
2337
2386
|
},
|
|
2338
2387
|
onError: () => h()
|
|
2339
2388
|
});
|
|
@@ -2356,7 +2405,7 @@ var Pt = class {
|
|
|
2356
2405
|
let n = await s(this.opts.credential);
|
|
2357
2406
|
if (this.destroyed || t !== this.loadGen) return;
|
|
2358
2407
|
this.setState("loading");
|
|
2359
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
2408
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Ne(this.opts.video, (e) => {
|
|
2360
2409
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
2361
2410
|
});
|
|
2362
2411
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -2375,14 +2424,14 @@ var Pt = class {
|
|
|
2375
2424
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
2376
2425
|
let n = e.analytics?.sid;
|
|
2377
2426
|
if (!n) return;
|
|
2378
|
-
let r = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ??
|
|
2427
|
+
let r = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ?? ut(this.opts.baseUrl);
|
|
2379
2428
|
if (!r) return;
|
|
2380
|
-
let i = this.opts.video, a = new
|
|
2429
|
+
let i = this.opts.video, a = new dt({
|
|
2381
2430
|
endpoint: r,
|
|
2382
2431
|
sid: n,
|
|
2383
2432
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
2384
|
-
sdkVersion:
|
|
2385
|
-
environment:
|
|
2433
|
+
sdkVersion: _t,
|
|
2434
|
+
environment: ht(i),
|
|
2386
2435
|
sample: () => {
|
|
2387
2436
|
let e = this.engine?.getStats() ?? I, t = i.buffered.length ? Math.max(0, i.buffered.end(i.buffered.length - 1) - i.currentTime) : 0;
|
|
2388
2437
|
return {
|
|
@@ -2398,7 +2447,7 @@ var Pt = class {
|
|
|
2398
2447
|
let o = () => a.noteSeek(), s = () => a.noteVolume(i.muted, i.volume);
|
|
2399
2448
|
i.addEventListener("seeking", o), i.addEventListener("volumechange", s), this.detachMediaListeners = () => {
|
|
2400
2449
|
i.removeEventListener("seeking", o), i.removeEventListener("volumechange", s);
|
|
2401
|
-
}, a.start(), a.seedVolume(i.muted, i.volume), a.notePresentation(this.currentPresentation()),
|
|
2450
|
+
}, a.start(), a.seedVolume(i.muted, i.volume), a.notePresentation(this.currentPresentation()), gt().then((e) => a.noteEnvironment(e)), this.opts.autoplay === !1 && a.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
2402
2451
|
}
|
|
2403
2452
|
currentPresentation() {
|
|
2404
2453
|
let e = this.opts.video;
|
|
@@ -2425,7 +2474,7 @@ var Pt = class {
|
|
|
2425
2474
|
if (o === "native") return new V(a);
|
|
2426
2475
|
if (o === "hls") return new U(a);
|
|
2427
2476
|
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && z(this.opts.video) && B()) return new V(a);
|
|
2428
|
-
if (
|
|
2477
|
+
if (Ie()) return new U(a);
|
|
2429
2478
|
if (z(this.opts.video)) return new V(a);
|
|
2430
2479
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
2431
2480
|
}
|
|
@@ -2469,7 +2518,7 @@ var Pt = class {
|
|
|
2469
2518
|
r = 0, i = !1;
|
|
2470
2519
|
},
|
|
2471
2520
|
onError: () => {
|
|
2472
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
2521
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Mt && (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
2522
|
}
|
|
2474
2523
|
});
|
|
2475
2524
|
}
|
|
@@ -2491,7 +2540,7 @@ var Pt = class {
|
|
|
2491
2540
|
scheduleRejoin(e) {
|
|
2492
2541
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
2493
2542
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
2494
|
-
}, Math.random() *
|
|
2543
|
+
}, Math.random() * jt));
|
|
2495
2544
|
}
|
|
2496
2545
|
cancelRejoin() {
|
|
2497
2546
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -2515,7 +2564,7 @@ var Pt = class {
|
|
|
2515
2564
|
}
|
|
2516
2565
|
t.controls = !1;
|
|
2517
2566
|
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 =
|
|
2567
|
+
r && r.insertBefore(n, t), n.appendChild(t), X(n, this.opts.theme), this.container = n, this.controlBar = Ct({
|
|
2519
2568
|
root: n,
|
|
2520
2569
|
video: t,
|
|
2521
2570
|
player: this,
|
|
@@ -2545,7 +2594,7 @@ var Pt = class {
|
|
|
2545
2594
|
}
|
|
2546
2595
|
startStats() {
|
|
2547
2596
|
this.stopStats();
|
|
2548
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
2597
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Nt);
|
|
2549
2598
|
this.statsTimer = setInterval(() => {
|
|
2550
2599
|
if (!this.engine) return;
|
|
2551
2600
|
let e = this.engine.getStats();
|
|
@@ -2557,7 +2606,7 @@ var Pt = class {
|
|
|
2557
2606
|
}
|
|
2558
2607
|
scheduleLicenseRefresh() {
|
|
2559
2608
|
this.stopRefresh();
|
|
2560
|
-
let e = this.opts.licenseRefreshMs ??
|
|
2609
|
+
let e = this.opts.licenseRefreshMs ?? Pt;
|
|
2561
2610
|
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
2562
2611
|
}
|
|
2563
2612
|
stopRefresh() {
|
|
@@ -2709,7 +2758,7 @@ function $(e) {
|
|
|
2709
2758
|
}
|
|
2710
2759
|
//#endregion
|
|
2711
2760
|
//#region src/embed/host.ts
|
|
2712
|
-
function
|
|
2761
|
+
function Lt(e) {
|
|
2713
2762
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
2714
2763
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
2715
2764
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -2768,8 +2817,8 @@ function Ft(e) {
|
|
|
2768
2817
|
}
|
|
2769
2818
|
//#endregion
|
|
2770
2819
|
//#region src/embed/page.ts
|
|
2771
|
-
var
|
|
2772
|
-
function
|
|
2820
|
+
var Rt = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
2821
|
+
function zt() {
|
|
2773
2822
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
2774
2823
|
if (e) return {
|
|
2775
2824
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -2791,9 +2840,9 @@ function Lt() {
|
|
|
2791
2840
|
waitForLive: !0
|
|
2792
2841
|
};
|
|
2793
2842
|
}
|
|
2794
|
-
async function
|
|
2795
|
-
let e =
|
|
2796
|
-
|
|
2843
|
+
async function Bt() {
|
|
2844
|
+
let e = zt();
|
|
2845
|
+
Ht();
|
|
2797
2846
|
let t = document.createElement("video");
|
|
2798
2847
|
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
2848
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -2848,12 +2897,12 @@ async function Rt() {
|
|
|
2848
2897
|
code: e.code,
|
|
2849
2898
|
message: e.message
|
|
2850
2899
|
})), e.on("autoplayblocked", () => {
|
|
2851
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
2900
|
+
i({ type: "oddin:autoplayblocked" }), Vt(t, e);
|
|
2852
2901
|
});
|
|
2853
2902
|
}, s = async (r) => {
|
|
2854
2903
|
a?.destroy(), a = null;
|
|
2855
2904
|
try {
|
|
2856
|
-
let n = await
|
|
2905
|
+
let n = await Ft({
|
|
2857
2906
|
video: t,
|
|
2858
2907
|
baseUrl: e.baseUrl,
|
|
2859
2908
|
matchUrn: r,
|
|
@@ -2914,7 +2963,7 @@ async function Rt() {
|
|
|
2914
2963
|
a?.retry();
|
|
2915
2964
|
break;
|
|
2916
2965
|
case "oddin:load":
|
|
2917
|
-
typeof e.matchUrn == "string" &&
|
|
2966
|
+
typeof e.matchUrn == "string" && Rt.test(e.matchUrn) && s(e.matchUrn);
|
|
2918
2967
|
break;
|
|
2919
2968
|
case "oddin:destroy": c();
|
|
2920
2969
|
}
|
|
@@ -2926,18 +2975,18 @@ async function Rt() {
|
|
|
2926
2975
|
protocol: 1
|
|
2927
2976
|
});
|
|
2928
2977
|
}
|
|
2929
|
-
function
|
|
2978
|
+
function Vt(e, t) {
|
|
2930
2979
|
if (document.getElementById("havik-tap")) return;
|
|
2931
2980
|
let n = document.createElement("button");
|
|
2932
2981
|
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
2982
|
n.remove(), t.play();
|
|
2934
2983
|
}), document.body.appendChild(n);
|
|
2935
2984
|
}
|
|
2936
|
-
function
|
|
2985
|
+
function Ht() {
|
|
2937
2986
|
let e = document.createElement("style");
|
|
2938
2987
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
2939
2988
|
}
|
|
2940
2989
|
//#endregion
|
|
2941
|
-
export { J as ODDIN_THEME, n as PlaybackError, X as applyTheme,
|
|
2990
|
+
export { J as ODDIN_THEME, n as PlaybackError, X as applyTheme, Bt as bootEmbed, _e as clearDeviceId, Ft 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, Lt as mountEmbed, oe as pollToLive, y as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, he as watchStatus };
|
|
2942
2991
|
|
|
2943
2992
|
//# sourceMappingURL=index.js.map
|