@oddin-gg/havik-player 2.16.6 → 2.16.7
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 +216 -201
- package/dist/index.js.map +1 -1
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -174,7 +174,7 @@ function ue(e, t) {
|
|
|
174
174
|
t?.addEventListener("abort", a, { once: !0 });
|
|
175
175
|
});
|
|
176
176
|
}
|
|
177
|
-
async function
|
|
177
|
+
async function de(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 v(e, t, r) {
|
|
|
200
200
|
}
|
|
201
201
|
//#endregion
|
|
202
202
|
//#region src/core/resolve.ts
|
|
203
|
-
async function
|
|
203
|
+
async function v(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 fe(t);
|
|
211
|
+
return he(await t.json(), e.matchUrn);
|
|
212
212
|
}
|
|
213
|
-
function
|
|
214
|
-
let t = () =>
|
|
215
|
-
return e.waitForLive ?
|
|
213
|
+
function y(e) {
|
|
214
|
+
let t = () => v(e);
|
|
215
|
+
return e.waitForLive ? de(t, e.waitForLive, e.signal) : t();
|
|
216
216
|
}
|
|
217
|
-
async function
|
|
217
|
+
async function fe(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 de(e) {
|
|
|
230
230
|
liveStartsAtMs: s
|
|
231
231
|
});
|
|
232
232
|
}
|
|
233
|
-
var
|
|
233
|
+
var pe = /* @__PURE__ */ new Set([
|
|
234
234
|
"matchUrn",
|
|
235
235
|
"protocol",
|
|
236
236
|
"drmEnabled",
|
|
@@ -241,7 +241,7 @@ var fe = /* @__PURE__ */ new Set([
|
|
|
241
241
|
"expiresAt",
|
|
242
242
|
"analytics"
|
|
243
243
|
]);
|
|
244
|
-
function
|
|
244
|
+
function b(e, t) {
|
|
245
245
|
let r;
|
|
246
246
|
try {
|
|
247
247
|
r = new URL(t);
|
|
@@ -251,7 +251,7 @@ function x(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 me(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 pe(e) {
|
|
|
260
260
|
g(`server analytics.endpoint ${JSON.stringify(e)} ignored: not a bare https origin.`);
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
|
-
function
|
|
263
|
+
function he(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: b("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 = me(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: b("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
|
|
280
|
+
licenseUrl: b("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
|
|
281
|
+
certificateUrl: b("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)) pe.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 ge(e) {
|
|
291
291
|
return e.ownerDocument ?? document;
|
|
292
292
|
}
|
|
293
|
-
function
|
|
293
|
+
function x(e) {
|
|
294
294
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
295
295
|
}
|
|
296
296
|
function S(e, t) {
|
|
297
|
-
let n = ge(
|
|
297
|
+
let n = x(ge(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 = ge(e), i = x(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 je = {
|
|
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
|
+
}, Me = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
|
|
680
|
+
function Ne(e) {
|
|
681
|
+
let t = L(e), n = Me.get(t);
|
|
682
682
|
if (n) return n;
|
|
683
683
|
let r = {
|
|
684
684
|
initDataTypes: ["cenc"],
|
|
@@ -696,23 +696,23 @@ function je(e) {
|
|
|
696
696
|
} catch {
|
|
697
697
|
return !1;
|
|
698
698
|
}
|
|
699
|
-
})().then((e) => (
|
|
700
|
-
return
|
|
699
|
+
})().then((e) => (R.set(t, e), e));
|
|
700
|
+
return Me.set(t, i), i;
|
|
701
701
|
}
|
|
702
|
-
function
|
|
703
|
-
if (j()) for (let e of Object.values(
|
|
702
|
+
function Pe() {
|
|
703
|
+
if (j()) for (let e of Object.values(je)) Ne(e);
|
|
704
704
|
}
|
|
705
|
-
function
|
|
705
|
+
function Fe(e) {
|
|
706
706
|
let t = I(e);
|
|
707
|
-
if (t) return t === "avc" ? !0 :
|
|
707
|
+
if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(je[t]));
|
|
708
708
|
}
|
|
709
709
|
//#endregion
|
|
710
710
|
//#region src/core/drm/support.ts
|
|
711
|
-
var
|
|
711
|
+
var Ie = 5e3, Le = "video/mp4; codecs=\"avc1.42E01E\"", Re = "audio/mp4; codecs=\"mp4a.40.2\"", ze = {
|
|
712
712
|
widevine: ["com.widevine.alpha"],
|
|
713
713
|
fairplay: ["com.apple.fps"]
|
|
714
714
|
};
|
|
715
|
-
function
|
|
715
|
+
function Be(e) {
|
|
716
716
|
return e === "fairplay" ? [{
|
|
717
717
|
initDataTypes: [
|
|
718
718
|
"sinf",
|
|
@@ -720,30 +720,30 @@ function Re(e) {
|
|
|
720
720
|
"cenc"
|
|
721
721
|
],
|
|
722
722
|
videoCapabilities: [{
|
|
723
|
-
contentType:
|
|
723
|
+
contentType: Le,
|
|
724
724
|
robustness: "",
|
|
725
725
|
encryptionScheme: "cbcs"
|
|
726
726
|
}],
|
|
727
727
|
audioCapabilities: [{
|
|
728
|
-
contentType:
|
|
728
|
+
contentType: Re,
|
|
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: Le,
|
|
736
736
|
robustness: F.video,
|
|
737
737
|
encryptionScheme: F.scheme
|
|
738
738
|
}],
|
|
739
739
|
audioCapabilities: [{
|
|
740
|
-
contentType:
|
|
740
|
+
contentType: Re,
|
|
741
741
|
robustness: F.audio,
|
|
742
742
|
encryptionScheme: F.scheme
|
|
743
743
|
}]
|
|
744
744
|
}]);
|
|
745
745
|
}
|
|
746
|
-
function
|
|
746
|
+
function Ve(e, t) {
|
|
747
747
|
return new Promise((n, r) => {
|
|
748
748
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
749
749
|
e.then((e) => {
|
|
@@ -753,8 +753,8 @@ function ze(e, t) {
|
|
|
753
753
|
});
|
|
754
754
|
});
|
|
755
755
|
}
|
|
756
|
-
async function
|
|
757
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
756
|
+
async function He(e = {}) {
|
|
757
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ie, r = {};
|
|
758
758
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
759
759
|
verdict: "insecure-context",
|
|
760
760
|
detail: r
|
|
@@ -766,7 +766,7 @@ async function Be(e = {}) {
|
|
|
766
766
|
};
|
|
767
767
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
768
768
|
for (let e of t) {
|
|
769
|
-
let t =
|
|
769
|
+
let t = ze[e];
|
|
770
770
|
if (!t) {
|
|
771
771
|
r[e] = "unknown system";
|
|
772
772
|
continue;
|
|
@@ -777,7 +777,7 @@ async function Be(e = {}) {
|
|
|
777
777
|
break;
|
|
778
778
|
}
|
|
779
779
|
try {
|
|
780
|
-
return await
|
|
780
|
+
return await Ve((await Ve(i(n, Be(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
781
781
|
verdict: "supported",
|
|
782
782
|
system: e,
|
|
783
783
|
detail: r
|
|
@@ -801,49 +801,49 @@ async function Be(e = {}) {
|
|
|
801
801
|
}
|
|
802
802
|
//#endregion
|
|
803
803
|
//#region src/core/manifest.ts
|
|
804
|
-
var
|
|
805
|
-
function
|
|
806
|
-
return
|
|
804
|
+
var Ue = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
805
|
+
function We(e) {
|
|
806
|
+
return Ue.test(e);
|
|
807
807
|
}
|
|
808
808
|
//#endregion
|
|
809
809
|
//#region src/core/env.ts
|
|
810
|
-
var
|
|
810
|
+
var Ge = {
|
|
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 Ke(e) {
|
|
815
|
+
let t = Object.prototype.hasOwnProperty.call(Ge, e) ? Ge[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 qe = { droppedFrames: 0 };
|
|
822
|
+
function z(e) {
|
|
823
823
|
try {
|
|
824
824
|
return new URL(e).host;
|
|
825
825
|
} catch {
|
|
826
826
|
return "";
|
|
827
827
|
}
|
|
828
828
|
}
|
|
829
|
-
var
|
|
830
|
-
function
|
|
829
|
+
var Je = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
830
|
+
function Ye(e) {
|
|
831
831
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
832
832
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
833
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
834
|
-
let e =
|
|
833
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Je.test(i.name)) && i.startTime >= n) {
|
|
834
|
+
let e = z(i.name);
|
|
835
835
|
e && (t = e, n = i.startTime);
|
|
836
836
|
}
|
|
837
837
|
return t;
|
|
838
838
|
}
|
|
839
|
-
function
|
|
839
|
+
function B(e) {
|
|
840
840
|
let t = e.getVideoPlaybackQuality?.();
|
|
841
841
|
return {
|
|
842
842
|
dropped: t?.droppedVideoFrames ?? 0,
|
|
843
843
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
844
844
|
};
|
|
845
845
|
}
|
|
846
|
-
var
|
|
846
|
+
var V = class {
|
|
847
847
|
video;
|
|
848
848
|
baseFrames = 0;
|
|
849
849
|
baseDropped = 0;
|
|
@@ -853,7 +853,7 @@ var Ye = class {
|
|
|
853
853
|
this.video = e;
|
|
854
854
|
}
|
|
855
855
|
read() {
|
|
856
|
-
let e =
|
|
856
|
+
let e = B(this.video);
|
|
857
857
|
return e.totalFrames < this.lastFrames && (this.baseFrames += this.lastFrames), e.dropped < this.lastDropped && (this.baseDropped += this.lastDropped), this.lastFrames = e.totalFrames, this.lastDropped = e.dropped, {
|
|
858
858
|
dropped: this.baseDropped + e.dropped,
|
|
859
859
|
totalFrames: this.baseFrames + e.totalFrames
|
|
@@ -927,7 +927,7 @@ var G = 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 V(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();
|
|
@@ -1069,7 +1069,7 @@ var G = class {
|
|
|
1069
1069
|
droppedFrames: t.dropped,
|
|
1070
1070
|
decodedFrames: t.totalFrames
|
|
1071
1071
|
};
|
|
1072
|
-
if (this.cdnHost ||=
|
|
1072
|
+
if (this.cdnHost ||= Ye(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1073
1073
|
if (n.isLive = !0, e.seekable.length > 0) {
|
|
1074
1074
|
let t = e.seekable.end(e.seekable.length - 1);
|
|
1075
1075
|
n.atLiveEdge = e.currentTime >= t - 2;
|
|
@@ -1320,21 +1320,21 @@ function ft(e, t) {
|
|
|
1320
1320
|
function pt() {
|
|
1321
1321
|
return e.isSupported();
|
|
1322
1322
|
}
|
|
1323
|
-
var mt = 3, ht = 5, gt = 3, _t = 1e4, vt = 3e4, yt = 12e3, bt = 3e3, xt =
|
|
1324
|
-
function
|
|
1323
|
+
var mt = 3, ht = 5, gt = 3, _t = 1e4, vt = 3e4, yt = 12e3, bt = 3e3, xt = .02, St = 6e3, Ct = .5, wt = 3, Tt = .5, Et = 1.1, Dt = .25, Ot = 5e3, kt = 4e3, At = 2, jt = 5, Mt = 2, Nt = 2, Pt = 4, Ft = 4, It = 2e3, Lt = 3e4, Rt = .2, zt = 30, Bt = 2, Vt = 2, Ht = 9, Ut = .5, Wt = 64;
|
|
1324
|
+
function Gt(e) {
|
|
1325
1325
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1326
1326
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1327
1327
|
return;
|
|
1328
1328
|
}
|
|
1329
|
-
e.liveSyncDuration ??=
|
|
1330
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1331
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1329
|
+
e.liveSyncDuration ??= Vt;
|
|
1330
|
+
let t = Math.max(12, e.liveSyncDuration + Ht);
|
|
1331
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Kt(e, e.liveSyncDuration);
|
|
1332
1332
|
}
|
|
1333
|
-
function
|
|
1333
|
+
function Kt(e, t) {
|
|
1334
1334
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1335
1335
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1336
1336
|
}
|
|
1337
|
-
var
|
|
1337
|
+
var qt = class {
|
|
1338
1338
|
name = "hls";
|
|
1339
1339
|
hls = null;
|
|
1340
1340
|
deps;
|
|
@@ -1414,7 +1414,7 @@ var Kt = class {
|
|
|
1414
1414
|
frameCounter;
|
|
1415
1415
|
detachFrames = null;
|
|
1416
1416
|
constructor(e) {
|
|
1417
|
-
this.deps = e, this.frameCounter = new
|
|
1417
|
+
this.deps = e, this.frameCounter = new V(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1418
1418
|
}
|
|
1419
1419
|
async load() {
|
|
1420
1420
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1427,7 +1427,7 @@ var Kt = class {
|
|
|
1427
1427
|
});
|
|
1428
1428
|
return;
|
|
1429
1429
|
}
|
|
1430
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r),
|
|
1430
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Pe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1431
1431
|
let e = this.hls;
|
|
1432
1432
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1433
1433
|
let t = e.liveSyncPosition;
|
|
@@ -1450,7 +1450,7 @@ var Kt = class {
|
|
|
1450
1450
|
}
|
|
1451
1451
|
this.loadSuspended = !0;
|
|
1452
1452
|
}
|
|
1453
|
-
},
|
|
1453
|
+
}, Ot));
|
|
1454
1454
|
}
|
|
1455
1455
|
resumeLoading() {
|
|
1456
1456
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1482,7 +1482,22 @@ var Kt = class {
|
|
|
1482
1482
|
let t = e.liveSyncPosition;
|
|
1483
1483
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1484
1484
|
let { video: n } = this.deps;
|
|
1485
|
-
n.currentTime <= t +
|
|
1485
|
+
n.currentTime <= t + Ut || (n.currentTime = t);
|
|
1486
|
+
}
|
|
1487
|
+
reanchorPartTimeline(e, t) {
|
|
1488
|
+
let { frag: n, part: r } = t;
|
|
1489
|
+
if (!r || r.index !== 0 || n.type !== "main" || typeof n.sn != "number") return;
|
|
1490
|
+
let i = e.levels[n.level]?.details;
|
|
1491
|
+
if (!i?.live) return;
|
|
1492
|
+
let a = r.elementaryStreams.video ?? r.elementaryStreams.audiovideo ?? r.elementaryStreams.audio;
|
|
1493
|
+
if (!a) return;
|
|
1494
|
+
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1495
|
+
if (!s) return;
|
|
1496
|
+
let c = a.startPTS - s.start;
|
|
1497
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < xt)) {
|
|
1498
|
+
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1499
|
+
i.fragmentHint?.setStart(i.fragmentHint.start + c), this.deps.debug === !0 && console.info(`havik-player: LL-HLS timeline re-anchored by ${c >= 0 ? "+" : ""}${c.toFixed(3)}s at sn ${n.sn} (level ${n.level})`);
|
|
1500
|
+
}
|
|
1486
1501
|
}
|
|
1487
1502
|
startHls() {
|
|
1488
1503
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1540,9 +1555,9 @@ var Kt = class {
|
|
|
1540
1555
|
}), t = lt(e);
|
|
1541
1556
|
t && (this.prefetch = e, d.fLoader = t);
|
|
1542
1557
|
}
|
|
1543
|
-
|
|
1558
|
+
Gt(d), this.catchUpRate = typeof d.maxLiveSyncPlaybackRate == "number" ? d.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (d.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = d.autoStartLoad !== !1;
|
|
1544
1559
|
let f = new e(d);
|
|
1545
|
-
if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1560
|
+
if (this.hls = f, f.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(f, t)), f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1546
1561
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(f), this.measureLadder(f), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1547
1562
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1548
1563
|
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(() => {
|
|
@@ -1555,10 +1570,10 @@ var Kt = class {
|
|
|
1555
1570
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1556
1571
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1557
1572
|
let i = n?.loading;
|
|
1558
|
-
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length >
|
|
1573
|
+
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Wt && this.requestTimesMs.shift());
|
|
1559
1574
|
let a = t?.frag?.url;
|
|
1560
1575
|
if (a) {
|
|
1561
|
-
let e =
|
|
1576
|
+
let e = z(a);
|
|
1562
1577
|
e && (this.cdnHost = e);
|
|
1563
1578
|
}
|
|
1564
1579
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1644,7 +1659,7 @@ var Kt = class {
|
|
|
1644
1659
|
return;
|
|
1645
1660
|
}
|
|
1646
1661
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1647
|
-
let t = e > this.sizeCapLevel ?
|
|
1662
|
+
let t = e > this.sizeCapLevel ? It : Lt;
|
|
1648
1663
|
this.capTimer = setTimeout(() => {
|
|
1649
1664
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1650
1665
|
}, t);
|
|
@@ -1654,9 +1669,9 @@ var Kt = class {
|
|
|
1654
1669
|
this.ladderHeights = t.length ? [...new Set(t)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = e.levels.length ? Math.round(Math.max(...e.levels.map((e) => e.bitrate)) / 1e3) : 0;
|
|
1655
1670
|
}
|
|
1656
1671
|
dropLevelsWidevineCannotPlay(e) {
|
|
1657
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1672
|
+
this.removeLevelsWhere(e, (e) => Fe(e) !== !0);
|
|
1658
1673
|
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
|
|
1659
|
-
for (let n of t)
|
|
1674
|
+
for (let n of t) Ne(n).then((t) => {
|
|
1660
1675
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1661
1676
|
});
|
|
1662
1677
|
}
|
|
@@ -1667,7 +1682,7 @@ var Kt = class {
|
|
|
1667
1682
|
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1668
1683
|
}), !r.length) return !1;
|
|
1669
1684
|
let a = [...i].join(", ");
|
|
1670
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) ||
|
|
1685
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Fe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1671
1686
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1672
1687
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1673
1688
|
}
|
|
@@ -1765,7 +1780,7 @@ var Kt = class {
|
|
|
1765
1780
|
return;
|
|
1766
1781
|
}
|
|
1767
1782
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1768
|
-
!this.chaseSuspended && e >
|
|
1783
|
+
!this.chaseSuspended && e > St && this.suspendChasing(), e > yt && this.emitEnded("stalled");
|
|
1769
1784
|
}
|
|
1770
1785
|
resetStarvationWindow() {
|
|
1771
1786
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1780,7 +1795,7 @@ var Kt = class {
|
|
|
1780
1795
|
this.resetStarvationWindow();
|
|
1781
1796
|
return;
|
|
1782
1797
|
}
|
|
1783
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1798
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < St, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > kt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
|
|
1784
1799
|
if (this.starvedFrames = c, !a || l) {
|
|
1785
1800
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1786
1801
|
return;
|
|
@@ -1789,12 +1804,12 @@ var Kt = class {
|
|
|
1789
1804
|
this.resetStarvationWindow();
|
|
1790
1805
|
return;
|
|
1791
1806
|
}
|
|
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 >
|
|
1807
|
+
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > Pt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= Mt && (this.clearKick(), this.starvationRebuilds < Nt)) {
|
|
1793
1808
|
this.starvationRebuilds += 1, this.resetStarvationWindow(), this.clearRecoveryReset(), console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
|
|
1794
1809
|
return;
|
|
1795
1810
|
}
|
|
1796
|
-
let u = i && this.starvedTicks >=
|
|
1797
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1811
|
+
let u = i && this.starvedTicks >= At, d = !i && this.deadTicks >= Pt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Ft;
|
|
1812
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= jt))) {
|
|
1798
1813
|
this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, this.kickKind = d ? "dead" : "quiet", this.clearRecoveryReset(), console.warn(d ? "havik-player: video starved while hls.js keeps loading media it never plays (dead pipeline at the live edge) — restarting the load" : "havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
|
|
1799
1814
|
try {
|
|
1800
1815
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1809,7 +1824,7 @@ var Kt = class {
|
|
|
1809
1824
|
let t = e.latency, n = e.targetLatency;
|
|
1810
1825
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1811
1826
|
let r = t - n;
|
|
1812
|
-
!this.catchUpEngaged && r >
|
|
1827
|
+
!this.catchUpEngaged && r > Ct ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Ct && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1813
1828
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1814
1829
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1815
1830
|
}
|
|
@@ -1830,16 +1845,16 @@ var Kt = class {
|
|
|
1830
1845
|
this.resetFrameDropWindow();
|
|
1831
1846
|
return;
|
|
1832
1847
|
}
|
|
1833
|
-
let { totalFrames: n, dropped: r } =
|
|
1834
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
1848
|
+
let { totalFrames: n, dropped: r } = B(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
1849
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < zt || o < 0) {
|
|
1835
1850
|
this.fpsBadTicks = 0;
|
|
1836
1851
|
return;
|
|
1837
1852
|
}
|
|
1838
|
-
if (o <=
|
|
1853
|
+
if (o <= Rt * a) {
|
|
1839
1854
|
this.fpsBadTicks = 0;
|
|
1840
1855
|
return;
|
|
1841
1856
|
}
|
|
1842
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
1857
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < Bt) return;
|
|
1843
1858
|
this.fpsBadTicks = 0;
|
|
1844
1859
|
let s = e.levels, c = s[e.currentLevel];
|
|
1845
1860
|
if (!c) return;
|
|
@@ -1856,20 +1871,20 @@ var Kt = class {
|
|
|
1856
1871
|
return;
|
|
1857
1872
|
}
|
|
1858
1873
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
1859
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
1874
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Et, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
1860
1875
|
this.resetChaseWindow();
|
|
1861
1876
|
return;
|
|
1862
1877
|
}
|
|
1863
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
1878
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= Tt) {
|
|
1864
1879
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
1865
1880
|
return;
|
|
1866
1881
|
}
|
|
1867
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
1882
|
+
if (this.chaseTicks += 1, this.chaseTicks < wt) return;
|
|
1868
1883
|
this.resetChaseWindow();
|
|
1869
1884
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
1870
1885
|
if (!(a > 1)) return;
|
|
1871
1886
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
1872
|
-
s < o +
|
|
1887
|
+
s < o + Dt || (console.warn(`havik-player: catch-up at ${r}x not gaining on the live edge (latency ${n.toFixed(1)}s); holding at ${s.toFixed(1)}s`), this.liveRetargets += 1, e.targetLatency = s);
|
|
1873
1888
|
}
|
|
1874
1889
|
suspendChasing() {
|
|
1875
1890
|
let e = this.hls;
|
|
@@ -1987,19 +2002,19 @@ var Kt = class {
|
|
|
1987
2002
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1988
2003
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1989
2004
|
}
|
|
1990
|
-
},
|
|
2005
|
+
}, Jt = 15e3, Yt = 6e5, Xt = 3e5, Zt = 100, q = 1, Qt = 1e3, $t = 3e4, en = 1e3, tn = {
|
|
1991
2006
|
inline: "PRESENTATION_INLINE",
|
|
1992
2007
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1993
2008
|
pip: "PRESENTATION_PIP"
|
|
1994
|
-
},
|
|
2009
|
+
}, nn = {
|
|
1995
2010
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1996
2011
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1997
2012
|
none: "KEY_SYSTEM_NONE"
|
|
1998
2013
|
};
|
|
1999
|
-
function
|
|
2014
|
+
function rn(e, t) {
|
|
2000
2015
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
2001
2016
|
}
|
|
2002
|
-
var
|
|
2017
|
+
var an = /* @__PURE__ */ new Set([
|
|
2003
2018
|
"INVALID_URN",
|
|
2004
2019
|
"NOT_FOUND",
|
|
2005
2020
|
"GONE",
|
|
@@ -2019,7 +2034,7 @@ var rn = /* @__PURE__ */ new Set([
|
|
|
2019
2034
|
ended: "PLAYER_STATE_ENDED",
|
|
2020
2035
|
error: "PLAYER_STATE_ERROR"
|
|
2021
2036
|
};
|
|
2022
|
-
function
|
|
2037
|
+
function on(e) {
|
|
2023
2038
|
try {
|
|
2024
2039
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2025
2040
|
return !n || r.length === 0 || n !== "feed" && !n.startsWith("feed-") ? void 0 : (t.hostname = [n.replace(/^feed/, "beacons"), ...r].join("."), t.pathname = "", t.search = "", t.origin);
|
|
@@ -2027,8 +2042,8 @@ function an(e) {
|
|
|
2027
2042
|
return;
|
|
2028
2043
|
}
|
|
2029
2044
|
}
|
|
2030
|
-
var
|
|
2031
|
-
function
|
|
2045
|
+
var sn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), cn = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), ln = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2046
|
+
function un(e) {
|
|
2032
2047
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2033
2048
|
let t;
|
|
2034
2049
|
try {
|
|
@@ -2037,19 +2052,19 @@ function ln(e) {
|
|
|
2037
2052
|
} catch {
|
|
2038
2053
|
return;
|
|
2039
2054
|
}
|
|
2040
|
-
if (
|
|
2041
|
-
Y.add(t), g(
|
|
2055
|
+
if (cn.has(t) && !Y.has(t)) {
|
|
2056
|
+
Y.add(t), g(ln(new URL(t).origin));
|
|
2042
2057
|
for (let e of X) e.noteCspBlocked();
|
|
2043
2058
|
}
|
|
2044
2059
|
}
|
|
2045
|
-
function
|
|
2060
|
+
function dn(e, t) {
|
|
2046
2061
|
return g(t, e), { disabledReason: t };
|
|
2047
2062
|
}
|
|
2048
|
-
function
|
|
2049
|
-
if (n) return t && !
|
|
2063
|
+
function fn(e, t, n) {
|
|
2064
|
+
if (n) return t && !sn(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2050
2065
|
if (t) return { endpoint: t };
|
|
2051
|
-
if (t !== void 0) return
|
|
2052
|
-
let r =
|
|
2066
|
+
if (t !== void 0) return dn("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).");
|
|
2067
|
+
let r = on(e);
|
|
2053
2068
|
if (r) return { endpoint: r };
|
|
2054
2069
|
let i;
|
|
2055
2070
|
try {
|
|
@@ -2057,9 +2072,9 @@ function dn(e, t, n) {
|
|
|
2057
2072
|
} catch {
|
|
2058
2073
|
i = e;
|
|
2059
2074
|
}
|
|
2060
|
-
return
|
|
2075
|
+
return dn(i, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${i}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
|
|
2061
2076
|
}
|
|
2062
|
-
var
|
|
2077
|
+
var pn = class {
|
|
2063
2078
|
opts;
|
|
2064
2079
|
url;
|
|
2065
2080
|
cspKey;
|
|
@@ -2141,8 +2156,8 @@ var fn = class {
|
|
|
2141
2156
|
constructor(e) {
|
|
2142
2157
|
this.opts = {
|
|
2143
2158
|
...e,
|
|
2144
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2145
|
-
idleMs: e.idleMs ??
|
|
2159
|
+
heartbeatMs: e.heartbeatMs ?? Jt,
|
|
2160
|
+
idleMs: e.idleMs ?? Yt
|
|
2146
2161
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2147
2162
|
try {
|
|
2148
2163
|
let e = new URL(this.url);
|
|
@@ -2159,11 +2174,11 @@ var fn = class {
|
|
|
2159
2174
|
sdkVersion: this.opts.sdkVersion,
|
|
2160
2175
|
...this.opts.environment
|
|
2161
2176
|
};
|
|
2162
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2177
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Qt), 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 && cn.add(this.cspKey), document.addEventListener("securitypolicyviolation", un), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2163
2178
|
}
|
|
2164
2179
|
checkSuspension(e) {
|
|
2165
2180
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2166
|
-
let t = Math.max(this.opts.idleMs,
|
|
2181
|
+
let t = Math.max(this.opts.idleMs, Xt);
|
|
2167
2182
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2168
2183
|
}
|
|
2169
2184
|
syncIdle(e) {
|
|
@@ -2186,12 +2201,12 @@ var fn = class {
|
|
|
2186
2201
|
let a = {
|
|
2187
2202
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2188
2203
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2189
|
-
presentation:
|
|
2204
|
+
presentation: tn[this.presentation]
|
|
2190
2205
|
}, o = this.causeOf(e, t, i);
|
|
2191
2206
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2192
2207
|
}
|
|
2193
2208
|
seekInduced(e) {
|
|
2194
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2209
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < en;
|
|
2195
2210
|
}
|
|
2196
2211
|
causeOf(e, t, n) {
|
|
2197
2212
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2265,7 +2280,7 @@ var fn = class {
|
|
|
2265
2280
|
let r = n ?? "";
|
|
2266
2281
|
if (r !== "") return /^fragLoad/i.test(r) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /^(manifest|level|audioTrack|subtitleTrack)/i.test(r) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(r) ? "ERROR_STAGE_DRM" : /parsing|append|buffer|remux|decrypt|media/i.test(r) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
|
|
2267
2282
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2268
|
-
if (
|
|
2283
|
+
if (an.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2269
2284
|
let i = t ?? "";
|
|
2270
2285
|
return /frag|segment/i.test(i) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /manifest|level|playlist/i.test(i) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(i) ? "ERROR_STAGE_DRM" : /buffer|decode|media|append/i.test(i) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
|
|
2271
2286
|
}
|
|
@@ -2312,14 +2327,14 @@ var fn = class {
|
|
|
2312
2327
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2313
2328
|
o.requestCountDelta = _;
|
|
2314
2329
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2315
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2330
|
+
n.length > 0 && (o.requestTimeP50Ms = rn(n, 50), o.requestTimeP95Ms = rn(n, 95));
|
|
2316
2331
|
}
|
|
2317
2332
|
typeof t.latencySeconds == "number" && typeof t.targetLatencySeconds == "number" && (o.driftMs = Math.round((t.latencySeconds - t.targetLatencySeconds) * 1e3)), typeof t.playbackRate == "number" && t.playbackRate > 0 && (o.playbackRate = t.playbackRate), t.qualityPinned === !0 && (o.qualityPinned = !0), t.cdnHost && (o.cdnHost = t.cdnHost), this.maybeEmitMediaInfo(t), this.enqueue({ heartbeat: o }), this.flush(), s > 0 && this.noteFirstBytes();
|
|
2318
2333
|
}
|
|
2319
2334
|
maybeEmitMediaInfo(e) {
|
|
2320
2335
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2321
2336
|
let t = {};
|
|
2322
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2337
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = nn[e.keySystem]), e.drmSecurityLevel && (t.drmSecurityLevel = e.drmSecurityLevel), e.ladderHeights?.length && (t.ladderHeights = e.ladderHeights), e.ladderTopBitrateKbps && (t.ladderTopBitrateKbps = e.ladderTopBitrateKbps), e.lowLatency && (t.lowLatency = !0);
|
|
2323
2338
|
let n = JSON.stringify(t);
|
|
2324
2339
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2325
2340
|
}
|
|
@@ -2339,7 +2354,7 @@ var fn = class {
|
|
|
2339
2354
|
let c = r?.positionMs ?? 0;
|
|
2340
2355
|
c > 0 && (i.exitPositionMs = Math.round(c)), this.activeTotalMs > 0 && (i.activeWatchTimeMs = Math.round(this.activeTotalMs)), this.mutedTotalMs > 0 && (i.mutedTimeMs = Math.round(this.mutedTotalMs));
|
|
2341
2356
|
let l = e !== "END_REASON_ENDED";
|
|
2342
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2357
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= $t && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= $t && (i.abandonAfterErrorMs = Math.max(q, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
|
|
2343
2358
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2344
2359
|
u > 0 && (i.decodedFramesTotal = u), e === "END_REASON_STOPPED" && this.startupTimeMs === 0 && this.lastErrorStage === null && (e = "END_REASON_ABORTED", i.reason = e), this.startupTimeMs === 0 && e !== "END_REASON_ABORTED" && (i.failedStage = this.lastErrorStage ?? (this.manifestLoadMs === 0 ? "ERROR_STAGE_MANIFEST" : this.firstFragLoadMs === 0 ? "ERROR_STAGE_FIRST_SEGMENT" : "ERROR_STAGE_OTHER")), this.pending.push(this.wrap({ sessionEnd: i })), this.flush(e === "END_REASON_PAGEHIDE");
|
|
2345
2360
|
}
|
|
@@ -2359,13 +2374,13 @@ var fn = class {
|
|
|
2359
2374
|
};
|
|
2360
2375
|
}
|
|
2361
2376
|
noteCspBlocked() {
|
|
2362
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2377
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(ln(new URL(this.url).origin)));
|
|
2363
2378
|
}
|
|
2364
2379
|
cspBlocked() {
|
|
2365
2380
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2366
2381
|
}
|
|
2367
2382
|
enqueue(e) {
|
|
2368
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2383
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Zt;) {
|
|
2369
2384
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2370
2385
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2371
2386
|
}
|
|
@@ -2392,7 +2407,7 @@ var fn = class {
|
|
|
2392
2407
|
};
|
|
2393
2408
|
//#endregion
|
|
2394
2409
|
//#region src/core/environment.ts
|
|
2395
|
-
function
|
|
2410
|
+
function mn() {
|
|
2396
2411
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2397
2412
|
let e;
|
|
2398
2413
|
try {
|
|
@@ -2417,14 +2432,14 @@ function pn() {
|
|
|
2417
2432
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2418
2433
|
};
|
|
2419
2434
|
}
|
|
2420
|
-
function
|
|
2435
|
+
function hn() {
|
|
2421
2436
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2422
2437
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2423
2438
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2424
2439
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2425
2440
|
return e?.mobile ?? (typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1 && n > 0 && n < 900) ? n >= 600 ? "DEVICE_CLASS_TABLET" : "DEVICE_CLASS_PHONE" : e || n >= 900 || /mac|win|linux|chrome os/i.test(t) ? "DEVICE_CLASS_DESKTOP" : "DEVICE_CLASS_OTHER";
|
|
2426
2441
|
}
|
|
2427
|
-
function
|
|
2442
|
+
function gn() {
|
|
2428
2443
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2429
2444
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2430
2445
|
let t = {
|
|
@@ -2443,17 +2458,17 @@ function hn() {
|
|
|
2443
2458
|
}
|
|
2444
2459
|
return typeof e.downlink == "number" && e.downlink > 0 && (i.downlinkKbps = Math.round(e.downlink * 1e3)), typeof e.rtt == "number" && e.rtt > 0 && (i.rttMs = Math.round(e.rtt)), e.saveData && (i.saveData = !0), i;
|
|
2445
2460
|
}
|
|
2446
|
-
function
|
|
2447
|
-
let t =
|
|
2448
|
-
deviceClass:
|
|
2461
|
+
function _n(e) {
|
|
2462
|
+
let t = mn(), n = {
|
|
2463
|
+
deviceClass: hn(),
|
|
2449
2464
|
integration: t.integration,
|
|
2450
|
-
...
|
|
2465
|
+
...gn()
|
|
2451
2466
|
};
|
|
2452
2467
|
t.host && (n.host = t.host), typeof screen < "u" && screen.width > 0 && (n.screenWidth = screen.width, n.screenHeight = screen.height), typeof window < "u" && window.devicePixelRatio > 0 && (n.devicePixelRatio = Math.round(window.devicePixelRatio * 100) / 100);
|
|
2453
2468
|
let r = e.getBoundingClientRect?.();
|
|
2454
2469
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2455
2470
|
}
|
|
2456
|
-
async function
|
|
2471
|
+
async function vn() {
|
|
2457
2472
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2458
2473
|
if (!e?.getHighEntropyValues) return {};
|
|
2459
2474
|
try {
|
|
@@ -2465,7 +2480,7 @@ async function _n() {
|
|
|
2465
2480
|
}
|
|
2466
2481
|
//#endregion
|
|
2467
2482
|
//#region src/core/version.ts
|
|
2468
|
-
var
|
|
2483
|
+
var yn = "2.16.7", bn = {
|
|
2469
2484
|
accent: "#E1B600",
|
|
2470
2485
|
accentText: "#1B1C23",
|
|
2471
2486
|
background: "#0e0f13",
|
|
@@ -2476,7 +2491,7 @@ var vn = "2.16.6", yn = {
|
|
|
2476
2491
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2477
2492
|
radius: "8px",
|
|
2478
2493
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2479
|
-
},
|
|
2494
|
+
}, xn = {
|
|
2480
2495
|
accent: "--havik-accent",
|
|
2481
2496
|
accentText: "--havik-accent-text",
|
|
2482
2497
|
background: "--havik-bg",
|
|
@@ -2488,26 +2503,26 @@ var vn = "2.16.6", yn = {
|
|
|
2488
2503
|
radius: "--havik-radius",
|
|
2489
2504
|
fontFamily: "--havik-font"
|
|
2490
2505
|
};
|
|
2491
|
-
function
|
|
2506
|
+
function Sn(e, t) {
|
|
2492
2507
|
let n = {
|
|
2493
|
-
...
|
|
2508
|
+
...bn,
|
|
2494
2509
|
...t
|
|
2495
2510
|
};
|
|
2496
|
-
for (let t of Object.keys(
|
|
2511
|
+
for (let t of Object.keys(xn)) e.style.setProperty(xn[t], n[t]);
|
|
2497
2512
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2498
2513
|
}
|
|
2499
2514
|
//#endregion
|
|
2500
2515
|
//#region src/ui/styles.ts
|
|
2501
|
-
var
|
|
2502
|
-
function
|
|
2503
|
-
let n = e.querySelector(`style#${
|
|
2516
|
+
var Cn = "havik-player-styles", wn = "\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();
|
|
2517
|
+
function Tn(e = document, t) {
|
|
2518
|
+
let n = e.querySelector(`style#${Cn}`);
|
|
2504
2519
|
if (n && (!t || Z.get(n) === t)) return;
|
|
2505
2520
|
let r = e.createElement("style");
|
|
2506
|
-
r.id =
|
|
2521
|
+
r.id = Cn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = wn, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2507
2522
|
}
|
|
2508
2523
|
//#endregion
|
|
2509
2524
|
//#region src/ui/icons.ts
|
|
2510
|
-
var
|
|
2525
|
+
var En = {
|
|
2511
2526
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2512
2527
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2513
2528
|
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\"/>",
|
|
@@ -2521,20 +2536,20 @@ var Tn = {
|
|
|
2521
2536
|
retry: "<path d=\"M17.65 6.35A8 8 0 1 0 19.73 13h-2.08A6 6 0 1 1 12 6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"/>"
|
|
2522
2537
|
};
|
|
2523
2538
|
function Q(e) {
|
|
2524
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2539
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${En[e]}</svg>`;
|
|
2525
2540
|
}
|
|
2526
2541
|
//#endregion
|
|
2527
2542
|
//#region src/ui/controls.ts
|
|
2528
|
-
var
|
|
2543
|
+
var Dn = 3e3, On = 250, kn = /* @__PURE__ */ new Set([
|
|
2529
2544
|
"GONE",
|
|
2530
2545
|
"NOT_FOUND",
|
|
2531
2546
|
"INVALID_URN",
|
|
2532
2547
|
"UNAUTHORIZED"
|
|
2533
2548
|
]);
|
|
2534
|
-
function
|
|
2535
|
-
return new
|
|
2549
|
+
function An(e) {
|
|
2550
|
+
return new jn(e);
|
|
2536
2551
|
}
|
|
2537
|
-
var
|
|
2552
|
+
var jn = class {
|
|
2538
2553
|
root;
|
|
2539
2554
|
video;
|
|
2540
2555
|
player;
|
|
@@ -2580,7 +2595,7 @@ var An = class {
|
|
|
2580
2595
|
scrubbing = !1;
|
|
2581
2596
|
offFns = [];
|
|
2582
2597
|
constructor(e) {
|
|
2583
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2598
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Dn, 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, Tn(this.doc, e.cspNonce), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
|
|
2584
2599
|
let t = (e, t, n) => {
|
|
2585
2600
|
let r = this.doc.createElement(e);
|
|
2586
2601
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2666,7 +2681,7 @@ var An = class {
|
|
|
2666
2681
|
let t = this.surfaceWasHidden;
|
|
2667
2682
|
this.tapTimer = setTimeout(() => {
|
|
2668
2683
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2669
|
-
},
|
|
2684
|
+
}, On);
|
|
2670
2685
|
}
|
|
2671
2686
|
toggleBar(e) {
|
|
2672
2687
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2701,7 +2716,7 @@ var An = class {
|
|
|
2701
2716
|
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);
|
|
2702
2717
|
} else {
|
|
2703
2718
|
let r = this.doc.createElement("div");
|
|
2704
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2719
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !kn.has(this.lastError.code)) {
|
|
2705
2720
|
let e = this.doc.createElement("button");
|
|
2706
2721
|
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);
|
|
2707
2722
|
}
|
|
@@ -2742,7 +2757,7 @@ var An = class {
|
|
|
2742
2757
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2743
2758
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2744
2759
|
}
|
|
2745
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2760
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Mn(this.video.currentTime)} / ${Mn(this.video.duration)}`);
|
|
2746
2761
|
}
|
|
2747
2762
|
syncLive() {
|
|
2748
2763
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2792,17 +2807,17 @@ var An = class {
|
|
|
2792
2807
|
renderQualityMenu() {
|
|
2793
2808
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2794
2809
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2795
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2810
|
+
for (let n of e) this.menu.append(this.menuItem(Nn(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2796
2811
|
}
|
|
2797
2812
|
renderAudioMenu() {
|
|
2798
2813
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2799
2814
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2800
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2815
|
+
for (let t of e) this.menu.append(this.menuItem(Pn(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2801
2816
|
}
|
|
2802
2817
|
renderCcMenu() {
|
|
2803
2818
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2804
2819
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2805
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2820
|
+
for (let t of e) this.menu.append(this.menuItem(Fn(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2806
2821
|
}
|
|
2807
2822
|
onTracksChanged() {
|
|
2808
2823
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2903,41 +2918,41 @@ var An = class {
|
|
|
2903
2918
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2904
2919
|
}
|
|
2905
2920
|
};
|
|
2906
|
-
function
|
|
2921
|
+
function Mn(e) {
|
|
2907
2922
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2908
2923
|
let t = Math.floor(e % 60), n = Math.floor(e / 60 % 60), r = Math.floor(e / 3600), i = r > 0 ? String(n).padStart(2, "0") : String(n), a = String(t).padStart(2, "0");
|
|
2909
2924
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2910
2925
|
}
|
|
2911
|
-
function
|
|
2926
|
+
function Nn(e) {
|
|
2912
2927
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2913
2928
|
}
|
|
2914
|
-
function
|
|
2929
|
+
function Pn(e) {
|
|
2915
2930
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2916
2931
|
}
|
|
2917
|
-
function
|
|
2932
|
+
function Fn(e) {
|
|
2918
2933
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2919
2934
|
}
|
|
2920
2935
|
//#endregion
|
|
2921
2936
|
//#region src/managed/index.ts
|
|
2922
|
-
var
|
|
2923
|
-
function
|
|
2937
|
+
var In = 6e3, Ln = 45e3, Rn = 2e3, zn = 3, Bn = 2e3, Vn = 48e4, Hn = "keySystemLicenseRequestFailed";
|
|
2938
|
+
function Un(e) {
|
|
2924
2939
|
if (e.env !== void 0 && e.baseUrl !== void 0) throw new n("INTERNAL", 0, `createPlayer: pass env OR baseUrl, not both (got env=${JSON.stringify(e.env)} and baseUrl=${JSON.stringify(e.baseUrl)})`);
|
|
2925
|
-
if (e.env !== void 0) return
|
|
2940
|
+
if (e.env !== void 0) return Ke(e.env);
|
|
2926
2941
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2927
2942
|
return e.baseUrl;
|
|
2928
2943
|
}
|
|
2929
|
-
async function
|
|
2944
|
+
async function Wn(e) {
|
|
2930
2945
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2931
|
-
let t =
|
|
2946
|
+
let t = Un(e);
|
|
2932
2947
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2933
2948
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2934
|
-
let r = new
|
|
2949
|
+
let r = new Gn({
|
|
2935
2950
|
...e,
|
|
2936
2951
|
baseUrl: t
|
|
2937
2952
|
});
|
|
2938
2953
|
return await r.start(), r;
|
|
2939
2954
|
}
|
|
2940
|
-
var
|
|
2955
|
+
var Gn = class {
|
|
2941
2956
|
opts;
|
|
2942
2957
|
abort = new AbortController();
|
|
2943
2958
|
listeners = {};
|
|
@@ -2984,7 +2999,7 @@ var Wn = class {
|
|
|
2984
2999
|
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");
|
|
2985
3000
|
let e = ++this.loadGen, t = this.resolveOptions();
|
|
2986
3001
|
try {
|
|
2987
|
-
let n = await
|
|
3002
|
+
let n = await v(t);
|
|
2988
3003
|
if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
|
|
2989
3004
|
let e = this._lastError;
|
|
2990
3005
|
throw this.destroy(), e;
|
|
@@ -3011,7 +3026,7 @@ var Wn = class {
|
|
|
3011
3026
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
3012
3027
|
}
|
|
3013
3028
|
beginArmingByPolling(e) {
|
|
3014
|
-
|
|
3029
|
+
y({
|
|
3015
3030
|
...this.resolveOptions(),
|
|
3016
3031
|
signal: this.abort.signal,
|
|
3017
3032
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -3028,7 +3043,7 @@ var Wn = class {
|
|
|
3028
3043
|
setTimeout(() => {
|
|
3029
3044
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3030
3045
|
phase: i ? "unavailable" : "tooEarly",
|
|
3031
|
-
retryInMs:
|
|
3046
|
+
retryInMs: Ln,
|
|
3032
3047
|
attempt: 1,
|
|
3033
3048
|
elapsedMs: 0,
|
|
3034
3049
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3045,7 +3060,7 @@ var Wn = class {
|
|
|
3045
3060
|
}
|
|
3046
3061
|
}
|
|
3047
3062
|
}, h = () => {
|
|
3048
|
-
a || s || p() || (s = !0,
|
|
3063
|
+
a || s || p() || (s = !0, y({
|
|
3049
3064
|
...this.resolveOptions(),
|
|
3050
3065
|
signal: c.signal,
|
|
3051
3066
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -3053,7 +3068,7 @@ var Wn = class {
|
|
|
3053
3068
|
a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
|
|
3054
3069
|
}));
|
|
3055
3070
|
}, g = () => {
|
|
3056
|
-
a || p() ||
|
|
3071
|
+
a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
|
|
3057
3072
|
if (!(a || p())) {
|
|
3058
3073
|
if (e instanceof n && o(e.code)) {
|
|
3059
3074
|
h();
|
|
@@ -3067,13 +3082,13 @@ var Wn = class {
|
|
|
3067
3082
|
!a && !p() && h();
|
|
3068
3083
|
}, e);
|
|
3069
3084
|
};
|
|
3070
|
-
_(
|
|
3085
|
+
_(In), this.armingSub = T({
|
|
3071
3086
|
eventsBaseUrl: t,
|
|
3072
3087
|
matchUrn: this.opts.matchUrn,
|
|
3073
3088
|
credential: this.opts.credential,
|
|
3074
|
-
onAlive: () => _(
|
|
3089
|
+
onAlive: () => _(Ln),
|
|
3075
3090
|
onState: (e) => {
|
|
3076
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3091
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Rn);
|
|
3077
3092
|
},
|
|
3078
3093
|
onError: () => h()
|
|
3079
3094
|
});
|
|
@@ -3118,26 +3133,26 @@ var Wn = class {
|
|
|
3118
3133
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3119
3134
|
let i = e.analytics?.sid;
|
|
3120
3135
|
if (!i) return;
|
|
3121
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3136
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = fn(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3122
3137
|
if (!o) {
|
|
3123
3138
|
s && setTimeout(() => {
|
|
3124
3139
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3125
3140
|
}, 0);
|
|
3126
3141
|
return;
|
|
3127
3142
|
}
|
|
3128
|
-
let c = this.opts.video, l = new
|
|
3143
|
+
let c = this.opts.video, l = new pn({
|
|
3129
3144
|
endpoint: o,
|
|
3130
3145
|
sid: i,
|
|
3131
3146
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3132
|
-
sdkVersion:
|
|
3133
|
-
environment:
|
|
3147
|
+
sdkVersion: yn,
|
|
3148
|
+
environment: _n(c),
|
|
3134
3149
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3135
3150
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3136
3151
|
onBlocked: (e) => setTimeout(() => {
|
|
3137
3152
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3138
3153
|
}, 0),
|
|
3139
3154
|
sample: () => {
|
|
3140
|
-
let e = this.engine?.getStats() ??
|
|
3155
|
+
let e = this.engine?.getStats() ?? qe, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3141
3156
|
return {
|
|
3142
3157
|
...e,
|
|
3143
3158
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3151,7 +3166,7 @@ var Wn = class {
|
|
|
3151
3166
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3152
3167
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3153
3168
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3154
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3169
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), vn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3155
3170
|
}
|
|
3156
3171
|
currentPresentation() {
|
|
3157
3172
|
let e = this.opts.video;
|
|
@@ -3178,9 +3193,9 @@ var Wn = class {
|
|
|
3178
3193
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3179
3194
|
}, o = this.opts.engine ?? "auto";
|
|
3180
3195
|
if (o === "native") return new G(a);
|
|
3181
|
-
if (o === "hls") return new
|
|
3196
|
+
if (o === "hls") return new qt(a);
|
|
3182
3197
|
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
|
|
3198
|
+
if (pt()) return new qt(a);
|
|
3184
3199
|
if (U(this.opts.video)) return new G(a);
|
|
3185
3200
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3186
3201
|
}
|
|
@@ -3243,7 +3258,7 @@ var Wn = class {
|
|
|
3243
3258
|
r = 0, i = !1;
|
|
3244
3259
|
},
|
|
3245
3260
|
onError: () => {
|
|
3246
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
3261
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= zn && (i = !0, this.emit("warning", new n("NETWORK", 0, `live-state events unreachable at ${t} after ${r} attempts — end-of-stream detection degraded to the HLS staleness watchdog. Check the events host, the api-key's allowed origins, and CSP connect-src.`))));
|
|
3247
3262
|
}
|
|
3248
3263
|
});
|
|
3249
3264
|
}
|
|
@@ -3265,7 +3280,7 @@ var Wn = class {
|
|
|
3265
3280
|
scheduleRejoin(e) {
|
|
3266
3281
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3267
3282
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3268
|
-
}, Math.random() *
|
|
3283
|
+
}, Math.random() * Rn));
|
|
3269
3284
|
}
|
|
3270
3285
|
cancelRejoin() {
|
|
3271
3286
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3289,7 +3304,7 @@ var Wn = class {
|
|
|
3289
3304
|
}
|
|
3290
3305
|
t.controls = !1;
|
|
3291
3306
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3292
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3307
|
+
r && r.insertBefore(n, t), n.appendChild(t), Sn(n, this.opts.theme), this.container = n, this.controlBar = An({
|
|
3293
3308
|
root: n,
|
|
3294
3309
|
video: t,
|
|
3295
3310
|
player: this,
|
|
@@ -3320,7 +3335,7 @@ var Wn = class {
|
|
|
3320
3335
|
}
|
|
3321
3336
|
startStats() {
|
|
3322
3337
|
this.stopStats();
|
|
3323
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3338
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Bn);
|
|
3324
3339
|
this.statsTimer = setInterval(() => {
|
|
3325
3340
|
if (!this.engine) return;
|
|
3326
3341
|
let e = this.engine.getStats();
|
|
@@ -3331,14 +3346,14 @@ var Wn = class {
|
|
|
3331
3346
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3332
3347
|
}
|
|
3333
3348
|
isStaleLicenseDenial(e) {
|
|
3334
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3349
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== Hn || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3335
3350
|
}
|
|
3336
3351
|
scheduleLicenseRefresh() {
|
|
3337
3352
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3338
3353
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3339
3354
|
document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3340
3355
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3341
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3356
|
+
let e = this.opts.licenseRefreshMs ?? Vn;
|
|
3342
3357
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3343
3358
|
}
|
|
3344
3359
|
stopRefresh() {
|
|
@@ -3350,7 +3365,7 @@ var Wn = class {
|
|
|
3350
3365
|
if (this.refreshInFlight?.engine === e) return this.refreshInFlight.promise;
|
|
3351
3366
|
let t = (async () => {
|
|
3352
3367
|
try {
|
|
3353
|
-
let t = await
|
|
3368
|
+
let t = await v(this.resolveOptions());
|
|
3354
3369
|
if (this.destroyed || this.engine !== e) return;
|
|
3355
3370
|
let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
|
|
3356
3371
|
return (n || r) && (e.setLicenseUrls({
|
|
@@ -3394,7 +3409,7 @@ var Wn = class {
|
|
|
3394
3409
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3395
3410
|
}
|
|
3396
3411
|
getStats() {
|
|
3397
|
-
return this.engine?.getStats() ??
|
|
3412
|
+
return this.engine?.getStats() ?? qe;
|
|
3398
3413
|
}
|
|
3399
3414
|
getQualityLevels() {
|
|
3400
3415
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3446,7 +3461,7 @@ var Wn = class {
|
|
|
3446
3461
|
let e = ++this.loadGen;
|
|
3447
3462
|
this.teardownPlayback();
|
|
3448
3463
|
try {
|
|
3449
|
-
let t = await
|
|
3464
|
+
let t = await y({
|
|
3450
3465
|
...this.resolveOptions(),
|
|
3451
3466
|
waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
|
|
3452
3467
|
});
|
|
@@ -3504,7 +3519,7 @@ function $(e) {
|
|
|
3504
3519
|
}
|
|
3505
3520
|
//#endregion
|
|
3506
3521
|
//#region src/embed/host.ts
|
|
3507
|
-
function
|
|
3522
|
+
function Kn(e) {
|
|
3508
3523
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3509
3524
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3510
3525
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3563,15 +3578,15 @@ function Gn(e) {
|
|
|
3563
3578
|
}
|
|
3564
3579
|
//#endregion
|
|
3565
3580
|
//#region src/embed/page.ts
|
|
3566
|
-
var
|
|
3567
|
-
function
|
|
3581
|
+
var qn = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3582
|
+
function Jn(e) {
|
|
3568
3583
|
if (typeof e == "boolean") return e;
|
|
3569
3584
|
if (typeof e == "object" && e) {
|
|
3570
3585
|
let t = e.endpoint;
|
|
3571
3586
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3572
3587
|
}
|
|
3573
3588
|
}
|
|
3574
|
-
function
|
|
3589
|
+
function Yn() {
|
|
3575
3590
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3576
3591
|
if (e) return {
|
|
3577
3592
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3581,7 +3596,7 @@ function Jn() {
|
|
|
3581
3596
|
autoplay: e.autoplay ?? !0,
|
|
3582
3597
|
muted: e.muted ?? !0,
|
|
3583
3598
|
waitForLive: e.waitForLive ?? !0,
|
|
3584
|
-
analytics:
|
|
3599
|
+
analytics: Jn(e.analytics)
|
|
3585
3600
|
};
|
|
3586
3601
|
let t = new URLSearchParams(location.search);
|
|
3587
3602
|
return {
|
|
@@ -3594,9 +3609,9 @@ function Jn() {
|
|
|
3594
3609
|
waitForLive: !0
|
|
3595
3610
|
};
|
|
3596
3611
|
}
|
|
3597
|
-
async function
|
|
3598
|
-
let e =
|
|
3599
|
-
|
|
3612
|
+
async function Xn() {
|
|
3613
|
+
let e = Yn();
|
|
3614
|
+
Qn();
|
|
3600
3615
|
let t = document.createElement("video");
|
|
3601
3616
|
t.setAttribute("playsinline", ""), t.muted = e.muted ?? !0, t.style.cssText = "width:100%;height:100%;object-fit:contain;background:#000;aspect-ratio:auto", document.body.appendChild(t);
|
|
3602
3617
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3651,12 +3666,12 @@ async function Yn() {
|
|
|
3651
3666
|
code: e.code,
|
|
3652
3667
|
message: e.message
|
|
3653
3668
|
})), e.on("autoplayblocked", () => {
|
|
3654
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3669
|
+
i({ type: "oddin:autoplayblocked" }), Zn(t, e);
|
|
3655
3670
|
});
|
|
3656
3671
|
}, s = async (r) => {
|
|
3657
3672
|
a?.destroy(), a = null;
|
|
3658
3673
|
try {
|
|
3659
|
-
let n = await
|
|
3674
|
+
let n = await Wn({
|
|
3660
3675
|
video: t,
|
|
3661
3676
|
baseUrl: e.baseUrl,
|
|
3662
3677
|
matchUrn: r,
|
|
@@ -3718,7 +3733,7 @@ async function Yn() {
|
|
|
3718
3733
|
a?.retry();
|
|
3719
3734
|
break;
|
|
3720
3735
|
case "oddin:load":
|
|
3721
|
-
typeof e.matchUrn == "string" &&
|
|
3736
|
+
typeof e.matchUrn == "string" && qn.test(e.matchUrn) && s(e.matchUrn);
|
|
3722
3737
|
break;
|
|
3723
3738
|
case "oddin:destroy": c();
|
|
3724
3739
|
}
|
|
@@ -3730,18 +3745,18 @@ async function Yn() {
|
|
|
3730
3745
|
protocol: 1
|
|
3731
3746
|
});
|
|
3732
3747
|
}
|
|
3733
|
-
function
|
|
3748
|
+
function Zn(e, t) {
|
|
3734
3749
|
if (document.getElementById("havik-tap")) return;
|
|
3735
3750
|
let n = document.createElement("button");
|
|
3736
3751
|
n.id = "havik-tap", n.textContent = "▶ Tap to play", n.style.cssText = "position:fixed;inset:0;width:100%;height:100%;border:0;background:rgba(0,0,0,.55);color:#fff;font:600 18px system-ui,sans-serif;cursor:pointer;z-index:9", n.addEventListener("click", () => {
|
|
3737
3752
|
n.remove(), t.play();
|
|
3738
3753
|
}), document.body.appendChild(n);
|
|
3739
3754
|
}
|
|
3740
|
-
function
|
|
3755
|
+
function Qn() {
|
|
3741
3756
|
let e = document.createElement("style");
|
|
3742
3757
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3743
3758
|
}
|
|
3744
3759
|
//#endregion
|
|
3745
|
-
export {
|
|
3760
|
+
export { bn as ODDIN_THEME, n as PlaybackError, Sn as applyTheme, Ke as baseUrlForEnv, Xn as bootEmbed, Te as clearDeviceId, Wn as createPlayer, E as deriveEventsBaseUrl, He as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, k as getDeviceId, We as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, Kn as mountEmbed, de as pollToLive, y as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
|
|
3746
3761
|
|
|
3747
3762
|
//# sourceMappingURL=index.js.map
|