@oddin-gg/havik-player 2.23.4 → 2.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/havik-player.global.js +15 -15
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +414 -341
- package/dist/index.js.map +1 -1
- package/docs/API.md +1 -0
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -700,19 +700,19 @@ function Ve(e, t) {
|
|
|
700
700
|
function N() {
|
|
701
701
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
702
702
|
}
|
|
703
|
-
var
|
|
704
|
-
function
|
|
703
|
+
var He = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
704
|
+
function Ue(e) {
|
|
705
705
|
return e.startsWith("com.widevine");
|
|
706
706
|
}
|
|
707
|
-
function
|
|
708
|
-
if (!
|
|
707
|
+
function P(e, t) {
|
|
708
|
+
if (!Ue(e)) return t;
|
|
709
709
|
let n = (e, t) => {
|
|
710
710
|
let n = e.videoCapabilities;
|
|
711
711
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
712
|
-
let n =
|
|
713
|
-
return n === -1 ||
|
|
712
|
+
let n = He.indexOf(e.robustness);
|
|
713
|
+
return n === -1 || He.indexOf(t) > n;
|
|
714
714
|
});
|
|
715
|
-
}, r =
|
|
715
|
+
}, r = He.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
716
716
|
...t,
|
|
717
717
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
718
718
|
...t,
|
|
@@ -721,53 +721,53 @@ function F(e, t) {
|
|
|
721
721
|
})));
|
|
722
722
|
return [...t, ...r];
|
|
723
723
|
}
|
|
724
|
-
function
|
|
725
|
-
return (t, n) => N() ? navigator.requestMediaKeySystemAccess(t,
|
|
724
|
+
function We(e) {
|
|
725
|
+
return (t, n) => N() ? navigator.requestMediaKeySystemAccess(t, P(t, n)).then((t) => ({
|
|
726
726
|
keySystem: t.keySystem,
|
|
727
727
|
getConfiguration: () => t.getConfiguration(),
|
|
728
728
|
createMediaKeys: () => Ve(e, t)
|
|
729
729
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
730
730
|
}
|
|
731
|
-
var
|
|
731
|
+
var F = {
|
|
732
732
|
video: "SW_SECURE_DECODE",
|
|
733
733
|
audio: "SW_SECURE_CRYPTO",
|
|
734
734
|
scheme: "cbcs"
|
|
735
735
|
};
|
|
736
|
-
function
|
|
736
|
+
function Ge(e) {
|
|
737
737
|
if (!N()) return;
|
|
738
738
|
let t = (e, t) => ({
|
|
739
739
|
contentType: e,
|
|
740
740
|
robustness: t,
|
|
741
|
-
encryptionScheme:
|
|
741
|
+
encryptionScheme: F.scheme
|
|
742
742
|
});
|
|
743
|
-
|
|
743
|
+
We(e)("com.widevine.alpha", [{
|
|
744
744
|
initDataTypes: ["cenc"],
|
|
745
745
|
distinctiveIdentifier: "optional",
|
|
746
746
|
persistentState: "optional",
|
|
747
747
|
sessionTypes: ["temporary"],
|
|
748
|
-
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"",
|
|
749
|
-
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"",
|
|
748
|
+
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", F.audio)],
|
|
749
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", F.video)]
|
|
750
750
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
751
751
|
}
|
|
752
|
-
function
|
|
753
|
-
let t =
|
|
752
|
+
function I(e) {
|
|
753
|
+
let t = L(e);
|
|
754
754
|
if (/^avc[13]/.test(t)) return "avc";
|
|
755
755
|
if (/^(hvc1|hev1)/.test(t)) return "hevc";
|
|
756
756
|
if (/^(dvh1|dvhe)/.test(t)) return "dv";
|
|
757
757
|
if (t.startsWith("av01")) return "av1";
|
|
758
758
|
if (/^vp0?9/.test(t)) return "vp9";
|
|
759
759
|
}
|
|
760
|
-
function
|
|
760
|
+
function L(e) {
|
|
761
761
|
return (e ?? "").trim().toLowerCase();
|
|
762
762
|
}
|
|
763
|
-
var
|
|
763
|
+
var Ke = {
|
|
764
764
|
hevc: "hvc1.1.6.L93.90",
|
|
765
765
|
dv: "dvh1.05.06",
|
|
766
766
|
av1: "av01.0.05M.08",
|
|
767
767
|
vp9: "vp09.00.10.08"
|
|
768
|
-
},
|
|
769
|
-
function
|
|
770
|
-
let t =
|
|
768
|
+
}, qe = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
|
|
769
|
+
function Je(e) {
|
|
770
|
+
let t = L(e), n = qe.get(t);
|
|
771
771
|
if (n) return n;
|
|
772
772
|
let r = {
|
|
773
773
|
initDataTypes: ["cenc"],
|
|
@@ -776,32 +776,32 @@ function qe(e) {
|
|
|
776
776
|
sessionTypes: ["temporary"],
|
|
777
777
|
videoCapabilities: [{
|
|
778
778
|
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
779
|
-
robustness:
|
|
780
|
-
encryptionScheme:
|
|
779
|
+
robustness: F.video,
|
|
780
|
+
encryptionScheme: F.scheme
|
|
781
781
|
}]
|
|
782
782
|
}, i = (async () => {
|
|
783
783
|
try {
|
|
784
|
-
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha",
|
|
784
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", P("com.widevine.alpha", [r])), !0;
|
|
785
785
|
} catch {
|
|
786
786
|
return !1;
|
|
787
787
|
}
|
|
788
|
-
})().then((e) => (
|
|
789
|
-
return
|
|
788
|
+
})().then((e) => (R.set(t, e), e));
|
|
789
|
+
return qe.set(t, i), i;
|
|
790
790
|
}
|
|
791
|
-
function
|
|
792
|
-
if (N()) for (let e of Object.values(
|
|
791
|
+
function Ye() {
|
|
792
|
+
if (N()) for (let e of Object.values(Ke)) Je(e);
|
|
793
793
|
}
|
|
794
|
-
function
|
|
795
|
-
let t =
|
|
796
|
-
if (t) return t === "avc" ? !0 :
|
|
794
|
+
function Xe(e) {
|
|
795
|
+
let t = I(e);
|
|
796
|
+
if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(Ke[t]));
|
|
797
797
|
}
|
|
798
798
|
//#endregion
|
|
799
799
|
//#region src/core/drm/support.ts
|
|
800
|
-
var
|
|
800
|
+
var Ze = 5e3, Qe = "video/mp4; codecs=\"avc1.42E01E\"", $e = "audio/mp4; codecs=\"mp4a.40.2\"", et = {
|
|
801
801
|
widevine: ["com.widevine.alpha"],
|
|
802
802
|
fairplay: ["com.apple.fps"]
|
|
803
803
|
};
|
|
804
|
-
function
|
|
804
|
+
function tt(e) {
|
|
805
805
|
return e === "fairplay" ? [{
|
|
806
806
|
initDataTypes: [
|
|
807
807
|
"sinf",
|
|
@@ -809,30 +809,30 @@ function et(e) {
|
|
|
809
809
|
"cenc"
|
|
810
810
|
],
|
|
811
811
|
videoCapabilities: [{
|
|
812
|
-
contentType:
|
|
812
|
+
contentType: Qe,
|
|
813
813
|
robustness: "",
|
|
814
814
|
encryptionScheme: "cbcs"
|
|
815
815
|
}],
|
|
816
816
|
audioCapabilities: [{
|
|
817
|
-
contentType:
|
|
817
|
+
contentType: $e,
|
|
818
818
|
robustness: "",
|
|
819
819
|
encryptionScheme: "cbcs"
|
|
820
820
|
}]
|
|
821
|
-
}] :
|
|
821
|
+
}] : P("com.widevine.alpha", [{
|
|
822
822
|
initDataTypes: ["cenc"],
|
|
823
823
|
videoCapabilities: [{
|
|
824
|
-
contentType:
|
|
825
|
-
robustness:
|
|
826
|
-
encryptionScheme:
|
|
824
|
+
contentType: Qe,
|
|
825
|
+
robustness: F.video,
|
|
826
|
+
encryptionScheme: F.scheme
|
|
827
827
|
}],
|
|
828
828
|
audioCapabilities: [{
|
|
829
|
-
contentType:
|
|
830
|
-
robustness:
|
|
831
|
-
encryptionScheme:
|
|
829
|
+
contentType: $e,
|
|
830
|
+
robustness: F.audio,
|
|
831
|
+
encryptionScheme: F.scheme
|
|
832
832
|
}]
|
|
833
833
|
}]);
|
|
834
834
|
}
|
|
835
|
-
function
|
|
835
|
+
function nt(e, t) {
|
|
836
836
|
return new Promise((n, r) => {
|
|
837
837
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
838
838
|
e.then((e) => {
|
|
@@ -842,8 +842,8 @@ function tt(e, t) {
|
|
|
842
842
|
});
|
|
843
843
|
});
|
|
844
844
|
}
|
|
845
|
-
async function
|
|
846
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
845
|
+
async function rt(e = {}) {
|
|
846
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ze, r = {};
|
|
847
847
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
848
848
|
verdict: "insecure-context",
|
|
849
849
|
detail: r
|
|
@@ -855,7 +855,7 @@ async function nt(e = {}) {
|
|
|
855
855
|
};
|
|
856
856
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
857
857
|
for (let e of t) {
|
|
858
|
-
let t =
|
|
858
|
+
let t = et[e];
|
|
859
859
|
if (!t) {
|
|
860
860
|
r[e] = "unknown system";
|
|
861
861
|
continue;
|
|
@@ -866,7 +866,7 @@ async function nt(e = {}) {
|
|
|
866
866
|
break;
|
|
867
867
|
}
|
|
868
868
|
try {
|
|
869
|
-
return await
|
|
869
|
+
return await nt((await nt(i(n, tt(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
870
870
|
verdict: "supported",
|
|
871
871
|
system: e,
|
|
872
872
|
detail: r
|
|
@@ -890,49 +890,49 @@ async function nt(e = {}) {
|
|
|
890
890
|
}
|
|
891
891
|
//#endregion
|
|
892
892
|
//#region src/core/manifest.ts
|
|
893
|
-
var
|
|
894
|
-
function
|
|
895
|
-
return
|
|
893
|
+
var it = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
894
|
+
function at(e) {
|
|
895
|
+
return it.test(e);
|
|
896
896
|
}
|
|
897
897
|
//#endregion
|
|
898
898
|
//#region src/core/env.ts
|
|
899
|
-
var
|
|
899
|
+
var ot = {
|
|
900
900
|
integration: "https://feed-dev.oddin-video.gg",
|
|
901
901
|
production: "https://feed.oddin-video.gg"
|
|
902
902
|
};
|
|
903
|
-
function
|
|
904
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
903
|
+
function st(e) {
|
|
904
|
+
let t = Object.prototype.hasOwnProperty.call(ot, e) ? ot[e] : void 0;
|
|
905
905
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
906
906
|
return t;
|
|
907
907
|
}
|
|
908
908
|
//#endregion
|
|
909
909
|
//#region src/core/stats.ts
|
|
910
|
-
var
|
|
911
|
-
function
|
|
910
|
+
var ct = { droppedFrames: 0 };
|
|
911
|
+
function lt(e) {
|
|
912
912
|
try {
|
|
913
913
|
return new URL(e).host;
|
|
914
914
|
} catch {
|
|
915
915
|
return "";
|
|
916
916
|
}
|
|
917
917
|
}
|
|
918
|
-
var
|
|
919
|
-
function
|
|
918
|
+
var ut = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
919
|
+
function dt(e) {
|
|
920
920
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
921
921
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
922
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
923
|
-
let e =
|
|
922
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || ut.test(i.name)) && i.startTime >= n) {
|
|
923
|
+
let e = lt(i.name);
|
|
924
924
|
e && (t = e, n = i.startTime);
|
|
925
925
|
}
|
|
926
926
|
return t;
|
|
927
927
|
}
|
|
928
|
-
function
|
|
928
|
+
function z(e) {
|
|
929
929
|
let t = e.getVideoPlaybackQuality?.();
|
|
930
930
|
return {
|
|
931
931
|
dropped: t?.droppedVideoFrames ?? 0,
|
|
932
932
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
933
933
|
};
|
|
934
934
|
}
|
|
935
|
-
var
|
|
935
|
+
var ft = class {
|
|
936
936
|
video;
|
|
937
937
|
baseFrames = 0;
|
|
938
938
|
baseDropped = 0;
|
|
@@ -942,7 +942,7 @@ var dt = class {
|
|
|
942
942
|
this.video = e;
|
|
943
943
|
}
|
|
944
944
|
read() {
|
|
945
|
-
let e =
|
|
945
|
+
let e = z(this.video);
|
|
946
946
|
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, {
|
|
947
947
|
dropped: this.baseDropped + e.dropped,
|
|
948
948
|
totalFrames: this.baseFrames + e.totalFrames
|
|
@@ -955,7 +955,7 @@ var dt = class {
|
|
|
955
955
|
};
|
|
956
956
|
}
|
|
957
957
|
};
|
|
958
|
-
function
|
|
958
|
+
function pt(e, t) {
|
|
959
959
|
let n = [
|
|
960
960
|
["playing", () => t("playing")],
|
|
961
961
|
["waiting", () => t("buffering")],
|
|
@@ -972,8 +972,8 @@ function ft(e, t) {
|
|
|
972
972
|
}
|
|
973
973
|
//#endregion
|
|
974
974
|
//#region src/core/engine/native.ts
|
|
975
|
-
var
|
|
976
|
-
function
|
|
975
|
+
var mt = 2e3, ht = 3, B = 500, gt = 6e3, _t = .25, vt = 250, yt = .05, bt = 4, xt = 12e3, St = .25, Ct = 1e3;
|
|
976
|
+
function wt(e) {
|
|
977
977
|
try {
|
|
978
978
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
979
979
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -981,20 +981,20 @@ function Ct(e) {
|
|
|
981
981
|
return;
|
|
982
982
|
}
|
|
983
983
|
}
|
|
984
|
-
function
|
|
984
|
+
function V(e) {
|
|
985
985
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
986
986
|
}
|
|
987
|
-
function
|
|
987
|
+
function H() {
|
|
988
988
|
if (typeof window > "u") return !1;
|
|
989
989
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
990
990
|
return e || t;
|
|
991
991
|
}
|
|
992
|
-
function
|
|
993
|
-
if (typeof navigator > "u" || !
|
|
992
|
+
function Tt() {
|
|
993
|
+
if (typeof navigator > "u" || !H()) return !1;
|
|
994
994
|
let e = navigator.userAgent ?? "";
|
|
995
995
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
996
996
|
}
|
|
997
|
-
var
|
|
997
|
+
var U = class {
|
|
998
998
|
name = "native";
|
|
999
999
|
deps;
|
|
1000
1000
|
onLoaded;
|
|
@@ -1024,7 +1024,7 @@ var W = class {
|
|
|
1024
1024
|
frameCounter;
|
|
1025
1025
|
detachFrames = null;
|
|
1026
1026
|
constructor(e) {
|
|
1027
|
-
this.deps = e, this.frameCounter = new
|
|
1027
|
+
this.deps = e, this.frameCounter = new ft(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
|
|
1028
1028
|
}
|
|
1029
1029
|
async load() {
|
|
1030
1030
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1045,7 +1045,7 @@ var W = class {
|
|
|
1045
1045
|
type: "error",
|
|
1046
1046
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
1047
1047
|
fatal: !0
|
|
1048
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
1048
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Dt(t.manifestUrl, t.analytics?.sid), e.load();
|
|
1049
1049
|
}
|
|
1050
1050
|
startLoad() {
|
|
1051
1051
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -1073,7 +1073,7 @@ var W = class {
|
|
|
1073
1073
|
};
|
|
1074
1074
|
this.onEncrypted = (n) => {
|
|
1075
1075
|
let a = n;
|
|
1076
|
-
a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
1076
|
+
a.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = wt(a.initData), (async () => {
|
|
1077
1077
|
try {
|
|
1078
1078
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
1079
1079
|
initDataTypes: [a.initDataType],
|
|
@@ -1173,10 +1173,10 @@ var W = class {
|
|
|
1173
1173
|
droppedFrames: t.dropped,
|
|
1174
1174
|
decodedFrames: t.totalFrames
|
|
1175
1175
|
};
|
|
1176
|
-
if (this.cdnHost ||=
|
|
1176
|
+
if (this.cdnHost ||= dt(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1177
1177
|
n.isLive = !0;
|
|
1178
1178
|
let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
|
|
1179
|
-
Number.isFinite(r) && (n.atLiveEdge = r <=
|
|
1179
|
+
Number.isFinite(r) && (n.atLiveEdge = r <= bt, !e.paused && r >= 0 && (n.latencySeconds = r));
|
|
1180
1180
|
} else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
|
|
1181
1181
|
return n;
|
|
1182
1182
|
}
|
|
@@ -1188,30 +1188,30 @@ var W = class {
|
|
|
1188
1188
|
}
|
|
1189
1189
|
watchRefocus() {
|
|
1190
1190
|
this.deps.snapToLiveOnRefocus === !1 || typeof document > "u" || this.onVisibility || (this.onVisibility = () => {
|
|
1191
|
-
let e =
|
|
1191
|
+
let e = W();
|
|
1192
1192
|
if (document.visibilityState === "hidden") {
|
|
1193
1193
|
this.hiddenSince = e, this.cancelRefocus();
|
|
1194
1194
|
return;
|
|
1195
1195
|
}
|
|
1196
1196
|
let t = this.hiddenSince;
|
|
1197
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1197
|
+
this.hiddenSince = null, t != null && e - t >= mt && this.armRefocus();
|
|
1198
1198
|
}, this.onPageShow = (e) => {
|
|
1199
1199
|
e.persisted && this.armRefocus();
|
|
1200
1200
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
1201
1201
|
}
|
|
1202
1202
|
armRefocus() {
|
|
1203
1203
|
if (this.cancelRefocus(), Number.isFinite(this.deps.video.duration)) return;
|
|
1204
|
-
let e = this.liveEnd(), t =
|
|
1204
|
+
let e = this.liveEnd(), t = W, n = t(), r = 0, i = () => {
|
|
1205
1205
|
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1206
|
-
r +=
|
|
1207
|
-
let a = this.liveEnd(), o = a != null && (e == null || a >= e +
|
|
1206
|
+
r += B;
|
|
1207
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + _t), s = Math.max(r, t() - n) >= gt;
|
|
1208
1208
|
if (o || s && a != null) {
|
|
1209
1209
|
this.snapToLive();
|
|
1210
1210
|
return;
|
|
1211
1211
|
}
|
|
1212
|
-
this.refocusTimer = setTimeout(i,
|
|
1212
|
+
this.refocusTimer = setTimeout(i, B);
|
|
1213
1213
|
};
|
|
1214
|
-
this.refocusTimer = setTimeout(i,
|
|
1214
|
+
this.refocusTimer = setTimeout(i, B);
|
|
1215
1215
|
}
|
|
1216
1216
|
cancelRefocus() {
|
|
1217
1217
|
this.refocusTimer != null && clearTimeout(this.refocusTimer), this.refocusTimer = null;
|
|
@@ -1224,24 +1224,24 @@ var W = class {
|
|
|
1224
1224
|
}, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
|
|
1225
1225
|
if (e.duration !== Infinity) return;
|
|
1226
1226
|
this.checkEndStale();
|
|
1227
|
-
let t =
|
|
1228
|
-
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >=
|
|
1229
|
-
},
|
|
1227
|
+
let t = Et(e, e.currentTime);
|
|
1228
|
+
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= yt) && (this.bufferedAdvancedAt = W()), this.lastBufferedEnd = t);
|
|
1229
|
+
}, vt);
|
|
1230
1230
|
}
|
|
1231
1231
|
checkEndStale() {
|
|
1232
1232
|
if (this.endedEmitted) return;
|
|
1233
|
-
let e =
|
|
1233
|
+
let e = W(), t = this.lastTickAt == null ? 0 : e - this.lastTickAt;
|
|
1234
1234
|
this.lastTickAt = e;
|
|
1235
1235
|
let n = this.liveEnd();
|
|
1236
1236
|
if (n == null) return;
|
|
1237
|
-
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >=
|
|
1237
|
+
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= St;
|
|
1238
1238
|
this.lastSeekableEnd = n;
|
|
1239
1239
|
let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
|
|
1240
|
-
if (r || t >
|
|
1240
|
+
if (r || t > Ct || a || i.paused) {
|
|
1241
1241
|
this.edgeStampedAt = e;
|
|
1242
1242
|
return;
|
|
1243
1243
|
}
|
|
1244
|
-
e - (this.edgeStampedAt ?? e) >
|
|
1244
|
+
e - (this.edgeStampedAt ?? e) > xt && (this.endedEmitted = !0, this.deps.emit({
|
|
1245
1245
|
type: "ended",
|
|
1246
1246
|
reason: "stalled"
|
|
1247
1247
|
}));
|
|
@@ -1255,9 +1255,9 @@ var W = class {
|
|
|
1255
1255
|
liveEdgeEstimate() {
|
|
1256
1256
|
let e = this.deps.video;
|
|
1257
1257
|
if (e.duration !== Infinity) return null;
|
|
1258
|
-
let t = this.liveEnd(), n =
|
|
1258
|
+
let t = this.liveEnd(), n = Et(e, e.currentTime) ?? this.lastBufferedEnd;
|
|
1259
1259
|
if (n != null) {
|
|
1260
|
-
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (
|
|
1260
|
+
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (W() - e) / 1e3));
|
|
1261
1261
|
(t == null || r > t) && (t = r);
|
|
1262
1262
|
}
|
|
1263
1263
|
return t != null && Number.isFinite(t) ? t : null;
|
|
@@ -1271,7 +1271,7 @@ var W = class {
|
|
|
1271
1271
|
snapToLive() {
|
|
1272
1272
|
let e = this.deps.video, t = this.liveEnd();
|
|
1273
1273
|
if (t == null) return;
|
|
1274
|
-
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t -
|
|
1274
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - ht, r);
|
|
1275
1275
|
try {
|
|
1276
1276
|
e.currentTime = i;
|
|
1277
1277
|
} catch {}
|
|
@@ -1289,10 +1289,10 @@ var W = class {
|
|
|
1289
1289
|
} catch {}
|
|
1290
1290
|
}
|
|
1291
1291
|
};
|
|
1292
|
-
function
|
|
1292
|
+
function W() {
|
|
1293
1293
|
return typeof performance < "u" ? performance.now() : Date.now();
|
|
1294
1294
|
}
|
|
1295
|
-
function
|
|
1295
|
+
function Et(e, t) {
|
|
1296
1296
|
let n = e.buffered;
|
|
1297
1297
|
if (!n || !Number.isFinite(t)) return null;
|
|
1298
1298
|
for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
|
|
@@ -1301,12 +1301,12 @@ function Tt(e, t) {
|
|
|
1301
1301
|
}
|
|
1302
1302
|
return null;
|
|
1303
1303
|
}
|
|
1304
|
-
function
|
|
1304
|
+
function Dt(e, t) {
|
|
1305
1305
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1306
1306
|
}
|
|
1307
1307
|
//#endregion
|
|
1308
1308
|
//#region src/core/drm/signedUrl.ts
|
|
1309
|
-
function
|
|
1309
|
+
function G(e, t = Date.now()) {
|
|
1310
1310
|
if (!e) return !1;
|
|
1311
1311
|
let n;
|
|
1312
1312
|
try {
|
|
@@ -1318,13 +1318,13 @@ function K(e, t = Date.now()) {
|
|
|
1318
1318
|
}
|
|
1319
1319
|
//#endregion
|
|
1320
1320
|
//#region src/core/drm/xhrBody.ts
|
|
1321
|
-
var
|
|
1322
|
-
function
|
|
1321
|
+
var Ot = 4096;
|
|
1322
|
+
function kt(e) {
|
|
1323
1323
|
if (!e || typeof e != "object") return;
|
|
1324
1324
|
let { response: t } = e;
|
|
1325
1325
|
if (typeof t == "string") return t;
|
|
1326
1326
|
let n;
|
|
1327
|
-
if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength >
|
|
1327
|
+
if (Object.prototype.toString.call(t) === "[object ArrayBuffer]" ? n = new Uint8Array(t) : ArrayBuffer.isView(t) && (n = new Uint8Array(t.buffer, t.byteOffset, t.byteLength)), !(!n || n.byteLength === 0 || n.byteLength > Ot)) try {
|
|
1328
1328
|
return new TextDecoder().decode(n);
|
|
1329
1329
|
} catch {
|
|
1330
1330
|
return;
|
|
@@ -1332,8 +1332,8 @@ function Ot(e) {
|
|
|
1332
1332
|
}
|
|
1333
1333
|
//#endregion
|
|
1334
1334
|
//#region src/core/engine/prefetch.ts
|
|
1335
|
-
var
|
|
1336
|
-
function
|
|
1335
|
+
var At = 15e3, jt = 5e3, Mt = 6, Nt = 4e3, Pt = 2;
|
|
1336
|
+
function K(e) {
|
|
1337
1337
|
try {
|
|
1338
1338
|
let t = new URL(e);
|
|
1339
1339
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1341,17 +1341,23 @@ function Mt(e) {
|
|
|
1341
1341
|
return e;
|
|
1342
1342
|
}
|
|
1343
1343
|
}
|
|
1344
|
-
var
|
|
1344
|
+
var Ft = class {
|
|
1345
1345
|
cmcd;
|
|
1346
1346
|
entries = /* @__PURE__ */ new Map();
|
|
1347
1347
|
keyed = /* @__PURE__ */ new Set();
|
|
1348
1348
|
perTrack = /* @__PURE__ */ new Map();
|
|
1349
|
+
hints = /* @__PURE__ */ new Map();
|
|
1349
1350
|
stats = {
|
|
1350
1351
|
started: 0,
|
|
1351
1352
|
served: 0,
|
|
1352
1353
|
missed: 0,
|
|
1353
1354
|
failed: 0,
|
|
1354
|
-
expired: 0
|
|
1355
|
+
expired: 0,
|
|
1356
|
+
hintStarted: 0,
|
|
1357
|
+
hintServed: 0,
|
|
1358
|
+
hintFailed: 0,
|
|
1359
|
+
hintExpired: 0,
|
|
1360
|
+
hintDropped: 0
|
|
1355
1361
|
};
|
|
1356
1362
|
constructor(e = {}) {
|
|
1357
1363
|
this.cmcd = e;
|
|
@@ -1364,32 +1370,58 @@ var Nt = class {
|
|
|
1364
1370
|
}
|
|
1365
1371
|
prefetch(e, t, n) {
|
|
1366
1372
|
if (!this.isActive(t)) return;
|
|
1367
|
-
let r =
|
|
1373
|
+
let r = K(e);
|
|
1368
1374
|
if (this.entries.has(r)) return;
|
|
1369
1375
|
let i = this.perTrack.get(t) ?? 0;
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1376
|
+
i >= Mt || (this.perTrack.set(t, i + 1), this.start(r, this.withCmcd(e, t, n), !1, At), this.stats.started += 1);
|
|
1377
|
+
}
|
|
1378
|
+
prefetchHint(e, t) {
|
|
1379
|
+
let n = K(e);
|
|
1380
|
+
if (this.entries.has(n)) return;
|
|
1381
|
+
let r = this.hints.get(t) ?? [];
|
|
1382
|
+
for (; r.length >= Pt;) {
|
|
1383
|
+
let e = r.shift();
|
|
1384
|
+
e !== void 0 && this.drop(e) && (this.stats.hintDropped += 1);
|
|
1385
|
+
}
|
|
1386
|
+
r.push(n), this.hints.set(t, r), this.start(n, this.withCmcd(e, t, "media"), !0, Nt), this.stats.hintStarted += 1;
|
|
1387
|
+
}
|
|
1388
|
+
dropHints(e) {
|
|
1389
|
+
for (let t of this.hints.get(e) ?? []) this.drop(t) && (this.stats.hintDropped += 1);
|
|
1390
|
+
this.hints.delete(e);
|
|
1391
|
+
}
|
|
1392
|
+
drop(e) {
|
|
1393
|
+
let t = this.entries.get(e);
|
|
1394
|
+
return t ? (this.entries.delete(e), t.abort.abort(), !0) : !1;
|
|
1395
|
+
}
|
|
1396
|
+
start(e, t, n, r) {
|
|
1397
|
+
let i = new AbortController(), a = {
|
|
1373
1398
|
started: performance.now(),
|
|
1374
1399
|
first: 0,
|
|
1400
|
+
end: 0,
|
|
1401
|
+
hint: n,
|
|
1402
|
+
headers: Promise.resolve(),
|
|
1375
1403
|
bytes: Promise.resolve(null),
|
|
1376
|
-
abort:
|
|
1377
|
-
};
|
|
1378
|
-
|
|
1404
|
+
abort: i
|
|
1405
|
+
}, o = () => {};
|
|
1406
|
+
a.headers = new Promise((e) => o = e), a.bytes = fetch(t, {
|
|
1379
1407
|
credentials: "omit",
|
|
1380
1408
|
mode: "cors",
|
|
1381
|
-
signal:
|
|
1382
|
-
}).then(async (e) =>
|
|
1383
|
-
|
|
1384
|
-
|
|
1409
|
+
signal: i.signal
|
|
1410
|
+
}).then(async (e) => {
|
|
1411
|
+
if (a.first = performance.now(), o(), !e.ok) return null;
|
|
1412
|
+
let t = await e.arrayBuffer();
|
|
1413
|
+
return a.end = performance.now(), t;
|
|
1414
|
+
}).catch(() => null).finally(o), this.entries.set(e, a), setTimeout(() => {
|
|
1415
|
+
this.entries.get(e) === a && (this.entries.delete(e), i.abort(), n ? this.stats.hintExpired += 1 : this.stats.expired += 1);
|
|
1416
|
+
}, r);
|
|
1385
1417
|
}
|
|
1386
1418
|
take(e) {
|
|
1387
|
-
let t =
|
|
1419
|
+
let t = K(e), n = this.entries.get(t);
|
|
1388
1420
|
return n && this.entries.delete(t), n;
|
|
1389
1421
|
}
|
|
1390
1422
|
destroy() {
|
|
1391
1423
|
for (let e of this.entries.values()) e.abort.abort();
|
|
1392
|
-
this.entries.clear();
|
|
1424
|
+
this.entries.clear(), this.hints.clear();
|
|
1393
1425
|
}
|
|
1394
1426
|
withCmcd(e, t, n) {
|
|
1395
1427
|
let { sessionId: r, contentId: i } = this.cmcd;
|
|
@@ -1404,40 +1436,51 @@ var Nt = class {
|
|
|
1404
1436
|
}
|
|
1405
1437
|
}
|
|
1406
1438
|
};
|
|
1407
|
-
function
|
|
1439
|
+
function It(t) {
|
|
1408
1440
|
let n = e.DefaultConfig?.loader;
|
|
1409
1441
|
if (typeof n != "function") return;
|
|
1410
1442
|
class r extends n {
|
|
1411
1443
|
served = !1;
|
|
1412
1444
|
cancelled = !1;
|
|
1413
|
-
|
|
1445
|
+
entry;
|
|
1446
|
+
stats = Lt();
|
|
1414
1447
|
load(e, n, r) {
|
|
1415
1448
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1416
1449
|
if (!i) {
|
|
1417
1450
|
super.load(e, n, r);
|
|
1418
1451
|
return;
|
|
1419
1452
|
}
|
|
1420
|
-
this.served = !0;
|
|
1421
|
-
let a = performance.now(), o =
|
|
1422
|
-
|
|
1423
|
-
},
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1453
|
+
this.served = !0, this.entry = i;
|
|
1454
|
+
let a = performance.now(), o = () => {
|
|
1455
|
+
i.hint ? t.stats.hintFailed += 1 : t.stats.failed += 1;
|
|
1456
|
+
}, s = () => {
|
|
1457
|
+
!this.cancelled && this.served && (i.abort.abort(), o(), this.served = !1, this.entry = void 0, super.load(e, n, r));
|
|
1458
|
+
}, c = n?.loadPolicy, l = c?.maxTimeToFirstByteMs || jt, u = setTimeout(s, l);
|
|
1459
|
+
i.headers.then(() => {
|
|
1460
|
+
clearTimeout(u);
|
|
1461
|
+
let e = c?.maxLoadTimeMs;
|
|
1462
|
+
e && (u = setTimeout(s, Math.max(0, e - (performance.now() - a))));
|
|
1463
|
+
}), i.bytes.then((s) => {
|
|
1464
|
+
if (clearTimeout(u), this.cancelled || !this.served) return;
|
|
1465
|
+
if (!s) {
|
|
1466
|
+
o(), this.served = !1, super.load(e, n, r);
|
|
1428
1467
|
return;
|
|
1429
1468
|
}
|
|
1430
|
-
t.stats.served += 1;
|
|
1431
1469
|
let c = this.stats;
|
|
1432
|
-
|
|
1470
|
+
if (i.hint) {
|
|
1471
|
+
t.stats.hintServed += 1;
|
|
1472
|
+
let e = performance.now(), n = Math.max(0, (i.end || e) - (i.first || e)), r = Math.max(0, (i.first || e) - a);
|
|
1473
|
+
c.loading.end = e, c.loading.first = e - n, c.loading.start = c.loading.first - r;
|
|
1474
|
+
} else t.stats.served += 1, c.loading.start = a, c.loading.first = Math.max(a, i.first || a), c.loading.end = performance.now();
|
|
1475
|
+
c.loaded = c.total = s.byteLength, this.entry = void 0, r.onSuccess({
|
|
1433
1476
|
url: e.url,
|
|
1434
|
-
data:
|
|
1477
|
+
data: s
|
|
1435
1478
|
}, c, e, null);
|
|
1436
1479
|
});
|
|
1437
1480
|
}
|
|
1438
1481
|
abort() {
|
|
1439
1482
|
if (this.served) {
|
|
1440
|
-
this.cancelled = !0, this.stats.aborted = !0;
|
|
1483
|
+
this.cancelled = !0, this.stats.aborted = !0, this.entry?.abort.abort(), this.entry = void 0;
|
|
1441
1484
|
return;
|
|
1442
1485
|
}
|
|
1443
1486
|
super.abort();
|
|
@@ -1445,7 +1488,7 @@ function Pt(t) {
|
|
|
1445
1488
|
}
|
|
1446
1489
|
return r;
|
|
1447
1490
|
}
|
|
1448
|
-
function
|
|
1491
|
+
function Lt() {
|
|
1449
1492
|
return {
|
|
1450
1493
|
aborted: !1,
|
|
1451
1494
|
loaded: 0,
|
|
@@ -1469,10 +1512,10 @@ function Ft() {
|
|
|
1469
1512
|
}
|
|
1470
1513
|
};
|
|
1471
1514
|
}
|
|
1472
|
-
function
|
|
1515
|
+
function Rt(e) {
|
|
1473
1516
|
return e === "audio" ? "audio" : "main";
|
|
1474
1517
|
}
|
|
1475
|
-
function
|
|
1518
|
+
function zt(e, t) {
|
|
1476
1519
|
let n = [];
|
|
1477
1520
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1478
1521
|
url: t.initSegment.url,
|
|
@@ -1489,6 +1532,17 @@ function Lt(e, t) {
|
|
|
1489
1532
|
});
|
|
1490
1533
|
return n;
|
|
1491
1534
|
}
|
|
1535
|
+
function Bt(e) {
|
|
1536
|
+
let t = e, n = t?.preloadHint;
|
|
1537
|
+
if (!n || !t?.url || n.TYPE !== "PART" || n["BYTERANGE-START"] !== void 0 || n["BYTERANGE-LENGTH"] !== void 0) return null;
|
|
1538
|
+
let r = n.URI;
|
|
1539
|
+
if (typeof r != "string" || !r) return null;
|
|
1540
|
+
try {
|
|
1541
|
+
return new URL(r, t.url).toString();
|
|
1542
|
+
} catch {
|
|
1543
|
+
return null;
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1492
1546
|
//#endregion
|
|
1493
1547
|
//#region src/core/percentile.ts
|
|
1494
1548
|
function q(e, t) {
|
|
@@ -1496,11 +1550,11 @@ function q(e, t) {
|
|
|
1496
1550
|
}
|
|
1497
1551
|
//#endregion
|
|
1498
1552
|
//#region src/core/engine/hls.ts
|
|
1499
|
-
function
|
|
1553
|
+
function Vt() {
|
|
1500
1554
|
return e.isSupported();
|
|
1501
1555
|
}
|
|
1502
|
-
var
|
|
1503
|
-
function
|
|
1556
|
+
var Ht = 3, Ut = 1e6, Wt = 20, Gt = 1e4, Kt = 3, qt = 5, Jt = 3, Yt = 1e4, Xt = 3e4, Zt = 12e3, Qt = 3e3, $t = .02, en = 6e3, tn = .5, nn = 3, rn = .5, an = 1.1, on = .25, sn = 5e3, cn = 4e3, ln = 2, un = 5, dn = 2, fn = 2, pn = 4, mn = 4, hn = 2e3, gn = 3e4, _n = 1, vn = 2;
|
|
1557
|
+
function yn(e, t, n) {
|
|
1504
1558
|
if (n <= 0 || t < 0 || t >= e.length) return t;
|
|
1505
1559
|
let r = (t, n) => e[t].width === e[n].width && e[t].height === e[n].height, i = (t) => {
|
|
1506
1560
|
for (; t + 1 < e.length && r(t + 1, t);) t++;
|
|
@@ -1509,11 +1563,11 @@ function hn(e, t, n) {
|
|
|
1509
1563
|
for (let t = 0; t < n && a + 1 < e.length; t++) a = i(a + 1);
|
|
1510
1564
|
return a;
|
|
1511
1565
|
}
|
|
1512
|
-
var
|
|
1513
|
-
function
|
|
1566
|
+
var bn = .2, xn = 30, Sn = 2, Cn = 2, wn = 2, Tn = 9, En = .5, Dn = 64, On = 1e4, kn = 8, An = .6, jn = .4, Mn = .4, Nn = 2, Pn = 6e4, J = .5, Fn = 3.5, In = 300;
|
|
1567
|
+
function Ln(e) {
|
|
1514
1568
|
return (e?.part ?? e?.frag)?.stats;
|
|
1515
1569
|
}
|
|
1516
|
-
function
|
|
1570
|
+
function Rn() {
|
|
1517
1571
|
if (typeof navigator > "u") return 0;
|
|
1518
1572
|
try {
|
|
1519
1573
|
let e = navigator.connection?.rtt;
|
|
@@ -1522,20 +1576,20 @@ function Pn() {
|
|
|
1522
1576
|
return 0;
|
|
1523
1577
|
}
|
|
1524
1578
|
}
|
|
1525
|
-
function
|
|
1579
|
+
function zn(e) {
|
|
1526
1580
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1527
1581
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1528
1582
|
return;
|
|
1529
1583
|
}
|
|
1530
|
-
e.liveSyncDuration ??=
|
|
1531
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1532
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1584
|
+
e.liveSyncDuration ??= wn;
|
|
1585
|
+
let t = Math.max(12, e.liveSyncDuration + Tn);
|
|
1586
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Bn(e, e.liveSyncDuration);
|
|
1533
1587
|
}
|
|
1534
|
-
function
|
|
1588
|
+
function Bn(e, t) {
|
|
1535
1589
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1536
1590
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1537
1591
|
}
|
|
1538
|
-
var
|
|
1592
|
+
var Vn = class {
|
|
1539
1593
|
name = "hls";
|
|
1540
1594
|
hls = null;
|
|
1541
1595
|
deps;
|
|
@@ -1629,11 +1683,11 @@ var Ln = class {
|
|
|
1629
1683
|
frameCounter;
|
|
1630
1684
|
detachFrames = null;
|
|
1631
1685
|
constructor(e) {
|
|
1632
|
-
this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.frameCounter = new
|
|
1686
|
+
this.deps = e, this.holdBackEnabled = e.adaptiveHoldBack !== !1, this.frameCounter = new ft(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1633
1687
|
}
|
|
1634
1688
|
async load() {
|
|
1635
1689
|
this.detachFrames ??= this.frameCounter.attach();
|
|
1636
|
-
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a =
|
|
1690
|
+
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = V(r) && H(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
1637
1691
|
if (e.drmEnabled && !o) {
|
|
1638
1692
|
i({
|
|
1639
1693
|
type: "error",
|
|
@@ -1642,7 +1696,7 @@ var Ln = class {
|
|
|
1642
1696
|
});
|
|
1643
1697
|
return;
|
|
1644
1698
|
}
|
|
1645
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1699
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ge(r), Ye()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1646
1700
|
let e = this.hls;
|
|
1647
1701
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1648
1702
|
let t = e.liveSyncPosition;
|
|
@@ -1665,7 +1719,7 @@ var Ln = class {
|
|
|
1665
1719
|
}
|
|
1666
1720
|
this.loadSuspended = !0;
|
|
1667
1721
|
}
|
|
1668
|
-
},
|
|
1722
|
+
}, sn));
|
|
1669
1723
|
}
|
|
1670
1724
|
resumeLoading() {
|
|
1671
1725
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1697,7 +1751,7 @@ var Ln = class {
|
|
|
1697
1751
|
let t = e.liveSyncPosition;
|
|
1698
1752
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1699
1753
|
let { video: n } = this.deps;
|
|
1700
|
-
n.currentTime <= t +
|
|
1754
|
+
n.currentTime <= t + En || (n.currentTime = t);
|
|
1701
1755
|
}
|
|
1702
1756
|
reanchorPartTimeline(e, t) {
|
|
1703
1757
|
let { frag: n, part: r } = t;
|
|
@@ -1709,7 +1763,7 @@ var Ln = class {
|
|
|
1709
1763
|
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1710
1764
|
if (!s) return;
|
|
1711
1765
|
let c = a.startPTS - s.start;
|
|
1712
|
-
if (!(!Number.isFinite(c) || Math.abs(c) <
|
|
1766
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < $t)) {
|
|
1713
1767
|
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1714
1768
|
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})`);
|
|
1715
1769
|
}
|
|
@@ -1717,7 +1771,7 @@ var Ln = class {
|
|
|
1717
1771
|
startHls() {
|
|
1718
1772
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
1719
1773
|
this.clearKick(), this.resetStarvationWindow(), this.resetChaseWindow(), this.resetFrameDropWindow(), this.lastFragLoadingMs = 0, this.lastEndSN = -1, this.lastAdvanceMs = 0;
|
|
1720
|
-
let u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d =
|
|
1774
|
+
let u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d = V(this.deps.video) && H(), f = {
|
|
1721
1775
|
debug: s === !0,
|
|
1722
1776
|
enableWorker: !o,
|
|
1723
1777
|
lowLatencyMode: o,
|
|
@@ -1732,24 +1786,24 @@ var Ln = class {
|
|
|
1732
1786
|
emeEnabled: !0,
|
|
1733
1787
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1734
1788
|
drmSystemOptions: {
|
|
1735
|
-
videoRobustness:
|
|
1736
|
-
audioRobustness:
|
|
1737
|
-
videoEncryptionScheme:
|
|
1738
|
-
audioEncryptionScheme:
|
|
1789
|
+
videoRobustness: F.video,
|
|
1790
|
+
audioRobustness: F.audio,
|
|
1791
|
+
videoEncryptionScheme: F.scheme,
|
|
1792
|
+
audioEncryptionScheme: F.scheme
|
|
1739
1793
|
},
|
|
1740
|
-
...N() ? { requestMediaKeySystemAccessFunc:
|
|
1794
|
+
...N() ? { requestMediaKeySystemAccessFunc: We(t) } : {},
|
|
1741
1795
|
licenseXhrSetup: (e, t) => {
|
|
1742
1796
|
let o = performance.now(), s = () => {
|
|
1743
1797
|
e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a), this.licenseRequested = !0, e.addEventListener("loadend", () => {
|
|
1744
1798
|
this.licenseTimeMs === 0 && (this.licenseTimeMs = Math.max(1, Math.round(performance.now() - o)));
|
|
1745
1799
|
});
|
|
1746
1800
|
}, { freshLicenseUrl: c } = this.deps;
|
|
1747
|
-
if (!c || !
|
|
1801
|
+
if (!c || !G(this.licenseUrl)) {
|
|
1748
1802
|
s();
|
|
1749
1803
|
return;
|
|
1750
1804
|
}
|
|
1751
1805
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1752
|
-
u = setTimeout(() => e(void 0),
|
|
1806
|
+
u = setTimeout(() => e(void 0), Yt);
|
|
1753
1807
|
});
|
|
1754
1808
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1755
1809
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1764,35 +1818,37 @@ var Ln = class {
|
|
|
1764
1818
|
} } : {},
|
|
1765
1819
|
...c
|
|
1766
1820
|
};
|
|
1767
|
-
|
|
1768
|
-
|
|
1821
|
+
this.prefetch?.destroy(), this.prefetch = null;
|
|
1822
|
+
let p = !1, m = !1, h = u && this.deps.mediaDuringKey !== !1, g = this.deps.preloadHints === !0;
|
|
1823
|
+
if ((h || g) && !f.fLoader) {
|
|
1824
|
+
let e = new Ft({
|
|
1769
1825
|
sessionId: n.analytics?.sid,
|
|
1770
1826
|
contentId: n.matchUrn
|
|
1771
|
-
}), t =
|
|
1772
|
-
t && (this.prefetch = e, f.fLoader = t);
|
|
1827
|
+
}), t = It(e);
|
|
1828
|
+
t && (this.prefetch = e, p = h, m = g, f.fLoader = t);
|
|
1773
1829
|
}
|
|
1774
|
-
|
|
1775
|
-
let
|
|
1776
|
-
if (this.hls =
|
|
1777
|
-
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(
|
|
1778
|
-
}),
|
|
1830
|
+
zn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
|
|
1831
|
+
let _ = new e(f);
|
|
1832
|
+
if (this.hls = _, this.armHoldBack(_, f), _.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(_, t)), _.on(e.Events.MANIFEST_PARSED, () => {
|
|
1833
|
+
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(_), this.measureLadder(_), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1834
|
+
}), _.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1779
1835
|
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(() => {
|
|
1780
1836
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1781
|
-
},
|
|
1782
|
-
}),
|
|
1837
|
+
}, Xt)));
|
|
1838
|
+
}), _.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1783
1839
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1784
|
-
}),
|
|
1840
|
+
}), _.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
1785
1841
|
t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
|
|
1786
|
-
let n = t?.frag, r =
|
|
1842
|
+
let n = t?.frag, r = Ln(t), i = r?.loaded;
|
|
1787
1843
|
typeof i == "number" && (this.bytesLoaded += i), !this.reportedFirstBytes && typeof i == "number" && i > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1788
1844
|
let a = r?.loading;
|
|
1789
|
-
a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length >
|
|
1845
|
+
a && a.end > 0 && a.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(a.end - a.start))), this.requestTimesMs.length > Dn && this.requestTimesMs.shift()), this.sampleHoldBack(t);
|
|
1790
1846
|
let o = n?.url;
|
|
1791
1847
|
if (o) {
|
|
1792
|
-
let e =
|
|
1848
|
+
let e = lt(o);
|
|
1793
1849
|
e && (this.cdnHost = e);
|
|
1794
1850
|
}
|
|
1795
|
-
}),
|
|
1851
|
+
}), _.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
1796
1852
|
let n = t?.stats?.loaded;
|
|
1797
1853
|
if (typeof n == "number" && (this.playlistBytesLoaded += n), this.reportedFirstPlaylist || (this.reportedFirstPlaylist = !0, l({ type: "firstPlaylist" })), this.detectedLowLatency) return;
|
|
1798
1854
|
let r = t.details;
|
|
@@ -1800,31 +1856,47 @@ var Ln = class {
|
|
|
1800
1856
|
type: "lowLatencyDetected",
|
|
1801
1857
|
value: !0
|
|
1802
1858
|
}));
|
|
1803
|
-
}),
|
|
1859
|
+
}), _.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch && m) {
|
|
1860
|
+
let t = this.prefetch, n = this.deps.video, r = (e, r) => {
|
|
1861
|
+
if (n.paused) return;
|
|
1862
|
+
let i = e;
|
|
1863
|
+
if (!i?.live || !i.partList?.length || typeof i.edge != "number") return;
|
|
1864
|
+
let a = n.buffered, o = a.length ? a.end(a.length - 1) : 0;
|
|
1865
|
+
if (i.edge - o > Ht * (i.partTarget || .5)) return;
|
|
1866
|
+
let s = Bt(e);
|
|
1867
|
+
s && t.prefetchHint(s, r);
|
|
1868
|
+
};
|
|
1869
|
+
_.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
1870
|
+
t.level === _.loadLevel && r(t.details, "main");
|
|
1871
|
+
}), _.on(e.Events.AUDIO_TRACK_LOADED, (e, t) => {
|
|
1872
|
+
t?.id === _.audioTrack && r(t?.details, "audio");
|
|
1873
|
+
}), _.on(e.Events.LEVEL_SWITCHING, () => t.dropHints("main")), _.on(e.Events.AUDIO_TRACK_SWITCHING, () => t.dropHints("audio"));
|
|
1874
|
+
}
|
|
1875
|
+
if (this.prefetch && p) {
|
|
1804
1876
|
let t = this.prefetch;
|
|
1805
|
-
|
|
1806
|
-
let r = n?.frag, i =
|
|
1807
|
-
if (r && t.isActive(i)) for (let e of
|
|
1808
|
-
}),
|
|
1877
|
+
_.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1878
|
+
let r = n?.frag, i = Rt(r?.type);
|
|
1879
|
+
if (r && t.isActive(i)) for (let e of zt(_, r)) t.prefetch(e.url, i, e.kind);
|
|
1880
|
+
}), _.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(Rt(n?.frag?.type)));
|
|
1809
1881
|
}
|
|
1810
|
-
|
|
1882
|
+
_.on(e.Events.KEY_LOADED, () => {
|
|
1811
1883
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1812
1884
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1813
1885
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.adaptHoldBack(), this.checkFrameDrops();
|
|
1814
|
-
},
|
|
1886
|
+
}, Qt), _.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1815
1887
|
this.renditionSwitches += 1;
|
|
1816
|
-
let n = this.lastLevelIndex >= 0 ?
|
|
1888
|
+
let n = this.lastLevelIndex >= 0 ? _.levels[this.lastLevelIndex] : void 0, r = _.levels[t.level];
|
|
1817
1889
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, this.armFrameDropGrace(), l({
|
|
1818
1890
|
type: "qualitychange",
|
|
1819
1891
|
index: t.level
|
|
1820
1892
|
});
|
|
1821
|
-
}),
|
|
1893
|
+
}), _.on(e.Events.AUDIO_TRACK_SWITCHED, (e, t) => l({
|
|
1822
1894
|
type: "audiotrackchange",
|
|
1823
1895
|
id: t.id
|
|
1824
|
-
})),
|
|
1896
|
+
})), _.on(e.Events.SUBTITLE_TRACK_SWITCH, (e, t) => l({
|
|
1825
1897
|
type: "texttrackchange",
|
|
1826
1898
|
id: t.id
|
|
1827
|
-
})),
|
|
1899
|
+
})), _.on(e.Events.ERROR, (e, t) => this.onError(t)), _.loadSource(n.manifestUrl), _.attachMedia(t);
|
|
1828
1900
|
}
|
|
1829
1901
|
getQualityLevels() {
|
|
1830
1902
|
return this.hls ? this.hls.levels.map((e, t) => ({
|
|
@@ -1862,9 +1934,9 @@ var Ln = class {
|
|
|
1862
1934
|
let o = e.config ?? {}, s = typeof self < "u" && self.devicePixelRatio > 0 ? self.devicePixelRatio : 1, c = o.ignoreDevicePixelRatio ? 1 : s;
|
|
1863
1935
|
c = Math.min(c, o.maxDevicePixelRatio ?? Infinity);
|
|
1864
1936
|
let l = t.getMaxLevelByMediaSize(e.levels, i * c, a * c), u = this.deps.sizeCapHeadroom;
|
|
1865
|
-
if (u == null && s >=
|
|
1866
|
-
let d = u ??
|
|
1867
|
-
return
|
|
1937
|
+
if (u == null && s >= vn) return l;
|
|
1938
|
+
let d = u ?? _n, f = Number.isNaN(d) ? _n : d === Infinity ? e.levels.length : Math.max(0, Math.floor(d));
|
|
1939
|
+
return yn(e.levels, l, f);
|
|
1868
1940
|
}
|
|
1869
1941
|
onMediaResize() {
|
|
1870
1942
|
if (!this.sizeCapManaged) return;
|
|
@@ -1879,7 +1951,7 @@ var Ln = class {
|
|
|
1879
1951
|
return;
|
|
1880
1952
|
}
|
|
1881
1953
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1882
|
-
let t = e > this.sizeCapLevel ?
|
|
1954
|
+
let t = e > this.sizeCapLevel ? hn : gn;
|
|
1883
1955
|
this.capTimer = setTimeout(() => {
|
|
1884
1956
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1885
1957
|
}, t);
|
|
@@ -1889,9 +1961,9 @@ var Ln = class {
|
|
|
1889
1961
|
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;
|
|
1890
1962
|
}
|
|
1891
1963
|
dropLevelsWidevineCannotPlay(e) {
|
|
1892
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1893
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1894
|
-
for (let n of t)
|
|
1964
|
+
this.removeLevelsWhere(e, (e) => Xe(e) !== !0);
|
|
1965
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
|
|
1966
|
+
for (let n of t) Je(n).then((t) => {
|
|
1895
1967
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1896
1968
|
});
|
|
1897
1969
|
}
|
|
@@ -1899,10 +1971,10 @@ var Ln = class {
|
|
|
1899
1971
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1900
1972
|
if (n.forEach((e, n) => {
|
|
1901
1973
|
let a = e.videoCodec;
|
|
1902
|
-
a &&
|
|
1974
|
+
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1903
1975
|
}), !r.length) return !1;
|
|
1904
1976
|
let a = [...i].join(", ");
|
|
1905
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !
|
|
1977
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Xe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1906
1978
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1907
1979
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1908
1980
|
}
|
|
@@ -2010,7 +2082,7 @@ var Ln = class {
|
|
|
2010
2082
|
return;
|
|
2011
2083
|
}
|
|
2012
2084
|
let e = Date.now() - this.lastAdvanceMs;
|
|
2013
|
-
!this.chaseSuspended && e >
|
|
2085
|
+
!this.chaseSuspended && e > en && this.suspendChasing(), e > Zt && this.emitEnded("stalled");
|
|
2014
2086
|
}
|
|
2015
2087
|
resetStarvationWindow() {
|
|
2016
2088
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -2025,7 +2097,7 @@ var Ln = class {
|
|
|
2025
2097
|
this.resetStarvationWindow();
|
|
2026
2098
|
return;
|
|
2027
2099
|
}
|
|
2028
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
2100
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < en, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > cn, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = z(t), c = o - s, l = c !== this.starvedFrames;
|
|
2029
2101
|
if (this.starvedFrames = c, !a || l) {
|
|
2030
2102
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
2031
2103
|
return;
|
|
@@ -2034,12 +2106,12 @@ var Ln = class {
|
|
|
2034
2106
|
this.resetStarvationWindow();
|
|
2035
2107
|
return;
|
|
2036
2108
|
}
|
|
2037
|
-
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 >
|
|
2109
|
+
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 > pn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= dn && (this.clearKick(), this.starvationRebuilds < fn)) {
|
|
2038
2110
|
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");
|
|
2039
2111
|
return;
|
|
2040
2112
|
}
|
|
2041
|
-
let u = i && this.starvedTicks >=
|
|
2042
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
2113
|
+
let u = i && this.starvedTicks >= ln, d = !i && this.deadTicks >= pn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= mn;
|
|
2114
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= un))) {
|
|
2043
2115
|
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");
|
|
2044
2116
|
try {
|
|
2045
2117
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -2054,7 +2126,7 @@ var Ln = class {
|
|
|
2054
2126
|
let t = e.latency, n = e.targetLatency;
|
|
2055
2127
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
2056
2128
|
let r = t - n;
|
|
2057
|
-
!this.catchUpEngaged && r >
|
|
2129
|
+
!this.catchUpEngaged && r > tn ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= tn && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
2058
2130
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
2059
2131
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
2060
2132
|
}
|
|
@@ -2067,7 +2139,7 @@ var Ln = class {
|
|
|
2067
2139
|
}), n < 0 ? 0 : n;
|
|
2068
2140
|
}
|
|
2069
2141
|
armFrameDropGrace() {
|
|
2070
|
-
this.fpsGraceTicks > 0 || (this.fpsGraceTicks =
|
|
2142
|
+
this.fpsGraceTicks > 0 || (this.fpsGraceTicks = Cn, this.fpsBadTicks = 0);
|
|
2071
2143
|
}
|
|
2072
2144
|
resetFrameDropWindow() {
|
|
2073
2145
|
this.fpsLastFrames = -1, this.fpsLastDropped = -1, this.fpsBadTicks = 0;
|
|
@@ -2078,8 +2150,8 @@ var Ln = class {
|
|
|
2078
2150
|
this.resetFrameDropWindow();
|
|
2079
2151
|
return;
|
|
2080
2152
|
}
|
|
2081
|
-
let { totalFrames: n, dropped: r } =
|
|
2082
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
2153
|
+
let { totalFrames: n, dropped: r } = z(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
2154
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < xn || o < 0) {
|
|
2083
2155
|
this.fpsBadTicks = 0;
|
|
2084
2156
|
return;
|
|
2085
2157
|
}
|
|
@@ -2087,11 +2159,11 @@ var Ln = class {
|
|
|
2087
2159
|
--this.fpsGraceTicks, this.fpsBadTicks = 0;
|
|
2088
2160
|
return;
|
|
2089
2161
|
}
|
|
2090
|
-
if (o <=
|
|
2162
|
+
if (o <= bn * a) {
|
|
2091
2163
|
this.fpsBadTicks = 0;
|
|
2092
2164
|
return;
|
|
2093
2165
|
}
|
|
2094
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
2166
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < Sn) return;
|
|
2095
2167
|
this.fpsBadTicks = 0;
|
|
2096
2168
|
let s = e.levels, c = s[e.currentLevel];
|
|
2097
2169
|
if (!c) return;
|
|
@@ -2108,22 +2180,22 @@ var Ln = class {
|
|
|
2108
2180
|
return;
|
|
2109
2181
|
}
|
|
2110
2182
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
2111
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
2183
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(an, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
2112
2184
|
this.resetChaseWindow();
|
|
2113
2185
|
return;
|
|
2114
2186
|
}
|
|
2115
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
2187
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= rn) {
|
|
2116
2188
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
2117
2189
|
return;
|
|
2118
2190
|
}
|
|
2119
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
2191
|
+
if (this.chaseTicks += 1, this.chaseTicks < nn) return;
|
|
2120
2192
|
this.resetChaseWindow();
|
|
2121
2193
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2122
2194
|
if (!(a > 1)) return;
|
|
2123
2195
|
let o = e.targetLatency;
|
|
2124
2196
|
if (typeof o != "number" || !(o > 0)) return;
|
|
2125
2197
|
let s = Math.min(n, a - 1);
|
|
2126
|
-
s < o +
|
|
2198
|
+
s < o + on || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s, this.deps.emit({
|
|
2127
2199
|
type: "livetargetchange",
|
|
2128
2200
|
change: {
|
|
2129
2201
|
targetSeconds: s,
|
|
@@ -2140,13 +2212,13 @@ var Ln = class {
|
|
|
2140
2212
|
if (!this.holdBackEnabled || this.holdBackPriorChecked || !e || (this.holdBackPriorChecked = !0, this.holdBackApplied > 0 || this.holdBackStepCount > 0)) return;
|
|
2141
2213
|
let t = e.targetLatency;
|
|
2142
2214
|
if (this.holdBackBase < 0 && typeof t == "number" && t > 0 && (this.holdBackBase = t), this.holdBackBase < 0) return;
|
|
2143
|
-
let n =
|
|
2144
|
-
if (!(n >=
|
|
2215
|
+
let n = Rn();
|
|
2216
|
+
if (!(n >= In)) return;
|
|
2145
2217
|
let r = typeof t == "number" && t > 0 ? t : this.holdBackBase, i = Math.min(this.holdBackCeiling(e), this.holdBackBase + J);
|
|
2146
2218
|
i > r && (this.holdBackStepCount = 1, this.moveHoldBack(e, r, i, "connection-rtt", `connection rtt ${n} ms`));
|
|
2147
2219
|
}
|
|
2148
2220
|
holdBackCeiling(e) {
|
|
2149
|
-
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t :
|
|
2221
|
+
let t = this.deps.adaptiveHoldBackCeiling, n = typeof t == "number" && Number.isFinite(t) ? t : Fn, r = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
2150
2222
|
return r > 1 ? Math.min(n, r - 1) : n;
|
|
2151
2223
|
}
|
|
2152
2224
|
sampleHoldBack(e) {
|
|
@@ -2155,7 +2227,7 @@ var Ln = class {
|
|
|
2155
2227
|
if (t !== "main" && t !== "audio") return;
|
|
2156
2228
|
let n = e.part ? e.part.duration : this.detectedLowLatency ? 0 : e.frag?.duration;
|
|
2157
2229
|
if (typeof n != "number" || !(n > 0)) return;
|
|
2158
|
-
let r =
|
|
2230
|
+
let r = Ln(e)?.loading;
|
|
2159
2231
|
if (!r || !(r.start > 0) || !(r.end > 0)) return;
|
|
2160
2232
|
let i = r.first > r.start ? r.first : r.end, a = Math.max(0, i - r.start) / (n * 1e3);
|
|
2161
2233
|
this.holdBackSamples.push({
|
|
@@ -2170,20 +2242,20 @@ var Ln = class {
|
|
|
2170
2242
|
this.holdBackSlowTicks = 0, this.holdBackFastSince = 0, this.holdBackSamples = [];
|
|
2171
2243
|
return;
|
|
2172
2244
|
}
|
|
2173
|
-
let t = Date.now(), n = t -
|
|
2245
|
+
let t = Date.now(), n = t - On, r = this.holdBackSamples, i = 0;
|
|
2174
2246
|
for (; i < r.length && r[i].t < n;) i += 1;
|
|
2175
2247
|
i > 0 && r.splice(0, i);
|
|
2176
2248
|
let a = e.targetLatency;
|
|
2177
2249
|
if (typeof a != "number" || !(a > 0)) return;
|
|
2178
2250
|
this.holdBackBase < 0 && (this.holdBackBase = a);
|
|
2179
2251
|
let o = this.holdBackBase, s = this.holdBackCeiling(e);
|
|
2180
|
-
if (r.length <
|
|
2252
|
+
if (r.length < kn) {
|
|
2181
2253
|
this.holdBackSlowTicks = 0;
|
|
2182
2254
|
return;
|
|
2183
2255
|
}
|
|
2184
2256
|
let c = r.map((e) => e.ratio).sort((e, t) => e - t), l = q(c, 95), u = q(c, 50), d = Math.round(l * 1e3);
|
|
2185
|
-
if (l >=
|
|
2186
|
-
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks <
|
|
2257
|
+
if (l >= An && u >= jn) {
|
|
2258
|
+
if (this.holdBackFastSince = 0, this.holdBackSlowTicks += 1, this.holdBackSlowTicks < Nn) return;
|
|
2187
2259
|
this.holdBackSlowTicks = 0;
|
|
2188
2260
|
let t = Math.ceil((s - o) / J), n = Math.ceil((a - o) / J - 1e-9);
|
|
2189
2261
|
if (n > this.holdBackStepCount && (this.holdBackStepCount = n), this.holdBackStepCount >= t) return;
|
|
@@ -2193,7 +2265,7 @@ var Ln = class {
|
|
|
2193
2265
|
this.moveHoldBack(e, a, r, "slow-fetches", `part fetches slow (first byte p50 ${Math.round(u * 1e3)} / p95 ${d} ms per 1 s of media)`);
|
|
2194
2266
|
return;
|
|
2195
2267
|
}
|
|
2196
|
-
if (this.holdBackSlowTicks = 0, l >=
|
|
2268
|
+
if (this.holdBackSlowTicks = 0, l >= Mn) {
|
|
2197
2269
|
this.holdBackFastSince = 0;
|
|
2198
2270
|
return;
|
|
2199
2271
|
}
|
|
@@ -2201,7 +2273,7 @@ var Ln = class {
|
|
|
2201
2273
|
this.holdBackFastSince = t;
|
|
2202
2274
|
return;
|
|
2203
2275
|
}
|
|
2204
|
-
if (t - this.holdBackFastSince <
|
|
2276
|
+
if (t - this.holdBackFastSince < Pn || (this.holdBackFastSince = t, this.holdBackStepCount === 0 || a !== this.holdBackApplied)) return;
|
|
2205
2277
|
--this.holdBackStepCount;
|
|
2206
2278
|
let f = Math.max(o, o + this.holdBackStepCount * J);
|
|
2207
2279
|
f >= a || this.moveHoldBack(e, a, f, "fast-fetches", `part fetches fast again (p95 first byte ${d} ms per 1 s of media)`);
|
|
@@ -2244,12 +2316,12 @@ var Ln = class {
|
|
|
2244
2316
|
} catch {}
|
|
2245
2317
|
}
|
|
2246
2318
|
startEstimate() {
|
|
2247
|
-
return this.deps.rememberBandwidth === !1 ?
|
|
2319
|
+
return this.deps.rememberBandwidth === !1 ? Ut : Le() ?? Ut;
|
|
2248
2320
|
}
|
|
2249
2321
|
maybeRememberBandwidth(e) {
|
|
2250
|
-
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded <
|
|
2322
|
+
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Wt) return;
|
|
2251
2323
|
let t = Date.now();
|
|
2252
|
-
if (!e && t - this.bwSavedAt <
|
|
2324
|
+
if (!e && t - this.bwSavedAt < Gt) return;
|
|
2253
2325
|
let n = this.hls?.bandwidthEstimate;
|
|
2254
2326
|
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Re(n));
|
|
2255
2327
|
}
|
|
@@ -2269,7 +2341,7 @@ var Ln = class {
|
|
|
2269
2341
|
scheduleLicenseRetry(t) {
|
|
2270
2342
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
2271
2343
|
let n = t.response?.code ?? 0;
|
|
2272
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
2344
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Jt) return !1;
|
|
2273
2345
|
this.licenseRecoveries += 1;
|
|
2274
2346
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
2275
2347
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -2301,7 +2373,7 @@ var Ln = class {
|
|
|
2301
2373
|
return;
|
|
2302
2374
|
}
|
|
2303
2375
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
2304
|
-
if (this.networkRecoveries <
|
|
2376
|
+
if (this.networkRecoveries < qt) {
|
|
2305
2377
|
this.networkRecoveries += 1;
|
|
2306
2378
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
2307
2379
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -2318,7 +2390,7 @@ var Ln = class {
|
|
|
2318
2390
|
return;
|
|
2319
2391
|
}
|
|
2320
2392
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
2321
|
-
if (this.mediaRecoveries <
|
|
2393
|
+
if (this.mediaRecoveries < Kt) {
|
|
2322
2394
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
2323
2395
|
return;
|
|
2324
2396
|
}
|
|
@@ -2339,18 +2411,18 @@ var Ln = class {
|
|
|
2339
2411
|
}
|
|
2340
2412
|
}
|
|
2341
2413
|
toError(t, r = "PLAYBACK") {
|
|
2342
|
-
let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(
|
|
2414
|
+
let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(kt(t.networkDetails)) : void 0;
|
|
2343
2415
|
return new n(r === "DRM" ? a(o, l) : o === 401 ? "UNAUTHORIZED" : o === 403 ? "FORBIDDEN" : "INTERNAL", o, `${r} error: ${s}${c ? ` (${c})` : ""}`, l ? { serverCode: l } : void 0);
|
|
2344
2416
|
}
|
|
2345
|
-
},
|
|
2417
|
+
}, Hn = 15e3, Un = 6e5, Wn = 3e5, Gn = 100, Y = 1, Kn = 1e3, qn = 3e4, Jn = 1e3, Yn = {
|
|
2346
2418
|
inline: "PRESENTATION_INLINE",
|
|
2347
2419
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2348
2420
|
pip: "PRESENTATION_PIP"
|
|
2349
|
-
},
|
|
2421
|
+
}, Xn = {
|
|
2350
2422
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2351
2423
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2352
2424
|
none: "KEY_SYSTEM_NONE"
|
|
2353
|
-
},
|
|
2425
|
+
}, Zn = /* @__PURE__ */ new Set([
|
|
2354
2426
|
"INVALID_URN",
|
|
2355
2427
|
"NOT_FOUND",
|
|
2356
2428
|
"GEO_DENIED",
|
|
@@ -2371,7 +2443,7 @@ var Ln = class {
|
|
|
2371
2443
|
ended: "PLAYER_STATE_ENDED",
|
|
2372
2444
|
error: "PLAYER_STATE_ERROR"
|
|
2373
2445
|
};
|
|
2374
|
-
function
|
|
2446
|
+
function Qn(e) {
|
|
2375
2447
|
try {
|
|
2376
2448
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2377
2449
|
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);
|
|
@@ -2379,8 +2451,8 @@ function Jn(e) {
|
|
|
2379
2451
|
return;
|
|
2380
2452
|
}
|
|
2381
2453
|
}
|
|
2382
|
-
var
|
|
2383
|
-
function
|
|
2454
|
+
var $n = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), er = /* @__PURE__ */ new Set(), Z = /* @__PURE__ */ new Set(), Q = /* @__PURE__ */ new Set(), tr = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2455
|
+
function nr(e) {
|
|
2384
2456
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2385
2457
|
let t;
|
|
2386
2458
|
try {
|
|
@@ -2389,19 +2461,19 @@ function Qn(e) {
|
|
|
2389
2461
|
} catch {
|
|
2390
2462
|
return;
|
|
2391
2463
|
}
|
|
2392
|
-
if (
|
|
2393
|
-
Z.add(t), _(
|
|
2464
|
+
if (er.has(t) && !Z.has(t)) {
|
|
2465
|
+
Z.add(t), _(tr(new URL(t).origin));
|
|
2394
2466
|
for (let e of Q) e.noteCspBlocked();
|
|
2395
2467
|
}
|
|
2396
2468
|
}
|
|
2397
|
-
function
|
|
2469
|
+
function rr(e, t) {
|
|
2398
2470
|
return _(t, e), { disabledReason: t };
|
|
2399
2471
|
}
|
|
2400
|
-
function
|
|
2401
|
-
if (n) return t &&
|
|
2472
|
+
function ir(e, t, n) {
|
|
2473
|
+
if (n) return t && !$n(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2402
2474
|
if (t) return { endpoint: t };
|
|
2403
|
-
if (t !== void 0) return
|
|
2404
|
-
let r =
|
|
2475
|
+
if (t !== void 0) return rr("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).");
|
|
2476
|
+
let r = Qn(e);
|
|
2405
2477
|
if (r) return { endpoint: r };
|
|
2406
2478
|
let i;
|
|
2407
2479
|
try {
|
|
@@ -2409,9 +2481,9 @@ function er(e, t, n) {
|
|
|
2409
2481
|
} catch {
|
|
2410
2482
|
i = e;
|
|
2411
2483
|
}
|
|
2412
|
-
return
|
|
2484
|
+
return rr(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).`);
|
|
2413
2485
|
}
|
|
2414
|
-
var
|
|
2486
|
+
var ar = class {
|
|
2415
2487
|
opts;
|
|
2416
2488
|
url;
|
|
2417
2489
|
cspKey;
|
|
@@ -2493,8 +2565,8 @@ var tr = class {
|
|
|
2493
2565
|
constructor(e) {
|
|
2494
2566
|
this.opts = {
|
|
2495
2567
|
...e,
|
|
2496
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2497
|
-
idleMs: e.idleMs ??
|
|
2568
|
+
heartbeatMs: e.heartbeatMs ?? Hn,
|
|
2569
|
+
idleMs: e.idleMs ?? Un
|
|
2498
2570
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2499
2571
|
try {
|
|
2500
2572
|
let e = new URL(this.url);
|
|
@@ -2511,11 +2583,11 @@ var tr = class {
|
|
|
2511
2583
|
sdkVersion: this.opts.sdkVersion,
|
|
2512
2584
|
...this.opts.environment
|
|
2513
2585
|
};
|
|
2514
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2586
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Kn), 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 && er.add(this.cspKey), document.addEventListener("securitypolicyviolation", nr), Q.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2515
2587
|
}
|
|
2516
2588
|
checkSuspension(e) {
|
|
2517
2589
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2518
|
-
let t = Math.max(this.opts.idleMs,
|
|
2590
|
+
let t = Math.max(this.opts.idleMs, Wn);
|
|
2519
2591
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2520
2592
|
}
|
|
2521
2593
|
syncIdle(e) {
|
|
@@ -2538,12 +2610,12 @@ var tr = class {
|
|
|
2538
2610
|
let a = {
|
|
2539
2611
|
fromState: X[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2540
2612
|
toState: X[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2541
|
-
presentation:
|
|
2613
|
+
presentation: Yn[this.presentation]
|
|
2542
2614
|
}, o = this.causeOf(e, t, i);
|
|
2543
2615
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2544
2616
|
}
|
|
2545
2617
|
seekInduced(e) {
|
|
2546
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2618
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < Jn;
|
|
2547
2619
|
}
|
|
2548
2620
|
causeOf(e, t, n) {
|
|
2549
2621
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2617,7 +2689,7 @@ var tr = class {
|
|
|
2617
2689
|
let r = n ?? "";
|
|
2618
2690
|
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";
|
|
2619
2691
|
if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
|
|
2620
|
-
if (
|
|
2692
|
+
if (Zn.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2621
2693
|
let i = t ?? "";
|
|
2622
2694
|
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";
|
|
2623
2695
|
}
|
|
@@ -2671,7 +2743,7 @@ var tr = class {
|
|
|
2671
2743
|
maybeEmitMediaInfo(e) {
|
|
2672
2744
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2673
2745
|
let t = {};
|
|
2674
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2746
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Xn[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);
|
|
2675
2747
|
let n = JSON.stringify(t);
|
|
2676
2748
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2677
2749
|
}
|
|
@@ -2691,7 +2763,7 @@ var tr = class {
|
|
|
2691
2763
|
let c = r?.positionMs ?? 0;
|
|
2692
2764
|
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));
|
|
2693
2765
|
let l = e !== "END_REASON_ENDED";
|
|
2694
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2766
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= qn && (i.abandonAfterStallMs = Math.max(Y, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= qn && (i.abandonAfterErrorMs = Math.max(Y, 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);
|
|
2695
2767
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2696
2768
|
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");
|
|
2697
2769
|
}
|
|
@@ -2711,13 +2783,13 @@ var tr = class {
|
|
|
2711
2783
|
};
|
|
2712
2784
|
}
|
|
2713
2785
|
noteCspBlocked() {
|
|
2714
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2786
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(tr(new URL(this.url).origin)));
|
|
2715
2787
|
}
|
|
2716
2788
|
cspBlocked() {
|
|
2717
2789
|
return !!this.cspKey && Z.has(this.cspKey);
|
|
2718
2790
|
}
|
|
2719
2791
|
enqueue(e) {
|
|
2720
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2792
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Gn;) {
|
|
2721
2793
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2722
2794
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2723
2795
|
}
|
|
@@ -2744,7 +2816,7 @@ var tr = class {
|
|
|
2744
2816
|
};
|
|
2745
2817
|
//#endregion
|
|
2746
2818
|
//#region src/core/environment.ts
|
|
2747
|
-
function
|
|
2819
|
+
function or() {
|
|
2748
2820
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2749
2821
|
let e;
|
|
2750
2822
|
try {
|
|
@@ -2769,14 +2841,14 @@ function nr() {
|
|
|
2769
2841
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2770
2842
|
};
|
|
2771
2843
|
}
|
|
2772
|
-
function
|
|
2844
|
+
function sr() {
|
|
2773
2845
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2774
2846
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2775
2847
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2776
2848
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2777
2849
|
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";
|
|
2778
2850
|
}
|
|
2779
|
-
function
|
|
2851
|
+
function cr() {
|
|
2780
2852
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2781
2853
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2782
2854
|
let t = {
|
|
@@ -2795,17 +2867,17 @@ function ir() {
|
|
|
2795
2867
|
}
|
|
2796
2868
|
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;
|
|
2797
2869
|
}
|
|
2798
|
-
function
|
|
2799
|
-
let t =
|
|
2800
|
-
deviceClass:
|
|
2870
|
+
function lr(e) {
|
|
2871
|
+
let t = or(), n = {
|
|
2872
|
+
deviceClass: sr(),
|
|
2801
2873
|
integration: t.integration,
|
|
2802
|
-
...
|
|
2874
|
+
...cr()
|
|
2803
2875
|
};
|
|
2804
2876
|
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);
|
|
2805
2877
|
let r = e.getBoundingClientRect?.();
|
|
2806
2878
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2807
2879
|
}
|
|
2808
|
-
async function
|
|
2880
|
+
async function ur() {
|
|
2809
2881
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2810
2882
|
if (!e?.getHighEntropyValues) return {};
|
|
2811
2883
|
try {
|
|
@@ -2817,7 +2889,7 @@ async function or() {
|
|
|
2817
2889
|
}
|
|
2818
2890
|
//#endregion
|
|
2819
2891
|
//#region src/core/version.ts
|
|
2820
|
-
var
|
|
2892
|
+
var dr = "2.24.0", fr = {
|
|
2821
2893
|
accent: "#E1B600",
|
|
2822
2894
|
accentText: "#1B1C23",
|
|
2823
2895
|
background: "#0e0f13",
|
|
@@ -2828,7 +2900,7 @@ var sr = "2.23.4", cr = {
|
|
|
2828
2900
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2829
2901
|
radius: "8px",
|
|
2830
2902
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2831
|
-
},
|
|
2903
|
+
}, pr = {
|
|
2832
2904
|
accent: "--havik-accent",
|
|
2833
2905
|
accentText: "--havik-accent-text",
|
|
2834
2906
|
background: "--havik-bg",
|
|
@@ -2840,26 +2912,26 @@ var sr = "2.23.4", cr = {
|
|
|
2840
2912
|
radius: "--havik-radius",
|
|
2841
2913
|
fontFamily: "--havik-font"
|
|
2842
2914
|
};
|
|
2843
|
-
function
|
|
2915
|
+
function mr(e, t) {
|
|
2844
2916
|
let n = {
|
|
2845
|
-
...
|
|
2917
|
+
...fr,
|
|
2846
2918
|
...t
|
|
2847
2919
|
};
|
|
2848
|
-
for (let t of Object.keys(
|
|
2920
|
+
for (let t of Object.keys(pr)) e.style.setProperty(pr[t], n[t]);
|
|
2849
2921
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2850
2922
|
}
|
|
2851
2923
|
//#endregion
|
|
2852
2924
|
//#region src/ui/styles.ts
|
|
2853
|
-
var
|
|
2854
|
-
function
|
|
2855
|
-
let n = e.querySelector(`style#${
|
|
2856
|
-
if (n && (!t ||
|
|
2925
|
+
var hr = "havik-player-styles", gr = "\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", _r = /* @__PURE__ */ new WeakMap();
|
|
2926
|
+
function vr(e = document, t) {
|
|
2927
|
+
let n = e.querySelector(`style#${hr}`);
|
|
2928
|
+
if (n && (!t || _r.get(n) === t)) return;
|
|
2857
2929
|
let r = e.createElement("style");
|
|
2858
|
-
r.id =
|
|
2930
|
+
r.id = hr, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = gr, _r.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2859
2931
|
}
|
|
2860
2932
|
//#endregion
|
|
2861
2933
|
//#region src/ui/icons.ts
|
|
2862
|
-
var
|
|
2934
|
+
var yr = {
|
|
2863
2935
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2864
2936
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2865
2937
|
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\"/>",
|
|
@@ -2873,11 +2945,11 @@ var hr = {
|
|
|
2873
2945
|
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\"/>"
|
|
2874
2946
|
};
|
|
2875
2947
|
function $(e) {
|
|
2876
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2948
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${yr[e]}</svg>`;
|
|
2877
2949
|
}
|
|
2878
2950
|
//#endregion
|
|
2879
2951
|
//#region src/ui/controls.ts
|
|
2880
|
-
var
|
|
2952
|
+
var br = 3e3, xr = 250, Sr = /* @__PURE__ */ new Set([
|
|
2881
2953
|
"GONE",
|
|
2882
2954
|
"NOT_FOUND",
|
|
2883
2955
|
"GEO_DENIED",
|
|
@@ -2885,15 +2957,15 @@ var gr = 3e3, _r = 250, vr = /* @__PURE__ */ new Set([
|
|
|
2885
2957
|
"UNAUTHORIZED",
|
|
2886
2958
|
"DRM_DEVICE_REVOKED"
|
|
2887
2959
|
]);
|
|
2888
|
-
function
|
|
2960
|
+
function Cr(e) {
|
|
2889
2961
|
let t = "This match isn't available in your country";
|
|
2890
2962
|
return e ? `${t} (${e})` : t;
|
|
2891
2963
|
}
|
|
2892
|
-
var
|
|
2893
|
-
function
|
|
2894
|
-
return new
|
|
2964
|
+
var wr = "This device can't play protected video";
|
|
2965
|
+
function Tr(e) {
|
|
2966
|
+
return new Er(e);
|
|
2895
2967
|
}
|
|
2896
|
-
var
|
|
2968
|
+
var Er = class {
|
|
2897
2969
|
root;
|
|
2898
2970
|
video;
|
|
2899
2971
|
player;
|
|
@@ -2941,7 +3013,7 @@ var Sr = class {
|
|
|
2941
3013
|
scrubbing = !1;
|
|
2942
3014
|
offFns = [];
|
|
2943
3015
|
constructor(e) {
|
|
2944
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
3016
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? br, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, vr(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");
|
|
2945
3017
|
let t = (e, t, n) => {
|
|
2946
3018
|
let r = this.doc.createElement(e);
|
|
2947
3019
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -3027,7 +3099,7 @@ var Sr = class {
|
|
|
3027
3099
|
let t = this.surfaceWasHidden;
|
|
3028
3100
|
this.tapTimer = setTimeout(() => {
|
|
3029
3101
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
3030
|
-
},
|
|
3102
|
+
}, xr);
|
|
3031
3103
|
}
|
|
3032
3104
|
toggleBar(e) {
|
|
3033
3105
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -3047,7 +3119,7 @@ var Sr = class {
|
|
|
3047
3119
|
this.statusOverlays && (e === "ended" ? t = "ended" : e === "error" ? t = "error" : e === "waiting" ? t = "waiting" : !this.hasPlayed && (e === "idle" || e === "paused") && (t = "preplay")), this.renderStatus(t);
|
|
3048
3120
|
}
|
|
3049
3121
|
statusMessageFor(e) {
|
|
3050
|
-
return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ?
|
|
3122
|
+
return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? Cr(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? wr : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
|
|
3051
3123
|
}
|
|
3052
3124
|
renderStatus(e) {
|
|
3053
3125
|
let t = this.statusMessageFor(e);
|
|
@@ -3062,7 +3134,7 @@ var Sr = class {
|
|
|
3062
3134
|
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = $("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
|
|
3063
3135
|
} else {
|
|
3064
3136
|
let r = this.doc.createElement("div");
|
|
3065
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
3137
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Sr.has(this.lastError.code)) {
|
|
3066
3138
|
let e = this.doc.createElement("button");
|
|
3067
3139
|
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${$("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
3068
3140
|
}
|
|
@@ -3103,7 +3175,7 @@ var Sr = class {
|
|
|
3103
3175
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
3104
3176
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
3105
3177
|
}
|
|
3106
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
3178
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Dr(this.video.currentTime)} / ${Dr(this.video.duration)}`);
|
|
3107
3179
|
}
|
|
3108
3180
|
syncLive() {
|
|
3109
3181
|
let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
|
|
@@ -3153,17 +3225,17 @@ var Sr = class {
|
|
|
3153
3225
|
renderQualityMenu() {
|
|
3154
3226
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
3155
3227
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
3156
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
3228
|
+
for (let n of e) this.menu.append(this.menuItem(Or(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
3157
3229
|
}
|
|
3158
3230
|
renderAudioMenu() {
|
|
3159
3231
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
3160
3232
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
3161
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3233
|
+
for (let t of e) this.menu.append(this.menuItem(kr(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
3162
3234
|
}
|
|
3163
3235
|
renderCcMenu() {
|
|
3164
3236
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
3165
3237
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
3166
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3238
|
+
for (let t of e) this.menu.append(this.menuItem(Ar(t), !1, () => this.player.setTextTrack(t.id)));
|
|
3167
3239
|
}
|
|
3168
3240
|
onTracksChanged() {
|
|
3169
3241
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -3268,41 +3340,41 @@ var Sr = class {
|
|
|
3268
3340
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
3269
3341
|
}
|
|
3270
3342
|
};
|
|
3271
|
-
function
|
|
3343
|
+
function Dr(e) {
|
|
3272
3344
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
3273
3345
|
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");
|
|
3274
3346
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
3275
3347
|
}
|
|
3276
|
-
function
|
|
3348
|
+
function Or(e) {
|
|
3277
3349
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
3278
3350
|
}
|
|
3279
|
-
function
|
|
3351
|
+
function kr(e) {
|
|
3280
3352
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3281
3353
|
}
|
|
3282
|
-
function
|
|
3354
|
+
function Ar(e) {
|
|
3283
3355
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3284
3356
|
}
|
|
3285
3357
|
//#endregion
|
|
3286
3358
|
//#region src/managed/index.ts
|
|
3287
|
-
var
|
|
3288
|
-
function
|
|
3359
|
+
var jr = 6e3, Mr = 45e3, Nr = 2e3, Pr = 3, Fr = 5e3, Ir = 2e3, Lr = 48e4, Rr = "keySystemLicenseRequestFailed";
|
|
3360
|
+
function zr(e) {
|
|
3289
3361
|
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)})`);
|
|
3290
|
-
if (e.env !== void 0) return
|
|
3362
|
+
if (e.env !== void 0) return st(e.env);
|
|
3291
3363
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
3292
3364
|
return e.baseUrl;
|
|
3293
3365
|
}
|
|
3294
|
-
async function
|
|
3366
|
+
async function Br(e) {
|
|
3295
3367
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
3296
|
-
let t =
|
|
3368
|
+
let t = zr(e);
|
|
3297
3369
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
3298
3370
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
3299
|
-
let r = new
|
|
3371
|
+
let r = new Vr({
|
|
3300
3372
|
...e,
|
|
3301
3373
|
baseUrl: t
|
|
3302
3374
|
});
|
|
3303
3375
|
return await r.start(), r;
|
|
3304
3376
|
}
|
|
3305
|
-
var
|
|
3377
|
+
var Vr = class {
|
|
3306
3378
|
opts;
|
|
3307
3379
|
abort = new AbortController();
|
|
3308
3380
|
listeners = {};
|
|
@@ -3397,7 +3469,7 @@ var Lr = class {
|
|
|
3397
3469
|
setTimeout(() => {
|
|
3398
3470
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3399
3471
|
phase: i ? "unavailable" : "tooEarly",
|
|
3400
|
-
retryInMs:
|
|
3472
|
+
retryInMs: Mr,
|
|
3401
3473
|
attempt: 1,
|
|
3402
3474
|
elapsedMs: 0,
|
|
3403
3475
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3436,13 +3508,13 @@ var Lr = class {
|
|
|
3436
3508
|
!a && !p() && h();
|
|
3437
3509
|
}, e);
|
|
3438
3510
|
};
|
|
3439
|
-
_(
|
|
3511
|
+
_(jr), this.armingSub = D({
|
|
3440
3512
|
eventsBaseUrl: t,
|
|
3441
3513
|
matchUrn: this.opts.matchUrn,
|
|
3442
3514
|
credential: this.opts.credential,
|
|
3443
|
-
onAlive: () => _(
|
|
3515
|
+
onAlive: () => _(Mr),
|
|
3444
3516
|
onState: (e) => {
|
|
3445
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3517
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Nr);
|
|
3446
3518
|
},
|
|
3447
3519
|
onError: () => h()
|
|
3448
3520
|
});
|
|
@@ -3465,7 +3537,7 @@ var Lr = class {
|
|
|
3465
3537
|
let n = await c(this.opts.credential);
|
|
3466
3538
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3467
3539
|
this.setState("loading");
|
|
3468
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3540
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = pt(this.opts.video, (e) => {
|
|
3469
3541
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3470
3542
|
});
|
|
3471
3543
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3487,26 +3559,26 @@ var Lr = class {
|
|
|
3487
3559
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3488
3560
|
let i = e.analytics?.sid;
|
|
3489
3561
|
if (!i) return;
|
|
3490
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3562
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = ir(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3491
3563
|
if (!o) {
|
|
3492
3564
|
s && setTimeout(() => {
|
|
3493
3565
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3494
3566
|
}, 0);
|
|
3495
3567
|
return;
|
|
3496
3568
|
}
|
|
3497
|
-
let c = this.opts.video, l = new
|
|
3569
|
+
let c = this.opts.video, l = new ar({
|
|
3498
3570
|
endpoint: o,
|
|
3499
3571
|
sid: i,
|
|
3500
3572
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3501
|
-
sdkVersion:
|
|
3502
|
-
environment:
|
|
3573
|
+
sdkVersion: dr,
|
|
3574
|
+
environment: lr(c),
|
|
3503
3575
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3504
3576
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3505
3577
|
onBlocked: (e) => setTimeout(() => {
|
|
3506
3578
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3507
3579
|
}, 0),
|
|
3508
3580
|
sample: () => {
|
|
3509
|
-
let e = this.engine?.getStats() ??
|
|
3581
|
+
let e = this.engine?.getStats() ?? ct, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3510
3582
|
return {
|
|
3511
3583
|
...e,
|
|
3512
3584
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3520,7 +3592,7 @@ var Lr = class {
|
|
|
3520
3592
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3521
3593
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3522
3594
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3523
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3595
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), ur().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3524
3596
|
}
|
|
3525
3597
|
currentPresentation() {
|
|
3526
3598
|
let e = this.opts.video;
|
|
@@ -3544,17 +3616,18 @@ var Lr = class {
|
|
|
3544
3616
|
adaptiveHoldBack: this.opts.adaptiveHoldBack,
|
|
3545
3617
|
adaptiveHoldBackCeiling: this.opts.adaptiveHoldBackCeiling,
|
|
3546
3618
|
mediaDuringKey: this.opts.mediaDuringKey,
|
|
3619
|
+
preloadHints: this.opts.preloadHints,
|
|
3547
3620
|
debug: this.opts.debug,
|
|
3548
3621
|
deferLoad: r,
|
|
3549
3622
|
hlsConfig: i,
|
|
3550
3623
|
emit: (e) => this.onEngineEvent(e),
|
|
3551
3624
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3552
3625
|
}, o = this.opts.engine ?? "auto";
|
|
3553
|
-
if (o === "native") return new
|
|
3554
|
-
if (o === "hls") return new
|
|
3555
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
3556
|
-
if (
|
|
3557
|
-
if (
|
|
3626
|
+
if (o === "native") return new U(a);
|
|
3627
|
+
if (o === "hls") return new Vn(a);
|
|
3628
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && V(this.opts.video) && H() || !e.drmEnabled && Tt() && V(this.opts.video)) return new U(a);
|
|
3629
|
+
if (Vt()) return new Vn(a);
|
|
3630
|
+
if (V(this.opts.video)) return new U(a);
|
|
3558
3631
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3559
3632
|
}
|
|
3560
3633
|
onEngineEvent(e) {
|
|
@@ -3624,7 +3697,7 @@ var Lr = class {
|
|
|
3624
3697
|
a = !0, this.emit("warning", new n(r(o.status), o.status, `live-state events answered HTTP ${o.status} for ${this.opts.matchUrn}: the match is ` + (o.terminal ? "gone, so the subscription stopped" : "not in the catalog (ended and dropped, or not listed yet), so it retries every 5 min") + " — end-of-stream detection falls back to the HLS staleness watchdog."));
|
|
3625
3698
|
return;
|
|
3626
3699
|
}
|
|
3627
|
-
i += 1, i >=
|
|
3700
|
+
i += 1, i >= Pr && (a = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${i} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`)));
|
|
3628
3701
|
}
|
|
3629
3702
|
}
|
|
3630
3703
|
});
|
|
@@ -3639,7 +3712,7 @@ var Lr = class {
|
|
|
3639
3712
|
return;
|
|
3640
3713
|
}
|
|
3641
3714
|
let e = this.hiddenAtMs;
|
|
3642
|
-
this.hiddenAtMs = null, e != null && Date.now() - e >=
|
|
3715
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= Fr && this.resyncLiveState();
|
|
3643
3716
|
}, this.onReturnPageShow = (e) => {
|
|
3644
3717
|
e.persisted && this.resyncLiveState();
|
|
3645
3718
|
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
@@ -3671,7 +3744,7 @@ var Lr = class {
|
|
|
3671
3744
|
scheduleRejoin(e) {
|
|
3672
3745
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3673
3746
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3674
|
-
}, Math.random() *
|
|
3747
|
+
}, Math.random() * Nr));
|
|
3675
3748
|
}
|
|
3676
3749
|
cancelRejoin() {
|
|
3677
3750
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3695,7 +3768,7 @@ var Lr = class {
|
|
|
3695
3768
|
}
|
|
3696
3769
|
t.controls = !1;
|
|
3697
3770
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3698
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3771
|
+
r && r.insertBefore(n, t), n.appendChild(t), mr(n, this.opts.theme), this.container = n, this.controlBar = Tr({
|
|
3699
3772
|
root: n,
|
|
3700
3773
|
video: t,
|
|
3701
3774
|
player: this,
|
|
@@ -3733,7 +3806,7 @@ var Lr = class {
|
|
|
3733
3806
|
}
|
|
3734
3807
|
startStats() {
|
|
3735
3808
|
this.stopStats();
|
|
3736
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3809
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Ir);
|
|
3737
3810
|
this.statsTimer = setInterval(() => {
|
|
3738
3811
|
if (!this.engine) return;
|
|
3739
3812
|
let e = this.engine.getStats();
|
|
@@ -3744,14 +3817,14 @@ var Lr = class {
|
|
|
3744
3817
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3745
3818
|
}
|
|
3746
3819
|
isStaleLicenseDenial(e) {
|
|
3747
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3820
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Rr || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : G(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3748
3821
|
}
|
|
3749
3822
|
scheduleLicenseRefresh() {
|
|
3750
3823
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3751
3824
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3752
|
-
document.visibilityState !== "visible" || this.destroyed ||
|
|
3825
|
+
document.visibilityState !== "visible" || this.destroyed || G(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3753
3826
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3754
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3827
|
+
let e = this.opts.licenseRefreshMs ?? Lr;
|
|
3755
3828
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3756
3829
|
}
|
|
3757
3830
|
stopRefresh() {
|
|
@@ -3808,7 +3881,7 @@ var Lr = class {
|
|
|
3808
3881
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3809
3882
|
}
|
|
3810
3883
|
getStats() {
|
|
3811
|
-
return this.engine?.getStats() ??
|
|
3884
|
+
return this.engine?.getStats() ?? ct;
|
|
3812
3885
|
}
|
|
3813
3886
|
getQualityLevels() {
|
|
3814
3887
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3916,12 +3989,12 @@ var Lr = class {
|
|
|
3916
3989
|
};
|
|
3917
3990
|
//#endregion
|
|
3918
3991
|
//#region src/embed/protocol.ts
|
|
3919
|
-
function
|
|
3992
|
+
function Hr(e) {
|
|
3920
3993
|
return !!e && typeof e == "object" && typeof e.type == "string" && e.type.startsWith("oddin:");
|
|
3921
3994
|
}
|
|
3922
3995
|
//#endregion
|
|
3923
3996
|
//#region src/embed/host.ts
|
|
3924
|
-
function
|
|
3997
|
+
function Ur(e) {
|
|
3925
3998
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3926
3999
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3927
4000
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3930,7 +4003,7 @@ function zr(e) {
|
|
|
3930
4003
|
let r = document.createElement("iframe");
|
|
3931
4004
|
r.src = t.toString(), r.allow = "autoplay; encrypted-media; fullscreen", r.setAttribute("allowfullscreen", ""), r.referrerPolicy = "no-referrer", r.setAttribute("sandbox", e.sandbox ?? "allow-scripts allow-same-origin allow-presentation"), r.style.cssText = "border:0;width:100%;height:100%;display:block", e.container.appendChild(r);
|
|
3932
4005
|
let i = /* @__PURE__ */ new Set(), a = (t) => {
|
|
3933
|
-
if (t.source !== r.contentWindow || t.origin !== n || !
|
|
4006
|
+
if (t.source !== r.contentWindow || t.origin !== n || !Hr(t.data)) return;
|
|
3934
4007
|
let a = t.data;
|
|
3935
4008
|
a.type === "oddin:ready" && a.protocol !== 1 && console.warn(`havik-player: embed protocol v${a.protocol} != host v1. Pin the embed page version to the SDK version to avoid skew.`), e.onEvent?.(a), i.forEach((e) => e(a));
|
|
3936
4009
|
};
|
|
@@ -3980,15 +4053,15 @@ function zr(e) {
|
|
|
3980
4053
|
}
|
|
3981
4054
|
//#endregion
|
|
3982
4055
|
//#region src/embed/page.ts
|
|
3983
|
-
var
|
|
3984
|
-
function
|
|
4056
|
+
var Wr = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
4057
|
+
function Gr(e) {
|
|
3985
4058
|
if (typeof e == "boolean") return e;
|
|
3986
4059
|
if (typeof e == "object" && e) {
|
|
3987
4060
|
let t = e.endpoint;
|
|
3988
4061
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3989
4062
|
}
|
|
3990
4063
|
}
|
|
3991
|
-
function
|
|
4064
|
+
function Kr() {
|
|
3992
4065
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3993
4066
|
if (e) return {
|
|
3994
4067
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3998,7 +4071,7 @@ function Hr() {
|
|
|
3998
4071
|
autoplay: e.autoplay ?? !0,
|
|
3999
4072
|
muted: e.muted ?? !0,
|
|
4000
4073
|
waitForLive: e.waitForLive ?? !0,
|
|
4001
|
-
analytics:
|
|
4074
|
+
analytics: Gr(e.analytics)
|
|
4002
4075
|
};
|
|
4003
4076
|
let t = new URLSearchParams(location.search);
|
|
4004
4077
|
return {
|
|
@@ -4011,9 +4084,9 @@ function Hr() {
|
|
|
4011
4084
|
waitForLive: !0
|
|
4012
4085
|
};
|
|
4013
4086
|
}
|
|
4014
|
-
async function
|
|
4015
|
-
let e =
|
|
4016
|
-
|
|
4087
|
+
async function qr() {
|
|
4088
|
+
let e = Kr();
|
|
4089
|
+
Yr();
|
|
4017
4090
|
let t = document.createElement("video");
|
|
4018
4091
|
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);
|
|
4019
4092
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -4069,12 +4142,12 @@ async function Ur() {
|
|
|
4069
4142
|
message: e.message,
|
|
4070
4143
|
...e.country === void 0 ? {} : { country: e.country }
|
|
4071
4144
|
})), e.on("autoplayblocked", () => {
|
|
4072
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
4145
|
+
i({ type: "oddin:autoplayblocked" }), Jr(t, e);
|
|
4073
4146
|
});
|
|
4074
4147
|
}, s = async (r) => {
|
|
4075
4148
|
a?.destroy(), a = null;
|
|
4076
4149
|
try {
|
|
4077
|
-
let n = await
|
|
4150
|
+
let n = await Br({
|
|
4078
4151
|
video: t,
|
|
4079
4152
|
baseUrl: e.baseUrl,
|
|
4080
4153
|
matchUrn: r,
|
|
@@ -4137,30 +4210,30 @@ async function Ur() {
|
|
|
4137
4210
|
a?.retry();
|
|
4138
4211
|
break;
|
|
4139
4212
|
case "oddin:load":
|
|
4140
|
-
typeof e.matchUrn == "string" &&
|
|
4213
|
+
typeof e.matchUrn == "string" && Wr.test(e.matchUrn) && s(e.matchUrn);
|
|
4141
4214
|
break;
|
|
4142
4215
|
case "oddin:destroy": c();
|
|
4143
4216
|
}
|
|
4144
4217
|
}, u = (e) => {
|
|
4145
|
-
r && e.origin === r &&
|
|
4218
|
+
r && e.origin === r && Hr(e.data) && l(e.data);
|
|
4146
4219
|
};
|
|
4147
4220
|
r && window.addEventListener("message", u), window.addEventListener("pagehide", c, { once: !0 }), await s(e.matchUrn), i({
|
|
4148
4221
|
type: "oddin:ready",
|
|
4149
4222
|
protocol: 1
|
|
4150
4223
|
});
|
|
4151
4224
|
}
|
|
4152
|
-
function
|
|
4225
|
+
function Jr(e, t) {
|
|
4153
4226
|
if (document.getElementById("havik-tap")) return;
|
|
4154
4227
|
let n = document.createElement("button");
|
|
4155
4228
|
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", () => {
|
|
4156
4229
|
n.remove(), t.play();
|
|
4157
4230
|
}), document.body.appendChild(n);
|
|
4158
4231
|
}
|
|
4159
|
-
function
|
|
4232
|
+
function Yr() {
|
|
4160
4233
|
let e = document.createElement("style");
|
|
4161
4234
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
4162
4235
|
}
|
|
4163
4236
|
//#endregion
|
|
4164
|
-
export { E as LiveStateHttpError,
|
|
4237
|
+
export { E as LiveStateHttpError, fr as ODDIN_THEME, n as PlaybackError, mr as applyTheme, st as baseUrlForEnv, qr as bootEmbed, De as clearDeviceId, ze as clearRememberedBandwidth, Br as createPlayer, O as deriveEventsBaseUrl, rt as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, j as getDeviceId, at as isLowLatencyManifest, Hr as isOddinMessage, ke as licenseRequestHeaders, Ur as mountEmbed, fe as pollToLive, y as resolveStream, D as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
|
|
4165
4238
|
|
|
4166
4239
|
//# sourceMappingURL=index.js.map
|