@oddin-gg/havik-player 2.15.4 → 2.15.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.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +293 -288
- package/dist/index.js.map +1 -1
- package/docs/API.md +16 -15
- 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,62 +260,62 @@ 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 S(e) {
|
|
294
294
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
295
295
|
}
|
|
296
|
-
function
|
|
297
|
-
let n =
|
|
296
|
+
function C(e, t) {
|
|
297
|
+
let n = S(he(e));
|
|
298
298
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
299
299
|
}
|
|
300
|
-
async function
|
|
300
|
+
async function w(e, t) {
|
|
301
301
|
let n = t ?? e;
|
|
302
302
|
if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
|
|
303
303
|
if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
|
|
304
304
|
let r = e;
|
|
305
305
|
return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
|
|
306
306
|
}
|
|
307
|
-
async function
|
|
307
|
+
async function T(e, t) {
|
|
308
308
|
let n = e;
|
|
309
309
|
if (n.webkitDisplayingFullscreen) {
|
|
310
310
|
n.webkitExitFullscreen?.();
|
|
311
311
|
return;
|
|
312
312
|
}
|
|
313
|
-
let r =
|
|
313
|
+
let r = he(e), i = S(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
|
|
317
317
|
//#region src/core/catalog.ts
|
|
318
|
-
async function
|
|
318
|
+
async function ge(e) {
|
|
319
319
|
let t = new URLSearchParams();
|
|
320
320
|
e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
|
|
321
321
|
let i = t.toString(), a = d(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
|
|
@@ -333,12 +333,12 @@ async function _e(e) {
|
|
|
333
333
|
};
|
|
334
334
|
if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
|
|
335
335
|
return {
|
|
336
|
-
tournaments:
|
|
336
|
+
tournaments: _e(await s.json()),
|
|
337
337
|
etag: s.headers.get("etag") ?? void 0,
|
|
338
338
|
notModified: !1
|
|
339
339
|
};
|
|
340
340
|
}
|
|
341
|
-
function
|
|
341
|
+
function _e(e) {
|
|
342
342
|
return (e.tournaments ?? []).map((e) => {
|
|
343
343
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
344
344
|
return {
|
|
@@ -360,7 +360,7 @@ function ve(e) {
|
|
|
360
360
|
};
|
|
361
361
|
});
|
|
362
362
|
}
|
|
363
|
-
async function
|
|
363
|
+
async function ve(e) {
|
|
364
364
|
let t = d(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
365
365
|
e.etag && i.set("If-None-Match", e.etag);
|
|
366
366
|
let a = await p(t, {
|
|
@@ -380,13 +380,13 @@ async function ye(e) {
|
|
|
380
380
|
};
|
|
381
381
|
if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
382
382
|
return {
|
|
383
|
-
tournament:
|
|
383
|
+
tournament: ye(await a.json()),
|
|
384
384
|
etag: a.headers.get("etag") ?? void 0,
|
|
385
385
|
notModified: !1,
|
|
386
386
|
notFound: !1
|
|
387
387
|
};
|
|
388
388
|
}
|
|
389
|
-
function
|
|
389
|
+
function ye(e) {
|
|
390
390
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
391
391
|
return {
|
|
392
392
|
urn: t,
|
|
@@ -406,17 +406,17 @@ function be(e) {
|
|
|
406
406
|
}))
|
|
407
407
|
};
|
|
408
408
|
}
|
|
409
|
-
function
|
|
409
|
+
function be(e) {
|
|
410
410
|
return e.tournaments.flatMap((e) => e.matches);
|
|
411
411
|
}
|
|
412
412
|
//#endregion
|
|
413
413
|
//#region src/core/poll.ts
|
|
414
|
-
var
|
|
414
|
+
var xe = /* @__PURE__ */ new Set([
|
|
415
415
|
"NOT_FOUND",
|
|
416
416
|
"GONE",
|
|
417
417
|
"INVALID_URN"
|
|
418
418
|
]);
|
|
419
|
-
function
|
|
419
|
+
function Se(e) {
|
|
420
420
|
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
|
|
421
421
|
u || (a = setTimeout(m, t));
|
|
422
422
|
}, m = async () => {
|
|
@@ -449,7 +449,7 @@ function Ce(e) {
|
|
|
449
449
|
} catch (t) {
|
|
450
450
|
if (!i.signal.aborted) {
|
|
451
451
|
let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
|
|
452
|
-
|
|
452
|
+
xe.has(r.code) && (u = !0), e.onError?.(r);
|
|
453
453
|
}
|
|
454
454
|
} finally {
|
|
455
455
|
f();
|
|
@@ -461,9 +461,9 @@ function Ce(e) {
|
|
|
461
461
|
}
|
|
462
462
|
//#endregion
|
|
463
463
|
//#region src/core/events.ts
|
|
464
|
-
var
|
|
465
|
-
function
|
|
466
|
-
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ??
|
|
464
|
+
var Ce = 45e3;
|
|
465
|
+
function E(e) {
|
|
466
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? Ce, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
|
|
467
467
|
if (a.signal.aborted) return t();
|
|
468
468
|
let n = setTimeout(t, e);
|
|
469
469
|
a.signal.addEventListener("abort", () => {
|
|
@@ -544,7 +544,7 @@ function T(e) {
|
|
|
544
544
|
o || (o = !0, a.abort());
|
|
545
545
|
} };
|
|
546
546
|
}
|
|
547
|
-
function
|
|
547
|
+
function D(e) {
|
|
548
548
|
try {
|
|
549
549
|
let t = new URL(e);
|
|
550
550
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -554,27 +554,27 @@ function E(e) {
|
|
|
554
554
|
}
|
|
555
555
|
//#endregion
|
|
556
556
|
//#region src/core/drm/deviceId.ts
|
|
557
|
-
var
|
|
558
|
-
function
|
|
559
|
-
if (
|
|
557
|
+
var O = "havik.player.deviceId", k;
|
|
558
|
+
function A() {
|
|
559
|
+
if (k) return k;
|
|
560
560
|
try {
|
|
561
|
-
let e = globalThis.localStorage?.getItem(
|
|
562
|
-
if (e) return
|
|
561
|
+
let e = globalThis.localStorage?.getItem(O);
|
|
562
|
+
if (e) return k = e, e;
|
|
563
563
|
} catch {}
|
|
564
|
-
let e =
|
|
565
|
-
|
|
564
|
+
let e = Te();
|
|
565
|
+
k = e;
|
|
566
566
|
try {
|
|
567
|
-
globalThis.localStorage?.setItem(
|
|
567
|
+
globalThis.localStorage?.setItem(O, e);
|
|
568
568
|
} catch {}
|
|
569
569
|
return e;
|
|
570
570
|
}
|
|
571
|
-
function
|
|
572
|
-
|
|
571
|
+
function we() {
|
|
572
|
+
k = void 0;
|
|
573
573
|
try {
|
|
574
|
-
globalThis.localStorage?.removeItem(
|
|
574
|
+
globalThis.localStorage?.removeItem(O);
|
|
575
575
|
} catch {}
|
|
576
576
|
}
|
|
577
|
-
function
|
|
577
|
+
function Te() {
|
|
578
578
|
let e = globalThis.crypto;
|
|
579
579
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
580
580
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -586,21 +586,21 @@ function Ee() {
|
|
|
586
586
|
}
|
|
587
587
|
//#endregion
|
|
588
588
|
//#region src/core/drm/headers.ts
|
|
589
|
-
function
|
|
589
|
+
function Ee(e, t, n = {}) {
|
|
590
590
|
let r = {
|
|
591
591
|
"x-api-key": t.apiKey,
|
|
592
592
|
"X-Match-Urn": e.matchUrn,
|
|
593
|
-
"X-Device-Id": n.deviceId ??
|
|
593
|
+
"X-Device-Id": n.deviceId ?? A(),
|
|
594
594
|
"Content-Type": "application/octet-stream"
|
|
595
595
|
};
|
|
596
596
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
597
597
|
}
|
|
598
598
|
//#endregion
|
|
599
599
|
//#region src/core/drm/cdm.ts
|
|
600
|
-
var
|
|
601
|
-
function
|
|
602
|
-
let n =
|
|
603
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
600
|
+
var j = /* @__PURE__ */ new WeakMap();
|
|
601
|
+
function De(e, t) {
|
|
602
|
+
let n = j.get(e);
|
|
603
|
+
n || (n = /* @__PURE__ */ new Map(), j.set(e, n));
|
|
604
604
|
let r = n.get(t.keySystem);
|
|
605
605
|
if (r) return r;
|
|
606
606
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -608,22 +608,22 @@ function Oe(e, t) {
|
|
|
608
608
|
});
|
|
609
609
|
return n.set(t.keySystem, i), i;
|
|
610
610
|
}
|
|
611
|
-
function
|
|
611
|
+
function M() {
|
|
612
612
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
613
613
|
}
|
|
614
|
-
var
|
|
615
|
-
function
|
|
614
|
+
var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
615
|
+
function Oe(e) {
|
|
616
616
|
return e.startsWith("com.widevine");
|
|
617
617
|
}
|
|
618
|
-
function
|
|
619
|
-
if (!
|
|
618
|
+
function P(e, t) {
|
|
619
|
+
if (!Oe(e)) return t;
|
|
620
620
|
let n = (e, t) => {
|
|
621
621
|
let n = e.videoCapabilities;
|
|
622
622
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
623
|
-
let n =
|
|
624
|
-
return n === -1 ||
|
|
623
|
+
let n = N.indexOf(e.robustness);
|
|
624
|
+
return n === -1 || N.indexOf(t) > n;
|
|
625
625
|
});
|
|
626
|
-
}, r =
|
|
626
|
+
}, r = N.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
627
627
|
...t,
|
|
628
628
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
629
629
|
...t,
|
|
@@ -632,53 +632,53 @@ function N(e, t) {
|
|
|
632
632
|
})));
|
|
633
633
|
return [...t, ...r];
|
|
634
634
|
}
|
|
635
|
-
function
|
|
636
|
-
return (t, n) =>
|
|
635
|
+
function F(e) {
|
|
636
|
+
return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, P(t, n)).then((t) => ({
|
|
637
637
|
keySystem: t.keySystem,
|
|
638
638
|
getConfiguration: () => t.getConfiguration(),
|
|
639
|
-
createMediaKeys: () =>
|
|
639
|
+
createMediaKeys: () => De(e, t)
|
|
640
640
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
641
641
|
}
|
|
642
|
-
var
|
|
642
|
+
var I = {
|
|
643
643
|
video: "SW_SECURE_DECODE",
|
|
644
644
|
audio: "SW_SECURE_CRYPTO",
|
|
645
645
|
scheme: "cbcs"
|
|
646
646
|
};
|
|
647
|
-
function
|
|
648
|
-
if (!
|
|
647
|
+
function ke(e) {
|
|
648
|
+
if (!M()) return;
|
|
649
649
|
let t = (e, t) => ({
|
|
650
650
|
contentType: e,
|
|
651
651
|
robustness: t,
|
|
652
|
-
encryptionScheme:
|
|
652
|
+
encryptionScheme: I.scheme
|
|
653
653
|
});
|
|
654
|
-
|
|
654
|
+
F(e)("com.widevine.alpha", [{
|
|
655
655
|
initDataTypes: ["cenc"],
|
|
656
656
|
distinctiveIdentifier: "optional",
|
|
657
657
|
persistentState: "optional",
|
|
658
658
|
sessionTypes: ["temporary"],
|
|
659
|
-
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"",
|
|
660
|
-
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"",
|
|
659
|
+
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", I.audio)],
|
|
660
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", I.video)]
|
|
661
661
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
662
662
|
}
|
|
663
|
-
function
|
|
664
|
-
let t =
|
|
663
|
+
function L(e) {
|
|
664
|
+
let t = R(e);
|
|
665
665
|
if (/^avc[13]/.test(t)) return "avc";
|
|
666
666
|
if (/^(hvc1|hev1)/.test(t)) return "hevc";
|
|
667
667
|
if (/^(dvh1|dvhe)/.test(t)) return "dv";
|
|
668
668
|
if (t.startsWith("av01")) return "av1";
|
|
669
669
|
if (/^vp0?9/.test(t)) return "vp9";
|
|
670
670
|
}
|
|
671
|
-
function
|
|
671
|
+
function R(e) {
|
|
672
672
|
return (e ?? "").trim().toLowerCase();
|
|
673
673
|
}
|
|
674
|
-
var
|
|
674
|
+
var Ae = {
|
|
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 =
|
|
679
|
+
}, je = /* @__PURE__ */ new Map(), z = /* @__PURE__ */ new Map();
|
|
680
|
+
function Me(e) {
|
|
681
|
+
let t = R(e), n = je.get(t);
|
|
682
682
|
if (n) return n;
|
|
683
683
|
let r = {
|
|
684
684
|
initDataTypes: ["cenc"],
|
|
@@ -687,32 +687,32 @@ function Ne(e) {
|
|
|
687
687
|
sessionTypes: ["temporary"],
|
|
688
688
|
videoCapabilities: [{
|
|
689
689
|
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
690
|
-
robustness:
|
|
691
|
-
encryptionScheme:
|
|
690
|
+
robustness: I.video,
|
|
691
|
+
encryptionScheme: I.scheme
|
|
692
692
|
}]
|
|
693
693
|
}, i = (async () => {
|
|
694
694
|
try {
|
|
695
|
-
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha",
|
|
695
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", P("com.widevine.alpha", [r])), !0;
|
|
696
696
|
} catch {
|
|
697
697
|
return !1;
|
|
698
698
|
}
|
|
699
|
-
})().then((e) => (
|
|
700
|
-
return
|
|
699
|
+
})().then((e) => (z.set(t, e), e));
|
|
700
|
+
return je.set(t, i), i;
|
|
701
701
|
}
|
|
702
|
-
function
|
|
703
|
-
if (
|
|
702
|
+
function Ne() {
|
|
703
|
+
if (M()) for (let e of Object.values(Ae)) Me(e);
|
|
704
704
|
}
|
|
705
|
-
function
|
|
706
|
-
let t =
|
|
707
|
-
if (t) return t === "avc" ? !0 :
|
|
705
|
+
function Pe(e) {
|
|
706
|
+
let t = L(e);
|
|
707
|
+
if (t) return t === "avc" ? !0 : z.get(R(e)) ?? z.get(R(Ae[t]));
|
|
708
708
|
}
|
|
709
709
|
//#endregion
|
|
710
710
|
//#region src/core/drm/support.ts
|
|
711
|
-
var
|
|
711
|
+
var Fe = 5e3, Ie = "video/mp4; codecs=\"avc1.42E01E\"", Le = "audio/mp4; codecs=\"mp4a.40.2\"", Re = {
|
|
712
712
|
widevine: ["com.widevine.alpha"],
|
|
713
713
|
fairplay: ["com.apple.fps"]
|
|
714
714
|
};
|
|
715
|
-
function
|
|
715
|
+
function ze(e) {
|
|
716
716
|
return e === "fairplay" ? [{
|
|
717
717
|
initDataTypes: [
|
|
718
718
|
"sinf",
|
|
@@ -720,30 +720,30 @@ function Be(e) {
|
|
|
720
720
|
"cenc"
|
|
721
721
|
],
|
|
722
722
|
videoCapabilities: [{
|
|
723
|
-
contentType:
|
|
723
|
+
contentType: Ie,
|
|
724
724
|
robustness: "",
|
|
725
725
|
encryptionScheme: "cbcs"
|
|
726
726
|
}],
|
|
727
727
|
audioCapabilities: [{
|
|
728
|
-
contentType:
|
|
728
|
+
contentType: Le,
|
|
729
729
|
robustness: "",
|
|
730
730
|
encryptionScheme: "cbcs"
|
|
731
731
|
}]
|
|
732
|
-
}] :
|
|
732
|
+
}] : P("com.widevine.alpha", [{
|
|
733
733
|
initDataTypes: ["cenc"],
|
|
734
734
|
videoCapabilities: [{
|
|
735
|
-
contentType:
|
|
736
|
-
robustness:
|
|
737
|
-
encryptionScheme:
|
|
735
|
+
contentType: Ie,
|
|
736
|
+
robustness: I.video,
|
|
737
|
+
encryptionScheme: I.scheme
|
|
738
738
|
}],
|
|
739
739
|
audioCapabilities: [{
|
|
740
|
-
contentType:
|
|
741
|
-
robustness:
|
|
742
|
-
encryptionScheme:
|
|
740
|
+
contentType: Le,
|
|
741
|
+
robustness: I.audio,
|
|
742
|
+
encryptionScheme: I.scheme
|
|
743
743
|
}]
|
|
744
744
|
}]);
|
|
745
745
|
}
|
|
746
|
-
function
|
|
746
|
+
function Be(e, t) {
|
|
747
747
|
return new Promise((n, r) => {
|
|
748
748
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
749
749
|
e.then((e) => {
|
|
@@ -753,8 +753,8 @@ function Ve(e, t) {
|
|
|
753
753
|
});
|
|
754
754
|
});
|
|
755
755
|
}
|
|
756
|
-
async function
|
|
757
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
756
|
+
async function Ve(e = {}) {
|
|
757
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Fe, r = {};
|
|
758
758
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
759
759
|
verdict: "insecure-context",
|
|
760
760
|
detail: r
|
|
@@ -766,7 +766,7 @@ async function He(e = {}) {
|
|
|
766
766
|
};
|
|
767
767
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
768
768
|
for (let e of t) {
|
|
769
|
-
let t =
|
|
769
|
+
let t = Re[e];
|
|
770
770
|
if (!t) {
|
|
771
771
|
r[e] = "unknown system";
|
|
772
772
|
continue;
|
|
@@ -777,7 +777,7 @@ async function He(e = {}) {
|
|
|
777
777
|
break;
|
|
778
778
|
}
|
|
779
779
|
try {
|
|
780
|
-
return await
|
|
780
|
+
return await Be((await Be(i(n, ze(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
781
781
|
verdict: "supported",
|
|
782
782
|
system: e,
|
|
783
783
|
detail: r
|
|
@@ -801,18 +801,18 @@ async function He(e = {}) {
|
|
|
801
801
|
}
|
|
802
802
|
//#endregion
|
|
803
803
|
//#region src/core/manifest.ts
|
|
804
|
-
var
|
|
805
|
-
function
|
|
806
|
-
return
|
|
804
|
+
var He = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
805
|
+
function Ue(e) {
|
|
806
|
+
return He.test(e);
|
|
807
807
|
}
|
|
808
808
|
//#endregion
|
|
809
809
|
//#region src/core/env.ts
|
|
810
|
-
var
|
|
810
|
+
var We = {
|
|
811
811
|
integration: "https://feed-dev.oddin-video.gg",
|
|
812
812
|
production: "https://feed.oddin-video.gg"
|
|
813
813
|
};
|
|
814
814
|
function B(e) {
|
|
815
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
815
|
+
let t = Object.prototype.hasOwnProperty.call(We, e) ? We[e] : void 0;
|
|
816
816
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
817
817
|
return t;
|
|
818
818
|
}
|
|
@@ -876,6 +876,11 @@ function G() {
|
|
|
876
876
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
877
877
|
return e || t;
|
|
878
878
|
}
|
|
879
|
+
function Ye() {
|
|
880
|
+
if (typeof navigator > "u" || !G()) return !1;
|
|
881
|
+
let e = navigator.userAgent ?? "";
|
|
882
|
+
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
883
|
+
}
|
|
879
884
|
var K = class {
|
|
880
885
|
name = "native";
|
|
881
886
|
deps;
|
|
@@ -912,7 +917,7 @@ var K = class {
|
|
|
912
917
|
type: "error",
|
|
913
918
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
914
919
|
fatal: !0
|
|
915
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
920
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Xe(t.manifestUrl, t.analytics?.sid), e.load();
|
|
916
921
|
}
|
|
917
922
|
startLoad() {
|
|
918
923
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -1052,13 +1057,13 @@ var K = class {
|
|
|
1052
1057
|
} catch {}
|
|
1053
1058
|
}
|
|
1054
1059
|
};
|
|
1055
|
-
function
|
|
1060
|
+
function Xe(e, t) {
|
|
1056
1061
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1057
1062
|
}
|
|
1058
1063
|
//#endregion
|
|
1059
1064
|
//#region src/core/engine/prefetch.ts
|
|
1060
|
-
var
|
|
1061
|
-
function
|
|
1065
|
+
var Ze = 15e3, Qe = 5e3, $e = 6;
|
|
1066
|
+
function et(e) {
|
|
1062
1067
|
try {
|
|
1063
1068
|
let t = new URL(e);
|
|
1064
1069
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1066,7 +1071,7 @@ function $e(e) {
|
|
|
1066
1071
|
return e;
|
|
1067
1072
|
}
|
|
1068
1073
|
}
|
|
1069
|
-
var
|
|
1074
|
+
var tt = class {
|
|
1070
1075
|
cmcd;
|
|
1071
1076
|
entries = /* @__PURE__ */ new Map();
|
|
1072
1077
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1089,10 +1094,10 @@ var et = class {
|
|
|
1089
1094
|
}
|
|
1090
1095
|
prefetch(e, t, n) {
|
|
1091
1096
|
if (!this.isActive(t)) return;
|
|
1092
|
-
let r =
|
|
1097
|
+
let r = et(e);
|
|
1093
1098
|
if (this.entries.has(r)) return;
|
|
1094
1099
|
let i = this.perTrack.get(t) ?? 0;
|
|
1095
|
-
if (i >=
|
|
1100
|
+
if (i >= $e) return;
|
|
1096
1101
|
this.perTrack.set(t, i + 1);
|
|
1097
1102
|
let a = new AbortController(), o = {
|
|
1098
1103
|
started: performance.now(),
|
|
@@ -1106,10 +1111,10 @@ var et = class {
|
|
|
1106
1111
|
signal: a.signal
|
|
1107
1112
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1108
1113
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1109
|
-
},
|
|
1114
|
+
}, Ze);
|
|
1110
1115
|
}
|
|
1111
1116
|
take(e) {
|
|
1112
|
-
let t =
|
|
1117
|
+
let t = et(e), n = this.entries.get(t);
|
|
1113
1118
|
return n && this.entries.delete(t), n;
|
|
1114
1119
|
}
|
|
1115
1120
|
destroy() {
|
|
@@ -1129,13 +1134,13 @@ var et = class {
|
|
|
1129
1134
|
}
|
|
1130
1135
|
}
|
|
1131
1136
|
};
|
|
1132
|
-
function
|
|
1137
|
+
function nt(t) {
|
|
1133
1138
|
let n = e.DefaultConfig?.loader;
|
|
1134
1139
|
if (typeof n != "function") return;
|
|
1135
1140
|
class r extends n {
|
|
1136
1141
|
served = !1;
|
|
1137
1142
|
cancelled = !1;
|
|
1138
|
-
stats =
|
|
1143
|
+
stats = rt();
|
|
1139
1144
|
load(e, n, r) {
|
|
1140
1145
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1141
1146
|
if (!i) {
|
|
@@ -1143,7 +1148,7 @@ function tt(t) {
|
|
|
1143
1148
|
return;
|
|
1144
1149
|
}
|
|
1145
1150
|
this.served = !0;
|
|
1146
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1151
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Qe, s = setTimeout(() => {
|
|
1147
1152
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1148
1153
|
}, o);
|
|
1149
1154
|
i.bytes.then((o) => {
|
|
@@ -1170,7 +1175,7 @@ function tt(t) {
|
|
|
1170
1175
|
}
|
|
1171
1176
|
return r;
|
|
1172
1177
|
}
|
|
1173
|
-
function
|
|
1178
|
+
function rt() {
|
|
1174
1179
|
return {
|
|
1175
1180
|
aborted: !1,
|
|
1176
1181
|
loaded: 0,
|
|
@@ -1194,10 +1199,10 @@ function nt() {
|
|
|
1194
1199
|
}
|
|
1195
1200
|
};
|
|
1196
1201
|
}
|
|
1197
|
-
function
|
|
1202
|
+
function it(e) {
|
|
1198
1203
|
return e === "audio" ? "audio" : "main";
|
|
1199
1204
|
}
|
|
1200
|
-
function
|
|
1205
|
+
function at(e, t) {
|
|
1201
1206
|
let n = [];
|
|
1202
1207
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1203
1208
|
url: t.initSegment.url,
|
|
@@ -1216,24 +1221,24 @@ function it(e, t) {
|
|
|
1216
1221
|
}
|
|
1217
1222
|
//#endregion
|
|
1218
1223
|
//#region src/core/engine/hls.ts
|
|
1219
|
-
function
|
|
1224
|
+
function ot() {
|
|
1220
1225
|
return e.isSupported();
|
|
1221
1226
|
}
|
|
1222
|
-
var
|
|
1223
|
-
function
|
|
1227
|
+
var st = 3, ct = 5, lt = 3, ut = 3e4, dt = 12e3, ft = 3e3, pt = 6e3, mt = .5, ht = 3, gt = .5, _t = 1.1, vt = .25, yt = 5e3, bt = 4e3, xt = 2, St = 5, Ct = 2, wt = 2, Tt = 4, Et = 4, Dt = 2e3, Ot = 3e4, kt = .2, At = 30, jt = 2, Mt = 2, Nt = 9, Pt = .5, Ft = 64;
|
|
1228
|
+
function It(e) {
|
|
1224
1229
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1225
1230
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1226
1231
|
return;
|
|
1227
1232
|
}
|
|
1228
|
-
e.liveSyncDuration ??=
|
|
1229
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1230
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1233
|
+
e.liveSyncDuration ??= Mt;
|
|
1234
|
+
let t = Math.max(12, e.liveSyncDuration + Nt);
|
|
1235
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Lt(e, e.liveSyncDuration);
|
|
1231
1236
|
}
|
|
1232
|
-
function
|
|
1237
|
+
function Lt(e, t) {
|
|
1233
1238
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1234
1239
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1235
1240
|
}
|
|
1236
|
-
var
|
|
1241
|
+
var Rt = class {
|
|
1237
1242
|
name = "hls";
|
|
1238
1243
|
hls = null;
|
|
1239
1244
|
deps;
|
|
@@ -1323,7 +1328,7 @@ var Lt = class {
|
|
|
1323
1328
|
});
|
|
1324
1329
|
return;
|
|
1325
1330
|
}
|
|
1326
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1331
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (ke(r), Ne()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1327
1332
|
let e = this.hls;
|
|
1328
1333
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1329
1334
|
let t = e.liveSyncPosition;
|
|
@@ -1346,7 +1351,7 @@ var Lt = class {
|
|
|
1346
1351
|
}
|
|
1347
1352
|
this.loadSuspended = !0;
|
|
1348
1353
|
}
|
|
1349
|
-
},
|
|
1354
|
+
}, yt));
|
|
1350
1355
|
}
|
|
1351
1356
|
resumeLoading() {
|
|
1352
1357
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1378,7 +1383,7 @@ var Lt = class {
|
|
|
1378
1383
|
let t = e.liveSyncPosition;
|
|
1379
1384
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1380
1385
|
let { video: n } = this.deps;
|
|
1381
|
-
n.currentTime <= t +
|
|
1386
|
+
n.currentTime <= t + Pt || (n.currentTime = t);
|
|
1382
1387
|
}
|
|
1383
1388
|
startHls() {
|
|
1384
1389
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1397,12 +1402,12 @@ var Lt = class {
|
|
|
1397
1402
|
emeEnabled: !0,
|
|
1398
1403
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1399
1404
|
drmSystemOptions: {
|
|
1400
|
-
videoRobustness:
|
|
1401
|
-
audioRobustness:
|
|
1402
|
-
videoEncryptionScheme:
|
|
1403
|
-
audioEncryptionScheme:
|
|
1405
|
+
videoRobustness: I.video,
|
|
1406
|
+
audioRobustness: I.audio,
|
|
1407
|
+
videoEncryptionScheme: I.scheme,
|
|
1408
|
+
audioEncryptionScheme: I.scheme
|
|
1404
1409
|
},
|
|
1405
|
-
...
|
|
1410
|
+
...M() ? { requestMediaKeySystemAccessFunc: F(t) } : {},
|
|
1406
1411
|
licenseXhrSetup: (e, t) => {
|
|
1407
1412
|
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;
|
|
1408
1413
|
let o = performance.now();
|
|
@@ -1419,20 +1424,20 @@ var Lt = class {
|
|
|
1419
1424
|
...c
|
|
1420
1425
|
};
|
|
1421
1426
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
|
|
1422
|
-
let e = new
|
|
1427
|
+
let e = new tt({
|
|
1423
1428
|
sessionId: n.analytics?.sid,
|
|
1424
1429
|
contentId: n.matchUrn
|
|
1425
|
-
}), t =
|
|
1430
|
+
}), t = nt(e);
|
|
1426
1431
|
t && (this.prefetch = e, d.fLoader = t);
|
|
1427
1432
|
}
|
|
1428
|
-
|
|
1433
|
+
It(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;
|
|
1429
1434
|
let f = new e(d);
|
|
1430
1435
|
if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1431
1436
|
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" });
|
|
1432
1437
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1433
1438
|
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(() => {
|
|
1434
1439
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1435
|
-
},
|
|
1440
|
+
}, ut)));
|
|
1436
1441
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1437
1442
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1438
1443
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1440,7 +1445,7 @@ var Lt = class {
|
|
|
1440
1445
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1441
1446
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1442
1447
|
let i = n?.loading;
|
|
1443
|
-
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 >
|
|
1448
|
+
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 > Ft && this.requestTimesMs.shift());
|
|
1444
1449
|
let a = t?.frag?.url;
|
|
1445
1450
|
if (a) {
|
|
1446
1451
|
let e = H(a);
|
|
@@ -1457,15 +1462,15 @@ var Lt = class {
|
|
|
1457
1462
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1458
1463
|
let t = this.prefetch;
|
|
1459
1464
|
f.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1460
|
-
let r = n?.frag, i =
|
|
1461
|
-
if (r && t.isActive(i)) for (let e of
|
|
1462
|
-
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1465
|
+
let r = n?.frag, i = it(r?.type);
|
|
1466
|
+
if (r && t.isActive(i)) for (let e of at(f, r)) t.prefetch(e.url, i, e.kind);
|
|
1467
|
+
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(it(n?.frag?.type)));
|
|
1463
1468
|
}
|
|
1464
1469
|
f.on(e.Events.KEY_LOADED, () => {
|
|
1465
1470
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1466
1471
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1467
1472
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1468
|
-
},
|
|
1473
|
+
}, ft), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1469
1474
|
this.renditionSwitches += 1;
|
|
1470
1475
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1471
1476
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1529,7 +1534,7 @@ var Lt = class {
|
|
|
1529
1534
|
return;
|
|
1530
1535
|
}
|
|
1531
1536
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1532
|
-
let t = e > this.sizeCapLevel ?
|
|
1537
|
+
let t = e > this.sizeCapLevel ? Dt : Ot;
|
|
1533
1538
|
this.capTimer = setTimeout(() => {
|
|
1534
1539
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1535
1540
|
}, t);
|
|
@@ -1539,9 +1544,9 @@ var Lt = class {
|
|
|
1539
1544
|
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;
|
|
1540
1545
|
}
|
|
1541
1546
|
dropLevelsWidevineCannotPlay(e) {
|
|
1542
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1543
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1544
|
-
for (let n of t)
|
|
1547
|
+
this.removeLevelsWhere(e, (e) => Pe(e) !== !0);
|
|
1548
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && L(e) !== "avc" && !!L(e)));
|
|
1549
|
+
for (let n of t) Me(n).then((t) => {
|
|
1545
1550
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1546
1551
|
});
|
|
1547
1552
|
}
|
|
@@ -1549,10 +1554,10 @@ var Lt = class {
|
|
|
1549
1554
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1550
1555
|
if (n.forEach((e, n) => {
|
|
1551
1556
|
let a = e.videoCodec;
|
|
1552
|
-
a &&
|
|
1557
|
+
a && L(a) && t(a) && (r.push(n), i.add(a));
|
|
1553
1558
|
}), !r.length) return !1;
|
|
1554
1559
|
let a = [...i].join(", ");
|
|
1555
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !
|
|
1560
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !L(e.videoCodec) || Pe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1556
1561
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1557
1562
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1558
1563
|
}
|
|
@@ -1650,7 +1655,7 @@ var Lt = class {
|
|
|
1650
1655
|
return;
|
|
1651
1656
|
}
|
|
1652
1657
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1653
|
-
!this.chaseSuspended && e >
|
|
1658
|
+
!this.chaseSuspended && e > pt && this.suspendChasing(), e > dt && this.emitEnded("stalled");
|
|
1654
1659
|
}
|
|
1655
1660
|
resetStarvationWindow() {
|
|
1656
1661
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1665,7 +1670,7 @@ var Lt = class {
|
|
|
1665
1670
|
this.resetStarvationWindow();
|
|
1666
1671
|
return;
|
|
1667
1672
|
}
|
|
1668
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1673
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < pt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > bt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = U(t), c = o - s, l = c !== this.starvedFrames;
|
|
1669
1674
|
if (this.starvedFrames = c, !a || l) {
|
|
1670
1675
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1671
1676
|
return;
|
|
@@ -1674,12 +1679,12 @@ var Lt = class {
|
|
|
1674
1679
|
this.resetStarvationWindow();
|
|
1675
1680
|
return;
|
|
1676
1681
|
}
|
|
1677
|
-
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 >
|
|
1682
|
+
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 > Tt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= Ct && (this.clearKick(), this.starvationRebuilds < wt)) {
|
|
1678
1683
|
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");
|
|
1679
1684
|
return;
|
|
1680
1685
|
}
|
|
1681
|
-
let u = i && this.starvedTicks >=
|
|
1682
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1686
|
+
let u = i && this.starvedTicks >= xt, d = !i && this.deadTicks >= Tt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Et;
|
|
1687
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= St))) {
|
|
1683
1688
|
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");
|
|
1684
1689
|
try {
|
|
1685
1690
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1694,7 +1699,7 @@ var Lt = class {
|
|
|
1694
1699
|
let t = e.latency, n = e.targetLatency;
|
|
1695
1700
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1696
1701
|
let r = t - n;
|
|
1697
|
-
!this.catchUpEngaged && r >
|
|
1702
|
+
!this.catchUpEngaged && r > mt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= mt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1698
1703
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1699
1704
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1700
1705
|
}
|
|
@@ -1716,15 +1721,15 @@ var Lt = class {
|
|
|
1716
1721
|
return;
|
|
1717
1722
|
}
|
|
1718
1723
|
let { totalFrames: n, dropped: r } = U(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
1719
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
1724
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < At || o < 0) {
|
|
1720
1725
|
this.fpsBadTicks = 0;
|
|
1721
1726
|
return;
|
|
1722
1727
|
}
|
|
1723
|
-
if (o <=
|
|
1728
|
+
if (o <= kt * a) {
|
|
1724
1729
|
this.fpsBadTicks = 0;
|
|
1725
1730
|
return;
|
|
1726
1731
|
}
|
|
1727
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
1732
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < jt) return;
|
|
1728
1733
|
this.fpsBadTicks = 0;
|
|
1729
1734
|
let s = e.levels, c = s[e.currentLevel];
|
|
1730
1735
|
if (!c) return;
|
|
@@ -1741,20 +1746,20 @@ var Lt = class {
|
|
|
1741
1746
|
return;
|
|
1742
1747
|
}
|
|
1743
1748
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
1744
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
1749
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(_t, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
1745
1750
|
this.resetChaseWindow();
|
|
1746
1751
|
return;
|
|
1747
1752
|
}
|
|
1748
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
1753
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= gt) {
|
|
1749
1754
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
1750
1755
|
return;
|
|
1751
1756
|
}
|
|
1752
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
1757
|
+
if (this.chaseTicks += 1, this.chaseTicks < ht) return;
|
|
1753
1758
|
this.resetChaseWindow();
|
|
1754
1759
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
1755
1760
|
if (!(a > 1)) return;
|
|
1756
1761
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
1757
|
-
s < o +
|
|
1762
|
+
s < o + vt || (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);
|
|
1758
1763
|
}
|
|
1759
1764
|
suspendChasing() {
|
|
1760
1765
|
let e = this.hls;
|
|
@@ -1799,7 +1804,7 @@ var Lt = class {
|
|
|
1799
1804
|
scheduleLicenseRetry(t) {
|
|
1800
1805
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1801
1806
|
let n = t.response?.code ?? 0;
|
|
1802
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1807
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= lt) return !1;
|
|
1803
1808
|
this.licenseRecoveries += 1;
|
|
1804
1809
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1805
1810
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1831,7 +1836,7 @@ var Lt = class {
|
|
|
1831
1836
|
return;
|
|
1832
1837
|
}
|
|
1833
1838
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1834
|
-
if (this.networkRecoveries <
|
|
1839
|
+
if (this.networkRecoveries < ct) {
|
|
1835
1840
|
this.networkRecoveries += 1;
|
|
1836
1841
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1837
1842
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1848,7 +1853,7 @@ var Lt = class {
|
|
|
1848
1853
|
return;
|
|
1849
1854
|
}
|
|
1850
1855
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1851
|
-
if (this.mediaRecoveries <
|
|
1856
|
+
if (this.mediaRecoveries < st) {
|
|
1852
1857
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1853
1858
|
return;
|
|
1854
1859
|
}
|
|
@@ -1872,19 +1877,19 @@ var Lt = class {
|
|
|
1872
1877
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1873
1878
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1874
1879
|
}
|
|
1875
|
-
},
|
|
1880
|
+
}, zt = 15e3, Bt = 6e5, Vt = 3e5, Ht = 100, q = 1, Ut = 1e3, Wt = 3e4, Gt = 1e3, Kt = {
|
|
1876
1881
|
inline: "PRESENTATION_INLINE",
|
|
1877
1882
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1878
1883
|
pip: "PRESENTATION_PIP"
|
|
1879
|
-
},
|
|
1884
|
+
}, qt = {
|
|
1880
1885
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1881
1886
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1882
1887
|
none: "KEY_SYSTEM_NONE"
|
|
1883
1888
|
};
|
|
1884
|
-
function
|
|
1889
|
+
function Jt(e, t) {
|
|
1885
1890
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1886
1891
|
}
|
|
1887
|
-
var
|
|
1892
|
+
var Yt = /* @__PURE__ */ new Set([
|
|
1888
1893
|
"INVALID_URN",
|
|
1889
1894
|
"NOT_FOUND",
|
|
1890
1895
|
"GONE",
|
|
@@ -1904,7 +1909,7 @@ var Jt = /* @__PURE__ */ new Set([
|
|
|
1904
1909
|
ended: "PLAYER_STATE_ENDED",
|
|
1905
1910
|
error: "PLAYER_STATE_ERROR"
|
|
1906
1911
|
};
|
|
1907
|
-
function
|
|
1912
|
+
function Xt(e) {
|
|
1908
1913
|
try {
|
|
1909
1914
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1910
1915
|
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);
|
|
@@ -1912,8 +1917,8 @@ function Yt(e) {
|
|
|
1912
1917
|
return;
|
|
1913
1918
|
}
|
|
1914
1919
|
}
|
|
1915
|
-
var
|
|
1916
|
-
function
|
|
1920
|
+
var Zt = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Qt = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), $t = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
1921
|
+
function en(e) {
|
|
1917
1922
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
1918
1923
|
let t;
|
|
1919
1924
|
try {
|
|
@@ -1922,19 +1927,19 @@ function $t(e) {
|
|
|
1922
1927
|
} catch {
|
|
1923
1928
|
return;
|
|
1924
1929
|
}
|
|
1925
|
-
if (
|
|
1926
|
-
Y.add(t), g(
|
|
1930
|
+
if (Qt.has(t) && !Y.has(t)) {
|
|
1931
|
+
Y.add(t), g($t(new URL(t).origin));
|
|
1927
1932
|
for (let e of X) e.noteCspBlocked();
|
|
1928
1933
|
}
|
|
1929
1934
|
}
|
|
1930
|
-
function
|
|
1935
|
+
function tn(e, t) {
|
|
1931
1936
|
return g(t, e), { disabledReason: t };
|
|
1932
1937
|
}
|
|
1933
|
-
function
|
|
1934
|
-
if (n) return t && !
|
|
1938
|
+
function nn(e, t, n) {
|
|
1939
|
+
if (n) return t && !Zt(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
1935
1940
|
if (t) return { endpoint: t };
|
|
1936
|
-
if (t !== void 0) return
|
|
1937
|
-
let r =
|
|
1941
|
+
if (t !== void 0) return tn("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).");
|
|
1942
|
+
let r = Xt(e);
|
|
1938
1943
|
if (r) return { endpoint: r };
|
|
1939
1944
|
let i;
|
|
1940
1945
|
try {
|
|
@@ -1942,9 +1947,9 @@ function tn(e, t, n) {
|
|
|
1942
1947
|
} catch {
|
|
1943
1948
|
i = e;
|
|
1944
1949
|
}
|
|
1945
|
-
return
|
|
1950
|
+
return tn(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).`);
|
|
1946
1951
|
}
|
|
1947
|
-
var
|
|
1952
|
+
var rn = class {
|
|
1948
1953
|
opts;
|
|
1949
1954
|
url;
|
|
1950
1955
|
cspKey;
|
|
@@ -2026,8 +2031,8 @@ var nn = class {
|
|
|
2026
2031
|
constructor(e) {
|
|
2027
2032
|
this.opts = {
|
|
2028
2033
|
...e,
|
|
2029
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2030
|
-
idleMs: e.idleMs ??
|
|
2034
|
+
heartbeatMs: e.heartbeatMs ?? zt,
|
|
2035
|
+
idleMs: e.idleMs ?? Bt
|
|
2031
2036
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2032
2037
|
try {
|
|
2033
2038
|
let e = new URL(this.url);
|
|
@@ -2044,11 +2049,11 @@ var nn = class {
|
|
|
2044
2049
|
sdkVersion: this.opts.sdkVersion,
|
|
2045
2050
|
...this.opts.environment
|
|
2046
2051
|
};
|
|
2047
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2052
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Ut), 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 && Qt.add(this.cspKey), document.addEventListener("securitypolicyviolation", en), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2048
2053
|
}
|
|
2049
2054
|
checkSuspension(e) {
|
|
2050
2055
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2051
|
-
let t = Math.max(this.opts.idleMs,
|
|
2056
|
+
let t = Math.max(this.opts.idleMs, Vt);
|
|
2052
2057
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2053
2058
|
}
|
|
2054
2059
|
syncIdle(e) {
|
|
@@ -2071,12 +2076,12 @@ var nn = class {
|
|
|
2071
2076
|
let a = {
|
|
2072
2077
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2073
2078
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2074
|
-
presentation:
|
|
2079
|
+
presentation: Kt[this.presentation]
|
|
2075
2080
|
}, o = this.causeOf(e, t, i);
|
|
2076
2081
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2077
2082
|
}
|
|
2078
2083
|
seekInduced(e) {
|
|
2079
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2084
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < Gt;
|
|
2080
2085
|
}
|
|
2081
2086
|
causeOf(e, t, n) {
|
|
2082
2087
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2150,7 +2155,7 @@ var nn = class {
|
|
|
2150
2155
|
let r = n ?? "";
|
|
2151
2156
|
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";
|
|
2152
2157
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2153
|
-
if (
|
|
2158
|
+
if (Yt.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2154
2159
|
let i = t ?? "";
|
|
2155
2160
|
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";
|
|
2156
2161
|
}
|
|
@@ -2197,14 +2202,14 @@ var nn = class {
|
|
|
2197
2202
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2198
2203
|
o.requestCountDelta = _;
|
|
2199
2204
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2200
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2205
|
+
n.length > 0 && (o.requestTimeP50Ms = Jt(n, 50), o.requestTimeP95Ms = Jt(n, 95));
|
|
2201
2206
|
}
|
|
2202
2207
|
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();
|
|
2203
2208
|
}
|
|
2204
2209
|
maybeEmitMediaInfo(e) {
|
|
2205
2210
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2206
2211
|
let t = {};
|
|
2207
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2212
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = qt[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);
|
|
2208
2213
|
let n = JSON.stringify(t);
|
|
2209
2214
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2210
2215
|
}
|
|
@@ -2224,7 +2229,7 @@ var nn = class {
|
|
|
2224
2229
|
let c = r?.positionMs ?? 0;
|
|
2225
2230
|
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));
|
|
2226
2231
|
let l = e !== "END_REASON_ENDED";
|
|
2227
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2232
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= Wt && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Wt && (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);
|
|
2228
2233
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2229
2234
|
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");
|
|
2230
2235
|
}
|
|
@@ -2244,13 +2249,13 @@ var nn = class {
|
|
|
2244
2249
|
};
|
|
2245
2250
|
}
|
|
2246
2251
|
noteCspBlocked() {
|
|
2247
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2252
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.($t(new URL(this.url).origin)));
|
|
2248
2253
|
}
|
|
2249
2254
|
cspBlocked() {
|
|
2250
2255
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2251
2256
|
}
|
|
2252
2257
|
enqueue(e) {
|
|
2253
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2258
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Ht;) {
|
|
2254
2259
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2255
2260
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2256
2261
|
}
|
|
@@ -2277,7 +2282,7 @@ var nn = class {
|
|
|
2277
2282
|
};
|
|
2278
2283
|
//#endregion
|
|
2279
2284
|
//#region src/core/environment.ts
|
|
2280
|
-
function
|
|
2285
|
+
function an() {
|
|
2281
2286
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2282
2287
|
let e;
|
|
2283
2288
|
try {
|
|
@@ -2302,14 +2307,14 @@ function rn() {
|
|
|
2302
2307
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2303
2308
|
};
|
|
2304
2309
|
}
|
|
2305
|
-
function
|
|
2310
|
+
function on() {
|
|
2306
2311
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2307
2312
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2308
2313
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2309
2314
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2310
2315
|
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";
|
|
2311
2316
|
}
|
|
2312
|
-
function
|
|
2317
|
+
function sn() {
|
|
2313
2318
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2314
2319
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2315
2320
|
let t = {
|
|
@@ -2328,17 +2333,17 @@ function on() {
|
|
|
2328
2333
|
}
|
|
2329
2334
|
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;
|
|
2330
2335
|
}
|
|
2331
|
-
function
|
|
2332
|
-
let t =
|
|
2333
|
-
deviceClass:
|
|
2336
|
+
function cn(e) {
|
|
2337
|
+
let t = an(), n = {
|
|
2338
|
+
deviceClass: on(),
|
|
2334
2339
|
integration: t.integration,
|
|
2335
|
-
...
|
|
2340
|
+
...sn()
|
|
2336
2341
|
};
|
|
2337
2342
|
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);
|
|
2338
2343
|
let r = e.getBoundingClientRect?.();
|
|
2339
2344
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2340
2345
|
}
|
|
2341
|
-
async function
|
|
2346
|
+
async function ln() {
|
|
2342
2347
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2343
2348
|
if (!e?.getHighEntropyValues) return {};
|
|
2344
2349
|
try {
|
|
@@ -2350,7 +2355,7 @@ async function cn() {
|
|
|
2350
2355
|
}
|
|
2351
2356
|
//#endregion
|
|
2352
2357
|
//#region src/core/version.ts
|
|
2353
|
-
var
|
|
2358
|
+
var un = "2.15.6", dn = {
|
|
2354
2359
|
accent: "#E1B600",
|
|
2355
2360
|
accentText: "#1B1C23",
|
|
2356
2361
|
background: "#0e0f13",
|
|
@@ -2361,7 +2366,7 @@ var ln = "2.15.4", un = {
|
|
|
2361
2366
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2362
2367
|
radius: "8px",
|
|
2363
2368
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2364
|
-
},
|
|
2369
|
+
}, fn = {
|
|
2365
2370
|
accent: "--havik-accent",
|
|
2366
2371
|
accentText: "--havik-accent-text",
|
|
2367
2372
|
background: "--havik-bg",
|
|
@@ -2373,26 +2378,26 @@ var ln = "2.15.4", un = {
|
|
|
2373
2378
|
radius: "--havik-radius",
|
|
2374
2379
|
fontFamily: "--havik-font"
|
|
2375
2380
|
};
|
|
2376
|
-
function
|
|
2381
|
+
function pn(e, t) {
|
|
2377
2382
|
let n = {
|
|
2378
|
-
...
|
|
2383
|
+
...dn,
|
|
2379
2384
|
...t
|
|
2380
2385
|
};
|
|
2381
|
-
for (let t of Object.keys(
|
|
2386
|
+
for (let t of Object.keys(fn)) e.style.setProperty(fn[t], n[t]);
|
|
2382
2387
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2383
2388
|
}
|
|
2384
2389
|
//#endregion
|
|
2385
2390
|
//#region src/ui/styles.ts
|
|
2386
|
-
var
|
|
2387
|
-
function
|
|
2388
|
-
let n = e.querySelector(`style#${
|
|
2391
|
+
var mn = "havik-player-styles", hn = "\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();
|
|
2392
|
+
function gn(e = document, t) {
|
|
2393
|
+
let n = e.querySelector(`style#${mn}`);
|
|
2389
2394
|
if (n && (!t || Z.get(n) === t)) return;
|
|
2390
2395
|
let r = e.createElement("style");
|
|
2391
|
-
r.id =
|
|
2396
|
+
r.id = mn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = hn, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2392
2397
|
}
|
|
2393
2398
|
//#endregion
|
|
2394
2399
|
//#region src/ui/icons.ts
|
|
2395
|
-
var
|
|
2400
|
+
var _n = {
|
|
2396
2401
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2397
2402
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2398
2403
|
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\"/>",
|
|
@@ -2406,20 +2411,20 @@ var gn = {
|
|
|
2406
2411
|
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\"/>"
|
|
2407
2412
|
};
|
|
2408
2413
|
function Q(e) {
|
|
2409
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2414
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${_n[e]}</svg>`;
|
|
2410
2415
|
}
|
|
2411
2416
|
//#endregion
|
|
2412
2417
|
//#region src/ui/controls.ts
|
|
2413
|
-
var
|
|
2418
|
+
var vn = 3e3, yn = 250, bn = /* @__PURE__ */ new Set([
|
|
2414
2419
|
"GONE",
|
|
2415
2420
|
"NOT_FOUND",
|
|
2416
2421
|
"INVALID_URN",
|
|
2417
2422
|
"UNAUTHORIZED"
|
|
2418
2423
|
]);
|
|
2419
|
-
function
|
|
2420
|
-
return new
|
|
2424
|
+
function xn(e) {
|
|
2425
|
+
return new Sn(e);
|
|
2421
2426
|
}
|
|
2422
|
-
var
|
|
2427
|
+
var Sn = class {
|
|
2423
2428
|
root;
|
|
2424
2429
|
video;
|
|
2425
2430
|
player;
|
|
@@ -2465,7 +2470,7 @@ var xn = class {
|
|
|
2465
2470
|
scrubbing = !1;
|
|
2466
2471
|
offFns = [];
|
|
2467
2472
|
constructor(e) {
|
|
2468
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2473
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? vn, 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, gn(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");
|
|
2469
2474
|
let t = (e, t, n) => {
|
|
2470
2475
|
let r = this.doc.createElement(e);
|
|
2471
2476
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2551,7 +2556,7 @@ var xn = class {
|
|
|
2551
2556
|
let t = this.surfaceWasHidden;
|
|
2552
2557
|
this.tapTimer = setTimeout(() => {
|
|
2553
2558
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2554
|
-
},
|
|
2559
|
+
}, yn);
|
|
2555
2560
|
}
|
|
2556
2561
|
toggleBar(e) {
|
|
2557
2562
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2586,7 +2591,7 @@ var xn = class {
|
|
|
2586
2591
|
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);
|
|
2587
2592
|
} else {
|
|
2588
2593
|
let r = this.doc.createElement("div");
|
|
2589
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2594
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !bn.has(this.lastError.code)) {
|
|
2590
2595
|
let e = this.doc.createElement("button");
|
|
2591
2596
|
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);
|
|
2592
2597
|
}
|
|
@@ -2627,7 +2632,7 @@ var xn = class {
|
|
|
2627
2632
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2628
2633
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2629
2634
|
}
|
|
2630
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2635
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Cn(this.video.currentTime)} / ${Cn(this.video.duration)}`);
|
|
2631
2636
|
}
|
|
2632
2637
|
syncLive() {
|
|
2633
2638
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2677,17 +2682,17 @@ var xn = class {
|
|
|
2677
2682
|
renderQualityMenu() {
|
|
2678
2683
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2679
2684
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2680
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2685
|
+
for (let n of e) this.menu.append(this.menuItem(wn(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2681
2686
|
}
|
|
2682
2687
|
renderAudioMenu() {
|
|
2683
2688
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2684
2689
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2685
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2690
|
+
for (let t of e) this.menu.append(this.menuItem(Tn(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2686
2691
|
}
|
|
2687
2692
|
renderCcMenu() {
|
|
2688
2693
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2689
2694
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2690
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2695
|
+
for (let t of e) this.menu.append(this.menuItem(En(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2691
2696
|
}
|
|
2692
2697
|
onTracksChanged() {
|
|
2693
2698
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2707,11 +2712,11 @@ var xn = class {
|
|
|
2707
2712
|
}
|
|
2708
2713
|
async toggleFullscreen() {
|
|
2709
2714
|
try {
|
|
2710
|
-
|
|
2715
|
+
C(this.video, this.root) ? await T(this.video, this.root) : await w(this.video, this.root);
|
|
2711
2716
|
} catch {}
|
|
2712
2717
|
}
|
|
2713
2718
|
syncFullscreen() {
|
|
2714
|
-
let e =
|
|
2719
|
+
let e = C(this.video, this.root);
|
|
2715
2720
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
2716
2721
|
}
|
|
2717
2722
|
poke() {
|
|
@@ -2788,41 +2793,41 @@ var xn = class {
|
|
|
2788
2793
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2789
2794
|
}
|
|
2790
2795
|
};
|
|
2791
|
-
function
|
|
2796
|
+
function Cn(e) {
|
|
2792
2797
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2793
2798
|
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");
|
|
2794
2799
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2795
2800
|
}
|
|
2796
|
-
function
|
|
2801
|
+
function wn(e) {
|
|
2797
2802
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2798
2803
|
}
|
|
2799
|
-
function
|
|
2804
|
+
function Tn(e) {
|
|
2800
2805
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2801
2806
|
}
|
|
2802
|
-
function
|
|
2807
|
+
function En(e) {
|
|
2803
2808
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2804
2809
|
}
|
|
2805
2810
|
//#endregion
|
|
2806
2811
|
//#region src/managed/index.ts
|
|
2807
|
-
var
|
|
2808
|
-
function
|
|
2812
|
+
var Dn = 6e3, On = 45e3, kn = 2e3, An = 3, jn = 2e3, Mn = 48e4;
|
|
2813
|
+
function Nn(e) {
|
|
2809
2814
|
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)})`);
|
|
2810
2815
|
if (e.env !== void 0) return B(e.env);
|
|
2811
2816
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2812
2817
|
return e.baseUrl;
|
|
2813
2818
|
}
|
|
2814
|
-
async function
|
|
2819
|
+
async function Pn(e) {
|
|
2815
2820
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2816
|
-
let t =
|
|
2821
|
+
let t = Nn(e);
|
|
2817
2822
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2818
2823
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2819
|
-
let r = new
|
|
2824
|
+
let r = new Fn({
|
|
2820
2825
|
...e,
|
|
2821
2826
|
baseUrl: t
|
|
2822
2827
|
});
|
|
2823
2828
|
return await r.start(), r;
|
|
2824
2829
|
}
|
|
2825
|
-
var
|
|
2830
|
+
var Fn = class {
|
|
2826
2831
|
opts;
|
|
2827
2832
|
abort = new AbortController();
|
|
2828
2833
|
listeners = {};
|
|
@@ -2866,7 +2871,7 @@ var Pn = class {
|
|
|
2866
2871
|
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");
|
|
2867
2872
|
let e = ++this.loadGen, t = this.resolveOptions();
|
|
2868
2873
|
try {
|
|
2869
|
-
let n = await
|
|
2874
|
+
let n = await y(t);
|
|
2870
2875
|
if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
|
|
2871
2876
|
let e = this._lastError;
|
|
2872
2877
|
throw this.destroy(), e;
|
|
@@ -2889,11 +2894,11 @@ var Pn = class {
|
|
|
2889
2894
|
};
|
|
2890
2895
|
}
|
|
2891
2896
|
beginArming(e, t, n = !1) {
|
|
2892
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
2897
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
|
|
2893
2898
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
2894
2899
|
}
|
|
2895
2900
|
beginArmingByPolling(e) {
|
|
2896
|
-
|
|
2901
|
+
b({
|
|
2897
2902
|
...this.resolveOptions(),
|
|
2898
2903
|
signal: this.abort.signal,
|
|
2899
2904
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -2910,7 +2915,7 @@ var Pn = class {
|
|
|
2910
2915
|
setTimeout(() => {
|
|
2911
2916
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
2912
2917
|
phase: i ? "unavailable" : "tooEarly",
|
|
2913
|
-
retryInMs:
|
|
2918
|
+
retryInMs: On,
|
|
2914
2919
|
attempt: 1,
|
|
2915
2920
|
elapsedMs: 0,
|
|
2916
2921
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -2927,7 +2932,7 @@ var Pn = class {
|
|
|
2927
2932
|
}
|
|
2928
2933
|
}
|
|
2929
2934
|
}, h = () => {
|
|
2930
|
-
a || s || p() || (s = !0,
|
|
2935
|
+
a || s || p() || (s = !0, b({
|
|
2931
2936
|
...this.resolveOptions(),
|
|
2932
2937
|
signal: c.signal,
|
|
2933
2938
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -2935,7 +2940,7 @@ var Pn = class {
|
|
|
2935
2940
|
a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
|
|
2936
2941
|
}));
|
|
2937
2942
|
}, g = () => {
|
|
2938
|
-
a || p() ||
|
|
2943
|
+
a || p() || y(this.resolveOptions()).then((e) => m(e)).catch((e) => {
|
|
2939
2944
|
if (!(a || p())) {
|
|
2940
2945
|
if (e instanceof n && o(e.code)) {
|
|
2941
2946
|
h();
|
|
@@ -2949,13 +2954,13 @@ var Pn = class {
|
|
|
2949
2954
|
!a && !p() && h();
|
|
2950
2955
|
}, e);
|
|
2951
2956
|
};
|
|
2952
|
-
_(
|
|
2957
|
+
_(Dn), this.armingSub = E({
|
|
2953
2958
|
eventsBaseUrl: t,
|
|
2954
2959
|
matchUrn: this.opts.matchUrn,
|
|
2955
2960
|
credential: this.opts.credential,
|
|
2956
|
-
onAlive: () => _(
|
|
2961
|
+
onAlive: () => _(On),
|
|
2957
2962
|
onState: (e) => {
|
|
2958
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
2963
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * kn);
|
|
2959
2964
|
},
|
|
2960
2965
|
onError: () => h()
|
|
2961
2966
|
});
|
|
@@ -3000,19 +3005,19 @@ var Pn = class {
|
|
|
3000
3005
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3001
3006
|
let i = e.analytics?.sid;
|
|
3002
3007
|
if (!i) return;
|
|
3003
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3008
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = nn(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3004
3009
|
if (!o) {
|
|
3005
3010
|
s && setTimeout(() => {
|
|
3006
3011
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3007
3012
|
}, 0);
|
|
3008
3013
|
return;
|
|
3009
3014
|
}
|
|
3010
|
-
let c = this.opts.video, l = new
|
|
3015
|
+
let c = this.opts.video, l = new rn({
|
|
3011
3016
|
endpoint: o,
|
|
3012
3017
|
sid: i,
|
|
3013
3018
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3014
|
-
sdkVersion:
|
|
3015
|
-
environment:
|
|
3019
|
+
sdkVersion: un,
|
|
3020
|
+
environment: cn(c),
|
|
3016
3021
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3017
3022
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3018
3023
|
onBlocked: (e) => setTimeout(() => {
|
|
@@ -3033,7 +3038,7 @@ var Pn = class {
|
|
|
3033
3038
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3034
3039
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3035
3040
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3036
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3041
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), ln().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3037
3042
|
}
|
|
3038
3043
|
currentPresentation() {
|
|
3039
3044
|
let e = this.opts.video;
|
|
@@ -3048,7 +3053,7 @@ var Pn = class {
|
|
|
3048
3053
|
video: this.opts.video,
|
|
3049
3054
|
descriptor: e,
|
|
3050
3055
|
credential: t,
|
|
3051
|
-
deviceId:
|
|
3056
|
+
deviceId: A(),
|
|
3052
3057
|
userId: this.opts.userId,
|
|
3053
3058
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
3054
3059
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -3059,9 +3064,9 @@ var Pn = class {
|
|
|
3059
3064
|
emit: (e) => this.onEngineEvent(e)
|
|
3060
3065
|
}, o = this.opts.engine ?? "auto";
|
|
3061
3066
|
if (o === "native") return new K(a);
|
|
3062
|
-
if (o === "hls") return new
|
|
3063
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G()) return new K(a);
|
|
3064
|
-
if (
|
|
3067
|
+
if (o === "hls") return new Rt(a);
|
|
3068
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G() || !e.drmEnabled && Ye() && W(this.opts.video)) return new K(a);
|
|
3069
|
+
if (ot()) return new Rt(a);
|
|
3065
3070
|
if (W(this.opts.video)) return new K(a);
|
|
3066
3071
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3067
3072
|
}
|
|
@@ -3099,11 +3104,11 @@ var Pn = class {
|
|
|
3099
3104
|
}
|
|
3100
3105
|
startLiveState(e) {
|
|
3101
3106
|
if (this.opts.liveStateEvents === !1) return;
|
|
3102
|
-
let t = this.opts.eventsBaseUrl ??
|
|
3107
|
+
let t = this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
|
|
3103
3108
|
if (!t) return;
|
|
3104
3109
|
this.closeLiveState();
|
|
3105
3110
|
let r = 0, i = !1;
|
|
3106
|
-
this.liveStateSub =
|
|
3111
|
+
this.liveStateSub = E({
|
|
3107
3112
|
eventsBaseUrl: t,
|
|
3108
3113
|
matchUrn: this.opts.matchUrn,
|
|
3109
3114
|
credential: this.opts.credential,
|
|
@@ -3114,7 +3119,7 @@ var Pn = class {
|
|
|
3114
3119
|
r = 0, i = !1;
|
|
3115
3120
|
},
|
|
3116
3121
|
onError: () => {
|
|
3117
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
3122
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= An && (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.`))));
|
|
3118
3123
|
}
|
|
3119
3124
|
});
|
|
3120
3125
|
}
|
|
@@ -3136,7 +3141,7 @@ var Pn = class {
|
|
|
3136
3141
|
scheduleRejoin(e) {
|
|
3137
3142
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3138
3143
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3139
|
-
}, Math.random() *
|
|
3144
|
+
}, Math.random() * kn));
|
|
3140
3145
|
}
|
|
3141
3146
|
cancelRejoin() {
|
|
3142
3147
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3160,7 +3165,7 @@ var Pn = class {
|
|
|
3160
3165
|
}
|
|
3161
3166
|
t.controls = !1;
|
|
3162
3167
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3163
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3168
|
+
r && r.insertBefore(n, t), n.appendChild(t), pn(n, this.opts.theme), this.container = n, this.controlBar = xn({
|
|
3164
3169
|
root: n,
|
|
3165
3170
|
video: t,
|
|
3166
3171
|
player: this,
|
|
@@ -3191,7 +3196,7 @@ var Pn = class {
|
|
|
3191
3196
|
}
|
|
3192
3197
|
startStats() {
|
|
3193
3198
|
this.stopStats();
|
|
3194
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3199
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? jn);
|
|
3195
3200
|
this.statsTimer = setInterval(() => {
|
|
3196
3201
|
if (!this.engine) return;
|
|
3197
3202
|
let e = this.engine.getStats();
|
|
@@ -3203,7 +3208,7 @@ var Pn = class {
|
|
|
3203
3208
|
}
|
|
3204
3209
|
scheduleLicenseRefresh() {
|
|
3205
3210
|
this.stopRefresh();
|
|
3206
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3211
|
+
let e = this.opts.licenseRefreshMs ?? Mn;
|
|
3207
3212
|
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3208
3213
|
}
|
|
3209
3214
|
stopRefresh() {
|
|
@@ -3212,7 +3217,7 @@ var Pn = class {
|
|
|
3212
3217
|
async refreshLicense() {
|
|
3213
3218
|
let e = this.engine;
|
|
3214
3219
|
if (!this.destroyed && e) try {
|
|
3215
|
-
let t = await
|
|
3220
|
+
let t = await y(this.resolveOptions());
|
|
3216
3221
|
if (this.destroyed || this.engine !== e) return;
|
|
3217
3222
|
let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
|
|
3218
3223
|
(n || r) && (e.setLicenseUrls({
|
|
@@ -3287,10 +3292,10 @@ var Pn = class {
|
|
|
3287
3292
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
3288
3293
|
}
|
|
3289
3294
|
async enterFullscreen() {
|
|
3290
|
-
return !this.destroyed &&
|
|
3295
|
+
return !this.destroyed && w(this.opts.video, this.container ?? void 0);
|
|
3291
3296
|
}
|
|
3292
3297
|
async exitFullscreen() {
|
|
3293
|
-
await
|
|
3298
|
+
await T(this.opts.video, this.container ?? void 0);
|
|
3294
3299
|
}
|
|
3295
3300
|
retry() {
|
|
3296
3301
|
return this.reload();
|
|
@@ -3300,7 +3305,7 @@ var Pn = class {
|
|
|
3300
3305
|
let e = ++this.loadGen;
|
|
3301
3306
|
this.teardownPlayback();
|
|
3302
3307
|
try {
|
|
3303
|
-
let t = await
|
|
3308
|
+
let t = await b({
|
|
3304
3309
|
...this.resolveOptions(),
|
|
3305
3310
|
waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
|
|
3306
3311
|
});
|
|
@@ -3358,7 +3363,7 @@ function $(e) {
|
|
|
3358
3363
|
}
|
|
3359
3364
|
//#endregion
|
|
3360
3365
|
//#region src/embed/host.ts
|
|
3361
|
-
function
|
|
3366
|
+
function In(e) {
|
|
3362
3367
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3363
3368
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3364
3369
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3417,15 +3422,15 @@ function Fn(e) {
|
|
|
3417
3422
|
}
|
|
3418
3423
|
//#endregion
|
|
3419
3424
|
//#region src/embed/page.ts
|
|
3420
|
-
var
|
|
3421
|
-
function
|
|
3425
|
+
var Ln = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3426
|
+
function Rn(e) {
|
|
3422
3427
|
if (typeof e == "boolean") return e;
|
|
3423
3428
|
if (typeof e == "object" && e) {
|
|
3424
3429
|
let t = e.endpoint;
|
|
3425
3430
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3426
3431
|
}
|
|
3427
3432
|
}
|
|
3428
|
-
function
|
|
3433
|
+
function zn() {
|
|
3429
3434
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3430
3435
|
if (e) return {
|
|
3431
3436
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3435,7 +3440,7 @@ function Rn() {
|
|
|
3435
3440
|
autoplay: e.autoplay ?? !0,
|
|
3436
3441
|
muted: e.muted ?? !0,
|
|
3437
3442
|
waitForLive: e.waitForLive ?? !0,
|
|
3438
|
-
analytics:
|
|
3443
|
+
analytics: Rn(e.analytics)
|
|
3439
3444
|
};
|
|
3440
3445
|
let t = new URLSearchParams(location.search);
|
|
3441
3446
|
return {
|
|
@@ -3448,9 +3453,9 @@ function Rn() {
|
|
|
3448
3453
|
waitForLive: !0
|
|
3449
3454
|
};
|
|
3450
3455
|
}
|
|
3451
|
-
async function
|
|
3452
|
-
let e =
|
|
3453
|
-
|
|
3456
|
+
async function Bn() {
|
|
3457
|
+
let e = zn();
|
|
3458
|
+
Hn();
|
|
3454
3459
|
let t = document.createElement("video");
|
|
3455
3460
|
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);
|
|
3456
3461
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3505,12 +3510,12 @@ async function zn() {
|
|
|
3505
3510
|
code: e.code,
|
|
3506
3511
|
message: e.message
|
|
3507
3512
|
})), e.on("autoplayblocked", () => {
|
|
3508
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3513
|
+
i({ type: "oddin:autoplayblocked" }), Vn(t, e);
|
|
3509
3514
|
});
|
|
3510
3515
|
}, s = async (r) => {
|
|
3511
3516
|
a?.destroy(), a = null;
|
|
3512
3517
|
try {
|
|
3513
|
-
let n = await
|
|
3518
|
+
let n = await Pn({
|
|
3514
3519
|
video: t,
|
|
3515
3520
|
baseUrl: e.baseUrl,
|
|
3516
3521
|
matchUrn: r,
|
|
@@ -3572,7 +3577,7 @@ async function zn() {
|
|
|
3572
3577
|
a?.retry();
|
|
3573
3578
|
break;
|
|
3574
3579
|
case "oddin:load":
|
|
3575
|
-
typeof e.matchUrn == "string" &&
|
|
3580
|
+
typeof e.matchUrn == "string" && Ln.test(e.matchUrn) && s(e.matchUrn);
|
|
3576
3581
|
break;
|
|
3577
3582
|
case "oddin:destroy": c();
|
|
3578
3583
|
}
|
|
@@ -3584,18 +3589,18 @@ async function zn() {
|
|
|
3584
3589
|
protocol: 1
|
|
3585
3590
|
});
|
|
3586
3591
|
}
|
|
3587
|
-
function
|
|
3592
|
+
function Vn(e, t) {
|
|
3588
3593
|
if (document.getElementById("havik-tap")) return;
|
|
3589
3594
|
let n = document.createElement("button");
|
|
3590
3595
|
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", () => {
|
|
3591
3596
|
n.remove(), t.play();
|
|
3592
3597
|
}), document.body.appendChild(n);
|
|
3593
3598
|
}
|
|
3594
|
-
function
|
|
3599
|
+
function Hn() {
|
|
3595
3600
|
let e = document.createElement("style");
|
|
3596
3601
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3597
3602
|
}
|
|
3598
3603
|
//#endregion
|
|
3599
|
-
export {
|
|
3604
|
+
export { dn as ODDIN_THEME, n as PlaybackError, pn as applyTheme, B as baseUrlForEnv, Bn as bootEmbed, we as clearDeviceId, Pn as createPlayer, D as deriveEventsBaseUrl, Ve as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ge as fetchCatalog, ve as fetchTournament, be as flattenMatches, A as getDeviceId, Ue as isLowLatencyManifest, $ as isOddinMessage, Ee as licenseRequestHeaders, In as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, Se as watchStatus };
|
|
3600
3605
|
|
|
3601
3606
|
//# sourceMappingURL=index.js.map
|