@oddin-gg/havik-player 2.16.1 → 2.16.3
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 +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +375 -324
- package/dist/index.js.map +1 -1
- package/docs/API.md +3 -2
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -174,7 +174,7 @@ function ue(e, t) {
|
|
|
174
174
|
t?.addEventListener("abort", a, { once: !0 });
|
|
175
175
|
});
|
|
176
176
|
}
|
|
177
|
-
async function
|
|
177
|
+
async function de(e, t, r) {
|
|
178
178
|
let i = ae(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
|
|
179
179
|
for (;;) {
|
|
180
180
|
if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
|
|
@@ -200,21 +200,21 @@ async function v(e, t, r) {
|
|
|
200
200
|
}
|
|
201
201
|
//#endregion
|
|
202
202
|
//#region src/core/resolve.ts
|
|
203
|
-
async function
|
|
203
|
+
async function v(e) {
|
|
204
204
|
if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
|
|
205
205
|
let t = await p(d(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
|
|
206
206
|
credential: e.credential,
|
|
207
207
|
signal: e.signal,
|
|
208
208
|
apiHeaders: e.apiHeaders
|
|
209
209
|
});
|
|
210
|
-
if (!t.ok) throw await
|
|
211
|
-
return
|
|
210
|
+
if (!t.ok) throw await fe(t);
|
|
211
|
+
return he(await t.json(), e.matchUrn);
|
|
212
212
|
}
|
|
213
|
-
function
|
|
214
|
-
let t = () =>
|
|
215
|
-
return e.waitForLive ?
|
|
213
|
+
function y(e) {
|
|
214
|
+
let t = () => v(e);
|
|
215
|
+
return e.waitForLive ? de(t, e.waitForLive, e.signal) : t();
|
|
216
216
|
}
|
|
217
|
-
async function
|
|
217
|
+
async function fe(e) {
|
|
218
218
|
let t = f(e.headers.get("retry-after")), i = e.headers.get("x-request-id") ?? e.headers.get("x-amzn-requestid") ?? void 0, a = e.statusText || `HTTP ${e.status}`, o, s;
|
|
219
219
|
try {
|
|
220
220
|
let t = await e.json();
|
|
@@ -230,7 +230,7 @@ async function de(e) {
|
|
|
230
230
|
liveStartsAtMs: s
|
|
231
231
|
});
|
|
232
232
|
}
|
|
233
|
-
var
|
|
233
|
+
var pe = /* @__PURE__ */ new Set([
|
|
234
234
|
"matchUrn",
|
|
235
235
|
"protocol",
|
|
236
236
|
"drmEnabled",
|
|
@@ -241,7 +241,7 @@ var fe = /* @__PURE__ */ new Set([
|
|
|
241
241
|
"expiresAt",
|
|
242
242
|
"analytics"
|
|
243
243
|
]);
|
|
244
|
-
function
|
|
244
|
+
function b(e, t) {
|
|
245
245
|
let r;
|
|
246
246
|
try {
|
|
247
247
|
r = new URL(t);
|
|
@@ -251,7 +251,7 @@ function x(e, t) {
|
|
|
251
251
|
if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
|
|
252
252
|
return t;
|
|
253
253
|
}
|
|
254
|
-
function
|
|
254
|
+
function me(e) {
|
|
255
255
|
if (e !== void 0) {
|
|
256
256
|
if (typeof e == "string" && !e.endsWith("/")) try {
|
|
257
257
|
let t = new URL(e);
|
|
@@ -260,62 +260,62 @@ function pe(e) {
|
|
|
260
260
|
g(`server analytics.endpoint ${JSON.stringify(e)} ignored: not a bare https origin.`);
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
|
-
function
|
|
263
|
+
function he(e, t) {
|
|
264
264
|
if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
|
|
265
265
|
let r = e.drmEnabled ?? !!e.drm, i = {
|
|
266
266
|
matchUrn: e.matchUrn ?? t,
|
|
267
267
|
protocol: "hls",
|
|
268
268
|
drmEnabled: r,
|
|
269
|
-
manifestUrl:
|
|
269
|
+
manifestUrl: b("manifestUrl", e.manifestUrl),
|
|
270
270
|
serverTime: e.serverTime ?? ""
|
|
271
271
|
};
|
|
272
272
|
if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid) {
|
|
273
273
|
i.analytics = { sid: e.analytics.sid };
|
|
274
|
-
let t =
|
|
274
|
+
let t = me(e.analytics.endpoint);
|
|
275
275
|
t && (i.analytics.endpoint = t);
|
|
276
276
|
}
|
|
277
277
|
if (r && e.drm) {
|
|
278
278
|
let t = {};
|
|
279
|
-
e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl:
|
|
280
|
-
licenseUrl:
|
|
281
|
-
certificateUrl:
|
|
279
|
+
e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: b("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
|
|
280
|
+
licenseUrl: b("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
|
|
281
|
+
certificateUrl: b("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
|
|
282
282
|
}), (t.widevine || t.fairplay) && (i.drm = t);
|
|
283
283
|
}
|
|
284
284
|
let a = {};
|
|
285
|
-
for (let [t, n] of Object.entries(e))
|
|
285
|
+
for (let [t, n] of Object.entries(e)) pe.has(t) || (a[t] = n);
|
|
286
286
|
return Object.keys(a).length > 0 && (i.extensions = a), i;
|
|
287
287
|
}
|
|
288
288
|
//#endregion
|
|
289
289
|
//#region src/core/fullscreen.ts
|
|
290
|
-
function
|
|
290
|
+
function ge(e) {
|
|
291
291
|
return e.ownerDocument ?? document;
|
|
292
292
|
}
|
|
293
|
-
function
|
|
293
|
+
function x(e) {
|
|
294
294
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
295
295
|
}
|
|
296
|
-
function
|
|
297
|
-
let n =
|
|
296
|
+
function S(e, t) {
|
|
297
|
+
let n = x(ge(e));
|
|
298
298
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
299
299
|
}
|
|
300
|
-
async function
|
|
300
|
+
async function C(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 w(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 = ge(e), i = x(r);
|
|
314
314
|
i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
|
|
315
315
|
}
|
|
316
316
|
//#endregion
|
|
317
317
|
//#region src/core/catalog.ts
|
|
318
|
-
async function
|
|
318
|
+
async function _e(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 ge(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: ve(await s.json()),
|
|
337
337
|
etag: s.headers.get("etag") ?? void 0,
|
|
338
338
|
notModified: !1
|
|
339
339
|
};
|
|
340
340
|
}
|
|
341
|
-
function
|
|
341
|
+
function ve(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 _e(e) {
|
|
|
360
360
|
};
|
|
361
361
|
});
|
|
362
362
|
}
|
|
363
|
-
async function
|
|
363
|
+
async function ye(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 ve(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: be(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 be(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 ye(e) {
|
|
|
406
406
|
}))
|
|
407
407
|
};
|
|
408
408
|
}
|
|
409
|
-
function
|
|
409
|
+
function xe(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 Se = /* @__PURE__ */ new Set([
|
|
415
415
|
"NOT_FOUND",
|
|
416
416
|
"GONE",
|
|
417
417
|
"INVALID_URN"
|
|
418
418
|
]);
|
|
419
|
-
function
|
|
419
|
+
function Ce(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 Se(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
|
+
Se.has(r.code) && (u = !0), e.onError?.(r);
|
|
453
453
|
}
|
|
454
454
|
} finally {
|
|
455
455
|
f();
|
|
@@ -461,9 +461,9 @@ function Se(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 we = 45e3;
|
|
465
|
+
function T(e) {
|
|
466
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? we, 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 E(e) {
|
|
|
544
544
|
o || (o = !0, a.abort());
|
|
545
545
|
} };
|
|
546
546
|
}
|
|
547
|
-
function
|
|
547
|
+
function E(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 D(e) {
|
|
|
554
554
|
}
|
|
555
555
|
//#endregion
|
|
556
556
|
//#region src/core/drm/deviceId.ts
|
|
557
|
-
var
|
|
558
|
-
function
|
|
559
|
-
if (
|
|
557
|
+
var D = "havik.player.deviceId", O;
|
|
558
|
+
function k() {
|
|
559
|
+
if (O) return O;
|
|
560
560
|
try {
|
|
561
|
-
let e = globalThis.localStorage?.getItem(
|
|
562
|
-
if (e) return
|
|
561
|
+
let e = globalThis.localStorage?.getItem(D);
|
|
562
|
+
if (e) return O = e, e;
|
|
563
563
|
} catch {}
|
|
564
|
-
let e =
|
|
565
|
-
|
|
564
|
+
let e = Ee();
|
|
565
|
+
O = e;
|
|
566
566
|
try {
|
|
567
|
-
globalThis.localStorage?.setItem(
|
|
567
|
+
globalThis.localStorage?.setItem(D, e);
|
|
568
568
|
} catch {}
|
|
569
569
|
return e;
|
|
570
570
|
}
|
|
571
|
-
function
|
|
572
|
-
|
|
571
|
+
function Te() {
|
|
572
|
+
O = void 0;
|
|
573
573
|
try {
|
|
574
|
-
globalThis.localStorage?.removeItem(
|
|
574
|
+
globalThis.localStorage?.removeItem(D);
|
|
575
575
|
} catch {}
|
|
576
576
|
}
|
|
577
|
-
function
|
|
577
|
+
function Ee() {
|
|
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 Te() {
|
|
|
586
586
|
}
|
|
587
587
|
//#endregion
|
|
588
588
|
//#region src/core/drm/headers.ts
|
|
589
|
-
function
|
|
589
|
+
function De(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 ?? k(),
|
|
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 A = /* @__PURE__ */ new WeakMap();
|
|
601
|
+
function Oe(e, t) {
|
|
602
|
+
let n = A.get(e);
|
|
603
|
+
n || (n = /* @__PURE__ */ new Map(), A.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 De(e, t) {
|
|
|
608
608
|
});
|
|
609
609
|
return n.set(t.keySystem, i), i;
|
|
610
610
|
}
|
|
611
|
-
function
|
|
611
|
+
function j() {
|
|
612
612
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
613
613
|
}
|
|
614
|
-
var
|
|
615
|
-
function
|
|
614
|
+
var M = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
615
|
+
function ke(e) {
|
|
616
616
|
return e.startsWith("com.widevine");
|
|
617
617
|
}
|
|
618
|
-
function
|
|
619
|
-
if (!
|
|
618
|
+
function N(e, t) {
|
|
619
|
+
if (!ke(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 = M.indexOf(e.robustness);
|
|
624
|
+
return n === -1 || M.indexOf(t) > n;
|
|
625
625
|
});
|
|
626
|
-
}, r =
|
|
626
|
+
}, r = M.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 P(e, t) {
|
|
|
632
632
|
})));
|
|
633
633
|
return [...t, ...r];
|
|
634
634
|
}
|
|
635
|
-
function
|
|
636
|
-
return (t, n) =>
|
|
635
|
+
function P(e) {
|
|
636
|
+
return (t, n) => j() ? navigator.requestMediaKeySystemAccess(t, N(t, n)).then((t) => ({
|
|
637
637
|
keySystem: t.keySystem,
|
|
638
638
|
getConfiguration: () => t.getConfiguration(),
|
|
639
|
-
createMediaKeys: () =>
|
|
639
|
+
createMediaKeys: () => Oe(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 F = {
|
|
643
643
|
video: "SW_SECURE_DECODE",
|
|
644
644
|
audio: "SW_SECURE_CRYPTO",
|
|
645
645
|
scheme: "cbcs"
|
|
646
646
|
};
|
|
647
|
-
function
|
|
648
|
-
if (!
|
|
647
|
+
function Ae(e) {
|
|
648
|
+
if (!j()) return;
|
|
649
649
|
let t = (e, t) => ({
|
|
650
650
|
contentType: e,
|
|
651
651
|
robustness: t,
|
|
652
|
-
encryptionScheme:
|
|
652
|
+
encryptionScheme: F.scheme
|
|
653
653
|
});
|
|
654
|
-
|
|
654
|
+
P(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\"", F.audio)],
|
|
660
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", F.video)]
|
|
661
661
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
662
662
|
}
|
|
663
|
-
function
|
|
664
|
-
let t =
|
|
663
|
+
function I(e) {
|
|
664
|
+
let t = L(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 L(e) {
|
|
672
672
|
return (e ?? "").trim().toLowerCase();
|
|
673
673
|
}
|
|
674
|
-
var
|
|
674
|
+
var je = {
|
|
675
675
|
hevc: "hvc1.1.6.L93.90",
|
|
676
676
|
dv: "dvh1.05.06",
|
|
677
677
|
av1: "av01.0.05M.08",
|
|
678
678
|
vp9: "vp09.00.10.08"
|
|
679
|
-
},
|
|
680
|
-
function
|
|
681
|
-
let t =
|
|
679
|
+
}, Me = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
|
|
680
|
+
function Ne(e) {
|
|
681
|
+
let t = L(e), n = Me.get(t);
|
|
682
682
|
if (n) return n;
|
|
683
683
|
let r = {
|
|
684
684
|
initDataTypes: ["cenc"],
|
|
@@ -687,32 +687,32 @@ function Me(e) {
|
|
|
687
687
|
sessionTypes: ["temporary"],
|
|
688
688
|
videoCapabilities: [{
|
|
689
689
|
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
690
|
-
robustness:
|
|
691
|
-
encryptionScheme:
|
|
690
|
+
robustness: F.video,
|
|
691
|
+
encryptionScheme: F.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", N("com.widevine.alpha", [r])), !0;
|
|
696
696
|
} catch {
|
|
697
697
|
return !1;
|
|
698
698
|
}
|
|
699
|
-
})().then((e) => (
|
|
700
|
-
return
|
|
699
|
+
})().then((e) => (R.set(t, e), e));
|
|
700
|
+
return Me.set(t, i), i;
|
|
701
701
|
}
|
|
702
|
-
function
|
|
703
|
-
if (
|
|
702
|
+
function Pe() {
|
|
703
|
+
if (j()) for (let e of Object.values(je)) Ne(e);
|
|
704
704
|
}
|
|
705
|
-
function
|
|
706
|
-
let t =
|
|
707
|
-
if (t) return t === "avc" ? !0 :
|
|
705
|
+
function Fe(e) {
|
|
706
|
+
let t = I(e);
|
|
707
|
+
if (t) return t === "avc" ? !0 : R.get(L(e)) ?? R.get(L(je[t]));
|
|
708
708
|
}
|
|
709
709
|
//#endregion
|
|
710
710
|
//#region src/core/drm/support.ts
|
|
711
|
-
var
|
|
711
|
+
var Ie = 5e3, Le = "video/mp4; codecs=\"avc1.42E01E\"", Re = "audio/mp4; codecs=\"mp4a.40.2\"", ze = {
|
|
712
712
|
widevine: ["com.widevine.alpha"],
|
|
713
713
|
fairplay: ["com.apple.fps"]
|
|
714
714
|
};
|
|
715
|
-
function
|
|
715
|
+
function Be(e) {
|
|
716
716
|
return e === "fairplay" ? [{
|
|
717
717
|
initDataTypes: [
|
|
718
718
|
"sinf",
|
|
@@ -720,30 +720,30 @@ function ze(e) {
|
|
|
720
720
|
"cenc"
|
|
721
721
|
],
|
|
722
722
|
videoCapabilities: [{
|
|
723
|
-
contentType:
|
|
723
|
+
contentType: Le,
|
|
724
724
|
robustness: "",
|
|
725
725
|
encryptionScheme: "cbcs"
|
|
726
726
|
}],
|
|
727
727
|
audioCapabilities: [{
|
|
728
|
-
contentType:
|
|
728
|
+
contentType: Re,
|
|
729
729
|
robustness: "",
|
|
730
730
|
encryptionScheme: "cbcs"
|
|
731
731
|
}]
|
|
732
|
-
}] :
|
|
732
|
+
}] : N("com.widevine.alpha", [{
|
|
733
733
|
initDataTypes: ["cenc"],
|
|
734
734
|
videoCapabilities: [{
|
|
735
|
-
contentType:
|
|
736
|
-
robustness:
|
|
737
|
-
encryptionScheme:
|
|
735
|
+
contentType: Le,
|
|
736
|
+
robustness: F.video,
|
|
737
|
+
encryptionScheme: F.scheme
|
|
738
738
|
}],
|
|
739
739
|
audioCapabilities: [{
|
|
740
|
-
contentType:
|
|
741
|
-
robustness:
|
|
742
|
-
encryptionScheme:
|
|
740
|
+
contentType: Re,
|
|
741
|
+
robustness: F.audio,
|
|
742
|
+
encryptionScheme: F.scheme
|
|
743
743
|
}]
|
|
744
744
|
}]);
|
|
745
745
|
}
|
|
746
|
-
function
|
|
746
|
+
function Ve(e, t) {
|
|
747
747
|
return new Promise((n, r) => {
|
|
748
748
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
749
749
|
e.then((e) => {
|
|
@@ -753,8 +753,8 @@ function Be(e, t) {
|
|
|
753
753
|
});
|
|
754
754
|
});
|
|
755
755
|
}
|
|
756
|
-
async function
|
|
757
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
756
|
+
async function He(e = {}) {
|
|
757
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ie, r = {};
|
|
758
758
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
759
759
|
verdict: "insecure-context",
|
|
760
760
|
detail: r
|
|
@@ -766,7 +766,7 @@ async function Ve(e = {}) {
|
|
|
766
766
|
};
|
|
767
767
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
768
768
|
for (let e of t) {
|
|
769
|
-
let t =
|
|
769
|
+
let t = ze[e];
|
|
770
770
|
if (!t) {
|
|
771
771
|
r[e] = "unknown system";
|
|
772
772
|
continue;
|
|
@@ -777,7 +777,7 @@ async function Ve(e = {}) {
|
|
|
777
777
|
break;
|
|
778
778
|
}
|
|
779
779
|
try {
|
|
780
|
-
return await
|
|
780
|
+
return await Ve((await Ve(i(n, Be(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
781
781
|
verdict: "supported",
|
|
782
782
|
system: e,
|
|
783
783
|
detail: r
|
|
@@ -801,49 +801,72 @@ async function Ve(e = {}) {
|
|
|
801
801
|
}
|
|
802
802
|
//#endregion
|
|
803
803
|
//#region src/core/manifest.ts
|
|
804
|
-
var
|
|
805
|
-
function
|
|
806
|
-
return
|
|
804
|
+
var Ue = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
805
|
+
function We(e) {
|
|
806
|
+
return Ue.test(e);
|
|
807
807
|
}
|
|
808
808
|
//#endregion
|
|
809
809
|
//#region src/core/env.ts
|
|
810
|
-
var
|
|
810
|
+
var Ge = {
|
|
811
811
|
integration: "https://feed-dev.oddin-video.gg",
|
|
812
812
|
production: "https://feed.oddin-video.gg"
|
|
813
813
|
};
|
|
814
|
-
function
|
|
815
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
814
|
+
function Ke(e) {
|
|
815
|
+
let t = Object.prototype.hasOwnProperty.call(Ge, e) ? Ge[e] : void 0;
|
|
816
816
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
817
817
|
return t;
|
|
818
818
|
}
|
|
819
819
|
//#endregion
|
|
820
820
|
//#region src/core/stats.ts
|
|
821
|
-
var
|
|
822
|
-
function
|
|
821
|
+
var z = { droppedFrames: 0 };
|
|
822
|
+
function B(e) {
|
|
823
823
|
try {
|
|
824
824
|
return new URL(e).host;
|
|
825
825
|
} catch {
|
|
826
826
|
return "";
|
|
827
827
|
}
|
|
828
828
|
}
|
|
829
|
-
var
|
|
830
|
-
function
|
|
829
|
+
var qe = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
830
|
+
function Je(e) {
|
|
831
831
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
832
832
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
833
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
834
|
-
let e =
|
|
833
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || qe.test(i.name)) && i.startTime >= n) {
|
|
834
|
+
let e = B(i.name);
|
|
835
835
|
e && (t = e, n = i.startTime);
|
|
836
836
|
}
|
|
837
837
|
return t;
|
|
838
838
|
}
|
|
839
|
-
function
|
|
839
|
+
function V(e) {
|
|
840
840
|
let t = e.getVideoPlaybackQuality?.();
|
|
841
841
|
return {
|
|
842
842
|
dropped: t?.droppedVideoFrames ?? 0,
|
|
843
843
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
844
844
|
};
|
|
845
845
|
}
|
|
846
|
-
|
|
846
|
+
var H = class {
|
|
847
|
+
video;
|
|
848
|
+
baseFrames = 0;
|
|
849
|
+
baseDropped = 0;
|
|
850
|
+
lastFrames = 0;
|
|
851
|
+
lastDropped = 0;
|
|
852
|
+
constructor(e) {
|
|
853
|
+
this.video = e;
|
|
854
|
+
}
|
|
855
|
+
read() {
|
|
856
|
+
let e = V(this.video);
|
|
857
|
+
return e.totalFrames < this.lastFrames && (this.baseFrames += this.lastFrames), e.dropped < this.lastDropped && (this.baseDropped += this.lastDropped), this.lastFrames = e.totalFrames, this.lastDropped = e.dropped, {
|
|
858
|
+
dropped: this.baseDropped + e.dropped,
|
|
859
|
+
totalFrames: this.baseFrames + e.totalFrames
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
attach() {
|
|
863
|
+
let e = () => void this.read();
|
|
864
|
+
return this.video.addEventListener("timeupdate", e), this.video.addEventListener("seeking", e), () => {
|
|
865
|
+
this.video.removeEventListener("timeupdate", e), this.video.removeEventListener("seeking", e);
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
function Ye(e, t) {
|
|
847
870
|
let n = [
|
|
848
871
|
["playing", () => t("playing")],
|
|
849
872
|
["waiting", () => t("buffering")],
|
|
@@ -860,8 +883,8 @@ function qe(e, t) {
|
|
|
860
883
|
}
|
|
861
884
|
//#endregion
|
|
862
885
|
//#region src/core/engine/native.ts
|
|
863
|
-
var
|
|
864
|
-
function
|
|
886
|
+
var Xe = 2e3, Ze = 3, U = 500, Qe = 6e3, $e = .25;
|
|
887
|
+
function et(e) {
|
|
865
888
|
try {
|
|
866
889
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
867
890
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -877,7 +900,7 @@ function G() {
|
|
|
877
900
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
878
901
|
return e || t;
|
|
879
902
|
}
|
|
880
|
-
function
|
|
903
|
+
function tt() {
|
|
881
904
|
if (typeof navigator > "u" || !G()) return !1;
|
|
882
905
|
let e = navigator.userAgent ?? "";
|
|
883
906
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
@@ -894,16 +917,20 @@ var K = class {
|
|
|
894
917
|
onVisibility = null;
|
|
895
918
|
onPageShow = null;
|
|
896
919
|
hiddenSince = null;
|
|
920
|
+
refocusTimer = null;
|
|
897
921
|
fairplayKeyIV;
|
|
898
922
|
loadStarted;
|
|
899
923
|
preloadTouched = !1;
|
|
900
924
|
savedPreload = null;
|
|
901
925
|
cdnHost = "";
|
|
902
926
|
builtAt;
|
|
927
|
+
frameCounter;
|
|
928
|
+
detachFrames = null;
|
|
903
929
|
constructor(e) {
|
|
904
|
-
this.deps = e, this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
|
|
930
|
+
this.deps = e, this.frameCounter = new H(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
|
|
905
931
|
}
|
|
906
932
|
async load() {
|
|
933
|
+
this.detachFrames ??= this.frameCounter.attach();
|
|
907
934
|
let { video: e, descriptor: t, emit: r } = this.deps;
|
|
908
935
|
if (this.watchRefocus(), this.loadStarted || (this.preloadTouched = !0, this.savedPreload = e.getAttribute("preload"), e.preload = "none"), t.drmEnabled) {
|
|
909
936
|
if (!t.drm?.fairplay) {
|
|
@@ -921,7 +948,7 @@ var K = class {
|
|
|
921
948
|
type: "error",
|
|
922
949
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
923
950
|
fatal: !0
|
|
924
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
951
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = nt(t.manifestUrl, t.analytics?.sid), e.load();
|
|
925
952
|
}
|
|
926
953
|
startLoad() {
|
|
927
954
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -943,7 +970,7 @@ var K = class {
|
|
|
943
970
|
});
|
|
944
971
|
this.onEncrypted = (n) => {
|
|
945
972
|
let i = n;
|
|
946
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
973
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = et(i.initData), (async () => {
|
|
947
974
|
try {
|
|
948
975
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
949
976
|
initDataTypes: [i.initDataType],
|
|
@@ -1038,11 +1065,11 @@ var K = class {
|
|
|
1038
1065
|
e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
|
|
1039
1066
|
}
|
|
1040
1067
|
getStats() {
|
|
1041
|
-
let e = this.deps.video, t =
|
|
1068
|
+
let e = this.deps.video, t = this.frameCounter.read(), n = {
|
|
1042
1069
|
droppedFrames: t.dropped,
|
|
1043
1070
|
decodedFrames: t.totalFrames
|
|
1044
1071
|
};
|
|
1045
|
-
if (this.cdnHost ||=
|
|
1072
|
+
if (this.cdnHost ||= Je(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1046
1073
|
if (n.isLive = !0, e.seekable.length > 0) {
|
|
1047
1074
|
let t = e.seekable.end(e.seekable.length - 1);
|
|
1048
1075
|
n.atLiveEdge = e.currentTime >= t - 2;
|
|
@@ -1061,27 +1088,48 @@ var K = class {
|
|
|
1061
1088
|
this.deps.snapToLiveOnRefocus === !1 || typeof document > "u" || this.onVisibility || (this.onVisibility = () => {
|
|
1062
1089
|
let e = typeof performance < "u" ? performance.now() : Date.now();
|
|
1063
1090
|
if (document.visibilityState === "hidden") {
|
|
1064
|
-
this.hiddenSince = e;
|
|
1091
|
+
this.hiddenSince = e, this.cancelRefocus();
|
|
1065
1092
|
return;
|
|
1066
1093
|
}
|
|
1067
1094
|
let t = this.hiddenSince;
|
|
1068
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1095
|
+
this.hiddenSince = null, t != null && e - t >= Xe && this.armRefocus();
|
|
1069
1096
|
}, this.onPageShow = (e) => {
|
|
1070
|
-
e.persisted && this.
|
|
1097
|
+
e.persisted && this.armRefocus();
|
|
1071
1098
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
1072
1099
|
}
|
|
1073
|
-
|
|
1100
|
+
armRefocus() {
|
|
1101
|
+
if (this.cancelRefocus(), Number.isFinite(this.deps.video.duration)) return;
|
|
1102
|
+
let e = this.liveEnd(), t = () => typeof performance < "u" ? performance.now() : Date.now(), n = t(), r = 0, i = () => {
|
|
1103
|
+
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1104
|
+
r += U;
|
|
1105
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + $e), s = Math.max(r, t() - n) >= Qe;
|
|
1106
|
+
if (o || s && a != null) {
|
|
1107
|
+
this.snapToLive();
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1110
|
+
this.refocusTimer = setTimeout(i, U);
|
|
1111
|
+
};
|
|
1112
|
+
this.refocusTimer = setTimeout(i, U);
|
|
1113
|
+
}
|
|
1114
|
+
cancelRefocus() {
|
|
1115
|
+
this.refocusTimer != null && clearTimeout(this.refocusTimer), this.refocusTimer = null;
|
|
1116
|
+
}
|
|
1117
|
+
liveEnd() {
|
|
1074
1118
|
let e = this.deps.video;
|
|
1075
|
-
if (e.duration !== Infinity || e.seekable.length === 0) return;
|
|
1076
|
-
let t = e.seekable.
|
|
1077
|
-
|
|
1078
|
-
|
|
1119
|
+
if (e.duration !== Infinity || e.seekable.length === 0) return null;
|
|
1120
|
+
let t = e.seekable.end(e.seekable.length - 1);
|
|
1121
|
+
return Number.isFinite(t) ? t : null;
|
|
1122
|
+
}
|
|
1123
|
+
snapToLive() {
|
|
1124
|
+
let e = this.deps.video, t = this.liveEnd();
|
|
1125
|
+
if (t == null) return;
|
|
1126
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - Ze, r);
|
|
1079
1127
|
try {
|
|
1080
|
-
e.currentTime =
|
|
1128
|
+
e.currentTime = i;
|
|
1081
1129
|
} catch {}
|
|
1082
1130
|
}
|
|
1083
1131
|
destroy() {
|
|
1084
|
-
this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onPageShow && typeof window < "u" && (window.removeEventListener("pageshow", this.onPageShow), this.onPageShow = null);
|
|
1132
|
+
this.detachFrames?.(), this.detachFrames = null, this.cancelRefocus(), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onPageShow && typeof window < "u" && (window.removeEventListener("pageshow", this.onPageShow), this.onPageShow = null);
|
|
1085
1133
|
let { video: e } = this.deps;
|
|
1086
1134
|
this.onLoaded && e.removeEventListener("loadedmetadata", this.onLoaded), this.onError && e.removeEventListener("error", this.onError), this.onEncrypted && e.removeEventListener("encrypted", this.onEncrypted), this.keySession?.close().catch(() => {}), this.keySession = null, this.fairplayArmed = !1, this.fairplayKeyIV = void 0;
|
|
1087
1135
|
try {
|
|
@@ -1093,13 +1141,13 @@ var K = class {
|
|
|
1093
1141
|
} catch {}
|
|
1094
1142
|
}
|
|
1095
1143
|
};
|
|
1096
|
-
function
|
|
1144
|
+
function nt(e, t) {
|
|
1097
1145
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1098
1146
|
}
|
|
1099
1147
|
//#endregion
|
|
1100
1148
|
//#region src/core/engine/prefetch.ts
|
|
1101
|
-
var
|
|
1102
|
-
function
|
|
1149
|
+
var rt = 15e3, it = 5e3, at = 6;
|
|
1150
|
+
function ot(e) {
|
|
1103
1151
|
try {
|
|
1104
1152
|
let t = new URL(e);
|
|
1105
1153
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1107,7 +1155,7 @@ function nt(e) {
|
|
|
1107
1155
|
return e;
|
|
1108
1156
|
}
|
|
1109
1157
|
}
|
|
1110
|
-
var
|
|
1158
|
+
var st = class {
|
|
1111
1159
|
cmcd;
|
|
1112
1160
|
entries = /* @__PURE__ */ new Map();
|
|
1113
1161
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1130,10 +1178,10 @@ var rt = class {
|
|
|
1130
1178
|
}
|
|
1131
1179
|
prefetch(e, t, n) {
|
|
1132
1180
|
if (!this.isActive(t)) return;
|
|
1133
|
-
let r =
|
|
1181
|
+
let r = ot(e);
|
|
1134
1182
|
if (this.entries.has(r)) return;
|
|
1135
1183
|
let i = this.perTrack.get(t) ?? 0;
|
|
1136
|
-
if (i >=
|
|
1184
|
+
if (i >= at) return;
|
|
1137
1185
|
this.perTrack.set(t, i + 1);
|
|
1138
1186
|
let a = new AbortController(), o = {
|
|
1139
1187
|
started: performance.now(),
|
|
@@ -1147,10 +1195,10 @@ var rt = class {
|
|
|
1147
1195
|
signal: a.signal
|
|
1148
1196
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1149
1197
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1150
|
-
},
|
|
1198
|
+
}, rt);
|
|
1151
1199
|
}
|
|
1152
1200
|
take(e) {
|
|
1153
|
-
let t =
|
|
1201
|
+
let t = ot(e), n = this.entries.get(t);
|
|
1154
1202
|
return n && this.entries.delete(t), n;
|
|
1155
1203
|
}
|
|
1156
1204
|
destroy() {
|
|
@@ -1170,13 +1218,13 @@ var rt = class {
|
|
|
1170
1218
|
}
|
|
1171
1219
|
}
|
|
1172
1220
|
};
|
|
1173
|
-
function
|
|
1221
|
+
function ct(t) {
|
|
1174
1222
|
let n = e.DefaultConfig?.loader;
|
|
1175
1223
|
if (typeof n != "function") return;
|
|
1176
1224
|
class r extends n {
|
|
1177
1225
|
served = !1;
|
|
1178
1226
|
cancelled = !1;
|
|
1179
|
-
stats =
|
|
1227
|
+
stats = lt();
|
|
1180
1228
|
load(e, n, r) {
|
|
1181
1229
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1182
1230
|
if (!i) {
|
|
@@ -1184,7 +1232,7 @@ function it(t) {
|
|
|
1184
1232
|
return;
|
|
1185
1233
|
}
|
|
1186
1234
|
this.served = !0;
|
|
1187
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1235
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || it, s = setTimeout(() => {
|
|
1188
1236
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1189
1237
|
}, o);
|
|
1190
1238
|
i.bytes.then((o) => {
|
|
@@ -1211,7 +1259,7 @@ function it(t) {
|
|
|
1211
1259
|
}
|
|
1212
1260
|
return r;
|
|
1213
1261
|
}
|
|
1214
|
-
function
|
|
1262
|
+
function lt() {
|
|
1215
1263
|
return {
|
|
1216
1264
|
aborted: !1,
|
|
1217
1265
|
loaded: 0,
|
|
@@ -1235,10 +1283,10 @@ function at() {
|
|
|
1235
1283
|
}
|
|
1236
1284
|
};
|
|
1237
1285
|
}
|
|
1238
|
-
function
|
|
1286
|
+
function ut(e) {
|
|
1239
1287
|
return e === "audio" ? "audio" : "main";
|
|
1240
1288
|
}
|
|
1241
|
-
function
|
|
1289
|
+
function dt(e, t) {
|
|
1242
1290
|
let n = [];
|
|
1243
1291
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1244
1292
|
url: t.initSegment.url,
|
|
@@ -1257,24 +1305,24 @@ function st(e, t) {
|
|
|
1257
1305
|
}
|
|
1258
1306
|
//#endregion
|
|
1259
1307
|
//#region src/core/engine/hls.ts
|
|
1260
|
-
function
|
|
1308
|
+
function ft() {
|
|
1261
1309
|
return e.isSupported();
|
|
1262
1310
|
}
|
|
1263
|
-
var
|
|
1264
|
-
function
|
|
1311
|
+
var pt = 3, mt = 5, ht = 3, gt = 3e4, _t = 12e3, vt = 3e3, yt = 6e3, bt = .5, xt = 3, St = .5, Ct = 1.1, wt = .25, Tt = 5e3, Et = 4e3, Dt = 2, Ot = 5, kt = 2, At = 2, jt = 4, Mt = 4, Nt = 2e3, Pt = 3e4, Ft = .2, It = 30, Lt = 2, Rt = 2, zt = 9, Bt = .5, Vt = 64;
|
|
1312
|
+
function Ht(e) {
|
|
1265
1313
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1266
1314
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1267
1315
|
return;
|
|
1268
1316
|
}
|
|
1269
|
-
e.liveSyncDuration ??=
|
|
1270
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1271
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1317
|
+
e.liveSyncDuration ??= Rt;
|
|
1318
|
+
let t = Math.max(12, e.liveSyncDuration + zt);
|
|
1319
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Ut(e, e.liveSyncDuration);
|
|
1272
1320
|
}
|
|
1273
|
-
function
|
|
1321
|
+
function Ut(e, t) {
|
|
1274
1322
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1275
1323
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1276
1324
|
}
|
|
1277
|
-
var
|
|
1325
|
+
var Wt = class {
|
|
1278
1326
|
name = "hls";
|
|
1279
1327
|
hls = null;
|
|
1280
1328
|
deps;
|
|
@@ -1351,10 +1399,13 @@ var Bt = class {
|
|
|
1351
1399
|
dprMedia = null;
|
|
1352
1400
|
onDprChange = null;
|
|
1353
1401
|
loadStarted;
|
|
1402
|
+
frameCounter;
|
|
1403
|
+
detachFrames = null;
|
|
1354
1404
|
constructor(e) {
|
|
1355
|
-
this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1405
|
+
this.deps = e, this.frameCounter = new H(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1356
1406
|
}
|
|
1357
1407
|
async load() {
|
|
1408
|
+
this.detachFrames ??= this.frameCounter.attach();
|
|
1358
1409
|
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = W(r) && G(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
1359
1410
|
if (e.drmEnabled && !o) {
|
|
1360
1411
|
i({
|
|
@@ -1364,7 +1415,7 @@ var Bt = class {
|
|
|
1364
1415
|
});
|
|
1365
1416
|
return;
|
|
1366
1417
|
}
|
|
1367
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1418
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Pe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1368
1419
|
let e = this.hls;
|
|
1369
1420
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1370
1421
|
let t = e.liveSyncPosition;
|
|
@@ -1387,7 +1438,7 @@ var Bt = class {
|
|
|
1387
1438
|
}
|
|
1388
1439
|
this.loadSuspended = !0;
|
|
1389
1440
|
}
|
|
1390
|
-
},
|
|
1441
|
+
}, Tt));
|
|
1391
1442
|
}
|
|
1392
1443
|
resumeLoading() {
|
|
1393
1444
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1419,7 +1470,7 @@ var Bt = class {
|
|
|
1419
1470
|
let t = e.liveSyncPosition;
|
|
1420
1471
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1421
1472
|
let { video: n } = this.deps;
|
|
1422
|
-
n.currentTime <= t +
|
|
1473
|
+
n.currentTime <= t + Bt || (n.currentTime = t);
|
|
1423
1474
|
}
|
|
1424
1475
|
startHls() {
|
|
1425
1476
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1438,12 +1489,12 @@ var Bt = class {
|
|
|
1438
1489
|
emeEnabled: !0,
|
|
1439
1490
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1440
1491
|
drmSystemOptions: {
|
|
1441
|
-
videoRobustness:
|
|
1442
|
-
audioRobustness:
|
|
1443
|
-
videoEncryptionScheme:
|
|
1444
|
-
audioEncryptionScheme:
|
|
1492
|
+
videoRobustness: F.video,
|
|
1493
|
+
audioRobustness: F.audio,
|
|
1494
|
+
videoEncryptionScheme: F.scheme,
|
|
1495
|
+
audioEncryptionScheme: F.scheme
|
|
1445
1496
|
},
|
|
1446
|
-
...
|
|
1497
|
+
...j() ? { requestMediaKeySystemAccessFunc: P(t) } : {},
|
|
1447
1498
|
licenseXhrSetup: (e, t) => {
|
|
1448
1499
|
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;
|
|
1449
1500
|
let o = performance.now();
|
|
@@ -1460,20 +1511,20 @@ var Bt = class {
|
|
|
1460
1511
|
...c
|
|
1461
1512
|
};
|
|
1462
1513
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
|
|
1463
|
-
let e = new
|
|
1514
|
+
let e = new st({
|
|
1464
1515
|
sessionId: n.analytics?.sid,
|
|
1465
1516
|
contentId: n.matchUrn
|
|
1466
|
-
}), t =
|
|
1517
|
+
}), t = ct(e);
|
|
1467
1518
|
t && (this.prefetch = e, d.fLoader = t);
|
|
1468
1519
|
}
|
|
1469
|
-
|
|
1520
|
+
Ht(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;
|
|
1470
1521
|
let f = new e(d);
|
|
1471
1522
|
if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1472
1523
|
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" });
|
|
1473
1524
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1474
1525
|
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(() => {
|
|
1475
1526
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1476
|
-
},
|
|
1527
|
+
}, gt)));
|
|
1477
1528
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1478
1529
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1479
1530
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1481,10 +1532,10 @@ var Bt = class {
|
|
|
1481
1532
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1482
1533
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1483
1534
|
let i = n?.loading;
|
|
1484
|
-
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 >
|
|
1535
|
+
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Vt && this.requestTimesMs.shift());
|
|
1485
1536
|
let a = t?.frag?.url;
|
|
1486
1537
|
if (a) {
|
|
1487
|
-
let e =
|
|
1538
|
+
let e = B(a);
|
|
1488
1539
|
e && (this.cdnHost = e);
|
|
1489
1540
|
}
|
|
1490
1541
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1498,15 +1549,15 @@ var Bt = class {
|
|
|
1498
1549
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1499
1550
|
let t = this.prefetch;
|
|
1500
1551
|
f.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1501
|
-
let r = n?.frag, i =
|
|
1502
|
-
if (r && t.isActive(i)) for (let e of
|
|
1503
|
-
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1552
|
+
let r = n?.frag, i = ut(r?.type);
|
|
1553
|
+
if (r && t.isActive(i)) for (let e of dt(f, r)) t.prefetch(e.url, i, e.kind);
|
|
1554
|
+
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(ut(n?.frag?.type)));
|
|
1504
1555
|
}
|
|
1505
1556
|
f.on(e.Events.KEY_LOADED, () => {
|
|
1506
1557
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1507
1558
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1508
1559
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1509
|
-
},
|
|
1560
|
+
}, vt), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1510
1561
|
this.renditionSwitches += 1;
|
|
1511
1562
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1512
1563
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1570,7 +1621,7 @@ var Bt = class {
|
|
|
1570
1621
|
return;
|
|
1571
1622
|
}
|
|
1572
1623
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1573
|
-
let t = e > this.sizeCapLevel ?
|
|
1624
|
+
let t = e > this.sizeCapLevel ? Nt : Pt;
|
|
1574
1625
|
this.capTimer = setTimeout(() => {
|
|
1575
1626
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1576
1627
|
}, t);
|
|
@@ -1580,9 +1631,9 @@ var Bt = class {
|
|
|
1580
1631
|
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;
|
|
1581
1632
|
}
|
|
1582
1633
|
dropLevelsWidevineCannotPlay(e) {
|
|
1583
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1584
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1585
|
-
for (let n of t)
|
|
1634
|
+
this.removeLevelsWhere(e, (e) => Fe(e) !== !0);
|
|
1635
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && I(e) !== "avc" && !!I(e)));
|
|
1636
|
+
for (let n of t) Ne(n).then((t) => {
|
|
1586
1637
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1587
1638
|
});
|
|
1588
1639
|
}
|
|
@@ -1590,10 +1641,10 @@ var Bt = class {
|
|
|
1590
1641
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1591
1642
|
if (n.forEach((e, n) => {
|
|
1592
1643
|
let a = e.videoCodec;
|
|
1593
|
-
a &&
|
|
1644
|
+
a && I(a) && t(a) && (r.push(n), i.add(a));
|
|
1594
1645
|
}), !r.length) return !1;
|
|
1595
1646
|
let a = [...i].join(", ");
|
|
1596
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !
|
|
1647
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !I(e.videoCodec) || Fe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1597
1648
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1598
1649
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1599
1650
|
}
|
|
@@ -1643,7 +1694,7 @@ var Bt = class {
|
|
|
1643
1694
|
e.widevine && (this.licenseUrl = e.widevine);
|
|
1644
1695
|
}
|
|
1645
1696
|
getStats() {
|
|
1646
|
-
let e = this.hls, t =
|
|
1697
|
+
let e = this.hls, t = this.frameCounter.read(), n = {
|
|
1647
1698
|
droppedFrames: t.dropped,
|
|
1648
1699
|
decodedFrames: t.totalFrames,
|
|
1649
1700
|
lowLatency: this.detectedLowLatency,
|
|
@@ -1691,7 +1742,7 @@ var Bt = class {
|
|
|
1691
1742
|
return;
|
|
1692
1743
|
}
|
|
1693
1744
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1694
|
-
!this.chaseSuspended && e >
|
|
1745
|
+
!this.chaseSuspended && e > yt && this.suspendChasing(), e > _t && this.emitEnded("stalled");
|
|
1695
1746
|
}
|
|
1696
1747
|
resetStarvationWindow() {
|
|
1697
1748
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1706,7 +1757,7 @@ var Bt = class {
|
|
|
1706
1757
|
this.resetStarvationWindow();
|
|
1707
1758
|
return;
|
|
1708
1759
|
}
|
|
1709
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1760
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < yt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Et, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = V(t), c = o - s, l = c !== this.starvedFrames;
|
|
1710
1761
|
if (this.starvedFrames = c, !a || l) {
|
|
1711
1762
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1712
1763
|
return;
|
|
@@ -1715,12 +1766,12 @@ var Bt = class {
|
|
|
1715
1766
|
this.resetStarvationWindow();
|
|
1716
1767
|
return;
|
|
1717
1768
|
}
|
|
1718
|
-
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 >
|
|
1769
|
+
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > jt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= kt && (this.clearKick(), this.starvationRebuilds < At)) {
|
|
1719
1770
|
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");
|
|
1720
1771
|
return;
|
|
1721
1772
|
}
|
|
1722
|
-
let u = i && this.starvedTicks >=
|
|
1723
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1773
|
+
let u = i && this.starvedTicks >= Dt, d = !i && this.deadTicks >= jt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= Mt;
|
|
1774
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= Ot))) {
|
|
1724
1775
|
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");
|
|
1725
1776
|
try {
|
|
1726
1777
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1735,7 +1786,7 @@ var Bt = class {
|
|
|
1735
1786
|
let t = e.latency, n = e.targetLatency;
|
|
1736
1787
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1737
1788
|
let r = t - n;
|
|
1738
|
-
!this.catchUpEngaged && r >
|
|
1789
|
+
!this.catchUpEngaged && r > bt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= bt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1739
1790
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1740
1791
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1741
1792
|
}
|
|
@@ -1756,16 +1807,16 @@ var Bt = class {
|
|
|
1756
1807
|
this.resetFrameDropWindow();
|
|
1757
1808
|
return;
|
|
1758
1809
|
}
|
|
1759
|
-
let { totalFrames: n, dropped: r } =
|
|
1760
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
1810
|
+
let { totalFrames: n, dropped: r } = V(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
1811
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < It || o < 0) {
|
|
1761
1812
|
this.fpsBadTicks = 0;
|
|
1762
1813
|
return;
|
|
1763
1814
|
}
|
|
1764
|
-
if (o <=
|
|
1815
|
+
if (o <= Ft * a) {
|
|
1765
1816
|
this.fpsBadTicks = 0;
|
|
1766
1817
|
return;
|
|
1767
1818
|
}
|
|
1768
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
1819
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < Lt) return;
|
|
1769
1820
|
this.fpsBadTicks = 0;
|
|
1770
1821
|
let s = e.levels, c = s[e.currentLevel];
|
|
1771
1822
|
if (!c) return;
|
|
@@ -1782,20 +1833,20 @@ var Bt = class {
|
|
|
1782
1833
|
return;
|
|
1783
1834
|
}
|
|
1784
1835
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
1785
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
1836
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Ct, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
1786
1837
|
this.resetChaseWindow();
|
|
1787
1838
|
return;
|
|
1788
1839
|
}
|
|
1789
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
1840
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= St) {
|
|
1790
1841
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
1791
1842
|
return;
|
|
1792
1843
|
}
|
|
1793
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
1844
|
+
if (this.chaseTicks += 1, this.chaseTicks < xt) return;
|
|
1794
1845
|
this.resetChaseWindow();
|
|
1795
1846
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
1796
1847
|
if (!(a > 1)) return;
|
|
1797
1848
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
1798
|
-
s < o +
|
|
1849
|
+
s < o + wt || (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);
|
|
1799
1850
|
}
|
|
1800
1851
|
suspendChasing() {
|
|
1801
1852
|
let e = this.hls;
|
|
@@ -1825,7 +1876,7 @@ var Bt = class {
|
|
|
1825
1876
|
} catch {}
|
|
1826
1877
|
}
|
|
1827
1878
|
destroy() {
|
|
1828
|
-
if (this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
|
|
1879
|
+
if (this.detachFrames?.(), this.detachFrames = null, this.prefetch?.destroy(), this.prefetch = null, this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onTimeUpdate &&= (this.deps.video.removeEventListener("timeupdate", this.onTimeUpdate), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
|
|
1829
1880
|
try {
|
|
1830
1881
|
this.hls.destroy();
|
|
1831
1882
|
} catch (e) {
|
|
@@ -1840,7 +1891,7 @@ var Bt = class {
|
|
|
1840
1891
|
scheduleLicenseRetry(t) {
|
|
1841
1892
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1842
1893
|
let n = t.response?.code ?? 0;
|
|
1843
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1894
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= ht) return !1;
|
|
1844
1895
|
this.licenseRecoveries += 1;
|
|
1845
1896
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1846
1897
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1872,7 +1923,7 @@ var Bt = class {
|
|
|
1872
1923
|
return;
|
|
1873
1924
|
}
|
|
1874
1925
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1875
|
-
if (this.networkRecoveries <
|
|
1926
|
+
if (this.networkRecoveries < mt) {
|
|
1876
1927
|
this.networkRecoveries += 1;
|
|
1877
1928
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1878
1929
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1889,7 +1940,7 @@ var Bt = class {
|
|
|
1889
1940
|
return;
|
|
1890
1941
|
}
|
|
1891
1942
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1892
|
-
if (this.mediaRecoveries <
|
|
1943
|
+
if (this.mediaRecoveries < pt) {
|
|
1893
1944
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1894
1945
|
return;
|
|
1895
1946
|
}
|
|
@@ -1913,19 +1964,19 @@ var Bt = class {
|
|
|
1913
1964
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1914
1965
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1915
1966
|
}
|
|
1916
|
-
},
|
|
1967
|
+
}, Gt = 15e3, Kt = 6e5, qt = 3e5, Jt = 100, q = 1, Yt = 1e3, Xt = 3e4, Zt = 1e3, Qt = {
|
|
1917
1968
|
inline: "PRESENTATION_INLINE",
|
|
1918
1969
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1919
1970
|
pip: "PRESENTATION_PIP"
|
|
1920
|
-
},
|
|
1971
|
+
}, $t = {
|
|
1921
1972
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1922
1973
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1923
1974
|
none: "KEY_SYSTEM_NONE"
|
|
1924
1975
|
};
|
|
1925
|
-
function
|
|
1976
|
+
function en(e, t) {
|
|
1926
1977
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1927
1978
|
}
|
|
1928
|
-
var
|
|
1979
|
+
var tn = /* @__PURE__ */ new Set([
|
|
1929
1980
|
"INVALID_URN",
|
|
1930
1981
|
"NOT_FOUND",
|
|
1931
1982
|
"GONE",
|
|
@@ -1945,7 +1996,7 @@ var Zt = /* @__PURE__ */ new Set([
|
|
|
1945
1996
|
ended: "PLAYER_STATE_ENDED",
|
|
1946
1997
|
error: "PLAYER_STATE_ERROR"
|
|
1947
1998
|
};
|
|
1948
|
-
function
|
|
1999
|
+
function nn(e) {
|
|
1949
2000
|
try {
|
|
1950
2001
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1951
2002
|
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);
|
|
@@ -1953,8 +2004,8 @@ function Qt(e) {
|
|
|
1953
2004
|
return;
|
|
1954
2005
|
}
|
|
1955
2006
|
}
|
|
1956
|
-
var
|
|
1957
|
-
function
|
|
2007
|
+
var rn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), an = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), on = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2008
|
+
function sn(e) {
|
|
1958
2009
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
1959
2010
|
let t;
|
|
1960
2011
|
try {
|
|
@@ -1963,19 +2014,19 @@ function nn(e) {
|
|
|
1963
2014
|
} catch {
|
|
1964
2015
|
return;
|
|
1965
2016
|
}
|
|
1966
|
-
if (
|
|
1967
|
-
Y.add(t), g(
|
|
2017
|
+
if (an.has(t) && !Y.has(t)) {
|
|
2018
|
+
Y.add(t), g(on(new URL(t).origin));
|
|
1968
2019
|
for (let e of X) e.noteCspBlocked();
|
|
1969
2020
|
}
|
|
1970
2021
|
}
|
|
1971
|
-
function
|
|
2022
|
+
function cn(e, t) {
|
|
1972
2023
|
return g(t, e), { disabledReason: t };
|
|
1973
2024
|
}
|
|
1974
|
-
function
|
|
1975
|
-
if (n) return t &&
|
|
2025
|
+
function ln(e, t, n) {
|
|
2026
|
+
if (n) return t && !rn(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
1976
2027
|
if (t) return { endpoint: t };
|
|
1977
|
-
if (t !== void 0) return
|
|
1978
|
-
let r =
|
|
2028
|
+
if (t !== void 0) return cn("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).");
|
|
2029
|
+
let r = nn(e);
|
|
1979
2030
|
if (r) return { endpoint: r };
|
|
1980
2031
|
let i;
|
|
1981
2032
|
try {
|
|
@@ -1983,9 +2034,9 @@ function an(e, t, n) {
|
|
|
1983
2034
|
} catch {
|
|
1984
2035
|
i = e;
|
|
1985
2036
|
}
|
|
1986
|
-
return
|
|
2037
|
+
return cn(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).`);
|
|
1987
2038
|
}
|
|
1988
|
-
var
|
|
2039
|
+
var un = class {
|
|
1989
2040
|
opts;
|
|
1990
2041
|
url;
|
|
1991
2042
|
cspKey;
|
|
@@ -2067,8 +2118,8 @@ var on = class {
|
|
|
2067
2118
|
constructor(e) {
|
|
2068
2119
|
this.opts = {
|
|
2069
2120
|
...e,
|
|
2070
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2071
|
-
idleMs: e.idleMs ??
|
|
2121
|
+
heartbeatMs: e.heartbeatMs ?? Gt,
|
|
2122
|
+
idleMs: e.idleMs ?? Kt
|
|
2072
2123
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2073
2124
|
try {
|
|
2074
2125
|
let e = new URL(this.url);
|
|
@@ -2085,11 +2136,11 @@ var on = class {
|
|
|
2085
2136
|
sdkVersion: this.opts.sdkVersion,
|
|
2086
2137
|
...this.opts.environment
|
|
2087
2138
|
};
|
|
2088
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2139
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), Yt), 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 && an.add(this.cspKey), document.addEventListener("securitypolicyviolation", sn), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2089
2140
|
}
|
|
2090
2141
|
checkSuspension(e) {
|
|
2091
2142
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2092
|
-
let t = Math.max(this.opts.idleMs,
|
|
2143
|
+
let t = Math.max(this.opts.idleMs, qt);
|
|
2093
2144
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2094
2145
|
}
|
|
2095
2146
|
syncIdle(e) {
|
|
@@ -2112,12 +2163,12 @@ var on = class {
|
|
|
2112
2163
|
let a = {
|
|
2113
2164
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2114
2165
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2115
|
-
presentation:
|
|
2166
|
+
presentation: Qt[this.presentation]
|
|
2116
2167
|
}, o = this.causeOf(e, t, i);
|
|
2117
2168
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2118
2169
|
}
|
|
2119
2170
|
seekInduced(e) {
|
|
2120
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2171
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < Zt;
|
|
2121
2172
|
}
|
|
2122
2173
|
causeOf(e, t, n) {
|
|
2123
2174
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2191,7 +2242,7 @@ var on = class {
|
|
|
2191
2242
|
let r = n ?? "";
|
|
2192
2243
|
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";
|
|
2193
2244
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2194
|
-
if (
|
|
2245
|
+
if (tn.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2195
2246
|
let i = t ?? "";
|
|
2196
2247
|
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";
|
|
2197
2248
|
}
|
|
@@ -2238,14 +2289,14 @@ var on = class {
|
|
|
2238
2289
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2239
2290
|
o.requestCountDelta = _;
|
|
2240
2291
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2241
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2292
|
+
n.length > 0 && (o.requestTimeP50Ms = en(n, 50), o.requestTimeP95Ms = en(n, 95));
|
|
2242
2293
|
}
|
|
2243
2294
|
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();
|
|
2244
2295
|
}
|
|
2245
2296
|
maybeEmitMediaInfo(e) {
|
|
2246
2297
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2247
2298
|
let t = {};
|
|
2248
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2299
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = $t[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);
|
|
2249
2300
|
let n = JSON.stringify(t);
|
|
2250
2301
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2251
2302
|
}
|
|
@@ -2265,7 +2316,7 @@ var on = class {
|
|
|
2265
2316
|
let c = r?.positionMs ?? 0;
|
|
2266
2317
|
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));
|
|
2267
2318
|
let l = e !== "END_REASON_ENDED";
|
|
2268
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2319
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= Xt && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Xt && (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);
|
|
2269
2320
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2270
2321
|
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");
|
|
2271
2322
|
}
|
|
@@ -2285,13 +2336,13 @@ var on = class {
|
|
|
2285
2336
|
};
|
|
2286
2337
|
}
|
|
2287
2338
|
noteCspBlocked() {
|
|
2288
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2339
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(on(new URL(this.url).origin)));
|
|
2289
2340
|
}
|
|
2290
2341
|
cspBlocked() {
|
|
2291
2342
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2292
2343
|
}
|
|
2293
2344
|
enqueue(e) {
|
|
2294
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2345
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > Jt;) {
|
|
2295
2346
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2296
2347
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2297
2348
|
}
|
|
@@ -2318,7 +2369,7 @@ var on = class {
|
|
|
2318
2369
|
};
|
|
2319
2370
|
//#endregion
|
|
2320
2371
|
//#region src/core/environment.ts
|
|
2321
|
-
function
|
|
2372
|
+
function dn() {
|
|
2322
2373
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2323
2374
|
let e;
|
|
2324
2375
|
try {
|
|
@@ -2343,14 +2394,14 @@ function sn() {
|
|
|
2343
2394
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2344
2395
|
};
|
|
2345
2396
|
}
|
|
2346
|
-
function
|
|
2397
|
+
function fn() {
|
|
2347
2398
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2348
2399
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2349
2400
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2350
2401
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2351
2402
|
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";
|
|
2352
2403
|
}
|
|
2353
|
-
function
|
|
2404
|
+
function pn() {
|
|
2354
2405
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2355
2406
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2356
2407
|
let t = {
|
|
@@ -2369,17 +2420,17 @@ function ln() {
|
|
|
2369
2420
|
}
|
|
2370
2421
|
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;
|
|
2371
2422
|
}
|
|
2372
|
-
function
|
|
2373
|
-
let t =
|
|
2374
|
-
deviceClass:
|
|
2423
|
+
function mn(e) {
|
|
2424
|
+
let t = dn(), n = {
|
|
2425
|
+
deviceClass: fn(),
|
|
2375
2426
|
integration: t.integration,
|
|
2376
|
-
...
|
|
2427
|
+
...pn()
|
|
2377
2428
|
};
|
|
2378
2429
|
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);
|
|
2379
2430
|
let r = e.getBoundingClientRect?.();
|
|
2380
2431
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2381
2432
|
}
|
|
2382
|
-
async function
|
|
2433
|
+
async function hn() {
|
|
2383
2434
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2384
2435
|
if (!e?.getHighEntropyValues) return {};
|
|
2385
2436
|
try {
|
|
@@ -2391,7 +2442,7 @@ async function dn() {
|
|
|
2391
2442
|
}
|
|
2392
2443
|
//#endregion
|
|
2393
2444
|
//#region src/core/version.ts
|
|
2394
|
-
var
|
|
2445
|
+
var gn = "2.16.3", _n = {
|
|
2395
2446
|
accent: "#E1B600",
|
|
2396
2447
|
accentText: "#1B1C23",
|
|
2397
2448
|
background: "#0e0f13",
|
|
@@ -2402,7 +2453,7 @@ var fn = "2.16.1", pn = {
|
|
|
2402
2453
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2403
2454
|
radius: "8px",
|
|
2404
2455
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2405
|
-
},
|
|
2456
|
+
}, vn = {
|
|
2406
2457
|
accent: "--havik-accent",
|
|
2407
2458
|
accentText: "--havik-accent-text",
|
|
2408
2459
|
background: "--havik-bg",
|
|
@@ -2414,26 +2465,26 @@ var fn = "2.16.1", pn = {
|
|
|
2414
2465
|
radius: "--havik-radius",
|
|
2415
2466
|
fontFamily: "--havik-font"
|
|
2416
2467
|
};
|
|
2417
|
-
function
|
|
2468
|
+
function Z(e, t) {
|
|
2418
2469
|
let n = {
|
|
2419
|
-
...
|
|
2470
|
+
..._n,
|
|
2420
2471
|
...t
|
|
2421
2472
|
};
|
|
2422
|
-
for (let t of Object.keys(
|
|
2473
|
+
for (let t of Object.keys(vn)) e.style.setProperty(vn[t], n[t]);
|
|
2423
2474
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2424
2475
|
}
|
|
2425
2476
|
//#endregion
|
|
2426
2477
|
//#region src/ui/styles.ts
|
|
2427
|
-
var
|
|
2428
|
-
function
|
|
2429
|
-
let n = e.querySelector(`style#${
|
|
2430
|
-
if (n && (!t ||
|
|
2478
|
+
var yn = "havik-player-styles", bn = "\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", xn = /* @__PURE__ */ new WeakMap();
|
|
2479
|
+
function Sn(e = document, t) {
|
|
2480
|
+
let n = e.querySelector(`style#${yn}`);
|
|
2481
|
+
if (n && (!t || xn.get(n) === t)) return;
|
|
2431
2482
|
let r = e.createElement("style");
|
|
2432
|
-
r.id =
|
|
2483
|
+
r.id = yn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = bn, xn.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2433
2484
|
}
|
|
2434
2485
|
//#endregion
|
|
2435
2486
|
//#region src/ui/icons.ts
|
|
2436
|
-
var
|
|
2487
|
+
var Cn = {
|
|
2437
2488
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2438
2489
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2439
2490
|
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\"/>",
|
|
@@ -2447,20 +2498,20 @@ var yn = {
|
|
|
2447
2498
|
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\"/>"
|
|
2448
2499
|
};
|
|
2449
2500
|
function Q(e) {
|
|
2450
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2501
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Cn[e]}</svg>`;
|
|
2451
2502
|
}
|
|
2452
2503
|
//#endregion
|
|
2453
2504
|
//#region src/ui/controls.ts
|
|
2454
|
-
var
|
|
2505
|
+
var wn = 3e3, Tn = 250, En = /* @__PURE__ */ new Set([
|
|
2455
2506
|
"GONE",
|
|
2456
2507
|
"NOT_FOUND",
|
|
2457
2508
|
"INVALID_URN",
|
|
2458
2509
|
"UNAUTHORIZED"
|
|
2459
2510
|
]);
|
|
2460
|
-
function
|
|
2461
|
-
return new
|
|
2511
|
+
function Dn(e) {
|
|
2512
|
+
return new On(e);
|
|
2462
2513
|
}
|
|
2463
|
-
var
|
|
2514
|
+
var On = class {
|
|
2464
2515
|
root;
|
|
2465
2516
|
video;
|
|
2466
2517
|
player;
|
|
@@ -2506,7 +2557,7 @@ var wn = class {
|
|
|
2506
2557
|
scrubbing = !1;
|
|
2507
2558
|
offFns = [];
|
|
2508
2559
|
constructor(e) {
|
|
2509
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2560
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? wn, 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, Sn(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");
|
|
2510
2561
|
let t = (e, t, n) => {
|
|
2511
2562
|
let r = this.doc.createElement(e);
|
|
2512
2563
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2592,7 +2643,7 @@ var wn = class {
|
|
|
2592
2643
|
let t = this.surfaceWasHidden;
|
|
2593
2644
|
this.tapTimer = setTimeout(() => {
|
|
2594
2645
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2595
|
-
},
|
|
2646
|
+
}, Tn);
|
|
2596
2647
|
}
|
|
2597
2648
|
toggleBar(e) {
|
|
2598
2649
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2627,7 +2678,7 @@ var wn = class {
|
|
|
2627
2678
|
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);
|
|
2628
2679
|
} else {
|
|
2629
2680
|
let r = this.doc.createElement("div");
|
|
2630
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2681
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !En.has(this.lastError.code)) {
|
|
2631
2682
|
let e = this.doc.createElement("button");
|
|
2632
2683
|
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);
|
|
2633
2684
|
}
|
|
@@ -2668,7 +2719,7 @@ var wn = class {
|
|
|
2668
2719
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2669
2720
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2670
2721
|
}
|
|
2671
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2722
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${kn(this.video.currentTime)} / ${kn(this.video.duration)}`);
|
|
2672
2723
|
}
|
|
2673
2724
|
syncLive() {
|
|
2674
2725
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2718,17 +2769,17 @@ var wn = class {
|
|
|
2718
2769
|
renderQualityMenu() {
|
|
2719
2770
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2720
2771
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2721
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2772
|
+
for (let n of e) this.menu.append(this.menuItem(An(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2722
2773
|
}
|
|
2723
2774
|
renderAudioMenu() {
|
|
2724
2775
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2725
2776
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2726
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2777
|
+
for (let t of e) this.menu.append(this.menuItem(jn(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2727
2778
|
}
|
|
2728
2779
|
renderCcMenu() {
|
|
2729
2780
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2730
2781
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2731
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2782
|
+
for (let t of e) this.menu.append(this.menuItem(Mn(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2732
2783
|
}
|
|
2733
2784
|
onTracksChanged() {
|
|
2734
2785
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2748,11 +2799,11 @@ var wn = class {
|
|
|
2748
2799
|
}
|
|
2749
2800
|
async toggleFullscreen() {
|
|
2750
2801
|
try {
|
|
2751
|
-
|
|
2802
|
+
S(this.video, this.root) ? await w(this.video, this.root) : await C(this.video, this.root);
|
|
2752
2803
|
} catch {}
|
|
2753
2804
|
}
|
|
2754
2805
|
syncFullscreen() {
|
|
2755
|
-
let e =
|
|
2806
|
+
let e = S(this.video, this.root);
|
|
2756
2807
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
2757
2808
|
}
|
|
2758
2809
|
poke() {
|
|
@@ -2829,41 +2880,41 @@ var wn = class {
|
|
|
2829
2880
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2830
2881
|
}
|
|
2831
2882
|
};
|
|
2832
|
-
function
|
|
2883
|
+
function kn(e) {
|
|
2833
2884
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2834
2885
|
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");
|
|
2835
2886
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2836
2887
|
}
|
|
2837
|
-
function
|
|
2888
|
+
function An(e) {
|
|
2838
2889
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2839
2890
|
}
|
|
2840
|
-
function
|
|
2891
|
+
function jn(e) {
|
|
2841
2892
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2842
2893
|
}
|
|
2843
|
-
function
|
|
2894
|
+
function Mn(e) {
|
|
2844
2895
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2845
2896
|
}
|
|
2846
2897
|
//#endregion
|
|
2847
2898
|
//#region src/managed/index.ts
|
|
2848
|
-
var
|
|
2849
|
-
function
|
|
2899
|
+
var Nn = 6e3, Pn = 45e3, Fn = 2e3, In = 3, Ln = 2e3, Rn = 48e4;
|
|
2900
|
+
function zn(e) {
|
|
2850
2901
|
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)})`);
|
|
2851
|
-
if (e.env !== void 0) return
|
|
2902
|
+
if (e.env !== void 0) return Ke(e.env);
|
|
2852
2903
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2853
2904
|
return e.baseUrl;
|
|
2854
2905
|
}
|
|
2855
|
-
async function
|
|
2906
|
+
async function Bn(e) {
|
|
2856
2907
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2857
|
-
let t =
|
|
2908
|
+
let t = zn(e);
|
|
2858
2909
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2859
2910
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2860
|
-
let r = new
|
|
2911
|
+
let r = new Vn({
|
|
2861
2912
|
...e,
|
|
2862
2913
|
baseUrl: t
|
|
2863
2914
|
});
|
|
2864
2915
|
return await r.start(), r;
|
|
2865
2916
|
}
|
|
2866
|
-
var
|
|
2917
|
+
var Vn = class {
|
|
2867
2918
|
opts;
|
|
2868
2919
|
abort = new AbortController();
|
|
2869
2920
|
listeners = {};
|
|
@@ -2907,7 +2958,7 @@ var Ln = class {
|
|
|
2907
2958
|
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");
|
|
2908
2959
|
let e = ++this.loadGen, t = this.resolveOptions();
|
|
2909
2960
|
try {
|
|
2910
|
-
let n = await
|
|
2961
|
+
let n = await v(t);
|
|
2911
2962
|
if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
|
|
2912
2963
|
let e = this._lastError;
|
|
2913
2964
|
throw this.destroy(), e;
|
|
@@ -2930,11 +2981,11 @@ var Ln = class {
|
|
|
2930
2981
|
};
|
|
2931
2982
|
}
|
|
2932
2983
|
beginArming(e, t, n = !1) {
|
|
2933
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
2984
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
|
|
2934
2985
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
2935
2986
|
}
|
|
2936
2987
|
beginArmingByPolling(e) {
|
|
2937
|
-
|
|
2988
|
+
y({
|
|
2938
2989
|
...this.resolveOptions(),
|
|
2939
2990
|
signal: this.abort.signal,
|
|
2940
2991
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -2951,7 +3002,7 @@ var Ln = class {
|
|
|
2951
3002
|
setTimeout(() => {
|
|
2952
3003
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
2953
3004
|
phase: i ? "unavailable" : "tooEarly",
|
|
2954
|
-
retryInMs:
|
|
3005
|
+
retryInMs: Pn,
|
|
2955
3006
|
attempt: 1,
|
|
2956
3007
|
elapsedMs: 0,
|
|
2957
3008
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -2968,7 +3019,7 @@ var Ln = class {
|
|
|
2968
3019
|
}
|
|
2969
3020
|
}
|
|
2970
3021
|
}, h = () => {
|
|
2971
|
-
a || s || p() || (s = !0,
|
|
3022
|
+
a || s || p() || (s = !0, y({
|
|
2972
3023
|
...this.resolveOptions(),
|
|
2973
3024
|
signal: c.signal,
|
|
2974
3025
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -2976,7 +3027,7 @@ var Ln = class {
|
|
|
2976
3027
|
a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
|
|
2977
3028
|
}));
|
|
2978
3029
|
}, g = () => {
|
|
2979
|
-
a || p() ||
|
|
3030
|
+
a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
|
|
2980
3031
|
if (!(a || p())) {
|
|
2981
3032
|
if (e instanceof n && o(e.code)) {
|
|
2982
3033
|
h();
|
|
@@ -2990,13 +3041,13 @@ var Ln = class {
|
|
|
2990
3041
|
!a && !p() && h();
|
|
2991
3042
|
}, e);
|
|
2992
3043
|
};
|
|
2993
|
-
_(
|
|
3044
|
+
_(Nn), this.armingSub = T({
|
|
2994
3045
|
eventsBaseUrl: t,
|
|
2995
3046
|
matchUrn: this.opts.matchUrn,
|
|
2996
3047
|
credential: this.opts.credential,
|
|
2997
|
-
onAlive: () => _(
|
|
3048
|
+
onAlive: () => _(Pn),
|
|
2998
3049
|
onState: (e) => {
|
|
2999
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3050
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Fn);
|
|
3000
3051
|
},
|
|
3001
3052
|
onError: () => h()
|
|
3002
3053
|
});
|
|
@@ -3019,7 +3070,7 @@ var Ln = class {
|
|
|
3019
3070
|
let n = await s(this.opts.credential);
|
|
3020
3071
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3021
3072
|
this.setState("loading");
|
|
3022
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3073
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = Ye(this.opts.video, (e) => {
|
|
3023
3074
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3024
3075
|
});
|
|
3025
3076
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3041,26 +3092,26 @@ var Ln = class {
|
|
|
3041
3092
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3042
3093
|
let i = e.analytics?.sid;
|
|
3043
3094
|
if (!i) return;
|
|
3044
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3095
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = ln(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3045
3096
|
if (!o) {
|
|
3046
3097
|
s && setTimeout(() => {
|
|
3047
3098
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3048
3099
|
}, 0);
|
|
3049
3100
|
return;
|
|
3050
3101
|
}
|
|
3051
|
-
let c = this.opts.video, l = new
|
|
3102
|
+
let c = this.opts.video, l = new un({
|
|
3052
3103
|
endpoint: o,
|
|
3053
3104
|
sid: i,
|
|
3054
3105
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3055
|
-
sdkVersion:
|
|
3056
|
-
environment:
|
|
3106
|
+
sdkVersion: gn,
|
|
3107
|
+
environment: mn(c),
|
|
3057
3108
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3058
3109
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3059
3110
|
onBlocked: (e) => setTimeout(() => {
|
|
3060
3111
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3061
3112
|
}, 0),
|
|
3062
3113
|
sample: () => {
|
|
3063
|
-
let e = this.engine?.getStats() ??
|
|
3114
|
+
let e = this.engine?.getStats() ?? z, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3064
3115
|
return {
|
|
3065
3116
|
...e,
|
|
3066
3117
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3074,7 +3125,7 @@ var Ln = class {
|
|
|
3074
3125
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3075
3126
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3076
3127
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3077
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3128
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), hn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3078
3129
|
}
|
|
3079
3130
|
currentPresentation() {
|
|
3080
3131
|
let e = this.opts.video;
|
|
@@ -3089,7 +3140,7 @@ var Ln = class {
|
|
|
3089
3140
|
video: this.opts.video,
|
|
3090
3141
|
descriptor: e,
|
|
3091
3142
|
credential: t,
|
|
3092
|
-
deviceId:
|
|
3143
|
+
deviceId: k(),
|
|
3093
3144
|
userId: this.opts.userId,
|
|
3094
3145
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
3095
3146
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -3100,9 +3151,9 @@ var Ln = class {
|
|
|
3100
3151
|
emit: (e) => this.onEngineEvent(e)
|
|
3101
3152
|
}, o = this.opts.engine ?? "auto";
|
|
3102
3153
|
if (o === "native") return new K(a);
|
|
3103
|
-
if (o === "hls") return new
|
|
3104
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G() || !e.drmEnabled &&
|
|
3105
|
-
if (
|
|
3154
|
+
if (o === "hls") return new Wt(a);
|
|
3155
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && W(this.opts.video) && G() || !e.drmEnabled && tt() && W(this.opts.video)) return new K(a);
|
|
3156
|
+
if (ft()) return new Wt(a);
|
|
3106
3157
|
if (W(this.opts.video)) return new K(a);
|
|
3107
3158
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3108
3159
|
}
|
|
@@ -3140,11 +3191,11 @@ var Ln = class {
|
|
|
3140
3191
|
}
|
|
3141
3192
|
startLiveState(e) {
|
|
3142
3193
|
if (this.opts.liveStateEvents === !1) return;
|
|
3143
|
-
let t = this.opts.eventsBaseUrl ??
|
|
3194
|
+
let t = this.opts.eventsBaseUrl ?? E(this.opts.baseUrl);
|
|
3144
3195
|
if (!t) return;
|
|
3145
3196
|
this.closeLiveState();
|
|
3146
3197
|
let r = 0, i = !1;
|
|
3147
|
-
this.liveStateSub =
|
|
3198
|
+
this.liveStateSub = T({
|
|
3148
3199
|
eventsBaseUrl: t,
|
|
3149
3200
|
matchUrn: this.opts.matchUrn,
|
|
3150
3201
|
credential: this.opts.credential,
|
|
@@ -3155,7 +3206,7 @@ var Ln = class {
|
|
|
3155
3206
|
r = 0, i = !1;
|
|
3156
3207
|
},
|
|
3157
3208
|
onError: () => {
|
|
3158
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
3209
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= In && (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.`))));
|
|
3159
3210
|
}
|
|
3160
3211
|
});
|
|
3161
3212
|
}
|
|
@@ -3177,7 +3228,7 @@ var Ln = class {
|
|
|
3177
3228
|
scheduleRejoin(e) {
|
|
3178
3229
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3179
3230
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3180
|
-
}, Math.random() *
|
|
3231
|
+
}, Math.random() * Fn));
|
|
3181
3232
|
}
|
|
3182
3233
|
cancelRejoin() {
|
|
3183
3234
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3201,7 +3252,7 @@ var Ln = class {
|
|
|
3201
3252
|
}
|
|
3202
3253
|
t.controls = !1;
|
|
3203
3254
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3204
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3255
|
+
r && r.insertBefore(n, t), n.appendChild(t), Z(n, this.opts.theme), this.container = n, this.controlBar = Dn({
|
|
3205
3256
|
root: n,
|
|
3206
3257
|
video: t,
|
|
3207
3258
|
player: this,
|
|
@@ -3232,7 +3283,7 @@ var Ln = class {
|
|
|
3232
3283
|
}
|
|
3233
3284
|
startStats() {
|
|
3234
3285
|
this.stopStats();
|
|
3235
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3286
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Ln);
|
|
3236
3287
|
this.statsTimer = setInterval(() => {
|
|
3237
3288
|
if (!this.engine) return;
|
|
3238
3289
|
let e = this.engine.getStats();
|
|
@@ -3244,7 +3295,7 @@ var Ln = class {
|
|
|
3244
3295
|
}
|
|
3245
3296
|
scheduleLicenseRefresh() {
|
|
3246
3297
|
this.stopRefresh();
|
|
3247
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3298
|
+
let e = this.opts.licenseRefreshMs ?? Rn;
|
|
3248
3299
|
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3249
3300
|
}
|
|
3250
3301
|
stopRefresh() {
|
|
@@ -3253,7 +3304,7 @@ var Ln = class {
|
|
|
3253
3304
|
async refreshLicense() {
|
|
3254
3305
|
let e = this.engine;
|
|
3255
3306
|
if (!this.destroyed && e) try {
|
|
3256
|
-
let t = await
|
|
3307
|
+
let t = await v(this.resolveOptions());
|
|
3257
3308
|
if (this.destroyed || this.engine !== e) return;
|
|
3258
3309
|
let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
|
|
3259
3310
|
(n || r) && (e.setLicenseUrls({
|
|
@@ -3289,7 +3340,7 @@ var Ln = class {
|
|
|
3289
3340
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3290
3341
|
}
|
|
3291
3342
|
getStats() {
|
|
3292
|
-
return this.engine?.getStats() ??
|
|
3343
|
+
return this.engine?.getStats() ?? z;
|
|
3293
3344
|
}
|
|
3294
3345
|
getQualityLevels() {
|
|
3295
3346
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3328,10 +3379,10 @@ var Ln = class {
|
|
|
3328
3379
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
3329
3380
|
}
|
|
3330
3381
|
async enterFullscreen() {
|
|
3331
|
-
return !this.destroyed &&
|
|
3382
|
+
return !this.destroyed && C(this.opts.video, this.container ?? void 0);
|
|
3332
3383
|
}
|
|
3333
3384
|
async exitFullscreen() {
|
|
3334
|
-
await
|
|
3385
|
+
await w(this.opts.video, this.container ?? void 0);
|
|
3335
3386
|
}
|
|
3336
3387
|
retry() {
|
|
3337
3388
|
return this.reload();
|
|
@@ -3341,7 +3392,7 @@ var Ln = class {
|
|
|
3341
3392
|
let e = ++this.loadGen;
|
|
3342
3393
|
this.teardownPlayback();
|
|
3343
3394
|
try {
|
|
3344
|
-
let t = await
|
|
3395
|
+
let t = await y({
|
|
3345
3396
|
...this.resolveOptions(),
|
|
3346
3397
|
waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
|
|
3347
3398
|
});
|
|
@@ -3399,7 +3450,7 @@ function $(e) {
|
|
|
3399
3450
|
}
|
|
3400
3451
|
//#endregion
|
|
3401
3452
|
//#region src/embed/host.ts
|
|
3402
|
-
function
|
|
3453
|
+
function Hn(e) {
|
|
3403
3454
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3404
3455
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3405
3456
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3458,15 +3509,15 @@ function Rn(e) {
|
|
|
3458
3509
|
}
|
|
3459
3510
|
//#endregion
|
|
3460
3511
|
//#region src/embed/page.ts
|
|
3461
|
-
var
|
|
3462
|
-
function
|
|
3512
|
+
var Un = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3513
|
+
function Wn(e) {
|
|
3463
3514
|
if (typeof e == "boolean") return e;
|
|
3464
3515
|
if (typeof e == "object" && e) {
|
|
3465
3516
|
let t = e.endpoint;
|
|
3466
3517
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3467
3518
|
}
|
|
3468
3519
|
}
|
|
3469
|
-
function
|
|
3520
|
+
function Gn() {
|
|
3470
3521
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3471
3522
|
if (e) return {
|
|
3472
3523
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3476,7 +3527,7 @@ function Vn() {
|
|
|
3476
3527
|
autoplay: e.autoplay ?? !0,
|
|
3477
3528
|
muted: e.muted ?? !0,
|
|
3478
3529
|
waitForLive: e.waitForLive ?? !0,
|
|
3479
|
-
analytics:
|
|
3530
|
+
analytics: Wn(e.analytics)
|
|
3480
3531
|
};
|
|
3481
3532
|
let t = new URLSearchParams(location.search);
|
|
3482
3533
|
return {
|
|
@@ -3489,9 +3540,9 @@ function Vn() {
|
|
|
3489
3540
|
waitForLive: !0
|
|
3490
3541
|
};
|
|
3491
3542
|
}
|
|
3492
|
-
async function
|
|
3493
|
-
let e =
|
|
3494
|
-
|
|
3543
|
+
async function Kn() {
|
|
3544
|
+
let e = Gn();
|
|
3545
|
+
Jn();
|
|
3495
3546
|
let t = document.createElement("video");
|
|
3496
3547
|
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);
|
|
3497
3548
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3546,12 +3597,12 @@ async function Hn() {
|
|
|
3546
3597
|
code: e.code,
|
|
3547
3598
|
message: e.message
|
|
3548
3599
|
})), e.on("autoplayblocked", () => {
|
|
3549
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3600
|
+
i({ type: "oddin:autoplayblocked" }), qn(t, e);
|
|
3550
3601
|
});
|
|
3551
3602
|
}, s = async (r) => {
|
|
3552
3603
|
a?.destroy(), a = null;
|
|
3553
3604
|
try {
|
|
3554
|
-
let n = await
|
|
3605
|
+
let n = await Bn({
|
|
3555
3606
|
video: t,
|
|
3556
3607
|
baseUrl: e.baseUrl,
|
|
3557
3608
|
matchUrn: r,
|
|
@@ -3613,7 +3664,7 @@ async function Hn() {
|
|
|
3613
3664
|
a?.retry();
|
|
3614
3665
|
break;
|
|
3615
3666
|
case "oddin:load":
|
|
3616
|
-
typeof e.matchUrn == "string" &&
|
|
3667
|
+
typeof e.matchUrn == "string" && Un.test(e.matchUrn) && s(e.matchUrn);
|
|
3617
3668
|
break;
|
|
3618
3669
|
case "oddin:destroy": c();
|
|
3619
3670
|
}
|
|
@@ -3625,18 +3676,18 @@ async function Hn() {
|
|
|
3625
3676
|
protocol: 1
|
|
3626
3677
|
});
|
|
3627
3678
|
}
|
|
3628
|
-
function
|
|
3679
|
+
function qn(e, t) {
|
|
3629
3680
|
if (document.getElementById("havik-tap")) return;
|
|
3630
3681
|
let n = document.createElement("button");
|
|
3631
3682
|
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", () => {
|
|
3632
3683
|
n.remove(), t.play();
|
|
3633
3684
|
}), document.body.appendChild(n);
|
|
3634
3685
|
}
|
|
3635
|
-
function
|
|
3686
|
+
function Jn() {
|
|
3636
3687
|
let e = document.createElement("style");
|
|
3637
3688
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3638
3689
|
}
|
|
3639
3690
|
//#endregion
|
|
3640
|
-
export {
|
|
3691
|
+
export { _n as ODDIN_THEME, n as PlaybackError, Z as applyTheme, Ke as baseUrlForEnv, Kn as bootEmbed, Te as clearDeviceId, Bn as createPlayer, E as deriveEventsBaseUrl, He as detectDrmSupport, C as enterVideoFullscreen, w as exitVideoFullscreen, _e as fetchCatalog, ye as fetchTournament, xe as flattenMatches, k as getDeviceId, We as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, Hn as mountEmbed, de as pollToLive, y as resolveStream, T as subscribeLiveState, S as videoFullscreenActive, Ce as watchStatus };
|
|
3641
3692
|
|
|
3642
3693
|
//# sourceMappingURL=index.js.map
|