@oddin-gg/havik-player 2.16.5 → 2.16.6
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.js +299 -274
- package/dist/index.js.map +1 -1
- package/docs/API.md +14 -12
- 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
|
+
}, z = /* @__PURE__ */ new Map(), B = /* @__PURE__ */ new Map();
|
|
680
|
+
function je(e) {
|
|
681
|
+
let t = L(e), n = z.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) => (B.set(t, e), e));
|
|
700
|
+
return z.set(t, i), i;
|
|
701
701
|
}
|
|
702
|
-
function
|
|
703
|
-
if (j()) for (let e of Object.values(
|
|
702
|
+
function Me() {
|
|
703
|
+
if (j()) for (let e of Object.values(R)) je(e);
|
|
704
704
|
}
|
|
705
|
-
function
|
|
705
|
+
function Ne(e) {
|
|
706
706
|
let t = I(e);
|
|
707
|
-
if (t) return t === "avc" ? !0 :
|
|
707
|
+
if (t) return t === "avc" ? !0 : B.get(L(e)) ?? B.get(L(R[t]));
|
|
708
708
|
}
|
|
709
709
|
//#endregion
|
|
710
710
|
//#region src/core/drm/support.ts
|
|
711
|
-
var
|
|
711
|
+
var Pe = 5e3, Fe = "video/mp4; codecs=\"avc1.42E01E\"", Ie = "audio/mp4; codecs=\"mp4a.40.2\"", Le = {
|
|
712
712
|
widevine: ["com.widevine.alpha"],
|
|
713
713
|
fairplay: ["com.apple.fps"]
|
|
714
714
|
};
|
|
715
|
-
function
|
|
715
|
+
function Re(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: Fe,
|
|
724
724
|
robustness: "",
|
|
725
725
|
encryptionScheme: "cbcs"
|
|
726
726
|
}],
|
|
727
727
|
audioCapabilities: [{
|
|
728
|
-
contentType:
|
|
728
|
+
contentType: Ie,
|
|
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: Fe,
|
|
736
736
|
robustness: F.video,
|
|
737
737
|
encryptionScheme: F.scheme
|
|
738
738
|
}],
|
|
739
739
|
audioCapabilities: [{
|
|
740
|
-
contentType:
|
|
740
|
+
contentType: Ie,
|
|
741
741
|
robustness: F.audio,
|
|
742
742
|
encryptionScheme: F.scheme
|
|
743
743
|
}]
|
|
744
744
|
}]);
|
|
745
745
|
}
|
|
746
|
-
function
|
|
746
|
+
function ze(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 Be(e = {}) {
|
|
757
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Pe, 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 = Le[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 ze((await ze(i(n, Re(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 Ve = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
805
|
+
function He(e) {
|
|
806
|
+
return Ve.test(e);
|
|
807
807
|
}
|
|
808
808
|
//#endregion
|
|
809
809
|
//#region src/core/env.ts
|
|
810
|
-
var
|
|
810
|
+
var Ue = {
|
|
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 We(e) {
|
|
815
|
+
let t = Object.prototype.hasOwnProperty.call(Ue, e) ? Ue[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 Ge = { droppedFrames: 0 };
|
|
822
|
+
function Ke(e) {
|
|
823
823
|
try {
|
|
824
824
|
return new URL(e).host;
|
|
825
825
|
} catch {
|
|
@@ -831,7 +831,7 @@ function Je(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" || qe.test(i.name)) && i.startTime >= n) {
|
|
834
|
-
let e =
|
|
834
|
+
let e = Ke(i.name);
|
|
835
835
|
e && (t = e, n = i.startTime);
|
|
836
836
|
}
|
|
837
837
|
return t;
|
|
@@ -843,7 +843,7 @@ function V(e) {
|
|
|
843
843
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
844
844
|
};
|
|
845
845
|
}
|
|
846
|
-
var
|
|
846
|
+
var Ye = class {
|
|
847
847
|
video;
|
|
848
848
|
baseFrames = 0;
|
|
849
849
|
baseDropped = 0;
|
|
@@ -866,7 +866,7 @@ var H = class {
|
|
|
866
866
|
};
|
|
867
867
|
}
|
|
868
868
|
};
|
|
869
|
-
function
|
|
869
|
+
function Xe(e, t) {
|
|
870
870
|
let n = [
|
|
871
871
|
["playing", () => t("playing")],
|
|
872
872
|
["waiting", () => t("buffering")],
|
|
@@ -883,8 +883,8 @@ function Ye(e, t) {
|
|
|
883
883
|
}
|
|
884
884
|
//#endregion
|
|
885
885
|
//#region src/core/engine/native.ts
|
|
886
|
-
var
|
|
887
|
-
function
|
|
886
|
+
var Ze = 2e3, Qe = 3, H = 500, $e = 6e3, et = .25;
|
|
887
|
+
function tt(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 et(e) {
|
|
|
892
892
|
return;
|
|
893
893
|
}
|
|
894
894
|
}
|
|
895
|
-
function
|
|
895
|
+
function U(e) {
|
|
896
896
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
897
897
|
}
|
|
898
|
-
function
|
|
898
|
+
function W() {
|
|
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 nt() {
|
|
904
|
+
if (typeof navigator > "u" || !W()) 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 G = class {
|
|
909
909
|
name = "native";
|
|
910
910
|
deps;
|
|
911
911
|
onLoaded;
|
|
@@ -927,7 +927,7 @@ var K = class {
|
|
|
927
927
|
frameCounter;
|
|
928
928
|
detachFrames = null;
|
|
929
929
|
constructor(e) {
|
|
930
|
-
this.deps = e, this.frameCounter = new
|
|
930
|
+
this.deps = e, this.frameCounter = new Ye(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
|
|
931
931
|
}
|
|
932
932
|
async load() {
|
|
933
933
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -948,7 +948,7 @@ var K = class {
|
|
|
948
948
|
type: "error",
|
|
949
949
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
950
950
|
fatal: !0
|
|
951
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
951
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = rt(t.manifestUrl, t.analytics?.sid), e.load();
|
|
952
952
|
}
|
|
953
953
|
startLoad() {
|
|
954
954
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -970,7 +970,7 @@ var K = class {
|
|
|
970
970
|
});
|
|
971
971
|
this.onEncrypted = (n) => {
|
|
972
972
|
let i = n;
|
|
973
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
973
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = tt(i.initData), (async () => {
|
|
974
974
|
try {
|
|
975
975
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
976
976
|
initDataTypes: [i.initDataType],
|
|
@@ -1092,7 +1092,7 @@ var K = class {
|
|
|
1092
1092
|
return;
|
|
1093
1093
|
}
|
|
1094
1094
|
let t = this.hiddenSince;
|
|
1095
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1095
|
+
this.hiddenSince = null, t != null && e - t >= Ze && this.armRefocus();
|
|
1096
1096
|
}, this.onPageShow = (e) => {
|
|
1097
1097
|
e.persisted && this.armRefocus();
|
|
1098
1098
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
@@ -1101,15 +1101,15 @@ var K = class {
|
|
|
1101
1101
|
if (this.cancelRefocus(), Number.isFinite(this.deps.video.duration)) return;
|
|
1102
1102
|
let e = this.liveEnd(), t = () => typeof performance < "u" ? performance.now() : Date.now(), n = t(), r = 0, i = () => {
|
|
1103
1103
|
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 +
|
|
1104
|
+
r += H;
|
|
1105
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + et), s = Math.max(r, t() - n) >= $e;
|
|
1106
1106
|
if (o || s && a != null) {
|
|
1107
1107
|
this.snapToLive();
|
|
1108
1108
|
return;
|
|
1109
1109
|
}
|
|
1110
|
-
this.refocusTimer = setTimeout(i,
|
|
1110
|
+
this.refocusTimer = setTimeout(i, H);
|
|
1111
1111
|
};
|
|
1112
|
-
this.refocusTimer = setTimeout(i,
|
|
1112
|
+
this.refocusTimer = setTimeout(i, H);
|
|
1113
1113
|
}
|
|
1114
1114
|
cancelRefocus() {
|
|
1115
1115
|
this.refocusTimer != null && clearTimeout(this.refocusTimer), this.refocusTimer = null;
|
|
@@ -1123,7 +1123,7 @@ var K = class {
|
|
|
1123
1123
|
snapToLive() {
|
|
1124
1124
|
let e = this.deps.video, t = this.liveEnd();
|
|
1125
1125
|
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 -
|
|
1126
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - Qe, r);
|
|
1127
1127
|
try {
|
|
1128
1128
|
e.currentTime = i;
|
|
1129
1129
|
} catch {}
|
|
@@ -1141,13 +1141,25 @@ var K = class {
|
|
|
1141
1141
|
} catch {}
|
|
1142
1142
|
}
|
|
1143
1143
|
};
|
|
1144
|
-
function
|
|
1144
|
+
function rt(e, t) {
|
|
1145
1145
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1146
1146
|
}
|
|
1147
1147
|
//#endregion
|
|
1148
|
+
//#region src/core/drm/signedUrl.ts
|
|
1149
|
+
function K(e, t = Date.now()) {
|
|
1150
|
+
if (!e) return !1;
|
|
1151
|
+
let n;
|
|
1152
|
+
try {
|
|
1153
|
+
n = new URL(e).searchParams.get("exp");
|
|
1154
|
+
} catch {
|
|
1155
|
+
return !1;
|
|
1156
|
+
}
|
|
1157
|
+
return !n || !/^\d+$/.test(n) ? !1 : Number(n) * 1e3 <= t;
|
|
1158
|
+
}
|
|
1159
|
+
//#endregion
|
|
1148
1160
|
//#region src/core/engine/prefetch.ts
|
|
1149
|
-
var
|
|
1150
|
-
function
|
|
1161
|
+
var it = 15e3, at = 5e3, ot = 6;
|
|
1162
|
+
function st(e) {
|
|
1151
1163
|
try {
|
|
1152
1164
|
let t = new URL(e);
|
|
1153
1165
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1155,7 +1167,7 @@ function ot(e) {
|
|
|
1155
1167
|
return e;
|
|
1156
1168
|
}
|
|
1157
1169
|
}
|
|
1158
|
-
var
|
|
1170
|
+
var ct = class {
|
|
1159
1171
|
cmcd;
|
|
1160
1172
|
entries = /* @__PURE__ */ new Map();
|
|
1161
1173
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1178,10 +1190,10 @@ var st = class {
|
|
|
1178
1190
|
}
|
|
1179
1191
|
prefetch(e, t, n) {
|
|
1180
1192
|
if (!this.isActive(t)) return;
|
|
1181
|
-
let r =
|
|
1193
|
+
let r = st(e);
|
|
1182
1194
|
if (this.entries.has(r)) return;
|
|
1183
1195
|
let i = this.perTrack.get(t) ?? 0;
|
|
1184
|
-
if (i >=
|
|
1196
|
+
if (i >= ot) return;
|
|
1185
1197
|
this.perTrack.set(t, i + 1);
|
|
1186
1198
|
let a = new AbortController(), o = {
|
|
1187
1199
|
started: performance.now(),
|
|
@@ -1195,10 +1207,10 @@ var st = class {
|
|
|
1195
1207
|
signal: a.signal
|
|
1196
1208
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1197
1209
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1198
|
-
},
|
|
1210
|
+
}, it);
|
|
1199
1211
|
}
|
|
1200
1212
|
take(e) {
|
|
1201
|
-
let t =
|
|
1213
|
+
let t = st(e), n = this.entries.get(t);
|
|
1202
1214
|
return n && this.entries.delete(t), n;
|
|
1203
1215
|
}
|
|
1204
1216
|
destroy() {
|
|
@@ -1218,13 +1230,13 @@ var st = class {
|
|
|
1218
1230
|
}
|
|
1219
1231
|
}
|
|
1220
1232
|
};
|
|
1221
|
-
function
|
|
1233
|
+
function lt(t) {
|
|
1222
1234
|
let n = e.DefaultConfig?.loader;
|
|
1223
1235
|
if (typeof n != "function") return;
|
|
1224
1236
|
class r extends n {
|
|
1225
1237
|
served = !1;
|
|
1226
1238
|
cancelled = !1;
|
|
1227
|
-
stats =
|
|
1239
|
+
stats = ut();
|
|
1228
1240
|
load(e, n, r) {
|
|
1229
1241
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1230
1242
|
if (!i) {
|
|
@@ -1232,7 +1244,7 @@ function ct(t) {
|
|
|
1232
1244
|
return;
|
|
1233
1245
|
}
|
|
1234
1246
|
this.served = !0;
|
|
1235
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1247
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || at, s = setTimeout(() => {
|
|
1236
1248
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1237
1249
|
}, o);
|
|
1238
1250
|
i.bytes.then((o) => {
|
|
@@ -1259,7 +1271,7 @@ function ct(t) {
|
|
|
1259
1271
|
}
|
|
1260
1272
|
return r;
|
|
1261
1273
|
}
|
|
1262
|
-
function
|
|
1274
|
+
function ut() {
|
|
1263
1275
|
return {
|
|
1264
1276
|
aborted: !1,
|
|
1265
1277
|
loaded: 0,
|
|
@@ -1283,10 +1295,10 @@ function lt() {
|
|
|
1283
1295
|
}
|
|
1284
1296
|
};
|
|
1285
1297
|
}
|
|
1286
|
-
function
|
|
1298
|
+
function dt(e) {
|
|
1287
1299
|
return e === "audio" ? "audio" : "main";
|
|
1288
1300
|
}
|
|
1289
|
-
function
|
|
1301
|
+
function ft(e, t) {
|
|
1290
1302
|
let n = [];
|
|
1291
1303
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1292
1304
|
url: t.initSegment.url,
|
|
@@ -1305,24 +1317,24 @@ function dt(e, t) {
|
|
|
1305
1317
|
}
|
|
1306
1318
|
//#endregion
|
|
1307
1319
|
//#region src/core/engine/hls.ts
|
|
1308
|
-
function
|
|
1320
|
+
function pt() {
|
|
1309
1321
|
return e.isSupported();
|
|
1310
1322
|
}
|
|
1311
|
-
var
|
|
1312
|
-
function
|
|
1323
|
+
var mt = 3, ht = 5, gt = 3, _t = 1e4, vt = 3e4, yt = 12e3, bt = 3e3, xt = 6e3, St = .5, Ct = 3, wt = .5, Tt = 1.1, Et = .25, Dt = 5e3, Ot = 4e3, kt = 2, At = 5, jt = 2, Mt = 2, Nt = 4, Pt = 4, Ft = 2e3, It = 3e4, Lt = .2, Rt = 30, zt = 2, Bt = 2, Vt = 9, Ht = .5, Ut = 64;
|
|
1324
|
+
function Wt(e) {
|
|
1313
1325
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1314
1326
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1315
1327
|
return;
|
|
1316
1328
|
}
|
|
1317
|
-
e.liveSyncDuration ??=
|
|
1318
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1319
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1329
|
+
e.liveSyncDuration ??= Bt;
|
|
1330
|
+
let t = Math.max(12, e.liveSyncDuration + Vt);
|
|
1331
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Gt(e, e.liveSyncDuration);
|
|
1320
1332
|
}
|
|
1321
|
-
function
|
|
1333
|
+
function Gt(e, t) {
|
|
1322
1334
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1323
1335
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1324
1336
|
}
|
|
1325
|
-
var
|
|
1337
|
+
var Kt = class {
|
|
1326
1338
|
name = "hls";
|
|
1327
1339
|
hls = null;
|
|
1328
1340
|
deps;
|
|
@@ -1402,11 +1414,11 @@ var Wt = class {
|
|
|
1402
1414
|
frameCounter;
|
|
1403
1415
|
detachFrames = null;
|
|
1404
1416
|
constructor(e) {
|
|
1405
|
-
this.deps = e, this.frameCounter = new
|
|
1417
|
+
this.deps = e, this.frameCounter = new Ye(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1406
1418
|
}
|
|
1407
1419
|
async load() {
|
|
1408
1420
|
this.detachFrames ??= this.frameCounter.attach();
|
|
1409
|
-
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a =
|
|
1421
|
+
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = U(r) && W(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
1410
1422
|
if (e.drmEnabled && !o) {
|
|
1411
1423
|
i({
|
|
1412
1424
|
type: "error",
|
|
@@ -1415,7 +1427,7 @@ var Wt = class {
|
|
|
1415
1427
|
});
|
|
1416
1428
|
return;
|
|
1417
1429
|
}
|
|
1418
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r),
|
|
1430
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Me()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1419
1431
|
let e = this.hls;
|
|
1420
1432
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1421
1433
|
let t = e.liveSyncPosition;
|
|
@@ -1438,7 +1450,7 @@ var Wt = class {
|
|
|
1438
1450
|
}
|
|
1439
1451
|
this.loadSuspended = !0;
|
|
1440
1452
|
}
|
|
1441
|
-
},
|
|
1453
|
+
}, Dt));
|
|
1442
1454
|
}
|
|
1443
1455
|
resumeLoading() {
|
|
1444
1456
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1470,7 +1482,7 @@ var Wt = class {
|
|
|
1470
1482
|
let t = e.liveSyncPosition;
|
|
1471
1483
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1472
1484
|
let { video: n } = this.deps;
|
|
1473
|
-
n.currentTime <= t +
|
|
1485
|
+
n.currentTime <= t + Ht || (n.currentTime = t);
|
|
1474
1486
|
}
|
|
1475
1487
|
startHls() {
|
|
1476
1488
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1496,10 +1508,21 @@ var Wt = class {
|
|
|
1496
1508
|
},
|
|
1497
1509
|
...j() ? { requestMediaKeySystemAccessFunc: P(t) } : {},
|
|
1498
1510
|
licenseXhrSetup: (e, t) => {
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1511
|
+
let o = performance.now(), s = () => {
|
|
1512
|
+
e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a), this.licenseRequested = !0, e.addEventListener("loadend", () => {
|
|
1513
|
+
this.licenseTimeMs === 0 && (this.licenseTimeMs = Math.max(1, Math.round(performance.now() - o)));
|
|
1514
|
+
});
|
|
1515
|
+
}, { freshLicenseUrl: c } = this.deps;
|
|
1516
|
+
if (!c || !K(this.licenseUrl)) {
|
|
1517
|
+
s();
|
|
1518
|
+
return;
|
|
1519
|
+
}
|
|
1520
|
+
let l = this.hls, u, d = new Promise((e) => {
|
|
1521
|
+
u = setTimeout(() => e(void 0), _t);
|
|
1522
|
+
});
|
|
1523
|
+
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1524
|
+
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
1525
|
+
e && (this.licenseUrl = e), s();
|
|
1503
1526
|
});
|
|
1504
1527
|
}
|
|
1505
1528
|
} : {},
|
|
@@ -1511,20 +1534,20 @@ var Wt = class {
|
|
|
1511
1534
|
...c
|
|
1512
1535
|
};
|
|
1513
1536
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
|
|
1514
|
-
let e = new
|
|
1537
|
+
let e = new ct({
|
|
1515
1538
|
sessionId: n.analytics?.sid,
|
|
1516
1539
|
contentId: n.matchUrn
|
|
1517
|
-
}), t =
|
|
1540
|
+
}), t = lt(e);
|
|
1518
1541
|
t && (this.prefetch = e, d.fLoader = t);
|
|
1519
1542
|
}
|
|
1520
|
-
|
|
1543
|
+
Wt(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;
|
|
1521
1544
|
let f = new e(d);
|
|
1522
1545
|
if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1523
1546
|
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" });
|
|
1524
1547
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1525
1548
|
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(() => {
|
|
1526
1549
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1527
|
-
},
|
|
1550
|
+
}, vt)));
|
|
1528
1551
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1529
1552
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1530
1553
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1532,10 +1555,10 @@ var Wt = class {
|
|
|
1532
1555
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1533
1556
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1534
1557
|
let i = n?.loading;
|
|
1535
|
-
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 >
|
|
1558
|
+
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Ut && this.requestTimesMs.shift());
|
|
1536
1559
|
let a = t?.frag?.url;
|
|
1537
1560
|
if (a) {
|
|
1538
|
-
let e =
|
|
1561
|
+
let e = Ke(a);
|
|
1539
1562
|
e && (this.cdnHost = e);
|
|
1540
1563
|
}
|
|
1541
1564
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1549,15 +1572,15 @@ var Wt = class {
|
|
|
1549
1572
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1550
1573
|
let t = this.prefetch;
|
|
1551
1574
|
f.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1552
|
-
let r = n?.frag, i =
|
|
1553
|
-
if (r && t.isActive(i)) for (let e of
|
|
1554
|
-
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1575
|
+
let r = n?.frag, i = dt(r?.type);
|
|
1576
|
+
if (r && t.isActive(i)) for (let e of ft(f, r)) t.prefetch(e.url, i, e.kind);
|
|
1577
|
+
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(dt(n?.frag?.type)));
|
|
1555
1578
|
}
|
|
1556
1579
|
f.on(e.Events.KEY_LOADED, () => {
|
|
1557
1580
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1558
1581
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1559
1582
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1560
|
-
},
|
|
1583
|
+
}, bt), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1561
1584
|
this.renditionSwitches += 1;
|
|
1562
1585
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1563
1586
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1621,7 +1644,7 @@ var Wt = class {
|
|
|
1621
1644
|
return;
|
|
1622
1645
|
}
|
|
1623
1646
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1624
|
-
let t = e > this.sizeCapLevel ?
|
|
1647
|
+
let t = e > this.sizeCapLevel ? Ft : It;
|
|
1625
1648
|
this.capTimer = setTimeout(() => {
|
|
1626
1649
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1627
1650
|
}, t);
|
|
@@ -1631,9 +1654,9 @@ var Wt = class {
|
|
|
1631
1654
|
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;
|
|
1632
1655
|
}
|
|
1633
1656
|
dropLevelsWidevineCannotPlay(e) {
|
|
1634
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1657
|
+
this.removeLevelsWhere(e, (e) => Ne(e) !== !0);
|
|
1635
1658
|
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
|
|
1636
|
-
for (let n of t)
|
|
1659
|
+
for (let n of t) je(n).then((t) => {
|
|
1637
1660
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1638
1661
|
});
|
|
1639
1662
|
}
|
|
@@ -1644,7 +1667,7 @@ var Wt = class {
|
|
|
1644
1667
|
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1645
1668
|
}), !r.length) return !1;
|
|
1646
1669
|
let a = [...i].join(", ");
|
|
1647
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) ||
|
|
1670
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Ne(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1648
1671
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1649
1672
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1650
1673
|
}
|
|
@@ -1742,7 +1765,7 @@ var Wt = class {
|
|
|
1742
1765
|
return;
|
|
1743
1766
|
}
|
|
1744
1767
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1745
|
-
!this.chaseSuspended && e >
|
|
1768
|
+
!this.chaseSuspended && e > xt && this.suspendChasing(), e > yt && this.emitEnded("stalled");
|
|
1746
1769
|
}
|
|
1747
1770
|
resetStarvationWindow() {
|
|
1748
1771
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1757,7 +1780,7 @@ var Wt = class {
|
|
|
1757
1780
|
this.resetStarvationWindow();
|
|
1758
1781
|
return;
|
|
1759
1782
|
}
|
|
1760
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1783
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < xt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Ot, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = V(t), c = o - s, l = c !== this.starvedFrames;
|
|
1761
1784
|
if (this.starvedFrames = c, !a || l) {
|
|
1762
1785
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1763
1786
|
return;
|
|
@@ -1766,12 +1789,12 @@ var Wt = class {
|
|
|
1766
1789
|
this.resetStarvationWindow();
|
|
1767
1790
|
return;
|
|
1768
1791
|
}
|
|
1769
|
-
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 >
|
|
1792
|
+
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > Nt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= jt && (this.clearKick(), this.starvationRebuilds < Mt)) {
|
|
1770
1793
|
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");
|
|
1771
1794
|
return;
|
|
1772
1795
|
}
|
|
1773
|
-
let u = i && this.starvedTicks >=
|
|
1774
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1796
|
+
let u = i && this.starvedTicks >= kt, d = !i && this.deadTicks >= Nt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Pt;
|
|
1797
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= At))) {
|
|
1775
1798
|
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");
|
|
1776
1799
|
try {
|
|
1777
1800
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1786,7 +1809,7 @@ var Wt = class {
|
|
|
1786
1809
|
let t = e.latency, n = e.targetLatency;
|
|
1787
1810
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1788
1811
|
let r = t - n;
|
|
1789
|
-
!this.catchUpEngaged && r >
|
|
1812
|
+
!this.catchUpEngaged && r > St ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= St && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1790
1813
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1791
1814
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1792
1815
|
}
|
|
@@ -1808,15 +1831,15 @@ var Wt = class {
|
|
|
1808
1831
|
return;
|
|
1809
1832
|
}
|
|
1810
1833
|
let { totalFrames: n, dropped: r } = V(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
1811
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
1834
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < Rt || o < 0) {
|
|
1812
1835
|
this.fpsBadTicks = 0;
|
|
1813
1836
|
return;
|
|
1814
1837
|
}
|
|
1815
|
-
if (o <=
|
|
1838
|
+
if (o <= Lt * a) {
|
|
1816
1839
|
this.fpsBadTicks = 0;
|
|
1817
1840
|
return;
|
|
1818
1841
|
}
|
|
1819
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
1842
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < zt) return;
|
|
1820
1843
|
this.fpsBadTicks = 0;
|
|
1821
1844
|
let s = e.levels, c = s[e.currentLevel];
|
|
1822
1845
|
if (!c) return;
|
|
@@ -1833,20 +1856,20 @@ var Wt = class {
|
|
|
1833
1856
|
return;
|
|
1834
1857
|
}
|
|
1835
1858
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
1836
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
1859
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Tt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
1837
1860
|
this.resetChaseWindow();
|
|
1838
1861
|
return;
|
|
1839
1862
|
}
|
|
1840
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
1863
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= wt) {
|
|
1841
1864
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
1842
1865
|
return;
|
|
1843
1866
|
}
|
|
1844
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
1867
|
+
if (this.chaseTicks += 1, this.chaseTicks < Ct) return;
|
|
1845
1868
|
this.resetChaseWindow();
|
|
1846
1869
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
1847
1870
|
if (!(a > 1)) return;
|
|
1848
1871
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
1849
|
-
s < o +
|
|
1872
|
+
s < o + Et || (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);
|
|
1850
1873
|
}
|
|
1851
1874
|
suspendChasing() {
|
|
1852
1875
|
let e = this.hls;
|
|
@@ -1891,7 +1914,7 @@ var Wt = class {
|
|
|
1891
1914
|
scheduleLicenseRetry(t) {
|
|
1892
1915
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1893
1916
|
let n = t.response?.code ?? 0;
|
|
1894
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1917
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= gt) return !1;
|
|
1895
1918
|
this.licenseRecoveries += 1;
|
|
1896
1919
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1897
1920
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1923,7 +1946,7 @@ var Wt = class {
|
|
|
1923
1946
|
return;
|
|
1924
1947
|
}
|
|
1925
1948
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1926
|
-
if (this.networkRecoveries <
|
|
1949
|
+
if (this.networkRecoveries < ht) {
|
|
1927
1950
|
this.networkRecoveries += 1;
|
|
1928
1951
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1929
1952
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1940,7 +1963,7 @@ var Wt = class {
|
|
|
1940
1963
|
return;
|
|
1941
1964
|
}
|
|
1942
1965
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1943
|
-
if (this.mediaRecoveries <
|
|
1966
|
+
if (this.mediaRecoveries < mt) {
|
|
1944
1967
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1945
1968
|
return;
|
|
1946
1969
|
}
|
|
@@ -1964,34 +1987,19 @@ var Wt = class {
|
|
|
1964
1987
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1965
1988
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1966
1989
|
}
|
|
1967
|
-
}
|
|
1968
|
-
//#endregion
|
|
1969
|
-
//#region src/core/drm/signedUrl.ts
|
|
1970
|
-
function Gt(e, t = Date.now()) {
|
|
1971
|
-
if (!e) return !1;
|
|
1972
|
-
let n;
|
|
1973
|
-
try {
|
|
1974
|
-
n = new URL(e).searchParams.get("exp");
|
|
1975
|
-
} catch {
|
|
1976
|
-
return !1;
|
|
1977
|
-
}
|
|
1978
|
-
return !n || !/^\d+$/.test(n) ? !1 : Number(n) * 1e3 <= t;
|
|
1979
|
-
}
|
|
1980
|
-
//#endregion
|
|
1981
|
-
//#region src/core/analytics.ts
|
|
1982
|
-
var Kt = 15e3, qt = 6e5, Jt = 3e5, Yt = 100, q = 1, Xt = 1e3, Zt = 3e4, Qt = 1e3, $t = {
|
|
1990
|
+
}, qt = 15e3, Jt = 6e5, Yt = 3e5, Xt = 100, q = 1, Zt = 1e3, Qt = 3e4, $t = 1e3, en = {
|
|
1983
1991
|
inline: "PRESENTATION_INLINE",
|
|
1984
1992
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1985
1993
|
pip: "PRESENTATION_PIP"
|
|
1986
|
-
},
|
|
1994
|
+
}, tn = {
|
|
1987
1995
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1988
1996
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1989
1997
|
none: "KEY_SYSTEM_NONE"
|
|
1990
1998
|
};
|
|
1991
|
-
function
|
|
1999
|
+
function nn(e, t) {
|
|
1992
2000
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1993
2001
|
}
|
|
1994
|
-
var
|
|
2002
|
+
var rn = /* @__PURE__ */ new Set([
|
|
1995
2003
|
"INVALID_URN",
|
|
1996
2004
|
"NOT_FOUND",
|
|
1997
2005
|
"GONE",
|
|
@@ -2011,7 +2019,7 @@ var nn = /* @__PURE__ */ new Set([
|
|
|
2011
2019
|
ended: "PLAYER_STATE_ENDED",
|
|
2012
2020
|
error: "PLAYER_STATE_ERROR"
|
|
2013
2021
|
};
|
|
2014
|
-
function
|
|
2022
|
+
function an(e) {
|
|
2015
2023
|
try {
|
|
2016
2024
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2017
2025
|
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);
|
|
@@ -2019,8 +2027,8 @@ function rn(e) {
|
|
|
2019
2027
|
return;
|
|
2020
2028
|
}
|
|
2021
2029
|
}
|
|
2022
|
-
var
|
|
2023
|
-
function
|
|
2030
|
+
var on = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), sn = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), cn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2031
|
+
function ln(e) {
|
|
2024
2032
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2025
2033
|
let t;
|
|
2026
2034
|
try {
|
|
@@ -2029,19 +2037,19 @@ function cn(e) {
|
|
|
2029
2037
|
} catch {
|
|
2030
2038
|
return;
|
|
2031
2039
|
}
|
|
2032
|
-
if (
|
|
2033
|
-
Y.add(t), g(
|
|
2040
|
+
if (sn.has(t) && !Y.has(t)) {
|
|
2041
|
+
Y.add(t), g(cn(new URL(t).origin));
|
|
2034
2042
|
for (let e of X) e.noteCspBlocked();
|
|
2035
2043
|
}
|
|
2036
2044
|
}
|
|
2037
|
-
function
|
|
2045
|
+
function un(e, t) {
|
|
2038
2046
|
return g(t, e), { disabledReason: t };
|
|
2039
2047
|
}
|
|
2040
|
-
function
|
|
2041
|
-
if (n) return t && !
|
|
2048
|
+
function dn(e, t, n) {
|
|
2049
|
+
if (n) return t && !on(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2042
2050
|
if (t) return { endpoint: t };
|
|
2043
|
-
if (t !== void 0) return
|
|
2044
|
-
let r =
|
|
2051
|
+
if (t !== void 0) return un("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).");
|
|
2052
|
+
let r = an(e);
|
|
2045
2053
|
if (r) return { endpoint: r };
|
|
2046
2054
|
let i;
|
|
2047
2055
|
try {
|
|
@@ -2049,9 +2057,9 @@ function un(e, t, n) {
|
|
|
2049
2057
|
} catch {
|
|
2050
2058
|
i = e;
|
|
2051
2059
|
}
|
|
2052
|
-
return
|
|
2060
|
+
return un(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).`);
|
|
2053
2061
|
}
|
|
2054
|
-
var
|
|
2062
|
+
var fn = class {
|
|
2055
2063
|
opts;
|
|
2056
2064
|
url;
|
|
2057
2065
|
cspKey;
|
|
@@ -2133,8 +2141,8 @@ var dn = class {
|
|
|
2133
2141
|
constructor(e) {
|
|
2134
2142
|
this.opts = {
|
|
2135
2143
|
...e,
|
|
2136
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2137
|
-
idleMs: e.idleMs ??
|
|
2144
|
+
heartbeatMs: e.heartbeatMs ?? qt,
|
|
2145
|
+
idleMs: e.idleMs ?? Jt
|
|
2138
2146
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2139
2147
|
try {
|
|
2140
2148
|
let e = new URL(this.url);
|
|
@@ -2151,11 +2159,11 @@ var dn = class {
|
|
|
2151
2159
|
sdkVersion: this.opts.sdkVersion,
|
|
2152
2160
|
...this.opts.environment
|
|
2153
2161
|
};
|
|
2154
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2162
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Zt), 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 && sn.add(this.cspKey), document.addEventListener("securitypolicyviolation", ln), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2155
2163
|
}
|
|
2156
2164
|
checkSuspension(e) {
|
|
2157
2165
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2158
|
-
let t = Math.max(this.opts.idleMs,
|
|
2166
|
+
let t = Math.max(this.opts.idleMs, Yt);
|
|
2159
2167
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2160
2168
|
}
|
|
2161
2169
|
syncIdle(e) {
|
|
@@ -2178,12 +2186,12 @@ var dn = class {
|
|
|
2178
2186
|
let a = {
|
|
2179
2187
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2180
2188
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2181
|
-
presentation:
|
|
2189
|
+
presentation: en[this.presentation]
|
|
2182
2190
|
}, o = this.causeOf(e, t, i);
|
|
2183
2191
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2184
2192
|
}
|
|
2185
2193
|
seekInduced(e) {
|
|
2186
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2194
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < $t;
|
|
2187
2195
|
}
|
|
2188
2196
|
causeOf(e, t, n) {
|
|
2189
2197
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2257,7 +2265,7 @@ var dn = class {
|
|
|
2257
2265
|
let r = n ?? "";
|
|
2258
2266
|
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";
|
|
2259
2267
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2260
|
-
if (
|
|
2268
|
+
if (rn.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2261
2269
|
let i = t ?? "";
|
|
2262
2270
|
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";
|
|
2263
2271
|
}
|
|
@@ -2304,14 +2312,14 @@ var dn = class {
|
|
|
2304
2312
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2305
2313
|
o.requestCountDelta = _;
|
|
2306
2314
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2307
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2315
|
+
n.length > 0 && (o.requestTimeP50Ms = nn(n, 50), o.requestTimeP95Ms = nn(n, 95));
|
|
2308
2316
|
}
|
|
2309
2317
|
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();
|
|
2310
2318
|
}
|
|
2311
2319
|
maybeEmitMediaInfo(e) {
|
|
2312
2320
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2313
2321
|
let t = {};
|
|
2314
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2322
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = tn[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);
|
|
2315
2323
|
let n = JSON.stringify(t);
|
|
2316
2324
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2317
2325
|
}
|
|
@@ -2331,7 +2339,7 @@ var dn = class {
|
|
|
2331
2339
|
let c = r?.positionMs ?? 0;
|
|
2332
2340
|
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));
|
|
2333
2341
|
let l = e !== "END_REASON_ENDED";
|
|
2334
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2342
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= Qt && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Qt && (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);
|
|
2335
2343
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2336
2344
|
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");
|
|
2337
2345
|
}
|
|
@@ -2351,13 +2359,13 @@ var dn = class {
|
|
|
2351
2359
|
};
|
|
2352
2360
|
}
|
|
2353
2361
|
noteCspBlocked() {
|
|
2354
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2362
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(cn(new URL(this.url).origin)));
|
|
2355
2363
|
}
|
|
2356
2364
|
cspBlocked() {
|
|
2357
2365
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2358
2366
|
}
|
|
2359
2367
|
enqueue(e) {
|
|
2360
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2368
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Xt;) {
|
|
2361
2369
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2362
2370
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2363
2371
|
}
|
|
@@ -2384,7 +2392,7 @@ var dn = class {
|
|
|
2384
2392
|
};
|
|
2385
2393
|
//#endregion
|
|
2386
2394
|
//#region src/core/environment.ts
|
|
2387
|
-
function
|
|
2395
|
+
function pn() {
|
|
2388
2396
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2389
2397
|
let e;
|
|
2390
2398
|
try {
|
|
@@ -2409,14 +2417,14 @@ function fn() {
|
|
|
2409
2417
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2410
2418
|
};
|
|
2411
2419
|
}
|
|
2412
|
-
function
|
|
2420
|
+
function mn() {
|
|
2413
2421
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2414
2422
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2415
2423
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2416
2424
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2417
2425
|
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";
|
|
2418
2426
|
}
|
|
2419
|
-
function
|
|
2427
|
+
function hn() {
|
|
2420
2428
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2421
2429
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2422
2430
|
let t = {
|
|
@@ -2435,17 +2443,17 @@ function mn() {
|
|
|
2435
2443
|
}
|
|
2436
2444
|
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;
|
|
2437
2445
|
}
|
|
2438
|
-
function
|
|
2439
|
-
let t =
|
|
2440
|
-
deviceClass:
|
|
2446
|
+
function gn(e) {
|
|
2447
|
+
let t = pn(), n = {
|
|
2448
|
+
deviceClass: mn(),
|
|
2441
2449
|
integration: t.integration,
|
|
2442
|
-
...
|
|
2450
|
+
...hn()
|
|
2443
2451
|
};
|
|
2444
2452
|
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);
|
|
2445
2453
|
let r = e.getBoundingClientRect?.();
|
|
2446
2454
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2447
2455
|
}
|
|
2448
|
-
async function
|
|
2456
|
+
async function _n() {
|
|
2449
2457
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2450
2458
|
if (!e?.getHighEntropyValues) return {};
|
|
2451
2459
|
try {
|
|
@@ -2457,7 +2465,7 @@ async function gn() {
|
|
|
2457
2465
|
}
|
|
2458
2466
|
//#endregion
|
|
2459
2467
|
//#region src/core/version.ts
|
|
2460
|
-
var
|
|
2468
|
+
var vn = "2.16.6", yn = {
|
|
2461
2469
|
accent: "#E1B600",
|
|
2462
2470
|
accentText: "#1B1C23",
|
|
2463
2471
|
background: "#0e0f13",
|
|
@@ -2468,7 +2476,7 @@ var _n = "2.16.5", vn = {
|
|
|
2468
2476
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2469
2477
|
radius: "8px",
|
|
2470
2478
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2471
|
-
},
|
|
2479
|
+
}, bn = {
|
|
2472
2480
|
accent: "--havik-accent",
|
|
2473
2481
|
accentText: "--havik-accent-text",
|
|
2474
2482
|
background: "--havik-bg",
|
|
@@ -2480,26 +2488,26 @@ var _n = "2.16.5", vn = {
|
|
|
2480
2488
|
radius: "--havik-radius",
|
|
2481
2489
|
fontFamily: "--havik-font"
|
|
2482
2490
|
};
|
|
2483
|
-
function
|
|
2491
|
+
function xn(e, t) {
|
|
2484
2492
|
let n = {
|
|
2485
|
-
...
|
|
2493
|
+
...yn,
|
|
2486
2494
|
...t
|
|
2487
2495
|
};
|
|
2488
|
-
for (let t of Object.keys(
|
|
2496
|
+
for (let t of Object.keys(bn)) e.style.setProperty(bn[t], n[t]);
|
|
2489
2497
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2490
2498
|
}
|
|
2491
2499
|
//#endregion
|
|
2492
2500
|
//#region src/ui/styles.ts
|
|
2493
|
-
var
|
|
2494
|
-
function
|
|
2495
|
-
let n = e.querySelector(`style#${
|
|
2496
|
-
if (n && (!t ||
|
|
2501
|
+
var Sn = "havik-player-styles", Cn = "\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", Z = /* @__PURE__ */ new WeakMap();
|
|
2502
|
+
function wn(e = document, t) {
|
|
2503
|
+
let n = e.querySelector(`style#${Sn}`);
|
|
2504
|
+
if (n && (!t || Z.get(n) === t)) return;
|
|
2497
2505
|
let r = e.createElement("style");
|
|
2498
|
-
r.id =
|
|
2506
|
+
r.id = Sn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Cn, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2499
2507
|
}
|
|
2500
2508
|
//#endregion
|
|
2501
2509
|
//#region src/ui/icons.ts
|
|
2502
|
-
var
|
|
2510
|
+
var Tn = {
|
|
2503
2511
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2504
2512
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2505
2513
|
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\"/>",
|
|
@@ -2513,20 +2521,20 @@ var wn = {
|
|
|
2513
2521
|
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\"/>"
|
|
2514
2522
|
};
|
|
2515
2523
|
function Q(e) {
|
|
2516
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2524
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Tn[e]}</svg>`;
|
|
2517
2525
|
}
|
|
2518
2526
|
//#endregion
|
|
2519
2527
|
//#region src/ui/controls.ts
|
|
2520
|
-
var
|
|
2528
|
+
var En = 3e3, Dn = 250, On = /* @__PURE__ */ new Set([
|
|
2521
2529
|
"GONE",
|
|
2522
2530
|
"NOT_FOUND",
|
|
2523
2531
|
"INVALID_URN",
|
|
2524
2532
|
"UNAUTHORIZED"
|
|
2525
2533
|
]);
|
|
2526
|
-
function
|
|
2527
|
-
return new
|
|
2534
|
+
function kn(e) {
|
|
2535
|
+
return new An(e);
|
|
2528
2536
|
}
|
|
2529
|
-
var
|
|
2537
|
+
var An = class {
|
|
2530
2538
|
root;
|
|
2531
2539
|
video;
|
|
2532
2540
|
player;
|
|
@@ -2572,7 +2580,7 @@ var kn = class {
|
|
|
2572
2580
|
scrubbing = !1;
|
|
2573
2581
|
offFns = [];
|
|
2574
2582
|
constructor(e) {
|
|
2575
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2583
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? En, 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, wn(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");
|
|
2576
2584
|
let t = (e, t, n) => {
|
|
2577
2585
|
let r = this.doc.createElement(e);
|
|
2578
2586
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2658,7 +2666,7 @@ var kn = class {
|
|
|
2658
2666
|
let t = this.surfaceWasHidden;
|
|
2659
2667
|
this.tapTimer = setTimeout(() => {
|
|
2660
2668
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2661
|
-
},
|
|
2669
|
+
}, Dn);
|
|
2662
2670
|
}
|
|
2663
2671
|
toggleBar(e) {
|
|
2664
2672
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2693,7 +2701,7 @@ var kn = class {
|
|
|
2693
2701
|
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Q("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
|
|
2694
2702
|
} else {
|
|
2695
2703
|
let r = this.doc.createElement("div");
|
|
2696
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2704
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !On.has(this.lastError.code)) {
|
|
2697
2705
|
let e = this.doc.createElement("button");
|
|
2698
2706
|
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Q("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
2699
2707
|
}
|
|
@@ -2734,7 +2742,7 @@ var kn = class {
|
|
|
2734
2742
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2735
2743
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2736
2744
|
}
|
|
2737
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2745
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${jn(this.video.currentTime)} / ${jn(this.video.duration)}`);
|
|
2738
2746
|
}
|
|
2739
2747
|
syncLive() {
|
|
2740
2748
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2784,17 +2792,17 @@ var kn = class {
|
|
|
2784
2792
|
renderQualityMenu() {
|
|
2785
2793
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2786
2794
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2787
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2795
|
+
for (let n of e) this.menu.append(this.menuItem(Mn(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2788
2796
|
}
|
|
2789
2797
|
renderAudioMenu() {
|
|
2790
2798
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2791
2799
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2792
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2800
|
+
for (let t of e) this.menu.append(this.menuItem(Nn(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2793
2801
|
}
|
|
2794
2802
|
renderCcMenu() {
|
|
2795
2803
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2796
2804
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2797
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2805
|
+
for (let t of e) this.menu.append(this.menuItem(Pn(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2798
2806
|
}
|
|
2799
2807
|
onTracksChanged() {
|
|
2800
2808
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2895,41 +2903,41 @@ var kn = class {
|
|
|
2895
2903
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2896
2904
|
}
|
|
2897
2905
|
};
|
|
2898
|
-
function
|
|
2906
|
+
function jn(e) {
|
|
2899
2907
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2900
2908
|
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");
|
|
2901
2909
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2902
2910
|
}
|
|
2903
|
-
function
|
|
2911
|
+
function Mn(e) {
|
|
2904
2912
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2905
2913
|
}
|
|
2906
|
-
function
|
|
2914
|
+
function Nn(e) {
|
|
2907
2915
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2908
2916
|
}
|
|
2909
|
-
function
|
|
2917
|
+
function Pn(e) {
|
|
2910
2918
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2911
2919
|
}
|
|
2912
2920
|
//#endregion
|
|
2913
2921
|
//#region src/managed/index.ts
|
|
2914
|
-
var
|
|
2915
|
-
function
|
|
2922
|
+
var Fn = 6e3, In = 45e3, Ln = 2e3, Rn = 3, zn = 2e3, Bn = 48e4, Vn = "keySystemLicenseRequestFailed";
|
|
2923
|
+
function Hn(e) {
|
|
2916
2924
|
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)})`);
|
|
2917
|
-
if (e.env !== void 0) return
|
|
2925
|
+
if (e.env !== void 0) return We(e.env);
|
|
2918
2926
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2919
2927
|
return e.baseUrl;
|
|
2920
2928
|
}
|
|
2921
|
-
async function
|
|
2929
|
+
async function Un(e) {
|
|
2922
2930
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2923
|
-
let t =
|
|
2931
|
+
let t = Hn(e);
|
|
2924
2932
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2925
2933
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2926
|
-
let r = new
|
|
2934
|
+
let r = new Wn({
|
|
2927
2935
|
...e,
|
|
2928
2936
|
baseUrl: t
|
|
2929
2937
|
});
|
|
2930
2938
|
return await r.start(), r;
|
|
2931
2939
|
}
|
|
2932
|
-
var
|
|
2940
|
+
var Wn = class {
|
|
2933
2941
|
opts;
|
|
2934
2942
|
abort = new AbortController();
|
|
2935
2943
|
listeners = {};
|
|
@@ -2940,6 +2948,8 @@ var Un = class {
|
|
|
2940
2948
|
detachPip;
|
|
2941
2949
|
statsTimer;
|
|
2942
2950
|
refreshTimer;
|
|
2951
|
+
refreshInFlight;
|
|
2952
|
+
onRefocus;
|
|
2943
2953
|
staleLicenseReloaded = !1;
|
|
2944
2954
|
_state = "idle";
|
|
2945
2955
|
_descriptor = null;
|
|
@@ -2974,7 +2984,7 @@ var Un = class {
|
|
|
2974
2984
|
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");
|
|
2975
2985
|
let e = ++this.loadGen, t = this.resolveOptions();
|
|
2976
2986
|
try {
|
|
2977
|
-
let n = await
|
|
2987
|
+
let n = await y(t);
|
|
2978
2988
|
if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
|
|
2979
2989
|
let e = this._lastError;
|
|
2980
2990
|
throw this.destroy(), e;
|
|
@@ -3001,7 +3011,7 @@ var Un = class {
|
|
|
3001
3011
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
3002
3012
|
}
|
|
3003
3013
|
beginArmingByPolling(e) {
|
|
3004
|
-
|
|
3014
|
+
b({
|
|
3005
3015
|
...this.resolveOptions(),
|
|
3006
3016
|
signal: this.abort.signal,
|
|
3007
3017
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -3018,7 +3028,7 @@ var Un = class {
|
|
|
3018
3028
|
setTimeout(() => {
|
|
3019
3029
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3020
3030
|
phase: i ? "unavailable" : "tooEarly",
|
|
3021
|
-
retryInMs:
|
|
3031
|
+
retryInMs: In,
|
|
3022
3032
|
attempt: 1,
|
|
3023
3033
|
elapsedMs: 0,
|
|
3024
3034
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3035,7 +3045,7 @@ var Un = class {
|
|
|
3035
3045
|
}
|
|
3036
3046
|
}
|
|
3037
3047
|
}, h = () => {
|
|
3038
|
-
a || s || p() || (s = !0,
|
|
3048
|
+
a || s || p() || (s = !0, b({
|
|
3039
3049
|
...this.resolveOptions(),
|
|
3040
3050
|
signal: c.signal,
|
|
3041
3051
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -3043,7 +3053,7 @@ var Un = class {
|
|
|
3043
3053
|
a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
|
|
3044
3054
|
}));
|
|
3045
3055
|
}, g = () => {
|
|
3046
|
-
a || p() ||
|
|
3056
|
+
a || p() || y(this.resolveOptions()).then((e) => m(e)).catch((e) => {
|
|
3047
3057
|
if (!(a || p())) {
|
|
3048
3058
|
if (e instanceof n && o(e.code)) {
|
|
3049
3059
|
h();
|
|
@@ -3057,13 +3067,13 @@ var Un = class {
|
|
|
3057
3067
|
!a && !p() && h();
|
|
3058
3068
|
}, e);
|
|
3059
3069
|
};
|
|
3060
|
-
_(
|
|
3070
|
+
_(Fn), this.armingSub = T({
|
|
3061
3071
|
eventsBaseUrl: t,
|
|
3062
3072
|
matchUrn: this.opts.matchUrn,
|
|
3063
3073
|
credential: this.opts.credential,
|
|
3064
|
-
onAlive: () => _(
|
|
3074
|
+
onAlive: () => _(In),
|
|
3065
3075
|
onState: (e) => {
|
|
3066
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3076
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Ln);
|
|
3067
3077
|
},
|
|
3068
3078
|
onError: () => h()
|
|
3069
3079
|
});
|
|
@@ -3086,7 +3096,7 @@ var Un = class {
|
|
|
3086
3096
|
let n = await s(this.opts.credential);
|
|
3087
3097
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3088
3098
|
this.setState("loading");
|
|
3089
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3099
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Xe(this.opts.video, (e) => {
|
|
3090
3100
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3091
3101
|
});
|
|
3092
3102
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3108,26 +3118,26 @@ var Un = class {
|
|
|
3108
3118
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3109
3119
|
let i = e.analytics?.sid;
|
|
3110
3120
|
if (!i) return;
|
|
3111
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3121
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = dn(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3112
3122
|
if (!o) {
|
|
3113
3123
|
s && setTimeout(() => {
|
|
3114
3124
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3115
3125
|
}, 0);
|
|
3116
3126
|
return;
|
|
3117
3127
|
}
|
|
3118
|
-
let c = this.opts.video, l = new
|
|
3128
|
+
let c = this.opts.video, l = new fn({
|
|
3119
3129
|
endpoint: o,
|
|
3120
3130
|
sid: i,
|
|
3121
3131
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3122
|
-
sdkVersion:
|
|
3123
|
-
environment:
|
|
3132
|
+
sdkVersion: vn,
|
|
3133
|
+
environment: gn(c),
|
|
3124
3134
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3125
3135
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3126
3136
|
onBlocked: (e) => setTimeout(() => {
|
|
3127
3137
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3128
3138
|
}, 0),
|
|
3129
3139
|
sample: () => {
|
|
3130
|
-
let e = this.engine?.getStats() ??
|
|
3140
|
+
let e = this.engine?.getStats() ?? Ge, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3131
3141
|
return {
|
|
3132
3142
|
...e,
|
|
3133
3143
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3141,7 +3151,7 @@ var Un = class {
|
|
|
3141
3151
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3142
3152
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3143
3153
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3144
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3154
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), _n().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3145
3155
|
}
|
|
3146
3156
|
currentPresentation() {
|
|
3147
3157
|
let e = this.opts.video;
|
|
@@ -3164,13 +3174,14 @@ var Un = class {
|
|
|
3164
3174
|
debug: this.opts.debug,
|
|
3165
3175
|
deferLoad: r,
|
|
3166
3176
|
hlsConfig: i,
|
|
3167
|
-
emit: (e) => this.onEngineEvent(e)
|
|
3177
|
+
emit: (e) => this.onEngineEvent(e),
|
|
3178
|
+
freshLicenseUrl: () => this.refreshLicense()
|
|
3168
3179
|
}, o = this.opts.engine ?? "auto";
|
|
3169
|
-
if (o === "native") return new
|
|
3170
|
-
if (o === "hls") return new
|
|
3171
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
3172
|
-
if (
|
|
3173
|
-
if (
|
|
3180
|
+
if (o === "native") return new G(a);
|
|
3181
|
+
if (o === "hls") return new Kt(a);
|
|
3182
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && U(this.opts.video) && W() || !e.drmEnabled && nt() && U(this.opts.video)) return new G(a);
|
|
3183
|
+
if (pt()) return new Kt(a);
|
|
3184
|
+
if (U(this.opts.video)) return new G(a);
|
|
3174
3185
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3175
3186
|
}
|
|
3176
3187
|
onEngineEvent(e) {
|
|
@@ -3232,7 +3243,7 @@ var Un = class {
|
|
|
3232
3243
|
r = 0, i = !1;
|
|
3233
3244
|
},
|
|
3234
3245
|
onError: () => {
|
|
3235
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
3246
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Rn && (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.`))));
|
|
3236
3247
|
}
|
|
3237
3248
|
});
|
|
3238
3249
|
}
|
|
@@ -3254,7 +3265,7 @@ var Un = class {
|
|
|
3254
3265
|
scheduleRejoin(e) {
|
|
3255
3266
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3256
3267
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3257
|
-
}, Math.random() *
|
|
3268
|
+
}, Math.random() * Ln));
|
|
3258
3269
|
}
|
|
3259
3270
|
cancelRejoin() {
|
|
3260
3271
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3278,7 +3289,7 @@ var Un = class {
|
|
|
3278
3289
|
}
|
|
3279
3290
|
t.controls = !1;
|
|
3280
3291
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3281
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3292
|
+
r && r.insertBefore(n, t), n.appendChild(t), xn(n, this.opts.theme), this.container = n, this.controlBar = kn({
|
|
3282
3293
|
root: n,
|
|
3283
3294
|
video: t,
|
|
3284
3295
|
player: this,
|
|
@@ -3309,7 +3320,7 @@ var Un = class {
|
|
|
3309
3320
|
}
|
|
3310
3321
|
startStats() {
|
|
3311
3322
|
this.stopStats();
|
|
3312
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3323
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? zn);
|
|
3313
3324
|
this.statsTimer = setInterval(() => {
|
|
3314
3325
|
if (!this.engine) return;
|
|
3315
3326
|
let e = this.engine.getStats();
|
|
@@ -3320,29 +3331,43 @@ var Un = class {
|
|
|
3320
3331
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3321
3332
|
}
|
|
3322
3333
|
isStaleLicenseDenial(e) {
|
|
3323
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3334
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Vn || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3324
3335
|
}
|
|
3325
3336
|
scheduleLicenseRefresh() {
|
|
3326
|
-
this.stopRefresh();
|
|
3327
|
-
|
|
3328
|
-
|
|
3337
|
+
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3338
|
+
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3339
|
+
document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3340
|
+
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3341
|
+
let e = this.opts.licenseRefreshMs ?? Bn;
|
|
3342
|
+
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3329
3343
|
}
|
|
3330
3344
|
stopRefresh() {
|
|
3331
|
-
this.refreshTimer && clearInterval(this.refreshTimer), this.refreshTimer = void 0;
|
|
3345
|
+
this.refreshTimer && clearInterval(this.refreshTimer), this.refreshTimer = void 0, this.onRefocus && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onRefocus), this.onRefocus = void 0);
|
|
3332
3346
|
}
|
|
3333
|
-
|
|
3347
|
+
refreshLicense() {
|
|
3334
3348
|
let e = this.engine;
|
|
3335
|
-
if (
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3349
|
+
if (this.destroyed || !e) return Promise.resolve(void 0);
|
|
3350
|
+
if (this.refreshInFlight?.engine === e) return this.refreshInFlight.promise;
|
|
3351
|
+
let t = (async () => {
|
|
3352
|
+
try {
|
|
3353
|
+
let t = await y(this.resolveOptions());
|
|
3354
|
+
if (this.destroyed || this.engine !== e) return;
|
|
3355
|
+
let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
|
|
3356
|
+
return (n || r) && (e.setLicenseUrls({
|
|
3357
|
+
widevine: n,
|
|
3358
|
+
fairplay: r
|
|
3359
|
+
}), this._descriptor = t), n;
|
|
3360
|
+
} catch (e) {
|
|
3361
|
+
e instanceof n && !o(e.code) && (this.stopRefresh(), this.destroyed || this.emit("warning", e));
|
|
3362
|
+
return;
|
|
3363
|
+
} finally {
|
|
3364
|
+
this.refreshInFlight?.promise === t && (this.refreshInFlight = void 0);
|
|
3365
|
+
}
|
|
3366
|
+
})();
|
|
3367
|
+
return this.refreshInFlight = {
|
|
3368
|
+
engine: e,
|
|
3369
|
+
promise: t
|
|
3370
|
+
}, t;
|
|
3346
3371
|
}
|
|
3347
3372
|
async play() {
|
|
3348
3373
|
if (this.destroyed) return;
|
|
@@ -3369,7 +3394,7 @@ var Un = class {
|
|
|
3369
3394
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3370
3395
|
}
|
|
3371
3396
|
getStats() {
|
|
3372
|
-
return this.engine?.getStats() ??
|
|
3397
|
+
return this.engine?.getStats() ?? Ge;
|
|
3373
3398
|
}
|
|
3374
3399
|
getQualityLevels() {
|
|
3375
3400
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3421,7 +3446,7 @@ var Un = class {
|
|
|
3421
3446
|
let e = ++this.loadGen;
|
|
3422
3447
|
this.teardownPlayback();
|
|
3423
3448
|
try {
|
|
3424
|
-
let t = await
|
|
3449
|
+
let t = await b({
|
|
3425
3450
|
...this.resolveOptions(),
|
|
3426
3451
|
waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
|
|
3427
3452
|
});
|
|
@@ -3479,7 +3504,7 @@ function $(e) {
|
|
|
3479
3504
|
}
|
|
3480
3505
|
//#endregion
|
|
3481
3506
|
//#region src/embed/host.ts
|
|
3482
|
-
function
|
|
3507
|
+
function Gn(e) {
|
|
3483
3508
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3484
3509
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3485
3510
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3538,15 +3563,15 @@ function Wn(e) {
|
|
|
3538
3563
|
}
|
|
3539
3564
|
//#endregion
|
|
3540
3565
|
//#region src/embed/page.ts
|
|
3541
|
-
var
|
|
3542
|
-
function
|
|
3566
|
+
var Kn = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3567
|
+
function qn(e) {
|
|
3543
3568
|
if (typeof e == "boolean") return e;
|
|
3544
3569
|
if (typeof e == "object" && e) {
|
|
3545
3570
|
let t = e.endpoint;
|
|
3546
3571
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3547
3572
|
}
|
|
3548
3573
|
}
|
|
3549
|
-
function
|
|
3574
|
+
function Jn() {
|
|
3550
3575
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3551
3576
|
if (e) return {
|
|
3552
3577
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3556,7 +3581,7 @@ function qn() {
|
|
|
3556
3581
|
autoplay: e.autoplay ?? !0,
|
|
3557
3582
|
muted: e.muted ?? !0,
|
|
3558
3583
|
waitForLive: e.waitForLive ?? !0,
|
|
3559
|
-
analytics:
|
|
3584
|
+
analytics: qn(e.analytics)
|
|
3560
3585
|
};
|
|
3561
3586
|
let t = new URLSearchParams(location.search);
|
|
3562
3587
|
return {
|
|
@@ -3569,9 +3594,9 @@ function qn() {
|
|
|
3569
3594
|
waitForLive: !0
|
|
3570
3595
|
};
|
|
3571
3596
|
}
|
|
3572
|
-
async function
|
|
3573
|
-
let e =
|
|
3574
|
-
|
|
3597
|
+
async function Yn() {
|
|
3598
|
+
let e = Jn();
|
|
3599
|
+
Zn();
|
|
3575
3600
|
let t = document.createElement("video");
|
|
3576
3601
|
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);
|
|
3577
3602
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3626,12 +3651,12 @@ async function Jn() {
|
|
|
3626
3651
|
code: e.code,
|
|
3627
3652
|
message: e.message
|
|
3628
3653
|
})), e.on("autoplayblocked", () => {
|
|
3629
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3654
|
+
i({ type: "oddin:autoplayblocked" }), Xn(t, e);
|
|
3630
3655
|
});
|
|
3631
3656
|
}, s = async (r) => {
|
|
3632
3657
|
a?.destroy(), a = null;
|
|
3633
3658
|
try {
|
|
3634
|
-
let n = await
|
|
3659
|
+
let n = await Un({
|
|
3635
3660
|
video: t,
|
|
3636
3661
|
baseUrl: e.baseUrl,
|
|
3637
3662
|
matchUrn: r,
|
|
@@ -3693,7 +3718,7 @@ async function Jn() {
|
|
|
3693
3718
|
a?.retry();
|
|
3694
3719
|
break;
|
|
3695
3720
|
case "oddin:load":
|
|
3696
|
-
typeof e.matchUrn == "string" &&
|
|
3721
|
+
typeof e.matchUrn == "string" && Kn.test(e.matchUrn) && s(e.matchUrn);
|
|
3697
3722
|
break;
|
|
3698
3723
|
case "oddin:destroy": c();
|
|
3699
3724
|
}
|
|
@@ -3705,18 +3730,18 @@ async function Jn() {
|
|
|
3705
3730
|
protocol: 1
|
|
3706
3731
|
});
|
|
3707
3732
|
}
|
|
3708
|
-
function
|
|
3733
|
+
function Xn(e, t) {
|
|
3709
3734
|
if (document.getElementById("havik-tap")) return;
|
|
3710
3735
|
let n = document.createElement("button");
|
|
3711
3736
|
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", () => {
|
|
3712
3737
|
n.remove(), t.play();
|
|
3713
3738
|
}), document.body.appendChild(n);
|
|
3714
3739
|
}
|
|
3715
|
-
function
|
|
3740
|
+
function Zn() {
|
|
3716
3741
|
let e = document.createElement("style");
|
|
3717
3742
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3718
3743
|
}
|
|
3719
3744
|
//#endregion
|
|
3720
|
-
export {
|
|
3745
|
+
export { yn as ODDIN_THEME, n as PlaybackError, xn as applyTheme, We as baseUrlForEnv, Yn as bootEmbed, Te as clearDeviceId, Un as createPlayer, E as deriveEventsBaseUrl, Be as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, k as getDeviceId, He as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, Gn as mountEmbed, v as pollToLive, b as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
|
|
3721
3746
|
|
|
3722
3747
|
//# sourceMappingURL=index.js.map
|