@oddin-gg/havik-player 2.16.7 → 2.16.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/havik-player.global.js +2 -2
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +299 -261
- package/dist/index.js.map +1 -1
- package/docs/API.md +1 -1
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -174,7 +174,7 @@ function ue(e, t) {
|
|
|
174
174
|
t?.addEventListener("abort", a, { once: !0 });
|
|
175
175
|
});
|
|
176
176
|
}
|
|
177
|
-
async function
|
|
177
|
+
async function v(e, t, r) {
|
|
178
178
|
let i = ae(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
|
|
179
179
|
for (;;) {
|
|
180
180
|
if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
|
|
@@ -200,21 +200,21 @@ async function de(e, t, r) {
|
|
|
200
200
|
}
|
|
201
201
|
//#endregion
|
|
202
202
|
//#region src/core/resolve.ts
|
|
203
|
-
async function
|
|
203
|
+
async function y(e) {
|
|
204
204
|
if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
|
|
205
205
|
let t = await p(d(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
|
|
206
206
|
credential: e.credential,
|
|
207
207
|
signal: e.signal,
|
|
208
208
|
apiHeaders: e.apiHeaders
|
|
209
209
|
});
|
|
210
|
-
if (!t.ok) throw await
|
|
211
|
-
return
|
|
210
|
+
if (!t.ok) throw await de(t);
|
|
211
|
+
return me(await t.json(), e.matchUrn);
|
|
212
212
|
}
|
|
213
|
-
function
|
|
214
|
-
let t = () =>
|
|
215
|
-
return e.waitForLive ?
|
|
213
|
+
function b(e) {
|
|
214
|
+
let t = () => y(e);
|
|
215
|
+
return e.waitForLive ? v(t, e.waitForLive, e.signal) : t();
|
|
216
216
|
}
|
|
217
|
-
async function
|
|
217
|
+
async function de(e) {
|
|
218
218
|
let t = f(e.headers.get("retry-after")), i = e.headers.get("x-request-id") ?? e.headers.get("x-amzn-requestid") ?? void 0, a = e.statusText || `HTTP ${e.status}`, o, s;
|
|
219
219
|
try {
|
|
220
220
|
let t = await e.json();
|
|
@@ -230,7 +230,7 @@ async function fe(e) {
|
|
|
230
230
|
liveStartsAtMs: s
|
|
231
231
|
});
|
|
232
232
|
}
|
|
233
|
-
var
|
|
233
|
+
var fe = /* @__PURE__ */ new Set([
|
|
234
234
|
"matchUrn",
|
|
235
235
|
"protocol",
|
|
236
236
|
"drmEnabled",
|
|
@@ -241,7 +241,7 @@ var pe = /* @__PURE__ */ new Set([
|
|
|
241
241
|
"expiresAt",
|
|
242
242
|
"analytics"
|
|
243
243
|
]);
|
|
244
|
-
function
|
|
244
|
+
function x(e, t) {
|
|
245
245
|
let r;
|
|
246
246
|
try {
|
|
247
247
|
r = new URL(t);
|
|
@@ -251,7 +251,7 @@ function b(e, t) {
|
|
|
251
251
|
if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
|
|
252
252
|
return t;
|
|
253
253
|
}
|
|
254
|
-
function
|
|
254
|
+
function pe(e) {
|
|
255
255
|
if (e !== void 0) {
|
|
256
256
|
if (typeof e == "string" && !e.endsWith("/")) try {
|
|
257
257
|
let t = new URL(e);
|
|
@@ -260,41 +260,41 @@ function me(e) {
|
|
|
260
260
|
g(`server analytics.endpoint ${JSON.stringify(e)} ignored: not a bare https origin.`);
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
|
-
function
|
|
263
|
+
function me(e, t) {
|
|
264
264
|
if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
|
|
265
265
|
let r = e.drmEnabled ?? !!e.drm, i = {
|
|
266
266
|
matchUrn: e.matchUrn ?? t,
|
|
267
267
|
protocol: "hls",
|
|
268
268
|
drmEnabled: r,
|
|
269
|
-
manifestUrl:
|
|
269
|
+
manifestUrl: x("manifestUrl", e.manifestUrl),
|
|
270
270
|
serverTime: e.serverTime ?? ""
|
|
271
271
|
};
|
|
272
272
|
if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid) {
|
|
273
273
|
i.analytics = { sid: e.analytics.sid };
|
|
274
|
-
let t =
|
|
274
|
+
let t = pe(e.analytics.endpoint);
|
|
275
275
|
t && (i.analytics.endpoint = t);
|
|
276
276
|
}
|
|
277
277
|
if (r && e.drm) {
|
|
278
278
|
let t = {};
|
|
279
|
-
e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl:
|
|
280
|
-
licenseUrl:
|
|
281
|
-
certificateUrl:
|
|
279
|
+
e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: x("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
|
|
280
|
+
licenseUrl: x("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
|
|
281
|
+
certificateUrl: x("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
|
|
282
282
|
}), (t.widevine || t.fairplay) && (i.drm = t);
|
|
283
283
|
}
|
|
284
284
|
let a = {};
|
|
285
|
-
for (let [t, n] of Object.entries(e))
|
|
285
|
+
for (let [t, n] of Object.entries(e)) fe.has(t) || (a[t] = n);
|
|
286
286
|
return Object.keys(a).length > 0 && (i.extensions = a), i;
|
|
287
287
|
}
|
|
288
288
|
//#endregion
|
|
289
289
|
//#region src/core/fullscreen.ts
|
|
290
|
-
function
|
|
290
|
+
function he(e) {
|
|
291
291
|
return e.ownerDocument ?? document;
|
|
292
292
|
}
|
|
293
|
-
function
|
|
293
|
+
function ge(e) {
|
|
294
294
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
295
295
|
}
|
|
296
296
|
function S(e, t) {
|
|
297
|
-
let n =
|
|
297
|
+
let n = ge(he(e));
|
|
298
298
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
299
299
|
}
|
|
300
300
|
async function C(e, t) {
|
|
@@ -310,7 +310,7 @@ async function w(e, t) {
|
|
|
310
310
|
n.webkitExitFullscreen?.();
|
|
311
311
|
return;
|
|
312
312
|
}
|
|
313
|
-
let r =
|
|
313
|
+
let r = he(e), i = ge(r);
|
|
314
314
|
i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
|
|
315
315
|
}
|
|
316
316
|
//#endregion
|
|
@@ -671,14 +671,14 @@ function I(e) {
|
|
|
671
671
|
function L(e) {
|
|
672
672
|
return (e ?? "").trim().toLowerCase();
|
|
673
673
|
}
|
|
674
|
-
var
|
|
674
|
+
var R = {
|
|
675
675
|
hevc: "hvc1.1.6.L93.90",
|
|
676
676
|
dv: "dvh1.05.06",
|
|
677
677
|
av1: "av01.0.05M.08",
|
|
678
678
|
vp9: "vp09.00.10.08"
|
|
679
|
-
},
|
|
680
|
-
function
|
|
681
|
-
let t = L(e), n =
|
|
679
|
+
}, je = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Map();
|
|
680
|
+
function Me(e) {
|
|
681
|
+
let t = L(e), n = je.get(t);
|
|
682
682
|
if (n) return n;
|
|
683
683
|
let r = {
|
|
684
684
|
initDataTypes: ["cenc"],
|
|
@@ -696,23 +696,23 @@ function Ne(e) {
|
|
|
696
696
|
} catch {
|
|
697
697
|
return !1;
|
|
698
698
|
}
|
|
699
|
-
})().then((e) => (
|
|
700
|
-
return
|
|
699
|
+
})().then((e) => (z.set(t, e), e));
|
|
700
|
+
return je.set(t, i), i;
|
|
701
701
|
}
|
|
702
|
-
function
|
|
703
|
-
if (j()) for (let e of Object.values(
|
|
702
|
+
function Ne() {
|
|
703
|
+
if (j()) for (let e of Object.values(R)) Me(e);
|
|
704
704
|
}
|
|
705
|
-
function
|
|
705
|
+
function Pe(e) {
|
|
706
706
|
let t = I(e);
|
|
707
|
-
if (t) return t === "avc" ? !0 :
|
|
707
|
+
if (t) return t === "avc" ? !0 : z.get(L(e)) ?? z.get(L(R[t]));
|
|
708
708
|
}
|
|
709
709
|
//#endregion
|
|
710
710
|
//#region src/core/drm/support.ts
|
|
711
|
-
var
|
|
711
|
+
var Fe = 5e3, Ie = "video/mp4; codecs=\"avc1.42E01E\"", Le = "audio/mp4; codecs=\"mp4a.40.2\"", Re = {
|
|
712
712
|
widevine: ["com.widevine.alpha"],
|
|
713
713
|
fairplay: ["com.apple.fps"]
|
|
714
714
|
};
|
|
715
|
-
function
|
|
715
|
+
function ze(e) {
|
|
716
716
|
return e === "fairplay" ? [{
|
|
717
717
|
initDataTypes: [
|
|
718
718
|
"sinf",
|
|
@@ -720,30 +720,30 @@ function Be(e) {
|
|
|
720
720
|
"cenc"
|
|
721
721
|
],
|
|
722
722
|
videoCapabilities: [{
|
|
723
|
-
contentType:
|
|
723
|
+
contentType: Ie,
|
|
724
724
|
robustness: "",
|
|
725
725
|
encryptionScheme: "cbcs"
|
|
726
726
|
}],
|
|
727
727
|
audioCapabilities: [{
|
|
728
|
-
contentType:
|
|
728
|
+
contentType: Le,
|
|
729
729
|
robustness: "",
|
|
730
730
|
encryptionScheme: "cbcs"
|
|
731
731
|
}]
|
|
732
732
|
}] : N("com.widevine.alpha", [{
|
|
733
733
|
initDataTypes: ["cenc"],
|
|
734
734
|
videoCapabilities: [{
|
|
735
|
-
contentType:
|
|
735
|
+
contentType: Ie,
|
|
736
736
|
robustness: F.video,
|
|
737
737
|
encryptionScheme: F.scheme
|
|
738
738
|
}],
|
|
739
739
|
audioCapabilities: [{
|
|
740
|
-
contentType:
|
|
740
|
+
contentType: Le,
|
|
741
741
|
robustness: F.audio,
|
|
742
742
|
encryptionScheme: F.scheme
|
|
743
743
|
}]
|
|
744
744
|
}]);
|
|
745
745
|
}
|
|
746
|
-
function
|
|
746
|
+
function Be(e, t) {
|
|
747
747
|
return new Promise((n, r) => {
|
|
748
748
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
749
749
|
e.then((e) => {
|
|
@@ -753,8 +753,8 @@ function Ve(e, t) {
|
|
|
753
753
|
});
|
|
754
754
|
});
|
|
755
755
|
}
|
|
756
|
-
async function
|
|
757
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
756
|
+
async function Ve(e = {}) {
|
|
757
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Fe, r = {};
|
|
758
758
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
759
759
|
verdict: "insecure-context",
|
|
760
760
|
detail: r
|
|
@@ -766,7 +766,7 @@ async function He(e = {}) {
|
|
|
766
766
|
};
|
|
767
767
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
768
768
|
for (let e of t) {
|
|
769
|
-
let t =
|
|
769
|
+
let t = Re[e];
|
|
770
770
|
if (!t) {
|
|
771
771
|
r[e] = "unknown system";
|
|
772
772
|
continue;
|
|
@@ -777,7 +777,7 @@ async function He(e = {}) {
|
|
|
777
777
|
break;
|
|
778
778
|
}
|
|
779
779
|
try {
|
|
780
|
-
return await
|
|
780
|
+
return await Be((await Be(i(n, ze(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
781
781
|
verdict: "supported",
|
|
782
782
|
system: e,
|
|
783
783
|
detail: r
|
|
@@ -801,25 +801,25 @@ async function He(e = {}) {
|
|
|
801
801
|
}
|
|
802
802
|
//#endregion
|
|
803
803
|
//#region src/core/manifest.ts
|
|
804
|
-
var
|
|
805
|
-
function
|
|
806
|
-
return
|
|
804
|
+
var He = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
805
|
+
function Ue(e) {
|
|
806
|
+
return He.test(e);
|
|
807
807
|
}
|
|
808
808
|
//#endregion
|
|
809
809
|
//#region src/core/env.ts
|
|
810
|
-
var
|
|
810
|
+
var We = {
|
|
811
811
|
integration: "https://feed-dev.oddin-video.gg",
|
|
812
812
|
production: "https://feed.oddin-video.gg"
|
|
813
813
|
};
|
|
814
|
-
function
|
|
815
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
814
|
+
function Ge(e) {
|
|
815
|
+
let t = Object.prototype.hasOwnProperty.call(We, e) ? We[e] : void 0;
|
|
816
816
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
817
817
|
return t;
|
|
818
818
|
}
|
|
819
819
|
//#endregion
|
|
820
820
|
//#region src/core/stats.ts
|
|
821
|
-
var
|
|
822
|
-
function
|
|
821
|
+
var Ke = { droppedFrames: 0 };
|
|
822
|
+
function qe(e) {
|
|
823
823
|
try {
|
|
824
824
|
return new URL(e).host;
|
|
825
825
|
} catch {
|
|
@@ -831,7 +831,7 @@ function Ye(e) {
|
|
|
831
831
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
832
832
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
833
833
|
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Je.test(i.name)) && i.startTime >= n) {
|
|
834
|
-
let e =
|
|
834
|
+
let e = qe(i.name);
|
|
835
835
|
e && (t = e, n = i.startTime);
|
|
836
836
|
}
|
|
837
837
|
return t;
|
|
@@ -843,7 +843,7 @@ function B(e) {
|
|
|
843
843
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
844
844
|
};
|
|
845
845
|
}
|
|
846
|
-
var
|
|
846
|
+
var Xe = class {
|
|
847
847
|
video;
|
|
848
848
|
baseFrames = 0;
|
|
849
849
|
baseDropped = 0;
|
|
@@ -866,7 +866,7 @@ var V = class {
|
|
|
866
866
|
};
|
|
867
867
|
}
|
|
868
868
|
};
|
|
869
|
-
function
|
|
869
|
+
function Ze(e, t) {
|
|
870
870
|
let n = [
|
|
871
871
|
["playing", () => t("playing")],
|
|
872
872
|
["waiting", () => t("buffering")],
|
|
@@ -883,8 +883,8 @@ function Xe(e, t) {
|
|
|
883
883
|
}
|
|
884
884
|
//#endregion
|
|
885
885
|
//#region src/core/engine/native.ts
|
|
886
|
-
var
|
|
887
|
-
function
|
|
886
|
+
var Qe = 2e3, $e = 3, V = 500, et = 6e3, tt = .25, nt = 250, rt = .05;
|
|
887
|
+
function it(e) {
|
|
888
888
|
try {
|
|
889
889
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
890
890
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -892,20 +892,20 @@ function tt(e) {
|
|
|
892
892
|
return;
|
|
893
893
|
}
|
|
894
894
|
}
|
|
895
|
-
function
|
|
895
|
+
function H(e) {
|
|
896
896
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
897
897
|
}
|
|
898
|
-
function
|
|
898
|
+
function U() {
|
|
899
899
|
if (typeof window > "u") return !1;
|
|
900
900
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
901
901
|
return e || t;
|
|
902
902
|
}
|
|
903
|
-
function
|
|
904
|
-
if (typeof navigator > "u" || !
|
|
903
|
+
function at() {
|
|
904
|
+
if (typeof navigator > "u" || !U()) return !1;
|
|
905
905
|
let e = navigator.userAgent ?? "";
|
|
906
906
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
907
907
|
}
|
|
908
|
-
var
|
|
908
|
+
var W = class {
|
|
909
909
|
name = "native";
|
|
910
910
|
deps;
|
|
911
911
|
onLoaded;
|
|
@@ -918,6 +918,10 @@ var G = class {
|
|
|
918
918
|
onPageShow = null;
|
|
919
919
|
hiddenSince = null;
|
|
920
920
|
refocusTimer = null;
|
|
921
|
+
edgeTimer = null;
|
|
922
|
+
onEdgeReset = null;
|
|
923
|
+
lastBufferedEnd = null;
|
|
924
|
+
bufferedAdvancedAt = null;
|
|
921
925
|
fairplayKeyIV;
|
|
922
926
|
loadStarted;
|
|
923
927
|
preloadTouched = !1;
|
|
@@ -927,12 +931,12 @@ var G = class {
|
|
|
927
931
|
frameCounter;
|
|
928
932
|
detachFrames = null;
|
|
929
933
|
constructor(e) {
|
|
930
|
-
this.deps = e, this.frameCounter = new
|
|
934
|
+
this.deps = e, this.frameCounter = new Xe(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
|
|
931
935
|
}
|
|
932
936
|
async load() {
|
|
933
937
|
this.detachFrames ??= this.frameCounter.attach();
|
|
934
938
|
let { video: e, descriptor: t, emit: r } = this.deps;
|
|
935
|
-
if (this.watchRefocus(), this.loadStarted || (this.preloadTouched = !0, this.savedPreload = e.getAttribute("preload"), e.preload = "none"), t.drmEnabled) {
|
|
939
|
+
if (this.watchRefocus(), this.watchBufferedEnd(), this.loadStarted || (this.preloadTouched = !0, this.savedPreload = e.getAttribute("preload"), e.preload = "none"), t.drmEnabled) {
|
|
936
940
|
if (!t.drm?.fairplay) {
|
|
937
941
|
r({
|
|
938
942
|
type: "error",
|
|
@@ -948,7 +952,7 @@ var G = class {
|
|
|
948
952
|
type: "error",
|
|
949
953
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
950
954
|
fatal: !0
|
|
951
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
955
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = st(t.manifestUrl, t.analytics?.sid), e.load();
|
|
952
956
|
}
|
|
953
957
|
startLoad() {
|
|
954
958
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -970,7 +974,7 @@ var G = class {
|
|
|
970
974
|
});
|
|
971
975
|
this.onEncrypted = (n) => {
|
|
972
976
|
let i = n;
|
|
973
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
977
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = it(i.initData), (async () => {
|
|
974
978
|
try {
|
|
975
979
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
976
980
|
initDataTypes: [i.initDataType],
|
|
@@ -1061,8 +1065,8 @@ var G = class {
|
|
|
1061
1065
|
for (let n = 0; n < t.length; n += 1) t[n].mode = n === e ? "showing" : "disabled";
|
|
1062
1066
|
}
|
|
1063
1067
|
seekToLive() {
|
|
1064
|
-
let e = this.deps.video;
|
|
1065
|
-
|
|
1068
|
+
let e = this.deps.video, t = this.liveEnd();
|
|
1069
|
+
t == null || t <= e.currentTime || (e.currentTime = t);
|
|
1066
1070
|
}
|
|
1067
1071
|
getStats() {
|
|
1068
1072
|
let e = this.deps.video, t = this.frameCounter.read(), n = {
|
|
@@ -1070,50 +1074,72 @@ var G = class {
|
|
|
1070
1074
|
decodedFrames: t.totalFrames
|
|
1071
1075
|
};
|
|
1072
1076
|
if (this.cdnHost ||= Ye(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
let r = t - e.currentTime;
|
|
1077
|
-
Number.isFinite(r) && r >= 0 && (n.latencySeconds = r);
|
|
1078
|
-
}
|
|
1077
|
+
n.isLive = !0;
|
|
1078
|
+
let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
|
|
1079
|
+
Number.isFinite(r) && (n.atLiveEdge = r <= 2, !e.paused && r >= 0 && (n.latencySeconds = r));
|
|
1079
1080
|
} else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
|
|
1080
1081
|
return n;
|
|
1081
1082
|
}
|
|
1082
1083
|
stop() {
|
|
1084
|
+
this.unwatchBufferedEnd();
|
|
1083
1085
|
try {
|
|
1084
1086
|
this.deps.video.pause();
|
|
1085
1087
|
} catch {}
|
|
1086
1088
|
}
|
|
1087
1089
|
watchRefocus() {
|
|
1088
1090
|
this.deps.snapToLiveOnRefocus === !1 || typeof document > "u" || this.onVisibility || (this.onVisibility = () => {
|
|
1089
|
-
let e =
|
|
1091
|
+
let e = G();
|
|
1090
1092
|
if (document.visibilityState === "hidden") {
|
|
1091
1093
|
this.hiddenSince = e, this.cancelRefocus();
|
|
1092
1094
|
return;
|
|
1093
1095
|
}
|
|
1094
1096
|
let t = this.hiddenSince;
|
|
1095
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1097
|
+
this.hiddenSince = null, t != null && e - t >= Qe && this.armRefocus();
|
|
1096
1098
|
}, this.onPageShow = (e) => {
|
|
1097
1099
|
e.persisted && this.armRefocus();
|
|
1098
1100
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
1099
1101
|
}
|
|
1100
1102
|
armRefocus() {
|
|
1101
1103
|
if (this.cancelRefocus(), Number.isFinite(this.deps.video.duration)) return;
|
|
1102
|
-
let e = this.liveEnd(), t =
|
|
1104
|
+
let e = this.liveEnd(), t = G, n = t(), r = 0, i = () => {
|
|
1103
1105
|
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1104
|
-
r +=
|
|
1105
|
-
let a = this.liveEnd(), o = a != null && (e == null || a >= e +
|
|
1106
|
+
r += V;
|
|
1107
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + tt), s = Math.max(r, t() - n) >= et;
|
|
1106
1108
|
if (o || s && a != null) {
|
|
1107
1109
|
this.snapToLive();
|
|
1108
1110
|
return;
|
|
1109
1111
|
}
|
|
1110
|
-
this.refocusTimer = setTimeout(i,
|
|
1112
|
+
this.refocusTimer = setTimeout(i, V);
|
|
1111
1113
|
};
|
|
1112
|
-
this.refocusTimer = setTimeout(i,
|
|
1114
|
+
this.refocusTimer = setTimeout(i, V);
|
|
1113
1115
|
}
|
|
1114
1116
|
cancelRefocus() {
|
|
1115
1117
|
this.refocusTimer != null && clearTimeout(this.refocusTimer), this.refocusTimer = null;
|
|
1116
1118
|
}
|
|
1119
|
+
watchBufferedEnd() {
|
|
1120
|
+
if (this.edgeTimer != null) return;
|
|
1121
|
+
let { video: e } = this.deps;
|
|
1122
|
+
this.onEdgeReset = () => {
|
|
1123
|
+
this.lastBufferedEnd = null, this.bufferedAdvancedAt = null;
|
|
1124
|
+
}, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
|
|
1125
|
+
if (e.duration !== Infinity) return;
|
|
1126
|
+
let t = ot(e, e.currentTime);
|
|
1127
|
+
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= rt) && (this.bufferedAdvancedAt = G()), this.lastBufferedEnd = t);
|
|
1128
|
+
}, nt);
|
|
1129
|
+
}
|
|
1130
|
+
unwatchBufferedEnd() {
|
|
1131
|
+
this.edgeTimer != null && clearInterval(this.edgeTimer), this.edgeTimer = null, this.onEdgeReset &&= (this.deps.video.removeEventListener("seeking", this.onEdgeReset), this.deps.video.removeEventListener("emptied", this.onEdgeReset), null), this.lastBufferedEnd = null, this.bufferedAdvancedAt = null;
|
|
1132
|
+
}
|
|
1133
|
+
liveEdgeEstimate() {
|
|
1134
|
+
let e = this.deps.video;
|
|
1135
|
+
if (e.duration !== Infinity) return null;
|
|
1136
|
+
let t = this.liveEnd(), n = ot(e, e.currentTime) ?? this.lastBufferedEnd;
|
|
1137
|
+
if (n != null) {
|
|
1138
|
+
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (G() - e) / 1e3));
|
|
1139
|
+
(t == null || r > t) && (t = r);
|
|
1140
|
+
}
|
|
1141
|
+
return t != null && Number.isFinite(t) ? t : null;
|
|
1142
|
+
}
|
|
1117
1143
|
liveEnd() {
|
|
1118
1144
|
let e = this.deps.video;
|
|
1119
1145
|
if (e.duration !== Infinity || e.seekable.length === 0) return null;
|
|
@@ -1123,13 +1149,13 @@ var G = class {
|
|
|
1123
1149
|
snapToLive() {
|
|
1124
1150
|
let e = this.deps.video, t = this.liveEnd();
|
|
1125
1151
|
if (t == null) return;
|
|
1126
|
-
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t -
|
|
1152
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - $e, r);
|
|
1127
1153
|
try {
|
|
1128
1154
|
e.currentTime = i;
|
|
1129
1155
|
} catch {}
|
|
1130
1156
|
}
|
|
1131
1157
|
destroy() {
|
|
1132
|
-
this.detachFrames?.(), this.detachFrames = null, this.cancelRefocus(), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onPageShow && typeof window < "u" && (window.removeEventListener("pageshow", this.onPageShow), this.onPageShow = null);
|
|
1158
|
+
this.detachFrames?.(), this.detachFrames = null, this.cancelRefocus(), this.unwatchBufferedEnd(), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onPageShow && typeof window < "u" && (window.removeEventListener("pageshow", this.onPageShow), this.onPageShow = null);
|
|
1133
1159
|
let { video: e } = this.deps;
|
|
1134
1160
|
this.onLoaded && e.removeEventListener("loadedmetadata", this.onLoaded), this.onError && e.removeEventListener("error", this.onError), this.onEncrypted && e.removeEventListener("encrypted", this.onEncrypted), this.keySession?.close().catch(() => {}), this.keySession = null, this.fairplayArmed = !1, this.fairplayKeyIV = void 0;
|
|
1135
1161
|
try {
|
|
@@ -1141,7 +1167,19 @@ var G = class {
|
|
|
1141
1167
|
} catch {}
|
|
1142
1168
|
}
|
|
1143
1169
|
};
|
|
1144
|
-
function
|
|
1170
|
+
function G() {
|
|
1171
|
+
return typeof performance < "u" ? performance.now() : Date.now();
|
|
1172
|
+
}
|
|
1173
|
+
function ot(e, t) {
|
|
1174
|
+
let n = e.buffered;
|
|
1175
|
+
if (!n || !Number.isFinite(t)) return null;
|
|
1176
|
+
for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
|
|
1177
|
+
let t = n.end(e);
|
|
1178
|
+
return Number.isFinite(t) ? t : null;
|
|
1179
|
+
}
|
|
1180
|
+
return null;
|
|
1181
|
+
}
|
|
1182
|
+
function st(e, t) {
|
|
1145
1183
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1146
1184
|
}
|
|
1147
1185
|
//#endregion
|
|
@@ -1158,8 +1196,8 @@ function K(e, t = Date.now()) {
|
|
|
1158
1196
|
}
|
|
1159
1197
|
//#endregion
|
|
1160
1198
|
//#region src/core/engine/prefetch.ts
|
|
1161
|
-
var
|
|
1162
|
-
function
|
|
1199
|
+
var ct = 15e3, lt = 5e3, ut = 6;
|
|
1200
|
+
function dt(e) {
|
|
1163
1201
|
try {
|
|
1164
1202
|
let t = new URL(e);
|
|
1165
1203
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1167,7 +1205,7 @@ function st(e) {
|
|
|
1167
1205
|
return e;
|
|
1168
1206
|
}
|
|
1169
1207
|
}
|
|
1170
|
-
var
|
|
1208
|
+
var ft = class {
|
|
1171
1209
|
cmcd;
|
|
1172
1210
|
entries = /* @__PURE__ */ new Map();
|
|
1173
1211
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1190,10 +1228,10 @@ var ct = class {
|
|
|
1190
1228
|
}
|
|
1191
1229
|
prefetch(e, t, n) {
|
|
1192
1230
|
if (!this.isActive(t)) return;
|
|
1193
|
-
let r =
|
|
1231
|
+
let r = dt(e);
|
|
1194
1232
|
if (this.entries.has(r)) return;
|
|
1195
1233
|
let i = this.perTrack.get(t) ?? 0;
|
|
1196
|
-
if (i >=
|
|
1234
|
+
if (i >= ut) return;
|
|
1197
1235
|
this.perTrack.set(t, i + 1);
|
|
1198
1236
|
let a = new AbortController(), o = {
|
|
1199
1237
|
started: performance.now(),
|
|
@@ -1207,10 +1245,10 @@ var ct = class {
|
|
|
1207
1245
|
signal: a.signal
|
|
1208
1246
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1209
1247
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1210
|
-
},
|
|
1248
|
+
}, ct);
|
|
1211
1249
|
}
|
|
1212
1250
|
take(e) {
|
|
1213
|
-
let t =
|
|
1251
|
+
let t = dt(e), n = this.entries.get(t);
|
|
1214
1252
|
return n && this.entries.delete(t), n;
|
|
1215
1253
|
}
|
|
1216
1254
|
destroy() {
|
|
@@ -1230,13 +1268,13 @@ var ct = class {
|
|
|
1230
1268
|
}
|
|
1231
1269
|
}
|
|
1232
1270
|
};
|
|
1233
|
-
function
|
|
1271
|
+
function pt(t) {
|
|
1234
1272
|
let n = e.DefaultConfig?.loader;
|
|
1235
1273
|
if (typeof n != "function") return;
|
|
1236
1274
|
class r extends n {
|
|
1237
1275
|
served = !1;
|
|
1238
1276
|
cancelled = !1;
|
|
1239
|
-
stats =
|
|
1277
|
+
stats = mt();
|
|
1240
1278
|
load(e, n, r) {
|
|
1241
1279
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1242
1280
|
if (!i) {
|
|
@@ -1244,7 +1282,7 @@ function lt(t) {
|
|
|
1244
1282
|
return;
|
|
1245
1283
|
}
|
|
1246
1284
|
this.served = !0;
|
|
1247
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1285
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || lt, s = setTimeout(() => {
|
|
1248
1286
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1249
1287
|
}, o);
|
|
1250
1288
|
i.bytes.then((o) => {
|
|
@@ -1271,7 +1309,7 @@ function lt(t) {
|
|
|
1271
1309
|
}
|
|
1272
1310
|
return r;
|
|
1273
1311
|
}
|
|
1274
|
-
function
|
|
1312
|
+
function mt() {
|
|
1275
1313
|
return {
|
|
1276
1314
|
aborted: !1,
|
|
1277
1315
|
loaded: 0,
|
|
@@ -1295,10 +1333,10 @@ function ut() {
|
|
|
1295
1333
|
}
|
|
1296
1334
|
};
|
|
1297
1335
|
}
|
|
1298
|
-
function
|
|
1336
|
+
function ht(e) {
|
|
1299
1337
|
return e === "audio" ? "audio" : "main";
|
|
1300
1338
|
}
|
|
1301
|
-
function
|
|
1339
|
+
function gt(e, t) {
|
|
1302
1340
|
let n = [];
|
|
1303
1341
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1304
1342
|
url: t.initSegment.url,
|
|
@@ -1317,24 +1355,24 @@ function ft(e, t) {
|
|
|
1317
1355
|
}
|
|
1318
1356
|
//#endregion
|
|
1319
1357
|
//#region src/core/engine/hls.ts
|
|
1320
|
-
function
|
|
1358
|
+
function _t() {
|
|
1321
1359
|
return e.isSupported();
|
|
1322
1360
|
}
|
|
1323
|
-
var
|
|
1324
|
-
function
|
|
1361
|
+
var vt = 3, yt = 5, bt = 3, xt = 1e4, St = 3e4, Ct = 12e3, wt = 3e3, Tt = .02, Et = 6e3, Dt = .5, Ot = 3, kt = .5, At = 1.1, jt = .25, Mt = 5e3, Nt = 4e3, Pt = 2, Ft = 5, It = 2, Lt = 2, Rt = 4, zt = 4, Bt = 2e3, Vt = 3e4, Ht = .2, Ut = 30, Wt = 2, Gt = 2, Kt = 9, qt = .5, Jt = 64;
|
|
1362
|
+
function Yt(e) {
|
|
1325
1363
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1326
1364
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1327
1365
|
return;
|
|
1328
1366
|
}
|
|
1329
|
-
e.liveSyncDuration ??=
|
|
1330
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1331
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1367
|
+
e.liveSyncDuration ??= Gt;
|
|
1368
|
+
let t = Math.max(12, e.liveSyncDuration + Kt);
|
|
1369
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Xt(e, e.liveSyncDuration);
|
|
1332
1370
|
}
|
|
1333
|
-
function
|
|
1371
|
+
function Xt(e, t) {
|
|
1334
1372
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1335
1373
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1336
1374
|
}
|
|
1337
|
-
var
|
|
1375
|
+
var Zt = class {
|
|
1338
1376
|
name = "hls";
|
|
1339
1377
|
hls = null;
|
|
1340
1378
|
deps;
|
|
@@ -1414,11 +1452,11 @@ var qt = class {
|
|
|
1414
1452
|
frameCounter;
|
|
1415
1453
|
detachFrames = null;
|
|
1416
1454
|
constructor(e) {
|
|
1417
|
-
this.deps = e, this.frameCounter = new
|
|
1455
|
+
this.deps = e, this.frameCounter = new Xe(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1418
1456
|
}
|
|
1419
1457
|
async load() {
|
|
1420
1458
|
this.detachFrames ??= this.frameCounter.attach();
|
|
1421
|
-
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a =
|
|
1459
|
+
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = H(r) && U(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
1422
1460
|
if (e.drmEnabled && !o) {
|
|
1423
1461
|
i({
|
|
1424
1462
|
type: "error",
|
|
@@ -1427,7 +1465,7 @@ var qt = class {
|
|
|
1427
1465
|
});
|
|
1428
1466
|
return;
|
|
1429
1467
|
}
|
|
1430
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r),
|
|
1468
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Ne()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1431
1469
|
let e = this.hls;
|
|
1432
1470
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1433
1471
|
let t = e.liveSyncPosition;
|
|
@@ -1450,7 +1488,7 @@ var qt = class {
|
|
|
1450
1488
|
}
|
|
1451
1489
|
this.loadSuspended = !0;
|
|
1452
1490
|
}
|
|
1453
|
-
},
|
|
1491
|
+
}, Mt));
|
|
1454
1492
|
}
|
|
1455
1493
|
resumeLoading() {
|
|
1456
1494
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1482,7 +1520,7 @@ var qt = class {
|
|
|
1482
1520
|
let t = e.liveSyncPosition;
|
|
1483
1521
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1484
1522
|
let { video: n } = this.deps;
|
|
1485
|
-
n.currentTime <= t +
|
|
1523
|
+
n.currentTime <= t + qt || (n.currentTime = t);
|
|
1486
1524
|
}
|
|
1487
1525
|
reanchorPartTimeline(e, t) {
|
|
1488
1526
|
let { frag: n, part: r } = t;
|
|
@@ -1494,7 +1532,7 @@ var qt = class {
|
|
|
1494
1532
|
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1495
1533
|
if (!s) return;
|
|
1496
1534
|
let c = a.startPTS - s.start;
|
|
1497
|
-
if (!(!Number.isFinite(c) || Math.abs(c) <
|
|
1535
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < Tt)) {
|
|
1498
1536
|
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1499
1537
|
i.fragmentHint?.setStart(i.fragmentHint.start + c), this.deps.debug === !0 && console.info(`havik-player: LL-HLS timeline re-anchored by ${c >= 0 ? "+" : ""}${c.toFixed(3)}s at sn ${n.sn} (level ${n.level})`);
|
|
1500
1538
|
}
|
|
@@ -1533,7 +1571,7 @@ var qt = class {
|
|
|
1533
1571
|
return;
|
|
1534
1572
|
}
|
|
1535
1573
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1536
|
-
u = setTimeout(() => e(void 0),
|
|
1574
|
+
u = setTimeout(() => e(void 0), xt);
|
|
1537
1575
|
});
|
|
1538
1576
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1539
1577
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1549,20 +1587,20 @@ var qt = class {
|
|
|
1549
1587
|
...c
|
|
1550
1588
|
};
|
|
1551
1589
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
|
|
1552
|
-
let e = new
|
|
1590
|
+
let e = new ft({
|
|
1553
1591
|
sessionId: n.analytics?.sid,
|
|
1554
1592
|
contentId: n.matchUrn
|
|
1555
|
-
}), t =
|
|
1593
|
+
}), t = pt(e);
|
|
1556
1594
|
t && (this.prefetch = e, d.fLoader = t);
|
|
1557
1595
|
}
|
|
1558
|
-
|
|
1596
|
+
Yt(d), this.catchUpRate = typeof d.maxLiveSyncPlaybackRate == "number" ? d.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (d.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = d.autoStartLoad !== !1;
|
|
1559
1597
|
let f = new e(d);
|
|
1560
1598
|
if (this.hls = f, f.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(f, t)), f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1561
1599
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(f), this.measureLadder(f), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1562
1600
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1563
1601
|
t?.frag?.type === "main" && (this.kickKind !== "dead" && this.clearKick(), (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
1564
1602
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1565
|
-
},
|
|
1603
|
+
}, St)));
|
|
1566
1604
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1567
1605
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1568
1606
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1570,10 +1608,10 @@ var qt = class {
|
|
|
1570
1608
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1571
1609
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1572
1610
|
let i = n?.loading;
|
|
1573
|
-
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length >
|
|
1611
|
+
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Jt && this.requestTimesMs.shift());
|
|
1574
1612
|
let a = t?.frag?.url;
|
|
1575
1613
|
if (a) {
|
|
1576
|
-
let e =
|
|
1614
|
+
let e = qe(a);
|
|
1577
1615
|
e && (this.cdnHost = e);
|
|
1578
1616
|
}
|
|
1579
1617
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1587,15 +1625,15 @@ var qt = class {
|
|
|
1587
1625
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1588
1626
|
let t = this.prefetch;
|
|
1589
1627
|
f.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1590
|
-
let r = n?.frag, i =
|
|
1591
|
-
if (r && t.isActive(i)) for (let e of
|
|
1592
|
-
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1628
|
+
let r = n?.frag, i = ht(r?.type);
|
|
1629
|
+
if (r && t.isActive(i)) for (let e of gt(f, r)) t.prefetch(e.url, i, e.kind);
|
|
1630
|
+
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(ht(n?.frag?.type)));
|
|
1593
1631
|
}
|
|
1594
1632
|
f.on(e.Events.KEY_LOADED, () => {
|
|
1595
1633
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1596
1634
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1597
1635
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1598
|
-
},
|
|
1636
|
+
}, wt), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1599
1637
|
this.renditionSwitches += 1;
|
|
1600
1638
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1601
1639
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1659,7 +1697,7 @@ var qt = class {
|
|
|
1659
1697
|
return;
|
|
1660
1698
|
}
|
|
1661
1699
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1662
|
-
let t = e > this.sizeCapLevel ?
|
|
1700
|
+
let t = e > this.sizeCapLevel ? Bt : Vt;
|
|
1663
1701
|
this.capTimer = setTimeout(() => {
|
|
1664
1702
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1665
1703
|
}, t);
|
|
@@ -1669,9 +1707,9 @@ var qt = class {
|
|
|
1669
1707
|
this.ladderHeights = t.length ? [...new Set(t)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = e.levels.length ? Math.round(Math.max(...e.levels.map((e) => e.bitrate)) / 1e3) : 0;
|
|
1670
1708
|
}
|
|
1671
1709
|
dropLevelsWidevineCannotPlay(e) {
|
|
1672
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1710
|
+
this.removeLevelsWhere(e, (e) => Pe(e) !== !0);
|
|
1673
1711
|
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
|
|
1674
|
-
for (let n of t)
|
|
1712
|
+
for (let n of t) Me(n).then((t) => {
|
|
1675
1713
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1676
1714
|
});
|
|
1677
1715
|
}
|
|
@@ -1682,7 +1720,7 @@ var qt = class {
|
|
|
1682
1720
|
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1683
1721
|
}), !r.length) return !1;
|
|
1684
1722
|
let a = [...i].join(", ");
|
|
1685
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) ||
|
|
1723
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Pe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1686
1724
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1687
1725
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1688
1726
|
}
|
|
@@ -1780,7 +1818,7 @@ var qt = class {
|
|
|
1780
1818
|
return;
|
|
1781
1819
|
}
|
|
1782
1820
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1783
|
-
!this.chaseSuspended && e >
|
|
1821
|
+
!this.chaseSuspended && e > Et && this.suspendChasing(), e > Ct && this.emitEnded("stalled");
|
|
1784
1822
|
}
|
|
1785
1823
|
resetStarvationWindow() {
|
|
1786
1824
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1795,7 +1833,7 @@ var qt = class {
|
|
|
1795
1833
|
this.resetStarvationWindow();
|
|
1796
1834
|
return;
|
|
1797
1835
|
}
|
|
1798
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1836
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < Et, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Nt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
|
|
1799
1837
|
if (this.starvedFrames = c, !a || l) {
|
|
1800
1838
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1801
1839
|
return;
|
|
@@ -1804,12 +1842,12 @@ var qt = class {
|
|
|
1804
1842
|
this.resetStarvationWindow();
|
|
1805
1843
|
return;
|
|
1806
1844
|
}
|
|
1807
|
-
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length >
|
|
1845
|
+
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > Rt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= It && (this.clearKick(), this.starvationRebuilds < Lt)) {
|
|
1808
1846
|
this.starvationRebuilds += 1, this.resetStarvationWindow(), this.clearRecoveryReset(), console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
|
|
1809
1847
|
return;
|
|
1810
1848
|
}
|
|
1811
|
-
let u = i && this.starvedTicks >=
|
|
1812
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1849
|
+
let u = i && this.starvedTicks >= Pt, d = !i && this.deadTicks >= Rt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= zt;
|
|
1850
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= Ft))) {
|
|
1813
1851
|
this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, this.kickKind = d ? "dead" : "quiet", this.clearRecoveryReset(), console.warn(d ? "havik-player: video starved while hls.js keeps loading media it never plays (dead pipeline at the live edge) — restarting the load" : "havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
|
|
1814
1852
|
try {
|
|
1815
1853
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1824,7 +1862,7 @@ var qt = class {
|
|
|
1824
1862
|
let t = e.latency, n = e.targetLatency;
|
|
1825
1863
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1826
1864
|
let r = t - n;
|
|
1827
|
-
!this.catchUpEngaged && r >
|
|
1865
|
+
!this.catchUpEngaged && r > Dt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Dt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1828
1866
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1829
1867
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1830
1868
|
}
|
|
@@ -1846,15 +1884,15 @@ var qt = class {
|
|
|
1846
1884
|
return;
|
|
1847
1885
|
}
|
|
1848
1886
|
let { totalFrames: n, dropped: r } = B(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
1849
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
1887
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Ut || o < 0) {
|
|
1850
1888
|
this.fpsBadTicks = 0;
|
|
1851
1889
|
return;
|
|
1852
1890
|
}
|
|
1853
|
-
if (o <=
|
|
1891
|
+
if (o <= Ht * a) {
|
|
1854
1892
|
this.fpsBadTicks = 0;
|
|
1855
1893
|
return;
|
|
1856
1894
|
}
|
|
1857
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
1895
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < Wt) return;
|
|
1858
1896
|
this.fpsBadTicks = 0;
|
|
1859
1897
|
let s = e.levels, c = s[e.currentLevel];
|
|
1860
1898
|
if (!c) return;
|
|
@@ -1871,20 +1909,20 @@ var qt = class {
|
|
|
1871
1909
|
return;
|
|
1872
1910
|
}
|
|
1873
1911
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
1874
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
1912
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(At, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
1875
1913
|
this.resetChaseWindow();
|
|
1876
1914
|
return;
|
|
1877
1915
|
}
|
|
1878
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
1916
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= kt) {
|
|
1879
1917
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
1880
1918
|
return;
|
|
1881
1919
|
}
|
|
1882
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
1920
|
+
if (this.chaseTicks += 1, this.chaseTicks < Ot) return;
|
|
1883
1921
|
this.resetChaseWindow();
|
|
1884
1922
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
1885
1923
|
if (!(a > 1)) return;
|
|
1886
1924
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
1887
|
-
s < o +
|
|
1925
|
+
s < o + jt || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s);
|
|
1888
1926
|
}
|
|
1889
1927
|
suspendChasing() {
|
|
1890
1928
|
let e = this.hls;
|
|
@@ -1929,7 +1967,7 @@ var qt = class {
|
|
|
1929
1967
|
scheduleLicenseRetry(t) {
|
|
1930
1968
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1931
1969
|
let n = t.response?.code ?? 0;
|
|
1932
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1970
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= bt) return !1;
|
|
1933
1971
|
this.licenseRecoveries += 1;
|
|
1934
1972
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1935
1973
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1961,7 +1999,7 @@ var qt = class {
|
|
|
1961
1999
|
return;
|
|
1962
2000
|
}
|
|
1963
2001
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1964
|
-
if (this.networkRecoveries <
|
|
2002
|
+
if (this.networkRecoveries < yt) {
|
|
1965
2003
|
this.networkRecoveries += 1;
|
|
1966
2004
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1967
2005
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1978,7 +2016,7 @@ var qt = class {
|
|
|
1978
2016
|
return;
|
|
1979
2017
|
}
|
|
1980
2018
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1981
|
-
if (this.mediaRecoveries <
|
|
2019
|
+
if (this.mediaRecoveries < vt) {
|
|
1982
2020
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1983
2021
|
return;
|
|
1984
2022
|
}
|
|
@@ -2002,19 +2040,19 @@ var qt = class {
|
|
|
2002
2040
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
2003
2041
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
2004
2042
|
}
|
|
2005
|
-
},
|
|
2043
|
+
}, Qt = 15e3, $t = 6e5, en = 3e5, tn = 100, q = 1, nn = 1e3, rn = 3e4, an = 1e3, on = {
|
|
2006
2044
|
inline: "PRESENTATION_INLINE",
|
|
2007
2045
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2008
2046
|
pip: "PRESENTATION_PIP"
|
|
2009
|
-
},
|
|
2047
|
+
}, sn = {
|
|
2010
2048
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2011
2049
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2012
2050
|
none: "KEY_SYSTEM_NONE"
|
|
2013
2051
|
};
|
|
2014
|
-
function
|
|
2052
|
+
function cn(e, t) {
|
|
2015
2053
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
2016
2054
|
}
|
|
2017
|
-
var
|
|
2055
|
+
var ln = /* @__PURE__ */ new Set([
|
|
2018
2056
|
"INVALID_URN",
|
|
2019
2057
|
"NOT_FOUND",
|
|
2020
2058
|
"GONE",
|
|
@@ -2034,7 +2072,7 @@ var an = /* @__PURE__ */ new Set([
|
|
|
2034
2072
|
ended: "PLAYER_STATE_ENDED",
|
|
2035
2073
|
error: "PLAYER_STATE_ERROR"
|
|
2036
2074
|
};
|
|
2037
|
-
function
|
|
2075
|
+
function un(e) {
|
|
2038
2076
|
try {
|
|
2039
2077
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2040
2078
|
return !n || r.length === 0 || n !== "feed" && !n.startsWith("feed-") ? void 0 : (t.hostname = [n.replace(/^feed/, "beacons"), ...r].join("."), t.pathname = "", t.search = "", t.origin);
|
|
@@ -2042,8 +2080,8 @@ function on(e) {
|
|
|
2042
2080
|
return;
|
|
2043
2081
|
}
|
|
2044
2082
|
}
|
|
2045
|
-
var
|
|
2046
|
-
function
|
|
2083
|
+
var dn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), fn = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), pn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2084
|
+
function mn(e) {
|
|
2047
2085
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2048
2086
|
let t;
|
|
2049
2087
|
try {
|
|
@@ -2052,19 +2090,19 @@ function un(e) {
|
|
|
2052
2090
|
} catch {
|
|
2053
2091
|
return;
|
|
2054
2092
|
}
|
|
2055
|
-
if (
|
|
2056
|
-
Y.add(t), g(
|
|
2093
|
+
if (fn.has(t) && !Y.has(t)) {
|
|
2094
|
+
Y.add(t), g(pn(new URL(t).origin));
|
|
2057
2095
|
for (let e of X) e.noteCspBlocked();
|
|
2058
2096
|
}
|
|
2059
2097
|
}
|
|
2060
|
-
function
|
|
2098
|
+
function hn(e, t) {
|
|
2061
2099
|
return g(t, e), { disabledReason: t };
|
|
2062
2100
|
}
|
|
2063
|
-
function
|
|
2064
|
-
if (n) return t && !
|
|
2101
|
+
function gn(e, t, n) {
|
|
2102
|
+
if (n) return t && !dn(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2065
2103
|
if (t) return { endpoint: t };
|
|
2066
|
-
if (t !== void 0) return
|
|
2067
|
-
let r =
|
|
2104
|
+
if (t !== void 0) return hn("empty-endpoint", "analytics is disabled: no QoE beacons will be sent. analytics.endpoint was supplied but empty. Pass a real beacons origin, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, or omit the option to derive it from baseUrl (or analytics: false to opt out).");
|
|
2105
|
+
let r = un(e);
|
|
2068
2106
|
if (r) return { endpoint: r };
|
|
2069
2107
|
let i;
|
|
2070
2108
|
try {
|
|
@@ -2072,9 +2110,9 @@ function fn(e, t, n) {
|
|
|
2072
2110
|
} catch {
|
|
2073
2111
|
i = e;
|
|
2074
2112
|
}
|
|
2075
|
-
return
|
|
2113
|
+
return hn(i, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${i}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
|
|
2076
2114
|
}
|
|
2077
|
-
var
|
|
2115
|
+
var _n = class {
|
|
2078
2116
|
opts;
|
|
2079
2117
|
url;
|
|
2080
2118
|
cspKey;
|
|
@@ -2156,8 +2194,8 @@ var pn = class {
|
|
|
2156
2194
|
constructor(e) {
|
|
2157
2195
|
this.opts = {
|
|
2158
2196
|
...e,
|
|
2159
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2160
|
-
idleMs: e.idleMs ??
|
|
2197
|
+
heartbeatMs: e.heartbeatMs ?? Qt,
|
|
2198
|
+
idleMs: e.idleMs ?? $t
|
|
2161
2199
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2162
2200
|
try {
|
|
2163
2201
|
let e = new URL(this.url);
|
|
@@ -2174,11 +2212,11 @@ var pn = class {
|
|
|
2174
2212
|
sdkVersion: this.opts.sdkVersion,
|
|
2175
2213
|
...this.opts.environment
|
|
2176
2214
|
};
|
|
2177
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2215
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), nn), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.cspKey && fn.add(this.cspKey), document.addEventListener("securitypolicyviolation", mn), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2178
2216
|
}
|
|
2179
2217
|
checkSuspension(e) {
|
|
2180
2218
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2181
|
-
let t = Math.max(this.opts.idleMs,
|
|
2219
|
+
let t = Math.max(this.opts.idleMs, en);
|
|
2182
2220
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2183
2221
|
}
|
|
2184
2222
|
syncIdle(e) {
|
|
@@ -2201,12 +2239,12 @@ var pn = class {
|
|
|
2201
2239
|
let a = {
|
|
2202
2240
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2203
2241
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2204
|
-
presentation:
|
|
2242
|
+
presentation: on[this.presentation]
|
|
2205
2243
|
}, o = this.causeOf(e, t, i);
|
|
2206
2244
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2207
2245
|
}
|
|
2208
2246
|
seekInduced(e) {
|
|
2209
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2247
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < an;
|
|
2210
2248
|
}
|
|
2211
2249
|
causeOf(e, t, n) {
|
|
2212
2250
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2280,7 +2318,7 @@ var pn = class {
|
|
|
2280
2318
|
let r = n ?? "";
|
|
2281
2319
|
if (r !== "") return /^fragLoad/i.test(r) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /^(manifest|level|audioTrack|subtitleTrack)/i.test(r) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(r) ? "ERROR_STAGE_DRM" : /parsing|append|buffer|remux|decrypt|media/i.test(r) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
|
|
2282
2320
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2283
|
-
if (
|
|
2321
|
+
if (ln.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2284
2322
|
let i = t ?? "";
|
|
2285
2323
|
return /frag|segment/i.test(i) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /manifest|level|playlist/i.test(i) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(i) ? "ERROR_STAGE_DRM" : /buffer|decode|media|append/i.test(i) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
|
|
2286
2324
|
}
|
|
@@ -2327,14 +2365,14 @@ var pn = class {
|
|
|
2327
2365
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2328
2366
|
o.requestCountDelta = _;
|
|
2329
2367
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2330
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2368
|
+
n.length > 0 && (o.requestTimeP50Ms = cn(n, 50), o.requestTimeP95Ms = cn(n, 95));
|
|
2331
2369
|
}
|
|
2332
2370
|
typeof t.latencySeconds == "number" && typeof t.targetLatencySeconds == "number" && (o.driftMs = Math.round((t.latencySeconds - t.targetLatencySeconds) * 1e3)), typeof t.playbackRate == "number" && t.playbackRate > 0 && (o.playbackRate = t.playbackRate), t.qualityPinned === !0 && (o.qualityPinned = !0), t.cdnHost && (o.cdnHost = t.cdnHost), this.maybeEmitMediaInfo(t), this.enqueue({ heartbeat: o }), this.flush(), s > 0 && this.noteFirstBytes();
|
|
2333
2371
|
}
|
|
2334
2372
|
maybeEmitMediaInfo(e) {
|
|
2335
2373
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2336
2374
|
let t = {};
|
|
2337
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2375
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = sn[e.keySystem]), e.drmSecurityLevel && (t.drmSecurityLevel = e.drmSecurityLevel), e.ladderHeights?.length && (t.ladderHeights = e.ladderHeights), e.ladderTopBitrateKbps && (t.ladderTopBitrateKbps = e.ladderTopBitrateKbps), e.lowLatency && (t.lowLatency = !0);
|
|
2338
2376
|
let n = JSON.stringify(t);
|
|
2339
2377
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2340
2378
|
}
|
|
@@ -2354,7 +2392,7 @@ var pn = class {
|
|
|
2354
2392
|
let c = r?.positionMs ?? 0;
|
|
2355
2393
|
c > 0 && (i.exitPositionMs = Math.round(c)), this.activeTotalMs > 0 && (i.activeWatchTimeMs = Math.round(this.activeTotalMs)), this.mutedTotalMs > 0 && (i.mutedTimeMs = Math.round(this.mutedTotalMs));
|
|
2356
2394
|
let l = e !== "END_REASON_ENDED";
|
|
2357
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2395
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= rn && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= rn && (i.abandonAfterErrorMs = Math.max(q, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
|
|
2358
2396
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2359
2397
|
u > 0 && (i.decodedFramesTotal = u), e === "END_REASON_STOPPED" && this.startupTimeMs === 0 && this.lastErrorStage === null && (e = "END_REASON_ABORTED", i.reason = e), this.startupTimeMs === 0 && e !== "END_REASON_ABORTED" && (i.failedStage = this.lastErrorStage ?? (this.manifestLoadMs === 0 ? "ERROR_STAGE_MANIFEST" : this.firstFragLoadMs === 0 ? "ERROR_STAGE_FIRST_SEGMENT" : "ERROR_STAGE_OTHER")), this.pending.push(this.wrap({ sessionEnd: i })), this.flush(e === "END_REASON_PAGEHIDE");
|
|
2360
2398
|
}
|
|
@@ -2374,13 +2412,13 @@ var pn = class {
|
|
|
2374
2412
|
};
|
|
2375
2413
|
}
|
|
2376
2414
|
noteCspBlocked() {
|
|
2377
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2415
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(pn(new URL(this.url).origin)));
|
|
2378
2416
|
}
|
|
2379
2417
|
cspBlocked() {
|
|
2380
2418
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2381
2419
|
}
|
|
2382
2420
|
enqueue(e) {
|
|
2383
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2421
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > tn;) {
|
|
2384
2422
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2385
2423
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2386
2424
|
}
|
|
@@ -2407,7 +2445,7 @@ var pn = class {
|
|
|
2407
2445
|
};
|
|
2408
2446
|
//#endregion
|
|
2409
2447
|
//#region src/core/environment.ts
|
|
2410
|
-
function
|
|
2448
|
+
function vn() {
|
|
2411
2449
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2412
2450
|
let e;
|
|
2413
2451
|
try {
|
|
@@ -2432,14 +2470,14 @@ function mn() {
|
|
|
2432
2470
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2433
2471
|
};
|
|
2434
2472
|
}
|
|
2435
|
-
function
|
|
2473
|
+
function yn() {
|
|
2436
2474
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2437
2475
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2438
2476
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2439
2477
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2440
2478
|
return e?.mobile ?? (typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1 && n > 0 && n < 900) ? n >= 600 ? "DEVICE_CLASS_TABLET" : "DEVICE_CLASS_PHONE" : e || n >= 900 || /mac|win|linux|chrome os/i.test(t) ? "DEVICE_CLASS_DESKTOP" : "DEVICE_CLASS_OTHER";
|
|
2441
2479
|
}
|
|
2442
|
-
function
|
|
2480
|
+
function bn() {
|
|
2443
2481
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2444
2482
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2445
2483
|
let t = {
|
|
@@ -2458,17 +2496,17 @@ function gn() {
|
|
|
2458
2496
|
}
|
|
2459
2497
|
return typeof e.downlink == "number" && e.downlink > 0 && (i.downlinkKbps = Math.round(e.downlink * 1e3)), typeof e.rtt == "number" && e.rtt > 0 && (i.rttMs = Math.round(e.rtt)), e.saveData && (i.saveData = !0), i;
|
|
2460
2498
|
}
|
|
2461
|
-
function
|
|
2462
|
-
let t =
|
|
2463
|
-
deviceClass:
|
|
2499
|
+
function xn(e) {
|
|
2500
|
+
let t = vn(), n = {
|
|
2501
|
+
deviceClass: yn(),
|
|
2464
2502
|
integration: t.integration,
|
|
2465
|
-
...
|
|
2503
|
+
...bn()
|
|
2466
2504
|
};
|
|
2467
2505
|
t.host && (n.host = t.host), typeof screen < "u" && screen.width > 0 && (n.screenWidth = screen.width, n.screenHeight = screen.height), typeof window < "u" && window.devicePixelRatio > 0 && (n.devicePixelRatio = Math.round(window.devicePixelRatio * 100) / 100);
|
|
2468
2506
|
let r = e.getBoundingClientRect?.();
|
|
2469
2507
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2470
2508
|
}
|
|
2471
|
-
async function
|
|
2509
|
+
async function Sn() {
|
|
2472
2510
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2473
2511
|
if (!e?.getHighEntropyValues) return {};
|
|
2474
2512
|
try {
|
|
@@ -2480,7 +2518,7 @@ async function vn() {
|
|
|
2480
2518
|
}
|
|
2481
2519
|
//#endregion
|
|
2482
2520
|
//#region src/core/version.ts
|
|
2483
|
-
var
|
|
2521
|
+
var Cn = "2.16.9", wn = {
|
|
2484
2522
|
accent: "#E1B600",
|
|
2485
2523
|
accentText: "#1B1C23",
|
|
2486
2524
|
background: "#0e0f13",
|
|
@@ -2491,7 +2529,7 @@ var yn = "2.16.7", bn = {
|
|
|
2491
2529
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2492
2530
|
radius: "8px",
|
|
2493
2531
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2494
|
-
},
|
|
2532
|
+
}, Tn = {
|
|
2495
2533
|
accent: "--havik-accent",
|
|
2496
2534
|
accentText: "--havik-accent-text",
|
|
2497
2535
|
background: "--havik-bg",
|
|
@@ -2503,26 +2541,26 @@ var yn = "2.16.7", bn = {
|
|
|
2503
2541
|
radius: "--havik-radius",
|
|
2504
2542
|
fontFamily: "--havik-font"
|
|
2505
2543
|
};
|
|
2506
|
-
function
|
|
2544
|
+
function En(e, t) {
|
|
2507
2545
|
let n = {
|
|
2508
|
-
...
|
|
2546
|
+
...wn,
|
|
2509
2547
|
...t
|
|
2510
2548
|
};
|
|
2511
|
-
for (let t of Object.keys(
|
|
2549
|
+
for (let t of Object.keys(Tn)) e.style.setProperty(Tn[t], n[t]);
|
|
2512
2550
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2513
2551
|
}
|
|
2514
2552
|
//#endregion
|
|
2515
2553
|
//#region src/ui/styles.ts
|
|
2516
|
-
var
|
|
2517
|
-
function
|
|
2518
|
-
let n = e.querySelector(`style#${
|
|
2519
|
-
if (n && (!t ||
|
|
2554
|
+
var Dn = "havik-player-styles", On = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", kn = /* @__PURE__ */ new WeakMap();
|
|
2555
|
+
function An(e = document, t) {
|
|
2556
|
+
let n = e.querySelector(`style#${Dn}`);
|
|
2557
|
+
if (n && (!t || kn.get(n) === t)) return;
|
|
2520
2558
|
let r = e.createElement("style");
|
|
2521
|
-
r.id =
|
|
2559
|
+
r.id = Dn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = On, kn.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2522
2560
|
}
|
|
2523
2561
|
//#endregion
|
|
2524
2562
|
//#region src/ui/icons.ts
|
|
2525
|
-
var
|
|
2563
|
+
var jn = {
|
|
2526
2564
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2527
2565
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2528
2566
|
volumeHigh: "<path d=\"M3 10v4h4l5 5V5L7 10H3zm13.5 2a4.5 4.5 0 0 0-2.5-4v8a4.5 4.5 0 0 0 2.5-4zm-2.5-9v2.06A7 7 0 0 1 14 19v2a9 9 0 0 0 0-18z\"/>",
|
|
@@ -2535,21 +2573,21 @@ var En = {
|
|
|
2535
2573
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
2536
2574
|
retry: "<path d=\"M17.65 6.35A8 8 0 1 0 19.73 13h-2.08A6 6 0 1 1 12 6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"/>"
|
|
2537
2575
|
};
|
|
2538
|
-
function
|
|
2539
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2576
|
+
function Z(e) {
|
|
2577
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${jn[e]}</svg>`;
|
|
2540
2578
|
}
|
|
2541
2579
|
//#endregion
|
|
2542
2580
|
//#region src/ui/controls.ts
|
|
2543
|
-
var
|
|
2581
|
+
var Mn = 3e3, Nn = 250, Pn = /* @__PURE__ */ new Set([
|
|
2544
2582
|
"GONE",
|
|
2545
2583
|
"NOT_FOUND",
|
|
2546
2584
|
"INVALID_URN",
|
|
2547
2585
|
"UNAUTHORIZED"
|
|
2548
2586
|
]);
|
|
2549
|
-
function
|
|
2550
|
-
return new
|
|
2587
|
+
function Fn(e) {
|
|
2588
|
+
return new In(e);
|
|
2551
2589
|
}
|
|
2552
|
-
var
|
|
2590
|
+
var In = class {
|
|
2553
2591
|
root;
|
|
2554
2592
|
video;
|
|
2555
2593
|
player;
|
|
@@ -2595,7 +2633,7 @@ var jn = class {
|
|
|
2595
2633
|
scrubbing = !1;
|
|
2596
2634
|
offFns = [];
|
|
2597
2635
|
constructor(e) {
|
|
2598
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2636
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Mn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, An(this.doc, e.cspNonce), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
|
|
2599
2637
|
let t = (e, t, n) => {
|
|
2600
2638
|
let r = this.doc.createElement(e);
|
|
2601
2639
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2606,12 +2644,12 @@ var jn = class {
|
|
|
2606
2644
|
"aria-label": r,
|
|
2607
2645
|
title: r
|
|
2608
2646
|
});
|
|
2609
|
-
return i.innerHTML =
|
|
2647
|
+
return i.innerHTML = Z(n), i;
|
|
2610
2648
|
};
|
|
2611
2649
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
2612
2650
|
type: "button",
|
|
2613
2651
|
"aria-label": "Play"
|
|
2614
|
-
}), this.center.innerHTML =
|
|
2652
|
+
}), this.center.innerHTML = Z("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
|
|
2615
2653
|
role: "slider",
|
|
2616
2654
|
"aria-label": "Seek",
|
|
2617
2655
|
"aria-valuemin": "0",
|
|
@@ -2629,7 +2667,7 @@ var jn = class {
|
|
|
2629
2667
|
"aria-label": "Volume"
|
|
2630
2668
|
});
|
|
2631
2669
|
let a = t("div", "havik-vol");
|
|
2632
|
-
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML =
|
|
2670
|
+
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Z("liveDot");
|
|
2633
2671
|
let o = this.doc.createElement("span");
|
|
2634
2672
|
o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
|
|
2635
2673
|
let s = t("div", "havik-spacer");
|
|
@@ -2681,7 +2719,7 @@ var jn = class {
|
|
|
2681
2719
|
let t = this.surfaceWasHidden;
|
|
2682
2720
|
this.tapTimer = setTimeout(() => {
|
|
2683
2721
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2684
|
-
},
|
|
2722
|
+
}, Nn);
|
|
2685
2723
|
}
|
|
2686
2724
|
toggleBar(e) {
|
|
2687
2725
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2713,12 +2751,12 @@ var jn = class {
|
|
|
2713
2751
|
}
|
|
2714
2752
|
if (e === "preplay") {
|
|
2715
2753
|
let e = this.doc.createElement("button");
|
|
2716
|
-
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML =
|
|
2754
|
+
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Z("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
|
|
2717
2755
|
} else {
|
|
2718
2756
|
let r = this.doc.createElement("div");
|
|
2719
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2757
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Pn.has(this.lastError.code)) {
|
|
2720
2758
|
let e = this.doc.createElement("button");
|
|
2721
|
-
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${
|
|
2759
|
+
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Z("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
2722
2760
|
}
|
|
2723
2761
|
}
|
|
2724
2762
|
this.root.append(n), this.statusBox = n, this.show();
|
|
@@ -2757,7 +2795,7 @@ var jn = class {
|
|
|
2757
2795
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2758
2796
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2759
2797
|
}
|
|
2760
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2798
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Ln(this.video.currentTime)} / ${Ln(this.video.duration)}`);
|
|
2761
2799
|
}
|
|
2762
2800
|
syncLive() {
|
|
2763
2801
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2807,17 +2845,17 @@ var jn = class {
|
|
|
2807
2845
|
renderQualityMenu() {
|
|
2808
2846
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2809
2847
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2810
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2848
|
+
for (let n of e) this.menu.append(this.menuItem(Rn(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2811
2849
|
}
|
|
2812
2850
|
renderAudioMenu() {
|
|
2813
2851
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2814
2852
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2815
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2853
|
+
for (let t of e) this.menu.append(this.menuItem(zn(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2816
2854
|
}
|
|
2817
2855
|
renderCcMenu() {
|
|
2818
2856
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2819
2857
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2820
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2858
|
+
for (let t of e) this.menu.append(this.menuItem(Bn(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2821
2859
|
}
|
|
2822
2860
|
onTracksChanged() {
|
|
2823
2861
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2901,7 +2939,7 @@ var jn = class {
|
|
|
2901
2939
|
}
|
|
2902
2940
|
}
|
|
2903
2941
|
setIcon(e, t) {
|
|
2904
|
-
e.innerHTML =
|
|
2942
|
+
e.innerHTML = Z(t);
|
|
2905
2943
|
}
|
|
2906
2944
|
destroy() {
|
|
2907
2945
|
this.hideTimer && clearTimeout(this.hideTimer), this.tapTimer && clearTimeout(this.tapTimer);
|
|
@@ -2918,41 +2956,41 @@ var jn = class {
|
|
|
2918
2956
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2919
2957
|
}
|
|
2920
2958
|
};
|
|
2921
|
-
function
|
|
2959
|
+
function Ln(e) {
|
|
2922
2960
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2923
2961
|
let t = Math.floor(e % 60), n = Math.floor(e / 60 % 60), r = Math.floor(e / 3600), i = r > 0 ? String(n).padStart(2, "0") : String(n), a = String(t).padStart(2, "0");
|
|
2924
2962
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2925
2963
|
}
|
|
2926
|
-
function
|
|
2964
|
+
function Rn(e) {
|
|
2927
2965
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2928
2966
|
}
|
|
2929
|
-
function
|
|
2967
|
+
function zn(e) {
|
|
2930
2968
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2931
2969
|
}
|
|
2932
|
-
function
|
|
2970
|
+
function Bn(e) {
|
|
2933
2971
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2934
2972
|
}
|
|
2935
2973
|
//#endregion
|
|
2936
2974
|
//#region src/managed/index.ts
|
|
2937
|
-
var
|
|
2938
|
-
function
|
|
2975
|
+
var Vn = 6e3, Q = 45e3, Hn = 2e3, Un = 3, Wn = 2e3, Gn = 48e4, Kn = "keySystemLicenseRequestFailed";
|
|
2976
|
+
function qn(e) {
|
|
2939
2977
|
if (e.env !== void 0 && e.baseUrl !== void 0) throw new n("INTERNAL", 0, `createPlayer: pass env OR baseUrl, not both (got env=${JSON.stringify(e.env)} and baseUrl=${JSON.stringify(e.baseUrl)})`);
|
|
2940
|
-
if (e.env !== void 0) return
|
|
2978
|
+
if (e.env !== void 0) return Ge(e.env);
|
|
2941
2979
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2942
2980
|
return e.baseUrl;
|
|
2943
2981
|
}
|
|
2944
|
-
async function
|
|
2982
|
+
async function Jn(e) {
|
|
2945
2983
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2946
|
-
let t =
|
|
2984
|
+
let t = qn(e);
|
|
2947
2985
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2948
2986
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2949
|
-
let r = new
|
|
2987
|
+
let r = new Yn({
|
|
2950
2988
|
...e,
|
|
2951
2989
|
baseUrl: t
|
|
2952
2990
|
});
|
|
2953
2991
|
return await r.start(), r;
|
|
2954
2992
|
}
|
|
2955
|
-
var
|
|
2993
|
+
var Yn = class {
|
|
2956
2994
|
opts;
|
|
2957
2995
|
abort = new AbortController();
|
|
2958
2996
|
listeners = {};
|
|
@@ -2999,7 +3037,7 @@ var Gn = class {
|
|
|
2999
3037
|
this.opts.muted && (this.opts.video.muted = !0), this.opts.poster && (this.opts.video.poster = this.opts.poster), this.mountControls(), this.attachPipListeners(), this.setState("loading");
|
|
3000
3038
|
let e = ++this.loadGen, t = this.resolveOptions();
|
|
3001
3039
|
try {
|
|
3002
|
-
let n = await
|
|
3040
|
+
let n = await y(t);
|
|
3003
3041
|
if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
|
|
3004
3042
|
let e = this._lastError;
|
|
3005
3043
|
throw this.destroy(), e;
|
|
@@ -3026,7 +3064,7 @@ var Gn = class {
|
|
|
3026
3064
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
3027
3065
|
}
|
|
3028
3066
|
beginArmingByPolling(e) {
|
|
3029
|
-
|
|
3067
|
+
b({
|
|
3030
3068
|
...this.resolveOptions(),
|
|
3031
3069
|
signal: this.abort.signal,
|
|
3032
3070
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -3043,7 +3081,7 @@ var Gn = class {
|
|
|
3043
3081
|
setTimeout(() => {
|
|
3044
3082
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3045
3083
|
phase: i ? "unavailable" : "tooEarly",
|
|
3046
|
-
retryInMs:
|
|
3084
|
+
retryInMs: Q,
|
|
3047
3085
|
attempt: 1,
|
|
3048
3086
|
elapsedMs: 0,
|
|
3049
3087
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3060,7 +3098,7 @@ var Gn = class {
|
|
|
3060
3098
|
}
|
|
3061
3099
|
}
|
|
3062
3100
|
}, h = () => {
|
|
3063
|
-
a || s || p() || (s = !0,
|
|
3101
|
+
a || s || p() || (s = !0, b({
|
|
3064
3102
|
...this.resolveOptions(),
|
|
3065
3103
|
signal: c.signal,
|
|
3066
3104
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -3068,7 +3106,7 @@ var Gn = class {
|
|
|
3068
3106
|
a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
|
|
3069
3107
|
}));
|
|
3070
3108
|
}, g = () => {
|
|
3071
|
-
a || p() ||
|
|
3109
|
+
a || p() || y(this.resolveOptions()).then((e) => m(e)).catch((e) => {
|
|
3072
3110
|
if (!(a || p())) {
|
|
3073
3111
|
if (e instanceof n && o(e.code)) {
|
|
3074
3112
|
h();
|
|
@@ -3082,13 +3120,13 @@ var Gn = class {
|
|
|
3082
3120
|
!a && !p() && h();
|
|
3083
3121
|
}, e);
|
|
3084
3122
|
};
|
|
3085
|
-
_(
|
|
3123
|
+
_(Vn), this.armingSub = T({
|
|
3086
3124
|
eventsBaseUrl: t,
|
|
3087
3125
|
matchUrn: this.opts.matchUrn,
|
|
3088
3126
|
credential: this.opts.credential,
|
|
3089
|
-
onAlive: () => _(
|
|
3127
|
+
onAlive: () => _(Q),
|
|
3090
3128
|
onState: (e) => {
|
|
3091
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3129
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Hn);
|
|
3092
3130
|
},
|
|
3093
3131
|
onError: () => h()
|
|
3094
3132
|
});
|
|
@@ -3111,7 +3149,7 @@ var Gn = class {
|
|
|
3111
3149
|
let n = await s(this.opts.credential);
|
|
3112
3150
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3113
3151
|
this.setState("loading");
|
|
3114
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3152
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Ze(this.opts.video, (e) => {
|
|
3115
3153
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3116
3154
|
});
|
|
3117
3155
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3133,26 +3171,26 @@ var Gn = class {
|
|
|
3133
3171
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3134
3172
|
let i = e.analytics?.sid;
|
|
3135
3173
|
if (!i) return;
|
|
3136
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3174
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = gn(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3137
3175
|
if (!o) {
|
|
3138
3176
|
s && setTimeout(() => {
|
|
3139
3177
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3140
3178
|
}, 0);
|
|
3141
3179
|
return;
|
|
3142
3180
|
}
|
|
3143
|
-
let c = this.opts.video, l = new
|
|
3181
|
+
let c = this.opts.video, l = new _n({
|
|
3144
3182
|
endpoint: o,
|
|
3145
3183
|
sid: i,
|
|
3146
3184
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3147
|
-
sdkVersion:
|
|
3148
|
-
environment:
|
|
3185
|
+
sdkVersion: Cn,
|
|
3186
|
+
environment: xn(c),
|
|
3149
3187
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3150
3188
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3151
3189
|
onBlocked: (e) => setTimeout(() => {
|
|
3152
3190
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3153
3191
|
}, 0),
|
|
3154
3192
|
sample: () => {
|
|
3155
|
-
let e = this.engine?.getStats() ??
|
|
3193
|
+
let e = this.engine?.getStats() ?? Ke, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3156
3194
|
return {
|
|
3157
3195
|
...e,
|
|
3158
3196
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3166,7 +3204,7 @@ var Gn = class {
|
|
|
3166
3204
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3167
3205
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3168
3206
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3169
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3207
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Sn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3170
3208
|
}
|
|
3171
3209
|
currentPresentation() {
|
|
3172
3210
|
let e = this.opts.video;
|
|
@@ -3192,11 +3230,11 @@ var Gn = class {
|
|
|
3192
3230
|
emit: (e) => this.onEngineEvent(e),
|
|
3193
3231
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3194
3232
|
}, o = this.opts.engine ?? "auto";
|
|
3195
|
-
if (o === "native") return new
|
|
3196
|
-
if (o === "hls") return new
|
|
3197
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
3198
|
-
if (
|
|
3199
|
-
if (
|
|
3233
|
+
if (o === "native") return new W(a);
|
|
3234
|
+
if (o === "hls") return new Zt(a);
|
|
3235
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled && at() && H(this.opts.video)) return new W(a);
|
|
3236
|
+
if (_t()) return new Zt(a);
|
|
3237
|
+
if (H(this.opts.video)) return new W(a);
|
|
3200
3238
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3201
3239
|
}
|
|
3202
3240
|
onEngineEvent(e) {
|
|
@@ -3258,7 +3296,7 @@ var Gn = class {
|
|
|
3258
3296
|
r = 0, i = !1;
|
|
3259
3297
|
},
|
|
3260
3298
|
onError: () => {
|
|
3261
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
3299
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Un && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
|
|
3262
3300
|
}
|
|
3263
3301
|
});
|
|
3264
3302
|
}
|
|
@@ -3280,7 +3318,7 @@ var Gn = class {
|
|
|
3280
3318
|
scheduleRejoin(e) {
|
|
3281
3319
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3282
3320
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3283
|
-
}, Math.random() *
|
|
3321
|
+
}, Math.random() * Hn));
|
|
3284
3322
|
}
|
|
3285
3323
|
cancelRejoin() {
|
|
3286
3324
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3304,7 +3342,7 @@ var Gn = class {
|
|
|
3304
3342
|
}
|
|
3305
3343
|
t.controls = !1;
|
|
3306
3344
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3307
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3345
|
+
r && r.insertBefore(n, t), n.appendChild(t), En(n, this.opts.theme), this.container = n, this.controlBar = Fn({
|
|
3308
3346
|
root: n,
|
|
3309
3347
|
video: t,
|
|
3310
3348
|
player: this,
|
|
@@ -3335,7 +3373,7 @@ var Gn = class {
|
|
|
3335
3373
|
}
|
|
3336
3374
|
startStats() {
|
|
3337
3375
|
this.stopStats();
|
|
3338
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3376
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Wn);
|
|
3339
3377
|
this.statsTimer = setInterval(() => {
|
|
3340
3378
|
if (!this.engine) return;
|
|
3341
3379
|
let e = this.engine.getStats();
|
|
@@ -3346,14 +3384,14 @@ var Gn = class {
|
|
|
3346
3384
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3347
3385
|
}
|
|
3348
3386
|
isStaleLicenseDenial(e) {
|
|
3349
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3387
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Kn || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3350
3388
|
}
|
|
3351
3389
|
scheduleLicenseRefresh() {
|
|
3352
3390
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3353
3391
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3354
3392
|
document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3355
3393
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3356
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3394
|
+
let e = this.opts.licenseRefreshMs ?? Gn;
|
|
3357
3395
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3358
3396
|
}
|
|
3359
3397
|
stopRefresh() {
|
|
@@ -3365,7 +3403,7 @@ var Gn = class {
|
|
|
3365
3403
|
if (this.refreshInFlight?.engine === e) return this.refreshInFlight.promise;
|
|
3366
3404
|
let t = (async () => {
|
|
3367
3405
|
try {
|
|
3368
|
-
let t = await
|
|
3406
|
+
let t = await y(this.resolveOptions());
|
|
3369
3407
|
if (this.destroyed || this.engine !== e) return;
|
|
3370
3408
|
let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
|
|
3371
3409
|
return (n || r) && (e.setLicenseUrls({
|
|
@@ -3409,7 +3447,7 @@ var Gn = class {
|
|
|
3409
3447
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3410
3448
|
}
|
|
3411
3449
|
getStats() {
|
|
3412
|
-
return this.engine?.getStats() ??
|
|
3450
|
+
return this.engine?.getStats() ?? Ke;
|
|
3413
3451
|
}
|
|
3414
3452
|
getQualityLevels() {
|
|
3415
3453
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3461,7 +3499,7 @@ var Gn = class {
|
|
|
3461
3499
|
let e = ++this.loadGen;
|
|
3462
3500
|
this.teardownPlayback();
|
|
3463
3501
|
try {
|
|
3464
|
-
let t = await
|
|
3502
|
+
let t = await b({
|
|
3465
3503
|
...this.resolveOptions(),
|
|
3466
3504
|
waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
|
|
3467
3505
|
});
|
|
@@ -3519,7 +3557,7 @@ function $(e) {
|
|
|
3519
3557
|
}
|
|
3520
3558
|
//#endregion
|
|
3521
3559
|
//#region src/embed/host.ts
|
|
3522
|
-
function
|
|
3560
|
+
function Xn(e) {
|
|
3523
3561
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3524
3562
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3525
3563
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3578,15 +3616,15 @@ function Kn(e) {
|
|
|
3578
3616
|
}
|
|
3579
3617
|
//#endregion
|
|
3580
3618
|
//#region src/embed/page.ts
|
|
3581
|
-
var
|
|
3582
|
-
function
|
|
3619
|
+
var Zn = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3620
|
+
function Qn(e) {
|
|
3583
3621
|
if (typeof e == "boolean") return e;
|
|
3584
3622
|
if (typeof e == "object" && e) {
|
|
3585
3623
|
let t = e.endpoint;
|
|
3586
3624
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3587
3625
|
}
|
|
3588
3626
|
}
|
|
3589
|
-
function
|
|
3627
|
+
function $n() {
|
|
3590
3628
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3591
3629
|
if (e) return {
|
|
3592
3630
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3596,7 +3634,7 @@ function Yn() {
|
|
|
3596
3634
|
autoplay: e.autoplay ?? !0,
|
|
3597
3635
|
muted: e.muted ?? !0,
|
|
3598
3636
|
waitForLive: e.waitForLive ?? !0,
|
|
3599
|
-
analytics:
|
|
3637
|
+
analytics: Qn(e.analytics)
|
|
3600
3638
|
};
|
|
3601
3639
|
let t = new URLSearchParams(location.search);
|
|
3602
3640
|
return {
|
|
@@ -3609,9 +3647,9 @@ function Yn() {
|
|
|
3609
3647
|
waitForLive: !0
|
|
3610
3648
|
};
|
|
3611
3649
|
}
|
|
3612
|
-
async function
|
|
3613
|
-
let e =
|
|
3614
|
-
|
|
3650
|
+
async function er() {
|
|
3651
|
+
let e = $n();
|
|
3652
|
+
nr();
|
|
3615
3653
|
let t = document.createElement("video");
|
|
3616
3654
|
t.setAttribute("playsinline", ""), t.muted = e.muted ?? !0, t.style.cssText = "width:100%;height:100%;object-fit:contain;background:#000;aspect-ratio:auto", document.body.appendChild(t);
|
|
3617
3655
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3666,12 +3704,12 @@ async function Xn() {
|
|
|
3666
3704
|
code: e.code,
|
|
3667
3705
|
message: e.message
|
|
3668
3706
|
})), e.on("autoplayblocked", () => {
|
|
3669
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3707
|
+
i({ type: "oddin:autoplayblocked" }), tr(t, e);
|
|
3670
3708
|
});
|
|
3671
3709
|
}, s = async (r) => {
|
|
3672
3710
|
a?.destroy(), a = null;
|
|
3673
3711
|
try {
|
|
3674
|
-
let n = await
|
|
3712
|
+
let n = await Jn({
|
|
3675
3713
|
video: t,
|
|
3676
3714
|
baseUrl: e.baseUrl,
|
|
3677
3715
|
matchUrn: r,
|
|
@@ -3733,7 +3771,7 @@ async function Xn() {
|
|
|
3733
3771
|
a?.retry();
|
|
3734
3772
|
break;
|
|
3735
3773
|
case "oddin:load":
|
|
3736
|
-
typeof e.matchUrn == "string" &&
|
|
3774
|
+
typeof e.matchUrn == "string" && Zn.test(e.matchUrn) && s(e.matchUrn);
|
|
3737
3775
|
break;
|
|
3738
3776
|
case "oddin:destroy": c();
|
|
3739
3777
|
}
|
|
@@ -3745,18 +3783,18 @@ async function Xn() {
|
|
|
3745
3783
|
protocol: 1
|
|
3746
3784
|
});
|
|
3747
3785
|
}
|
|
3748
|
-
function
|
|
3786
|
+
function tr(e, t) {
|
|
3749
3787
|
if (document.getElementById("havik-tap")) return;
|
|
3750
3788
|
let n = document.createElement("button");
|
|
3751
3789
|
n.id = "havik-tap", n.textContent = "▶ Tap to play", n.style.cssText = "position:fixed;inset:0;width:100%;height:100%;border:0;background:rgba(0,0,0,.55);color:#fff;font:600 18px system-ui,sans-serif;cursor:pointer;z-index:9", n.addEventListener("click", () => {
|
|
3752
3790
|
n.remove(), t.play();
|
|
3753
3791
|
}), document.body.appendChild(n);
|
|
3754
3792
|
}
|
|
3755
|
-
function
|
|
3793
|
+
function nr() {
|
|
3756
3794
|
let e = document.createElement("style");
|
|
3757
3795
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3758
3796
|
}
|
|
3759
3797
|
//#endregion
|
|
3760
|
-
export {
|
|
3798
|
+
export { wn as ODDIN_THEME, n as PlaybackError, En as applyTheme, Ge as baseUrlForEnv, er as bootEmbed, Te as clearDeviceId, Jn as createPlayer, E as deriveEventsBaseUrl, Ve as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, k as getDeviceId, Ue as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, Xn as mountEmbed, v as pollToLive, b as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
|
|
3761
3799
|
|
|
3762
3800
|
//# sourceMappingURL=index.js.map
|