@oddin-gg/havik-player 2.16.6 → 2.16.8
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 +2 -2
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +290 -237
- package/dist/index.js.map +1 -1
- package/docs/API.md +1 -1
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -676,9 +676,9 @@ var R = {
|
|
|
676
676
|
dv: "dvh1.05.06",
|
|
677
677
|
av1: "av01.0.05M.08",
|
|
678
678
|
vp9: "vp09.00.10.08"
|
|
679
|
-
},
|
|
680
|
-
function
|
|
681
|
-
let t = L(e), n =
|
|
679
|
+
}, je = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Map();
|
|
680
|
+
function Me(e) {
|
|
681
|
+
let t = L(e), n = je.get(t);
|
|
682
682
|
if (n) return n;
|
|
683
683
|
let r = {
|
|
684
684
|
initDataTypes: ["cenc"],
|
|
@@ -696,23 +696,23 @@ function je(e) {
|
|
|
696
696
|
} catch {
|
|
697
697
|
return !1;
|
|
698
698
|
}
|
|
699
|
-
})().then((e) => (
|
|
700
|
-
return
|
|
699
|
+
})().then((e) => (z.set(t, e), e));
|
|
700
|
+
return je.set(t, i), i;
|
|
701
701
|
}
|
|
702
|
-
function
|
|
703
|
-
if (j()) for (let e of Object.values(R))
|
|
702
|
+
function Ne() {
|
|
703
|
+
if (j()) for (let e of Object.values(R)) Me(e);
|
|
704
704
|
}
|
|
705
|
-
function
|
|
705
|
+
function Pe(e) {
|
|
706
706
|
let t = I(e);
|
|
707
|
-
if (t) return t === "avc" ? !0 :
|
|
707
|
+
if (t) return t === "avc" ? !0 : z.get(L(e)) ?? z.get(L(R[t]));
|
|
708
708
|
}
|
|
709
709
|
//#endregion
|
|
710
710
|
//#region src/core/drm/support.ts
|
|
711
|
-
var
|
|
711
|
+
var Fe = 5e3, Ie = "video/mp4; codecs=\"avc1.42E01E\"", Le = "audio/mp4; codecs=\"mp4a.40.2\"", Re = {
|
|
712
712
|
widevine: ["com.widevine.alpha"],
|
|
713
713
|
fairplay: ["com.apple.fps"]
|
|
714
714
|
};
|
|
715
|
-
function
|
|
715
|
+
function ze(e) {
|
|
716
716
|
return e === "fairplay" ? [{
|
|
717
717
|
initDataTypes: [
|
|
718
718
|
"sinf",
|
|
@@ -720,30 +720,30 @@ function Re(e) {
|
|
|
720
720
|
"cenc"
|
|
721
721
|
],
|
|
722
722
|
videoCapabilities: [{
|
|
723
|
-
contentType:
|
|
723
|
+
contentType: Ie,
|
|
724
724
|
robustness: "",
|
|
725
725
|
encryptionScheme: "cbcs"
|
|
726
726
|
}],
|
|
727
727
|
audioCapabilities: [{
|
|
728
|
-
contentType:
|
|
728
|
+
contentType: Le,
|
|
729
729
|
robustness: "",
|
|
730
730
|
encryptionScheme: "cbcs"
|
|
731
731
|
}]
|
|
732
732
|
}] : N("com.widevine.alpha", [{
|
|
733
733
|
initDataTypes: ["cenc"],
|
|
734
734
|
videoCapabilities: [{
|
|
735
|
-
contentType:
|
|
735
|
+
contentType: Ie,
|
|
736
736
|
robustness: F.video,
|
|
737
737
|
encryptionScheme: F.scheme
|
|
738
738
|
}],
|
|
739
739
|
audioCapabilities: [{
|
|
740
|
-
contentType:
|
|
740
|
+
contentType: Le,
|
|
741
741
|
robustness: F.audio,
|
|
742
742
|
encryptionScheme: F.scheme
|
|
743
743
|
}]
|
|
744
744
|
}]);
|
|
745
745
|
}
|
|
746
|
-
function
|
|
746
|
+
function Be(e, t) {
|
|
747
747
|
return new Promise((n, r) => {
|
|
748
748
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
749
749
|
e.then((e) => {
|
|
@@ -753,8 +753,8 @@ function ze(e, t) {
|
|
|
753
753
|
});
|
|
754
754
|
});
|
|
755
755
|
}
|
|
756
|
-
async function
|
|
757
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
756
|
+
async function Ve(e = {}) {
|
|
757
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Fe, r = {};
|
|
758
758
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
759
759
|
verdict: "insecure-context",
|
|
760
760
|
detail: r
|
|
@@ -766,7 +766,7 @@ async function Be(e = {}) {
|
|
|
766
766
|
};
|
|
767
767
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
768
768
|
for (let e of t) {
|
|
769
|
-
let t =
|
|
769
|
+
let t = Re[e];
|
|
770
770
|
if (!t) {
|
|
771
771
|
r[e] = "unknown system";
|
|
772
772
|
continue;
|
|
@@ -777,7 +777,7 @@ async function Be(e = {}) {
|
|
|
777
777
|
break;
|
|
778
778
|
}
|
|
779
779
|
try {
|
|
780
|
-
return await
|
|
780
|
+
return await Be((await Be(i(n, ze(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
781
781
|
verdict: "supported",
|
|
782
782
|
system: e,
|
|
783
783
|
detail: r
|
|
@@ -801,49 +801,49 @@ async function Be(e = {}) {
|
|
|
801
801
|
}
|
|
802
802
|
//#endregion
|
|
803
803
|
//#region src/core/manifest.ts
|
|
804
|
-
var
|
|
805
|
-
function
|
|
806
|
-
return
|
|
804
|
+
var He = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
805
|
+
function Ue(e) {
|
|
806
|
+
return He.test(e);
|
|
807
807
|
}
|
|
808
808
|
//#endregion
|
|
809
809
|
//#region src/core/env.ts
|
|
810
|
-
var
|
|
810
|
+
var We = {
|
|
811
811
|
integration: "https://feed-dev.oddin-video.gg",
|
|
812
812
|
production: "https://feed.oddin-video.gg"
|
|
813
813
|
};
|
|
814
|
-
function
|
|
815
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
814
|
+
function Ge(e) {
|
|
815
|
+
let t = Object.prototype.hasOwnProperty.call(We, e) ? We[e] : void 0;
|
|
816
816
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
817
817
|
return t;
|
|
818
818
|
}
|
|
819
819
|
//#endregion
|
|
820
820
|
//#region src/core/stats.ts
|
|
821
|
-
var
|
|
822
|
-
function
|
|
821
|
+
var Ke = { droppedFrames: 0 };
|
|
822
|
+
function qe(e) {
|
|
823
823
|
try {
|
|
824
824
|
return new URL(e).host;
|
|
825
825
|
} catch {
|
|
826
826
|
return "";
|
|
827
827
|
}
|
|
828
828
|
}
|
|
829
|
-
var
|
|
830
|
-
function
|
|
829
|
+
var Je = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
830
|
+
function Ye(e) {
|
|
831
831
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
832
832
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
833
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
834
|
-
let e =
|
|
833
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Je.test(i.name)) && i.startTime >= n) {
|
|
834
|
+
let e = qe(i.name);
|
|
835
835
|
e && (t = e, n = i.startTime);
|
|
836
836
|
}
|
|
837
837
|
return t;
|
|
838
838
|
}
|
|
839
|
-
function
|
|
839
|
+
function B(e) {
|
|
840
840
|
let t = e.getVideoPlaybackQuality?.();
|
|
841
841
|
return {
|
|
842
842
|
dropped: t?.droppedVideoFrames ?? 0,
|
|
843
843
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
844
844
|
};
|
|
845
845
|
}
|
|
846
|
-
var
|
|
846
|
+
var Xe = class {
|
|
847
847
|
video;
|
|
848
848
|
baseFrames = 0;
|
|
849
849
|
baseDropped = 0;
|
|
@@ -853,7 +853,7 @@ var Ye = class {
|
|
|
853
853
|
this.video = e;
|
|
854
854
|
}
|
|
855
855
|
read() {
|
|
856
|
-
let e =
|
|
856
|
+
let e = B(this.video);
|
|
857
857
|
return e.totalFrames < this.lastFrames && (this.baseFrames += this.lastFrames), e.dropped < this.lastDropped && (this.baseDropped += this.lastDropped), this.lastFrames = e.totalFrames, this.lastDropped = e.dropped, {
|
|
858
858
|
dropped: this.baseDropped + e.dropped,
|
|
859
859
|
totalFrames: this.baseFrames + e.totalFrames
|
|
@@ -866,7 +866,7 @@ var Ye = class {
|
|
|
866
866
|
};
|
|
867
867
|
}
|
|
868
868
|
};
|
|
869
|
-
function
|
|
869
|
+
function Ze(e, t) {
|
|
870
870
|
let n = [
|
|
871
871
|
["playing", () => t("playing")],
|
|
872
872
|
["waiting", () => t("buffering")],
|
|
@@ -883,8 +883,8 @@ function Xe(e, t) {
|
|
|
883
883
|
}
|
|
884
884
|
//#endregion
|
|
885
885
|
//#region src/core/engine/native.ts
|
|
886
|
-
var
|
|
887
|
-
function
|
|
886
|
+
var Qe = 2e3, $e = 3, V = 500, et = 6e3, tt = .25, nt = 250, rt = .05;
|
|
887
|
+
function it(e) {
|
|
888
888
|
try {
|
|
889
889
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
890
890
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -892,20 +892,20 @@ function tt(e) {
|
|
|
892
892
|
return;
|
|
893
893
|
}
|
|
894
894
|
}
|
|
895
|
-
function
|
|
895
|
+
function H(e) {
|
|
896
896
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
897
897
|
}
|
|
898
|
-
function
|
|
898
|
+
function U() {
|
|
899
899
|
if (typeof window > "u") return !1;
|
|
900
900
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
901
901
|
return e || t;
|
|
902
902
|
}
|
|
903
|
-
function
|
|
904
|
-
if (typeof navigator > "u" || !
|
|
903
|
+
function at() {
|
|
904
|
+
if (typeof navigator > "u" || !U()) return !1;
|
|
905
905
|
let e = navigator.userAgent ?? "";
|
|
906
906
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
907
907
|
}
|
|
908
|
-
var
|
|
908
|
+
var W = class {
|
|
909
909
|
name = "native";
|
|
910
910
|
deps;
|
|
911
911
|
onLoaded;
|
|
@@ -918,6 +918,10 @@ var G = class {
|
|
|
918
918
|
onPageShow = null;
|
|
919
919
|
hiddenSince = null;
|
|
920
920
|
refocusTimer = null;
|
|
921
|
+
edgeTimer = null;
|
|
922
|
+
onEdgeReset = null;
|
|
923
|
+
lastBufferedEnd = null;
|
|
924
|
+
bufferedAdvancedAt = null;
|
|
921
925
|
fairplayKeyIV;
|
|
922
926
|
loadStarted;
|
|
923
927
|
preloadTouched = !1;
|
|
@@ -927,12 +931,12 @@ var G = class {
|
|
|
927
931
|
frameCounter;
|
|
928
932
|
detachFrames = null;
|
|
929
933
|
constructor(e) {
|
|
930
|
-
this.deps = e, this.frameCounter = new
|
|
934
|
+
this.deps = e, this.frameCounter = new Xe(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
|
|
931
935
|
}
|
|
932
936
|
async load() {
|
|
933
937
|
this.detachFrames ??= this.frameCounter.attach();
|
|
934
938
|
let { video: e, descriptor: t, emit: r } = this.deps;
|
|
935
|
-
if (this.watchRefocus(), this.loadStarted || (this.preloadTouched = !0, this.savedPreload = e.getAttribute("preload"), e.preload = "none"), t.drmEnabled) {
|
|
939
|
+
if (this.watchRefocus(), this.watchBufferedEnd(), this.loadStarted || (this.preloadTouched = !0, this.savedPreload = e.getAttribute("preload"), e.preload = "none"), t.drmEnabled) {
|
|
936
940
|
if (!t.drm?.fairplay) {
|
|
937
941
|
r({
|
|
938
942
|
type: "error",
|
|
@@ -948,7 +952,7 @@ var G = class {
|
|
|
948
952
|
type: "error",
|
|
949
953
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
950
954
|
fatal: !0
|
|
951
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
955
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = st(t.manifestUrl, t.analytics?.sid), e.load();
|
|
952
956
|
}
|
|
953
957
|
startLoad() {
|
|
954
958
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -970,7 +974,7 @@ var G = class {
|
|
|
970
974
|
});
|
|
971
975
|
this.onEncrypted = (n) => {
|
|
972
976
|
let i = n;
|
|
973
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
977
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = it(i.initData), (async () => {
|
|
974
978
|
try {
|
|
975
979
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
976
980
|
initDataTypes: [i.initDataType],
|
|
@@ -1069,51 +1073,73 @@ var G = class {
|
|
|
1069
1073
|
droppedFrames: t.dropped,
|
|
1070
1074
|
decodedFrames: t.totalFrames
|
|
1071
1075
|
};
|
|
1072
|
-
if (this.cdnHost ||=
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
let r = t - e.currentTime;
|
|
1077
|
-
Number.isFinite(r) && r >= 0 && (n.latencySeconds = r);
|
|
1078
|
-
}
|
|
1076
|
+
if (this.cdnHost ||= Ye(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1077
|
+
n.isLive = !0;
|
|
1078
|
+
let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
|
|
1079
|
+
Number.isFinite(r) && (n.atLiveEdge = r <= 2, !e.paused && r >= 0 && (n.latencySeconds = r));
|
|
1079
1080
|
} else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
|
|
1080
1081
|
return n;
|
|
1081
1082
|
}
|
|
1082
1083
|
stop() {
|
|
1084
|
+
this.unwatchBufferedEnd();
|
|
1083
1085
|
try {
|
|
1084
1086
|
this.deps.video.pause();
|
|
1085
1087
|
} catch {}
|
|
1086
1088
|
}
|
|
1087
1089
|
watchRefocus() {
|
|
1088
1090
|
this.deps.snapToLiveOnRefocus === !1 || typeof document > "u" || this.onVisibility || (this.onVisibility = () => {
|
|
1089
|
-
let e =
|
|
1091
|
+
let e = G();
|
|
1090
1092
|
if (document.visibilityState === "hidden") {
|
|
1091
1093
|
this.hiddenSince = e, this.cancelRefocus();
|
|
1092
1094
|
return;
|
|
1093
1095
|
}
|
|
1094
1096
|
let t = this.hiddenSince;
|
|
1095
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1097
|
+
this.hiddenSince = null, t != null && e - t >= Qe && this.armRefocus();
|
|
1096
1098
|
}, this.onPageShow = (e) => {
|
|
1097
1099
|
e.persisted && this.armRefocus();
|
|
1098
1100
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
1099
1101
|
}
|
|
1100
1102
|
armRefocus() {
|
|
1101
1103
|
if (this.cancelRefocus(), Number.isFinite(this.deps.video.duration)) return;
|
|
1102
|
-
let e = this.liveEnd(), t =
|
|
1104
|
+
let e = this.liveEnd(), t = G, n = t(), r = 0, i = () => {
|
|
1103
1105
|
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1104
|
-
r +=
|
|
1105
|
-
let a = this.liveEnd(), o = a != null && (e == null || a >= e +
|
|
1106
|
+
r += V;
|
|
1107
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + tt), s = Math.max(r, t() - n) >= et;
|
|
1106
1108
|
if (o || s && a != null) {
|
|
1107
1109
|
this.snapToLive();
|
|
1108
1110
|
return;
|
|
1109
1111
|
}
|
|
1110
|
-
this.refocusTimer = setTimeout(i,
|
|
1112
|
+
this.refocusTimer = setTimeout(i, V);
|
|
1111
1113
|
};
|
|
1112
|
-
this.refocusTimer = setTimeout(i,
|
|
1114
|
+
this.refocusTimer = setTimeout(i, V);
|
|
1113
1115
|
}
|
|
1114
1116
|
cancelRefocus() {
|
|
1115
1117
|
this.refocusTimer != null && clearTimeout(this.refocusTimer), this.refocusTimer = null;
|
|
1116
1118
|
}
|
|
1119
|
+
watchBufferedEnd() {
|
|
1120
|
+
if (this.edgeTimer != null) return;
|
|
1121
|
+
let { video: e } = this.deps;
|
|
1122
|
+
this.onEdgeReset = () => {
|
|
1123
|
+
this.lastBufferedEnd = null, this.bufferedAdvancedAt = null;
|
|
1124
|
+
}, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
|
|
1125
|
+
if (e.duration !== Infinity) return;
|
|
1126
|
+
let t = ot(e, e.currentTime);
|
|
1127
|
+
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= rt) && (this.bufferedAdvancedAt = G()), this.lastBufferedEnd = t);
|
|
1128
|
+
}, nt);
|
|
1129
|
+
}
|
|
1130
|
+
unwatchBufferedEnd() {
|
|
1131
|
+
this.edgeTimer != null && clearInterval(this.edgeTimer), this.edgeTimer = null, this.onEdgeReset &&= (this.deps.video.removeEventListener("seeking", this.onEdgeReset), this.deps.video.removeEventListener("emptied", this.onEdgeReset), null), this.lastBufferedEnd = null, this.bufferedAdvancedAt = null;
|
|
1132
|
+
}
|
|
1133
|
+
liveEdgeEstimate() {
|
|
1134
|
+
let e = this.deps.video;
|
|
1135
|
+
if (e.duration !== Infinity) return null;
|
|
1136
|
+
let t = this.liveEnd(), n = ot(e, e.currentTime) ?? this.lastBufferedEnd;
|
|
1137
|
+
if (n != null) {
|
|
1138
|
+
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (G() - e) / 1e3));
|
|
1139
|
+
(t == null || r > t) && (t = r);
|
|
1140
|
+
}
|
|
1141
|
+
return t != null && Number.isFinite(t) ? t : null;
|
|
1142
|
+
}
|
|
1117
1143
|
liveEnd() {
|
|
1118
1144
|
let e = this.deps.video;
|
|
1119
1145
|
if (e.duration !== Infinity || e.seekable.length === 0) return null;
|
|
@@ -1123,13 +1149,13 @@ var G = class {
|
|
|
1123
1149
|
snapToLive() {
|
|
1124
1150
|
let e = this.deps.video, t = this.liveEnd();
|
|
1125
1151
|
if (t == null) return;
|
|
1126
|
-
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t -
|
|
1152
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - $e, r);
|
|
1127
1153
|
try {
|
|
1128
1154
|
e.currentTime = i;
|
|
1129
1155
|
} catch {}
|
|
1130
1156
|
}
|
|
1131
1157
|
destroy() {
|
|
1132
|
-
this.detachFrames?.(), this.detachFrames = null, this.cancelRefocus(), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onPageShow && typeof window < "u" && (window.removeEventListener("pageshow", this.onPageShow), this.onPageShow = null);
|
|
1158
|
+
this.detachFrames?.(), this.detachFrames = null, this.cancelRefocus(), this.unwatchBufferedEnd(), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onPageShow && typeof window < "u" && (window.removeEventListener("pageshow", this.onPageShow), this.onPageShow = null);
|
|
1133
1159
|
let { video: e } = this.deps;
|
|
1134
1160
|
this.onLoaded && e.removeEventListener("loadedmetadata", this.onLoaded), this.onError && e.removeEventListener("error", this.onError), this.onEncrypted && e.removeEventListener("encrypted", this.onEncrypted), this.keySession?.close().catch(() => {}), this.keySession = null, this.fairplayArmed = !1, this.fairplayKeyIV = void 0;
|
|
1135
1161
|
try {
|
|
@@ -1141,7 +1167,19 @@ var G = class {
|
|
|
1141
1167
|
} catch {}
|
|
1142
1168
|
}
|
|
1143
1169
|
};
|
|
1144
|
-
function
|
|
1170
|
+
function G() {
|
|
1171
|
+
return typeof performance < "u" ? performance.now() : Date.now();
|
|
1172
|
+
}
|
|
1173
|
+
function ot(e, t) {
|
|
1174
|
+
let n = e.buffered;
|
|
1175
|
+
if (!n || !Number.isFinite(t)) return null;
|
|
1176
|
+
for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
|
|
1177
|
+
let t = n.end(e);
|
|
1178
|
+
return Number.isFinite(t) ? t : null;
|
|
1179
|
+
}
|
|
1180
|
+
return null;
|
|
1181
|
+
}
|
|
1182
|
+
function st(e, t) {
|
|
1145
1183
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1146
1184
|
}
|
|
1147
1185
|
//#endregion
|
|
@@ -1158,8 +1196,8 @@ function K(e, t = Date.now()) {
|
|
|
1158
1196
|
}
|
|
1159
1197
|
//#endregion
|
|
1160
1198
|
//#region src/core/engine/prefetch.ts
|
|
1161
|
-
var
|
|
1162
|
-
function
|
|
1199
|
+
var ct = 15e3, lt = 5e3, ut = 6;
|
|
1200
|
+
function dt(e) {
|
|
1163
1201
|
try {
|
|
1164
1202
|
let t = new URL(e);
|
|
1165
1203
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1167,7 +1205,7 @@ function st(e) {
|
|
|
1167
1205
|
return e;
|
|
1168
1206
|
}
|
|
1169
1207
|
}
|
|
1170
|
-
var
|
|
1208
|
+
var ft = class {
|
|
1171
1209
|
cmcd;
|
|
1172
1210
|
entries = /* @__PURE__ */ new Map();
|
|
1173
1211
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1190,10 +1228,10 @@ var ct = class {
|
|
|
1190
1228
|
}
|
|
1191
1229
|
prefetch(e, t, n) {
|
|
1192
1230
|
if (!this.isActive(t)) return;
|
|
1193
|
-
let r =
|
|
1231
|
+
let r = dt(e);
|
|
1194
1232
|
if (this.entries.has(r)) return;
|
|
1195
1233
|
let i = this.perTrack.get(t) ?? 0;
|
|
1196
|
-
if (i >=
|
|
1234
|
+
if (i >= ut) return;
|
|
1197
1235
|
this.perTrack.set(t, i + 1);
|
|
1198
1236
|
let a = new AbortController(), o = {
|
|
1199
1237
|
started: performance.now(),
|
|
@@ -1207,10 +1245,10 @@ var ct = class {
|
|
|
1207
1245
|
signal: a.signal
|
|
1208
1246
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1209
1247
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1210
|
-
},
|
|
1248
|
+
}, ct);
|
|
1211
1249
|
}
|
|
1212
1250
|
take(e) {
|
|
1213
|
-
let t =
|
|
1251
|
+
let t = dt(e), n = this.entries.get(t);
|
|
1214
1252
|
return n && this.entries.delete(t), n;
|
|
1215
1253
|
}
|
|
1216
1254
|
destroy() {
|
|
@@ -1230,13 +1268,13 @@ var ct = class {
|
|
|
1230
1268
|
}
|
|
1231
1269
|
}
|
|
1232
1270
|
};
|
|
1233
|
-
function
|
|
1271
|
+
function pt(t) {
|
|
1234
1272
|
let n = e.DefaultConfig?.loader;
|
|
1235
1273
|
if (typeof n != "function") return;
|
|
1236
1274
|
class r extends n {
|
|
1237
1275
|
served = !1;
|
|
1238
1276
|
cancelled = !1;
|
|
1239
|
-
stats =
|
|
1277
|
+
stats = mt();
|
|
1240
1278
|
load(e, n, r) {
|
|
1241
1279
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1242
1280
|
if (!i) {
|
|
@@ -1244,7 +1282,7 @@ function lt(t) {
|
|
|
1244
1282
|
return;
|
|
1245
1283
|
}
|
|
1246
1284
|
this.served = !0;
|
|
1247
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1285
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || lt, s = setTimeout(() => {
|
|
1248
1286
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1249
1287
|
}, o);
|
|
1250
1288
|
i.bytes.then((o) => {
|
|
@@ -1271,7 +1309,7 @@ function lt(t) {
|
|
|
1271
1309
|
}
|
|
1272
1310
|
return r;
|
|
1273
1311
|
}
|
|
1274
|
-
function
|
|
1312
|
+
function mt() {
|
|
1275
1313
|
return {
|
|
1276
1314
|
aborted: !1,
|
|
1277
1315
|
loaded: 0,
|
|
@@ -1295,10 +1333,10 @@ function ut() {
|
|
|
1295
1333
|
}
|
|
1296
1334
|
};
|
|
1297
1335
|
}
|
|
1298
|
-
function
|
|
1336
|
+
function ht(e) {
|
|
1299
1337
|
return e === "audio" ? "audio" : "main";
|
|
1300
1338
|
}
|
|
1301
|
-
function
|
|
1339
|
+
function gt(e, t) {
|
|
1302
1340
|
let n = [];
|
|
1303
1341
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1304
1342
|
url: t.initSegment.url,
|
|
@@ -1317,24 +1355,24 @@ function ft(e, t) {
|
|
|
1317
1355
|
}
|
|
1318
1356
|
//#endregion
|
|
1319
1357
|
//#region src/core/engine/hls.ts
|
|
1320
|
-
function
|
|
1358
|
+
function _t() {
|
|
1321
1359
|
return e.isSupported();
|
|
1322
1360
|
}
|
|
1323
|
-
var
|
|
1324
|
-
function
|
|
1361
|
+
var vt = 3, yt = 5, bt = 3, xt = 1e4, St = 3e4, Ct = 12e3, wt = 3e3, Tt = .02, Et = 6e3, Dt = .5, Ot = 3, kt = .5, At = 1.1, jt = .25, Mt = 5e3, Nt = 4e3, Pt = 2, Ft = 5, It = 2, Lt = 2, Rt = 4, zt = 4, Bt = 2e3, Vt = 3e4, Ht = .2, Ut = 30, Wt = 2, Gt = 2, Kt = 9, qt = .5, Jt = 64;
|
|
1362
|
+
function Yt(e) {
|
|
1325
1363
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1326
1364
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1327
1365
|
return;
|
|
1328
1366
|
}
|
|
1329
|
-
e.liveSyncDuration ??=
|
|
1330
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1331
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1367
|
+
e.liveSyncDuration ??= Gt;
|
|
1368
|
+
let t = Math.max(12, e.liveSyncDuration + Kt);
|
|
1369
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Xt(e, e.liveSyncDuration);
|
|
1332
1370
|
}
|
|
1333
|
-
function
|
|
1371
|
+
function Xt(e, t) {
|
|
1334
1372
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1335
1373
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1336
1374
|
}
|
|
1337
|
-
var
|
|
1375
|
+
var Zt = class {
|
|
1338
1376
|
name = "hls";
|
|
1339
1377
|
hls = null;
|
|
1340
1378
|
deps;
|
|
@@ -1414,11 +1452,11 @@ var Kt = class {
|
|
|
1414
1452
|
frameCounter;
|
|
1415
1453
|
detachFrames = null;
|
|
1416
1454
|
constructor(e) {
|
|
1417
|
-
this.deps = e, this.frameCounter = new
|
|
1455
|
+
this.deps = e, this.frameCounter = new Xe(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1418
1456
|
}
|
|
1419
1457
|
async load() {
|
|
1420
1458
|
this.detachFrames ??= this.frameCounter.attach();
|
|
1421
|
-
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a =
|
|
1459
|
+
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = H(r) && U(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
1422
1460
|
if (e.drmEnabled && !o) {
|
|
1423
1461
|
i({
|
|
1424
1462
|
type: "error",
|
|
@@ -1427,7 +1465,7 @@ var Kt = class {
|
|
|
1427
1465
|
});
|
|
1428
1466
|
return;
|
|
1429
1467
|
}
|
|
1430
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r),
|
|
1468
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Ne()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1431
1469
|
let e = this.hls;
|
|
1432
1470
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1433
1471
|
let t = e.liveSyncPosition;
|
|
@@ -1450,7 +1488,7 @@ var Kt = class {
|
|
|
1450
1488
|
}
|
|
1451
1489
|
this.loadSuspended = !0;
|
|
1452
1490
|
}
|
|
1453
|
-
},
|
|
1491
|
+
}, Mt));
|
|
1454
1492
|
}
|
|
1455
1493
|
resumeLoading() {
|
|
1456
1494
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1482,7 +1520,22 @@ var Kt = class {
|
|
|
1482
1520
|
let t = e.liveSyncPosition;
|
|
1483
1521
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1484
1522
|
let { video: n } = this.deps;
|
|
1485
|
-
n.currentTime <= t +
|
|
1523
|
+
n.currentTime <= t + qt || (n.currentTime = t);
|
|
1524
|
+
}
|
|
1525
|
+
reanchorPartTimeline(e, t) {
|
|
1526
|
+
let { frag: n, part: r } = t;
|
|
1527
|
+
if (!r || r.index !== 0 || n.type !== "main" || typeof n.sn != "number") return;
|
|
1528
|
+
let i = e.levels[n.level]?.details;
|
|
1529
|
+
if (!i?.live) return;
|
|
1530
|
+
let a = r.elementaryStreams.video ?? r.elementaryStreams.audiovideo ?? r.elementaryStreams.audio;
|
|
1531
|
+
if (!a) return;
|
|
1532
|
+
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1533
|
+
if (!s) return;
|
|
1534
|
+
let c = a.startPTS - s.start;
|
|
1535
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < Tt)) {
|
|
1536
|
+
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1537
|
+
i.fragmentHint?.setStart(i.fragmentHint.start + c), this.deps.debug === !0 && console.info(`havik-player: LL-HLS timeline re-anchored by ${c >= 0 ? "+" : ""}${c.toFixed(3)}s at sn ${n.sn} (level ${n.level})`);
|
|
1538
|
+
}
|
|
1486
1539
|
}
|
|
1487
1540
|
startHls() {
|
|
1488
1541
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1518,7 +1571,7 @@ var Kt = class {
|
|
|
1518
1571
|
return;
|
|
1519
1572
|
}
|
|
1520
1573
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1521
|
-
u = setTimeout(() => e(void 0),
|
|
1574
|
+
u = setTimeout(() => e(void 0), xt);
|
|
1522
1575
|
});
|
|
1523
1576
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1524
1577
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1534,20 +1587,20 @@ var Kt = class {
|
|
|
1534
1587
|
...c
|
|
1535
1588
|
};
|
|
1536
1589
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
|
|
1537
|
-
let e = new
|
|
1590
|
+
let e = new ft({
|
|
1538
1591
|
sessionId: n.analytics?.sid,
|
|
1539
1592
|
contentId: n.matchUrn
|
|
1540
|
-
}), t =
|
|
1593
|
+
}), t = pt(e);
|
|
1541
1594
|
t && (this.prefetch = e, d.fLoader = t);
|
|
1542
1595
|
}
|
|
1543
|
-
|
|
1596
|
+
Yt(d), this.catchUpRate = typeof d.maxLiveSyncPlaybackRate == "number" ? d.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (d.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = d.autoStartLoad !== !1;
|
|
1544
1597
|
let f = new e(d);
|
|
1545
|
-
if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1598
|
+
if (this.hls = f, f.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(f, t)), f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1546
1599
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(f), this.measureLadder(f), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1547
1600
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1548
1601
|
t?.frag?.type === "main" && (this.kickKind !== "dead" && this.clearKick(), (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
1549
1602
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1550
|
-
},
|
|
1603
|
+
}, St)));
|
|
1551
1604
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1552
1605
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1553
1606
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1555,10 +1608,10 @@ var Kt = class {
|
|
|
1555
1608
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1556
1609
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1557
1610
|
let i = n?.loading;
|
|
1558
|
-
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 >
|
|
1611
|
+
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 > Jt && this.requestTimesMs.shift());
|
|
1559
1612
|
let a = t?.frag?.url;
|
|
1560
1613
|
if (a) {
|
|
1561
|
-
let e =
|
|
1614
|
+
let e = qe(a);
|
|
1562
1615
|
e && (this.cdnHost = e);
|
|
1563
1616
|
}
|
|
1564
1617
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1572,15 +1625,15 @@ var Kt = class {
|
|
|
1572
1625
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1573
1626
|
let t = this.prefetch;
|
|
1574
1627
|
f.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1575
|
-
let r = n?.frag, i =
|
|
1576
|
-
if (r && t.isActive(i)) for (let e of
|
|
1577
|
-
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1628
|
+
let r = n?.frag, i = ht(r?.type);
|
|
1629
|
+
if (r && t.isActive(i)) for (let e of gt(f, r)) t.prefetch(e.url, i, e.kind);
|
|
1630
|
+
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(ht(n?.frag?.type)));
|
|
1578
1631
|
}
|
|
1579
1632
|
f.on(e.Events.KEY_LOADED, () => {
|
|
1580
1633
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1581
1634
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1582
1635
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1583
|
-
},
|
|
1636
|
+
}, wt), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1584
1637
|
this.renditionSwitches += 1;
|
|
1585
1638
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1586
1639
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1644,7 +1697,7 @@ var Kt = class {
|
|
|
1644
1697
|
return;
|
|
1645
1698
|
}
|
|
1646
1699
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1647
|
-
let t = e > this.sizeCapLevel ?
|
|
1700
|
+
let t = e > this.sizeCapLevel ? Bt : Vt;
|
|
1648
1701
|
this.capTimer = setTimeout(() => {
|
|
1649
1702
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1650
1703
|
}, t);
|
|
@@ -1654,9 +1707,9 @@ var Kt = class {
|
|
|
1654
1707
|
this.ladderHeights = t.length ? [...new Set(t)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = e.levels.length ? Math.round(Math.max(...e.levels.map((e) => e.bitrate)) / 1e3) : 0;
|
|
1655
1708
|
}
|
|
1656
1709
|
dropLevelsWidevineCannotPlay(e) {
|
|
1657
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1710
|
+
this.removeLevelsWhere(e, (e) => Pe(e) !== !0);
|
|
1658
1711
|
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
|
|
1659
|
-
for (let n of t)
|
|
1712
|
+
for (let n of t) Me(n).then((t) => {
|
|
1660
1713
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1661
1714
|
});
|
|
1662
1715
|
}
|
|
@@ -1667,7 +1720,7 @@ var Kt = class {
|
|
|
1667
1720
|
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1668
1721
|
}), !r.length) return !1;
|
|
1669
1722
|
let a = [...i].join(", ");
|
|
1670
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) ||
|
|
1723
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Pe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1671
1724
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1672
1725
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1673
1726
|
}
|
|
@@ -1765,7 +1818,7 @@ var Kt = class {
|
|
|
1765
1818
|
return;
|
|
1766
1819
|
}
|
|
1767
1820
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1768
|
-
!this.chaseSuspended && e >
|
|
1821
|
+
!this.chaseSuspended && e > Et && this.suspendChasing(), e > Ct && this.emitEnded("stalled");
|
|
1769
1822
|
}
|
|
1770
1823
|
resetStarvationWindow() {
|
|
1771
1824
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1780,7 +1833,7 @@ var Kt = class {
|
|
|
1780
1833
|
this.resetStarvationWindow();
|
|
1781
1834
|
return;
|
|
1782
1835
|
}
|
|
1783
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1836
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < Et, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Nt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
|
|
1784
1837
|
if (this.starvedFrames = c, !a || l) {
|
|
1785
1838
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1786
1839
|
return;
|
|
@@ -1789,12 +1842,12 @@ var Kt = class {
|
|
|
1789
1842
|
this.resetStarvationWindow();
|
|
1790
1843
|
return;
|
|
1791
1844
|
}
|
|
1792
|
-
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length >
|
|
1845
|
+
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > Rt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= It && (this.clearKick(), this.starvationRebuilds < Lt)) {
|
|
1793
1846
|
this.starvationRebuilds += 1, this.resetStarvationWindow(), this.clearRecoveryReset(), console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
|
|
1794
1847
|
return;
|
|
1795
1848
|
}
|
|
1796
|
-
let u = i && this.starvedTicks >=
|
|
1797
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1849
|
+
let u = i && this.starvedTicks >= Pt, d = !i && this.deadTicks >= Rt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= zt;
|
|
1850
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= Ft))) {
|
|
1798
1851
|
this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, this.kickKind = d ? "dead" : "quiet", this.clearRecoveryReset(), console.warn(d ? "havik-player: video starved while hls.js keeps loading media it never plays (dead pipeline at the live edge) — restarting the load" : "havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
|
|
1799
1852
|
try {
|
|
1800
1853
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1809,7 +1862,7 @@ var Kt = class {
|
|
|
1809
1862
|
let t = e.latency, n = e.targetLatency;
|
|
1810
1863
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1811
1864
|
let r = t - n;
|
|
1812
|
-
!this.catchUpEngaged && r >
|
|
1865
|
+
!this.catchUpEngaged && r > Dt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Dt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1813
1866
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1814
1867
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1815
1868
|
}
|
|
@@ -1830,16 +1883,16 @@ var Kt = class {
|
|
|
1830
1883
|
this.resetFrameDropWindow();
|
|
1831
1884
|
return;
|
|
1832
1885
|
}
|
|
1833
|
-
let { totalFrames: n, dropped: r } =
|
|
1834
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
1886
|
+
let { totalFrames: n, dropped: r } = B(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
1887
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Ut || o < 0) {
|
|
1835
1888
|
this.fpsBadTicks = 0;
|
|
1836
1889
|
return;
|
|
1837
1890
|
}
|
|
1838
|
-
if (o <=
|
|
1891
|
+
if (o <= Ht * a) {
|
|
1839
1892
|
this.fpsBadTicks = 0;
|
|
1840
1893
|
return;
|
|
1841
1894
|
}
|
|
1842
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
1895
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < Wt) return;
|
|
1843
1896
|
this.fpsBadTicks = 0;
|
|
1844
1897
|
let s = e.levels, c = s[e.currentLevel];
|
|
1845
1898
|
if (!c) return;
|
|
@@ -1856,20 +1909,20 @@ var Kt = class {
|
|
|
1856
1909
|
return;
|
|
1857
1910
|
}
|
|
1858
1911
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
1859
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
1912
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(At, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
1860
1913
|
this.resetChaseWindow();
|
|
1861
1914
|
return;
|
|
1862
1915
|
}
|
|
1863
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
1916
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= kt) {
|
|
1864
1917
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
1865
1918
|
return;
|
|
1866
1919
|
}
|
|
1867
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
1920
|
+
if (this.chaseTicks += 1, this.chaseTicks < Ot) return;
|
|
1868
1921
|
this.resetChaseWindow();
|
|
1869
1922
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
1870
1923
|
if (!(a > 1)) return;
|
|
1871
1924
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
1872
|
-
s < o +
|
|
1925
|
+
s < o + jt || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s);
|
|
1873
1926
|
}
|
|
1874
1927
|
suspendChasing() {
|
|
1875
1928
|
let e = this.hls;
|
|
@@ -1914,7 +1967,7 @@ var Kt = class {
|
|
|
1914
1967
|
scheduleLicenseRetry(t) {
|
|
1915
1968
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1916
1969
|
let n = t.response?.code ?? 0;
|
|
1917
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1970
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= bt) return !1;
|
|
1918
1971
|
this.licenseRecoveries += 1;
|
|
1919
1972
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1920
1973
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1946,7 +1999,7 @@ var Kt = class {
|
|
|
1946
1999
|
return;
|
|
1947
2000
|
}
|
|
1948
2001
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1949
|
-
if (this.networkRecoveries <
|
|
2002
|
+
if (this.networkRecoveries < yt) {
|
|
1950
2003
|
this.networkRecoveries += 1;
|
|
1951
2004
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1952
2005
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1963,7 +2016,7 @@ var Kt = class {
|
|
|
1963
2016
|
return;
|
|
1964
2017
|
}
|
|
1965
2018
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1966
|
-
if (this.mediaRecoveries <
|
|
2019
|
+
if (this.mediaRecoveries < vt) {
|
|
1967
2020
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1968
2021
|
return;
|
|
1969
2022
|
}
|
|
@@ -1987,19 +2040,19 @@ var Kt = class {
|
|
|
1987
2040
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1988
2041
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1989
2042
|
}
|
|
1990
|
-
},
|
|
2043
|
+
}, Qt = 15e3, $t = 6e5, en = 3e5, tn = 100, q = 1, nn = 1e3, rn = 3e4, an = 1e3, on = {
|
|
1991
2044
|
inline: "PRESENTATION_INLINE",
|
|
1992
2045
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1993
2046
|
pip: "PRESENTATION_PIP"
|
|
1994
|
-
},
|
|
2047
|
+
}, sn = {
|
|
1995
2048
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1996
2049
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1997
2050
|
none: "KEY_SYSTEM_NONE"
|
|
1998
2051
|
};
|
|
1999
|
-
function
|
|
2052
|
+
function cn(e, t) {
|
|
2000
2053
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
2001
2054
|
}
|
|
2002
|
-
var
|
|
2055
|
+
var ln = /* @__PURE__ */ new Set([
|
|
2003
2056
|
"INVALID_URN",
|
|
2004
2057
|
"NOT_FOUND",
|
|
2005
2058
|
"GONE",
|
|
@@ -2019,7 +2072,7 @@ var rn = /* @__PURE__ */ new Set([
|
|
|
2019
2072
|
ended: "PLAYER_STATE_ENDED",
|
|
2020
2073
|
error: "PLAYER_STATE_ERROR"
|
|
2021
2074
|
};
|
|
2022
|
-
function
|
|
2075
|
+
function un(e) {
|
|
2023
2076
|
try {
|
|
2024
2077
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2025
2078
|
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);
|
|
@@ -2027,8 +2080,8 @@ function an(e) {
|
|
|
2027
2080
|
return;
|
|
2028
2081
|
}
|
|
2029
2082
|
}
|
|
2030
|
-
var
|
|
2031
|
-
function
|
|
2083
|
+
var dn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), fn = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), pn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2084
|
+
function mn(e) {
|
|
2032
2085
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2033
2086
|
let t;
|
|
2034
2087
|
try {
|
|
@@ -2037,19 +2090,19 @@ function ln(e) {
|
|
|
2037
2090
|
} catch {
|
|
2038
2091
|
return;
|
|
2039
2092
|
}
|
|
2040
|
-
if (
|
|
2041
|
-
Y.add(t), g(
|
|
2093
|
+
if (fn.has(t) && !Y.has(t)) {
|
|
2094
|
+
Y.add(t), g(pn(new URL(t).origin));
|
|
2042
2095
|
for (let e of X) e.noteCspBlocked();
|
|
2043
2096
|
}
|
|
2044
2097
|
}
|
|
2045
|
-
function
|
|
2098
|
+
function hn(e, t) {
|
|
2046
2099
|
return g(t, e), { disabledReason: t };
|
|
2047
2100
|
}
|
|
2048
|
-
function
|
|
2049
|
-
if (n) return t && !
|
|
2101
|
+
function gn(e, t, n) {
|
|
2102
|
+
if (n) return t && !dn(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2050
2103
|
if (t) return { endpoint: t };
|
|
2051
|
-
if (t !== void 0) return
|
|
2052
|
-
let r =
|
|
2104
|
+
if (t !== void 0) return hn("empty-endpoint", "analytics is disabled: no QoE beacons will be sent. analytics.endpoint was supplied but empty. Pass a real beacons origin, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, or omit the option to derive it from baseUrl (or analytics: false to opt out).");
|
|
2105
|
+
let r = un(e);
|
|
2053
2106
|
if (r) return { endpoint: r };
|
|
2054
2107
|
let i;
|
|
2055
2108
|
try {
|
|
@@ -2057,9 +2110,9 @@ function dn(e, t, n) {
|
|
|
2057
2110
|
} catch {
|
|
2058
2111
|
i = e;
|
|
2059
2112
|
}
|
|
2060
|
-
return
|
|
2113
|
+
return hn(i, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${i}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
|
|
2061
2114
|
}
|
|
2062
|
-
var
|
|
2115
|
+
var _n = class {
|
|
2063
2116
|
opts;
|
|
2064
2117
|
url;
|
|
2065
2118
|
cspKey;
|
|
@@ -2141,8 +2194,8 @@ var fn = class {
|
|
|
2141
2194
|
constructor(e) {
|
|
2142
2195
|
this.opts = {
|
|
2143
2196
|
...e,
|
|
2144
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2145
|
-
idleMs: e.idleMs ??
|
|
2197
|
+
heartbeatMs: e.heartbeatMs ?? Qt,
|
|
2198
|
+
idleMs: e.idleMs ?? $t
|
|
2146
2199
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2147
2200
|
try {
|
|
2148
2201
|
let e = new URL(this.url);
|
|
@@ -2159,11 +2212,11 @@ var fn = class {
|
|
|
2159
2212
|
sdkVersion: this.opts.sdkVersion,
|
|
2160
2213
|
...this.opts.environment
|
|
2161
2214
|
};
|
|
2162
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2215
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), nn), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.cspKey && fn.add(this.cspKey), document.addEventListener("securitypolicyviolation", mn), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2163
2216
|
}
|
|
2164
2217
|
checkSuspension(e) {
|
|
2165
2218
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2166
|
-
let t = Math.max(this.opts.idleMs,
|
|
2219
|
+
let t = Math.max(this.opts.idleMs, en);
|
|
2167
2220
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2168
2221
|
}
|
|
2169
2222
|
syncIdle(e) {
|
|
@@ -2186,12 +2239,12 @@ var fn = class {
|
|
|
2186
2239
|
let a = {
|
|
2187
2240
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2188
2241
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2189
|
-
presentation:
|
|
2242
|
+
presentation: on[this.presentation]
|
|
2190
2243
|
}, o = this.causeOf(e, t, i);
|
|
2191
2244
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2192
2245
|
}
|
|
2193
2246
|
seekInduced(e) {
|
|
2194
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2247
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < an;
|
|
2195
2248
|
}
|
|
2196
2249
|
causeOf(e, t, n) {
|
|
2197
2250
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2265,7 +2318,7 @@ var fn = class {
|
|
|
2265
2318
|
let r = n ?? "";
|
|
2266
2319
|
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";
|
|
2267
2320
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2268
|
-
if (
|
|
2321
|
+
if (ln.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2269
2322
|
let i = t ?? "";
|
|
2270
2323
|
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";
|
|
2271
2324
|
}
|
|
@@ -2312,14 +2365,14 @@ var fn = class {
|
|
|
2312
2365
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2313
2366
|
o.requestCountDelta = _;
|
|
2314
2367
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2315
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2368
|
+
n.length > 0 && (o.requestTimeP50Ms = cn(n, 50), o.requestTimeP95Ms = cn(n, 95));
|
|
2316
2369
|
}
|
|
2317
2370
|
typeof t.latencySeconds == "number" && typeof t.targetLatencySeconds == "number" && (o.driftMs = Math.round((t.latencySeconds - t.targetLatencySeconds) * 1e3)), typeof t.playbackRate == "number" && t.playbackRate > 0 && (o.playbackRate = t.playbackRate), t.qualityPinned === !0 && (o.qualityPinned = !0), t.cdnHost && (o.cdnHost = t.cdnHost), this.maybeEmitMediaInfo(t), this.enqueue({ heartbeat: o }), this.flush(), s > 0 && this.noteFirstBytes();
|
|
2318
2371
|
}
|
|
2319
2372
|
maybeEmitMediaInfo(e) {
|
|
2320
2373
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2321
2374
|
let t = {};
|
|
2322
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2375
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = sn[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);
|
|
2323
2376
|
let n = JSON.stringify(t);
|
|
2324
2377
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2325
2378
|
}
|
|
@@ -2339,7 +2392,7 @@ var fn = class {
|
|
|
2339
2392
|
let c = r?.positionMs ?? 0;
|
|
2340
2393
|
c > 0 && (i.exitPositionMs = Math.round(c)), this.activeTotalMs > 0 && (i.activeWatchTimeMs = Math.round(this.activeTotalMs)), this.mutedTotalMs > 0 && (i.mutedTimeMs = Math.round(this.mutedTotalMs));
|
|
2341
2394
|
let l = e !== "END_REASON_ENDED";
|
|
2342
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2395
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= rn && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= rn && (i.abandonAfterErrorMs = Math.max(q, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
|
|
2343
2396
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2344
2397
|
u > 0 && (i.decodedFramesTotal = u), e === "END_REASON_STOPPED" && this.startupTimeMs === 0 && this.lastErrorStage === null && (e = "END_REASON_ABORTED", i.reason = e), this.startupTimeMs === 0 && e !== "END_REASON_ABORTED" && (i.failedStage = this.lastErrorStage ?? (this.manifestLoadMs === 0 ? "ERROR_STAGE_MANIFEST" : this.firstFragLoadMs === 0 ? "ERROR_STAGE_FIRST_SEGMENT" : "ERROR_STAGE_OTHER")), this.pending.push(this.wrap({ sessionEnd: i })), this.flush(e === "END_REASON_PAGEHIDE");
|
|
2345
2398
|
}
|
|
@@ -2359,13 +2412,13 @@ var fn = class {
|
|
|
2359
2412
|
};
|
|
2360
2413
|
}
|
|
2361
2414
|
noteCspBlocked() {
|
|
2362
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2415
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(pn(new URL(this.url).origin)));
|
|
2363
2416
|
}
|
|
2364
2417
|
cspBlocked() {
|
|
2365
2418
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2366
2419
|
}
|
|
2367
2420
|
enqueue(e) {
|
|
2368
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2421
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > tn;) {
|
|
2369
2422
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2370
2423
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2371
2424
|
}
|
|
@@ -2392,7 +2445,7 @@ var fn = class {
|
|
|
2392
2445
|
};
|
|
2393
2446
|
//#endregion
|
|
2394
2447
|
//#region src/core/environment.ts
|
|
2395
|
-
function
|
|
2448
|
+
function vn() {
|
|
2396
2449
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2397
2450
|
let e;
|
|
2398
2451
|
try {
|
|
@@ -2417,14 +2470,14 @@ function pn() {
|
|
|
2417
2470
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2418
2471
|
};
|
|
2419
2472
|
}
|
|
2420
|
-
function
|
|
2473
|
+
function yn() {
|
|
2421
2474
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2422
2475
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2423
2476
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2424
2477
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2425
2478
|
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";
|
|
2426
2479
|
}
|
|
2427
|
-
function
|
|
2480
|
+
function bn() {
|
|
2428
2481
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2429
2482
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2430
2483
|
let t = {
|
|
@@ -2443,17 +2496,17 @@ function hn() {
|
|
|
2443
2496
|
}
|
|
2444
2497
|
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;
|
|
2445
2498
|
}
|
|
2446
|
-
function
|
|
2447
|
-
let t =
|
|
2448
|
-
deviceClass:
|
|
2499
|
+
function xn(e) {
|
|
2500
|
+
let t = vn(), n = {
|
|
2501
|
+
deviceClass: yn(),
|
|
2449
2502
|
integration: t.integration,
|
|
2450
|
-
...
|
|
2503
|
+
...bn()
|
|
2451
2504
|
};
|
|
2452
2505
|
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);
|
|
2453
2506
|
let r = e.getBoundingClientRect?.();
|
|
2454
2507
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2455
2508
|
}
|
|
2456
|
-
async function
|
|
2509
|
+
async function Sn() {
|
|
2457
2510
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2458
2511
|
if (!e?.getHighEntropyValues) return {};
|
|
2459
2512
|
try {
|
|
@@ -2465,7 +2518,7 @@ async function _n() {
|
|
|
2465
2518
|
}
|
|
2466
2519
|
//#endregion
|
|
2467
2520
|
//#region src/core/version.ts
|
|
2468
|
-
var
|
|
2521
|
+
var Cn = "2.16.8", wn = {
|
|
2469
2522
|
accent: "#E1B600",
|
|
2470
2523
|
accentText: "#1B1C23",
|
|
2471
2524
|
background: "#0e0f13",
|
|
@@ -2476,7 +2529,7 @@ var vn = "2.16.6", yn = {
|
|
|
2476
2529
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2477
2530
|
radius: "8px",
|
|
2478
2531
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2479
|
-
},
|
|
2532
|
+
}, Tn = {
|
|
2480
2533
|
accent: "--havik-accent",
|
|
2481
2534
|
accentText: "--havik-accent-text",
|
|
2482
2535
|
background: "--havik-bg",
|
|
@@ -2488,26 +2541,26 @@ var vn = "2.16.6", yn = {
|
|
|
2488
2541
|
radius: "--havik-radius",
|
|
2489
2542
|
fontFamily: "--havik-font"
|
|
2490
2543
|
};
|
|
2491
|
-
function
|
|
2544
|
+
function En(e, t) {
|
|
2492
2545
|
let n = {
|
|
2493
|
-
...
|
|
2546
|
+
...wn,
|
|
2494
2547
|
...t
|
|
2495
2548
|
};
|
|
2496
|
-
for (let t of Object.keys(
|
|
2549
|
+
for (let t of Object.keys(Tn)) e.style.setProperty(Tn[t], n[t]);
|
|
2497
2550
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2498
2551
|
}
|
|
2499
2552
|
//#endregion
|
|
2500
2553
|
//#region src/ui/styles.ts
|
|
2501
|
-
var
|
|
2502
|
-
function
|
|
2503
|
-
let n = e.querySelector(`style#${
|
|
2504
|
-
if (n && (!t ||
|
|
2554
|
+
var Dn = "havik-player-styles", On = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", kn = /* @__PURE__ */ new WeakMap();
|
|
2555
|
+
function An(e = document, t) {
|
|
2556
|
+
let n = e.querySelector(`style#${Dn}`);
|
|
2557
|
+
if (n && (!t || kn.get(n) === t)) return;
|
|
2505
2558
|
let r = e.createElement("style");
|
|
2506
|
-
r.id =
|
|
2559
|
+
r.id = Dn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = On, kn.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2507
2560
|
}
|
|
2508
2561
|
//#endregion
|
|
2509
2562
|
//#region src/ui/icons.ts
|
|
2510
|
-
var
|
|
2563
|
+
var jn = {
|
|
2511
2564
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2512
2565
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2513
2566
|
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\"/>",
|
|
@@ -2520,21 +2573,21 @@ var Tn = {
|
|
|
2520
2573
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
2521
2574
|
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\"/>"
|
|
2522
2575
|
};
|
|
2523
|
-
function
|
|
2524
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2576
|
+
function Z(e) {
|
|
2577
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${jn[e]}</svg>`;
|
|
2525
2578
|
}
|
|
2526
2579
|
//#endregion
|
|
2527
2580
|
//#region src/ui/controls.ts
|
|
2528
|
-
var
|
|
2581
|
+
var Mn = 3e3, Nn = 250, Pn = /* @__PURE__ */ new Set([
|
|
2529
2582
|
"GONE",
|
|
2530
2583
|
"NOT_FOUND",
|
|
2531
2584
|
"INVALID_URN",
|
|
2532
2585
|
"UNAUTHORIZED"
|
|
2533
2586
|
]);
|
|
2534
|
-
function
|
|
2535
|
-
return new
|
|
2587
|
+
function Fn(e) {
|
|
2588
|
+
return new In(e);
|
|
2536
2589
|
}
|
|
2537
|
-
var
|
|
2590
|
+
var In = class {
|
|
2538
2591
|
root;
|
|
2539
2592
|
video;
|
|
2540
2593
|
player;
|
|
@@ -2580,7 +2633,7 @@ var An = class {
|
|
|
2580
2633
|
scrubbing = !1;
|
|
2581
2634
|
offFns = [];
|
|
2582
2635
|
constructor(e) {
|
|
2583
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2636
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Mn, 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, An(this.doc, e.cspNonce), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
|
|
2584
2637
|
let t = (e, t, n) => {
|
|
2585
2638
|
let r = this.doc.createElement(e);
|
|
2586
2639
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2591,12 +2644,12 @@ var An = class {
|
|
|
2591
2644
|
"aria-label": r,
|
|
2592
2645
|
title: r
|
|
2593
2646
|
});
|
|
2594
|
-
return i.innerHTML =
|
|
2647
|
+
return i.innerHTML = Z(n), i;
|
|
2595
2648
|
};
|
|
2596
2649
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
2597
2650
|
type: "button",
|
|
2598
2651
|
"aria-label": "Play"
|
|
2599
|
-
}), this.center.innerHTML =
|
|
2652
|
+
}), this.center.innerHTML = Z("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
|
|
2600
2653
|
role: "slider",
|
|
2601
2654
|
"aria-label": "Seek",
|
|
2602
2655
|
"aria-valuemin": "0",
|
|
@@ -2614,7 +2667,7 @@ var An = class {
|
|
|
2614
2667
|
"aria-label": "Volume"
|
|
2615
2668
|
});
|
|
2616
2669
|
let a = t("div", "havik-vol");
|
|
2617
|
-
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML =
|
|
2670
|
+
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Z("liveDot");
|
|
2618
2671
|
let o = this.doc.createElement("span");
|
|
2619
2672
|
o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
|
|
2620
2673
|
let s = t("div", "havik-spacer");
|
|
@@ -2666,7 +2719,7 @@ var An = class {
|
|
|
2666
2719
|
let t = this.surfaceWasHidden;
|
|
2667
2720
|
this.tapTimer = setTimeout(() => {
|
|
2668
2721
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2669
|
-
},
|
|
2722
|
+
}, Nn);
|
|
2670
2723
|
}
|
|
2671
2724
|
toggleBar(e) {
|
|
2672
2725
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2698,12 +2751,12 @@ var An = class {
|
|
|
2698
2751
|
}
|
|
2699
2752
|
if (e === "preplay") {
|
|
2700
2753
|
let e = this.doc.createElement("button");
|
|
2701
|
-
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML =
|
|
2754
|
+
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Z("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
|
|
2702
2755
|
} else {
|
|
2703
2756
|
let r = this.doc.createElement("div");
|
|
2704
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2757
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Pn.has(this.lastError.code)) {
|
|
2705
2758
|
let e = this.doc.createElement("button");
|
|
2706
|
-
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${
|
|
2759
|
+
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Z("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
2707
2760
|
}
|
|
2708
2761
|
}
|
|
2709
2762
|
this.root.append(n), this.statusBox = n, this.show();
|
|
@@ -2742,7 +2795,7 @@ var An = class {
|
|
|
2742
2795
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2743
2796
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2744
2797
|
}
|
|
2745
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2798
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Ln(this.video.currentTime)} / ${Ln(this.video.duration)}`);
|
|
2746
2799
|
}
|
|
2747
2800
|
syncLive() {
|
|
2748
2801
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2792,17 +2845,17 @@ var An = class {
|
|
|
2792
2845
|
renderQualityMenu() {
|
|
2793
2846
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2794
2847
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2795
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2848
|
+
for (let n of e) this.menu.append(this.menuItem(Rn(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2796
2849
|
}
|
|
2797
2850
|
renderAudioMenu() {
|
|
2798
2851
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2799
2852
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2800
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2853
|
+
for (let t of e) this.menu.append(this.menuItem(zn(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2801
2854
|
}
|
|
2802
2855
|
renderCcMenu() {
|
|
2803
2856
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2804
2857
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2805
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2858
|
+
for (let t of e) this.menu.append(this.menuItem(Bn(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2806
2859
|
}
|
|
2807
2860
|
onTracksChanged() {
|
|
2808
2861
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2886,7 +2939,7 @@ var An = class {
|
|
|
2886
2939
|
}
|
|
2887
2940
|
}
|
|
2888
2941
|
setIcon(e, t) {
|
|
2889
|
-
e.innerHTML =
|
|
2942
|
+
e.innerHTML = Z(t);
|
|
2890
2943
|
}
|
|
2891
2944
|
destroy() {
|
|
2892
2945
|
this.hideTimer && clearTimeout(this.hideTimer), this.tapTimer && clearTimeout(this.tapTimer);
|
|
@@ -2903,41 +2956,41 @@ var An = class {
|
|
|
2903
2956
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2904
2957
|
}
|
|
2905
2958
|
};
|
|
2906
|
-
function
|
|
2959
|
+
function Ln(e) {
|
|
2907
2960
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2908
2961
|
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");
|
|
2909
2962
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2910
2963
|
}
|
|
2911
|
-
function
|
|
2964
|
+
function Rn(e) {
|
|
2912
2965
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2913
2966
|
}
|
|
2914
|
-
function
|
|
2967
|
+
function zn(e) {
|
|
2915
2968
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2916
2969
|
}
|
|
2917
|
-
function
|
|
2970
|
+
function Bn(e) {
|
|
2918
2971
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2919
2972
|
}
|
|
2920
2973
|
//#endregion
|
|
2921
2974
|
//#region src/managed/index.ts
|
|
2922
|
-
var
|
|
2923
|
-
function
|
|
2975
|
+
var Vn = 6e3, Q = 45e3, Hn = 2e3, Un = 3, Wn = 2e3, Gn = 48e4, Kn = "keySystemLicenseRequestFailed";
|
|
2976
|
+
function qn(e) {
|
|
2924
2977
|
if (e.env !== void 0 && e.baseUrl !== void 0) throw new n("INTERNAL", 0, `createPlayer: pass env OR baseUrl, not both (got env=${JSON.stringify(e.env)} and baseUrl=${JSON.stringify(e.baseUrl)})`);
|
|
2925
|
-
if (e.env !== void 0) return
|
|
2978
|
+
if (e.env !== void 0) return Ge(e.env);
|
|
2926
2979
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2927
2980
|
return e.baseUrl;
|
|
2928
2981
|
}
|
|
2929
|
-
async function
|
|
2982
|
+
async function Jn(e) {
|
|
2930
2983
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2931
|
-
let t =
|
|
2984
|
+
let t = qn(e);
|
|
2932
2985
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2933
2986
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2934
|
-
let r = new
|
|
2987
|
+
let r = new Yn({
|
|
2935
2988
|
...e,
|
|
2936
2989
|
baseUrl: t
|
|
2937
2990
|
});
|
|
2938
2991
|
return await r.start(), r;
|
|
2939
2992
|
}
|
|
2940
|
-
var
|
|
2993
|
+
var Yn = class {
|
|
2941
2994
|
opts;
|
|
2942
2995
|
abort = new AbortController();
|
|
2943
2996
|
listeners = {};
|
|
@@ -3028,7 +3081,7 @@ var Wn = class {
|
|
|
3028
3081
|
setTimeout(() => {
|
|
3029
3082
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3030
3083
|
phase: i ? "unavailable" : "tooEarly",
|
|
3031
|
-
retryInMs:
|
|
3084
|
+
retryInMs: Q,
|
|
3032
3085
|
attempt: 1,
|
|
3033
3086
|
elapsedMs: 0,
|
|
3034
3087
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3067,13 +3120,13 @@ var Wn = class {
|
|
|
3067
3120
|
!a && !p() && h();
|
|
3068
3121
|
}, e);
|
|
3069
3122
|
};
|
|
3070
|
-
_(
|
|
3123
|
+
_(Vn), this.armingSub = T({
|
|
3071
3124
|
eventsBaseUrl: t,
|
|
3072
3125
|
matchUrn: this.opts.matchUrn,
|
|
3073
3126
|
credential: this.opts.credential,
|
|
3074
|
-
onAlive: () => _(
|
|
3127
|
+
onAlive: () => _(Q),
|
|
3075
3128
|
onState: (e) => {
|
|
3076
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3129
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Hn);
|
|
3077
3130
|
},
|
|
3078
3131
|
onError: () => h()
|
|
3079
3132
|
});
|
|
@@ -3096,7 +3149,7 @@ var Wn = class {
|
|
|
3096
3149
|
let n = await s(this.opts.credential);
|
|
3097
3150
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3098
3151
|
this.setState("loading");
|
|
3099
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3152
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Ze(this.opts.video, (e) => {
|
|
3100
3153
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3101
3154
|
});
|
|
3102
3155
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3118,26 +3171,26 @@ var Wn = class {
|
|
|
3118
3171
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3119
3172
|
let i = e.analytics?.sid;
|
|
3120
3173
|
if (!i) return;
|
|
3121
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3174
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = gn(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3122
3175
|
if (!o) {
|
|
3123
3176
|
s && setTimeout(() => {
|
|
3124
3177
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3125
3178
|
}, 0);
|
|
3126
3179
|
return;
|
|
3127
3180
|
}
|
|
3128
|
-
let c = this.opts.video, l = new
|
|
3181
|
+
let c = this.opts.video, l = new _n({
|
|
3129
3182
|
endpoint: o,
|
|
3130
3183
|
sid: i,
|
|
3131
3184
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3132
|
-
sdkVersion:
|
|
3133
|
-
environment:
|
|
3185
|
+
sdkVersion: Cn,
|
|
3186
|
+
environment: xn(c),
|
|
3134
3187
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3135
3188
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3136
3189
|
onBlocked: (e) => setTimeout(() => {
|
|
3137
3190
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3138
3191
|
}, 0),
|
|
3139
3192
|
sample: () => {
|
|
3140
|
-
let e = this.engine?.getStats() ??
|
|
3193
|
+
let e = this.engine?.getStats() ?? Ke, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3141
3194
|
return {
|
|
3142
3195
|
...e,
|
|
3143
3196
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3151,7 +3204,7 @@ var Wn = class {
|
|
|
3151
3204
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3152
3205
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3153
3206
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3154
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3207
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Sn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3155
3208
|
}
|
|
3156
3209
|
currentPresentation() {
|
|
3157
3210
|
let e = this.opts.video;
|
|
@@ -3177,11 +3230,11 @@ var Wn = class {
|
|
|
3177
3230
|
emit: (e) => this.onEngineEvent(e),
|
|
3178
3231
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3179
3232
|
}, o = this.opts.engine ?? "auto";
|
|
3180
|
-
if (o === "native") return new
|
|
3181
|
-
if (o === "hls") return new
|
|
3182
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
3183
|
-
if (
|
|
3184
|
-
if (
|
|
3233
|
+
if (o === "native") return new W(a);
|
|
3234
|
+
if (o === "hls") return new Zt(a);
|
|
3235
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled && at() && H(this.opts.video)) return new W(a);
|
|
3236
|
+
if (_t()) return new Zt(a);
|
|
3237
|
+
if (H(this.opts.video)) return new W(a);
|
|
3185
3238
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3186
3239
|
}
|
|
3187
3240
|
onEngineEvent(e) {
|
|
@@ -3243,7 +3296,7 @@ var Wn = class {
|
|
|
3243
3296
|
r = 0, i = !1;
|
|
3244
3297
|
},
|
|
3245
3298
|
onError: () => {
|
|
3246
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
3299
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Un && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
|
|
3247
3300
|
}
|
|
3248
3301
|
});
|
|
3249
3302
|
}
|
|
@@ -3265,7 +3318,7 @@ var Wn = class {
|
|
|
3265
3318
|
scheduleRejoin(e) {
|
|
3266
3319
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3267
3320
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3268
|
-
}, Math.random() *
|
|
3321
|
+
}, Math.random() * Hn));
|
|
3269
3322
|
}
|
|
3270
3323
|
cancelRejoin() {
|
|
3271
3324
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3289,7 +3342,7 @@ var Wn = class {
|
|
|
3289
3342
|
}
|
|
3290
3343
|
t.controls = !1;
|
|
3291
3344
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3292
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3345
|
+
r && r.insertBefore(n, t), n.appendChild(t), En(n, this.opts.theme), this.container = n, this.controlBar = Fn({
|
|
3293
3346
|
root: n,
|
|
3294
3347
|
video: t,
|
|
3295
3348
|
player: this,
|
|
@@ -3320,7 +3373,7 @@ var Wn = class {
|
|
|
3320
3373
|
}
|
|
3321
3374
|
startStats() {
|
|
3322
3375
|
this.stopStats();
|
|
3323
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3376
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Wn);
|
|
3324
3377
|
this.statsTimer = setInterval(() => {
|
|
3325
3378
|
if (!this.engine) return;
|
|
3326
3379
|
let e = this.engine.getStats();
|
|
@@ -3331,14 +3384,14 @@ var Wn = class {
|
|
|
3331
3384
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3332
3385
|
}
|
|
3333
3386
|
isStaleLicenseDenial(e) {
|
|
3334
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3387
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Kn || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3335
3388
|
}
|
|
3336
3389
|
scheduleLicenseRefresh() {
|
|
3337
3390
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3338
3391
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3339
3392
|
document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3340
3393
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3341
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3394
|
+
let e = this.opts.licenseRefreshMs ?? Gn;
|
|
3342
3395
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3343
3396
|
}
|
|
3344
3397
|
stopRefresh() {
|
|
@@ -3394,7 +3447,7 @@ var Wn = class {
|
|
|
3394
3447
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3395
3448
|
}
|
|
3396
3449
|
getStats() {
|
|
3397
|
-
return this.engine?.getStats() ??
|
|
3450
|
+
return this.engine?.getStats() ?? Ke;
|
|
3398
3451
|
}
|
|
3399
3452
|
getQualityLevels() {
|
|
3400
3453
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3504,7 +3557,7 @@ function $(e) {
|
|
|
3504
3557
|
}
|
|
3505
3558
|
//#endregion
|
|
3506
3559
|
//#region src/embed/host.ts
|
|
3507
|
-
function
|
|
3560
|
+
function Xn(e) {
|
|
3508
3561
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3509
3562
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3510
3563
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3563,15 +3616,15 @@ function Gn(e) {
|
|
|
3563
3616
|
}
|
|
3564
3617
|
//#endregion
|
|
3565
3618
|
//#region src/embed/page.ts
|
|
3566
|
-
var
|
|
3567
|
-
function
|
|
3619
|
+
var Zn = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3620
|
+
function Qn(e) {
|
|
3568
3621
|
if (typeof e == "boolean") return e;
|
|
3569
3622
|
if (typeof e == "object" && e) {
|
|
3570
3623
|
let t = e.endpoint;
|
|
3571
3624
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3572
3625
|
}
|
|
3573
3626
|
}
|
|
3574
|
-
function
|
|
3627
|
+
function $n() {
|
|
3575
3628
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3576
3629
|
if (e) return {
|
|
3577
3630
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3581,7 +3634,7 @@ function Jn() {
|
|
|
3581
3634
|
autoplay: e.autoplay ?? !0,
|
|
3582
3635
|
muted: e.muted ?? !0,
|
|
3583
3636
|
waitForLive: e.waitForLive ?? !0,
|
|
3584
|
-
analytics:
|
|
3637
|
+
analytics: Qn(e.analytics)
|
|
3585
3638
|
};
|
|
3586
3639
|
let t = new URLSearchParams(location.search);
|
|
3587
3640
|
return {
|
|
@@ -3594,9 +3647,9 @@ function Jn() {
|
|
|
3594
3647
|
waitForLive: !0
|
|
3595
3648
|
};
|
|
3596
3649
|
}
|
|
3597
|
-
async function
|
|
3598
|
-
let e =
|
|
3599
|
-
|
|
3650
|
+
async function er() {
|
|
3651
|
+
let e = $n();
|
|
3652
|
+
nr();
|
|
3600
3653
|
let t = document.createElement("video");
|
|
3601
3654
|
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);
|
|
3602
3655
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3651,12 +3704,12 @@ async function Yn() {
|
|
|
3651
3704
|
code: e.code,
|
|
3652
3705
|
message: e.message
|
|
3653
3706
|
})), e.on("autoplayblocked", () => {
|
|
3654
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3707
|
+
i({ type: "oddin:autoplayblocked" }), tr(t, e);
|
|
3655
3708
|
});
|
|
3656
3709
|
}, s = async (r) => {
|
|
3657
3710
|
a?.destroy(), a = null;
|
|
3658
3711
|
try {
|
|
3659
|
-
let n = await
|
|
3712
|
+
let n = await Jn({
|
|
3660
3713
|
video: t,
|
|
3661
3714
|
baseUrl: e.baseUrl,
|
|
3662
3715
|
matchUrn: r,
|
|
@@ -3718,7 +3771,7 @@ async function Yn() {
|
|
|
3718
3771
|
a?.retry();
|
|
3719
3772
|
break;
|
|
3720
3773
|
case "oddin:load":
|
|
3721
|
-
typeof e.matchUrn == "string" &&
|
|
3774
|
+
typeof e.matchUrn == "string" && Zn.test(e.matchUrn) && s(e.matchUrn);
|
|
3722
3775
|
break;
|
|
3723
3776
|
case "oddin:destroy": c();
|
|
3724
3777
|
}
|
|
@@ -3730,18 +3783,18 @@ async function Yn() {
|
|
|
3730
3783
|
protocol: 1
|
|
3731
3784
|
});
|
|
3732
3785
|
}
|
|
3733
|
-
function
|
|
3786
|
+
function tr(e, t) {
|
|
3734
3787
|
if (document.getElementById("havik-tap")) return;
|
|
3735
3788
|
let n = document.createElement("button");
|
|
3736
3789
|
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", () => {
|
|
3737
3790
|
n.remove(), t.play();
|
|
3738
3791
|
}), document.body.appendChild(n);
|
|
3739
3792
|
}
|
|
3740
|
-
function
|
|
3793
|
+
function nr() {
|
|
3741
3794
|
let e = document.createElement("style");
|
|
3742
3795
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3743
3796
|
}
|
|
3744
3797
|
//#endregion
|
|
3745
|
-
export {
|
|
3798
|
+
export { wn as ODDIN_THEME, n as PlaybackError, En as applyTheme, Ge as baseUrlForEnv, er as bootEmbed, Te as clearDeviceId, Jn as createPlayer, E as deriveEventsBaseUrl, Ve as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, k as getDeviceId, Ue as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, Xn as mountEmbed, v as pollToLive, b as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
|
|
3746
3799
|
|
|
3747
3800
|
//# sourceMappingURL=index.js.map
|