@oddin-gg/havik-player 2.17.0 → 2.18.0
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 +17 -17
- 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 +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +405 -344
- package/dist/index.js.map +1 -1
- package/docs/API.md +21 -1
- package/docs/STABILITY.md +1 -1
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -174,7 +174,7 @@ function ue(e, t) {
|
|
|
174
174
|
t?.addEventListener("abort", a, { once: !0 });
|
|
175
175
|
});
|
|
176
176
|
}
|
|
177
|
-
async function
|
|
177
|
+
async function 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 _e(e) {
|
|
294
294
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
295
295
|
}
|
|
296
|
-
function
|
|
297
|
-
let n = ge(
|
|
296
|
+
function x(e, t) {
|
|
297
|
+
let n = _e(ge(e));
|
|
298
298
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
299
299
|
}
|
|
300
|
-
async function
|
|
300
|
+
async function S(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 C(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 = _e(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 ve(e) {
|
|
319
319
|
let t = new URLSearchParams();
|
|
320
320
|
e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
|
|
321
321
|
let i = t.toString(), a = d(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
|
|
@@ -333,12 +333,12 @@ async function _e(e) {
|
|
|
333
333
|
};
|
|
334
334
|
if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
|
|
335
335
|
return {
|
|
336
|
-
tournaments:
|
|
336
|
+
tournaments: ye(await s.json()),
|
|
337
337
|
etag: s.headers.get("etag") ?? void 0,
|
|
338
338
|
notModified: !1
|
|
339
339
|
};
|
|
340
340
|
}
|
|
341
|
-
function
|
|
341
|
+
function ye(e) {
|
|
342
342
|
return (e.tournaments ?? []).map((e) => {
|
|
343
343
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
344
344
|
return {
|
|
@@ -360,7 +360,7 @@ function ve(e) {
|
|
|
360
360
|
};
|
|
361
361
|
});
|
|
362
362
|
}
|
|
363
|
-
async function
|
|
363
|
+
async function be(e) {
|
|
364
364
|
let t = d(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
365
365
|
e.etag && i.set("If-None-Match", e.etag);
|
|
366
366
|
let a = await p(t, {
|
|
@@ -380,13 +380,13 @@ async function ye(e) {
|
|
|
380
380
|
};
|
|
381
381
|
if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
382
382
|
return {
|
|
383
|
-
tournament:
|
|
383
|
+
tournament: xe(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 xe(e) {
|
|
390
390
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
391
391
|
return {
|
|
392
392
|
urn: t,
|
|
@@ -406,17 +406,17 @@ function be(e) {
|
|
|
406
406
|
}))
|
|
407
407
|
};
|
|
408
408
|
}
|
|
409
|
-
function
|
|
409
|
+
function Se(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 Ce = /* @__PURE__ */ new Set([
|
|
415
415
|
"NOT_FOUND",
|
|
416
416
|
"GONE",
|
|
417
417
|
"INVALID_URN"
|
|
418
418
|
]);
|
|
419
|
-
function
|
|
419
|
+
function we(e) {
|
|
420
420
|
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
|
|
421
421
|
u || (a = setTimeout(m, t));
|
|
422
422
|
}, m = async () => {
|
|
@@ -449,7 +449,7 @@ function Ce(e) {
|
|
|
449
449
|
} catch (t) {
|
|
450
450
|
if (!i.signal.aborted) {
|
|
451
451
|
let r = t instanceof n ? t : new n("NETWORK", 0, String(t));
|
|
452
|
-
|
|
452
|
+
Ce.has(r.code) && (u = !0), e.onError?.(r);
|
|
453
453
|
}
|
|
454
454
|
} finally {
|
|
455
455
|
f();
|
|
@@ -461,9 +461,9 @@ function Ce(e) {
|
|
|
461
461
|
}
|
|
462
462
|
//#endregion
|
|
463
463
|
//#region src/core/events.ts
|
|
464
|
-
var
|
|
465
|
-
function
|
|
466
|
-
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ??
|
|
464
|
+
var Te = 45e3;
|
|
465
|
+
function w(e) {
|
|
466
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? Te, 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", () => {
|
|
@@ -545,7 +545,7 @@ function T(e) {
|
|
|
545
545
|
o || (o = !0, a.abort());
|
|
546
546
|
} };
|
|
547
547
|
}
|
|
548
|
-
function
|
|
548
|
+
function T(e) {
|
|
549
549
|
try {
|
|
550
550
|
let t = new URL(e);
|
|
551
551
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -555,27 +555,27 @@ function E(e) {
|
|
|
555
555
|
}
|
|
556
556
|
//#endregion
|
|
557
557
|
//#region src/core/drm/deviceId.ts
|
|
558
|
-
var
|
|
559
|
-
function
|
|
560
|
-
if (
|
|
558
|
+
var E = "havik.player.deviceId", D;
|
|
559
|
+
function O() {
|
|
560
|
+
if (D) return D;
|
|
561
561
|
try {
|
|
562
|
-
let e = globalThis.localStorage?.getItem(
|
|
563
|
-
if (e) return
|
|
562
|
+
let e = globalThis.localStorage?.getItem(E);
|
|
563
|
+
if (e) return D = e, e;
|
|
564
564
|
} catch {}
|
|
565
|
-
let e =
|
|
566
|
-
|
|
565
|
+
let e = De();
|
|
566
|
+
D = e;
|
|
567
567
|
try {
|
|
568
|
-
globalThis.localStorage?.setItem(
|
|
568
|
+
globalThis.localStorage?.setItem(E, e);
|
|
569
569
|
} catch {}
|
|
570
570
|
return e;
|
|
571
571
|
}
|
|
572
|
-
function
|
|
573
|
-
|
|
572
|
+
function Ee() {
|
|
573
|
+
D = void 0;
|
|
574
574
|
try {
|
|
575
|
-
globalThis.localStorage?.removeItem(
|
|
575
|
+
globalThis.localStorage?.removeItem(E);
|
|
576
576
|
} catch {}
|
|
577
577
|
}
|
|
578
|
-
function
|
|
578
|
+
function De() {
|
|
579
579
|
let e = globalThis.crypto;
|
|
580
580
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
581
581
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -587,21 +587,69 @@ function Ee() {
|
|
|
587
587
|
}
|
|
588
588
|
//#endregion
|
|
589
589
|
//#region src/core/drm/headers.ts
|
|
590
|
-
function
|
|
590
|
+
function Oe(e, t, n = {}) {
|
|
591
591
|
let r = {
|
|
592
592
|
"x-api-key": t.apiKey,
|
|
593
593
|
"X-Match-Urn": e.matchUrn,
|
|
594
|
-
"X-Device-Id": n.deviceId ??
|
|
594
|
+
"X-Device-Id": n.deviceId ?? O(),
|
|
595
595
|
"Content-Type": "application/octet-stream"
|
|
596
596
|
};
|
|
597
597
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
598
598
|
}
|
|
599
599
|
//#endregion
|
|
600
|
+
//#region src/core/bandwidthMemory.ts
|
|
601
|
+
var k = "havik.player.bandwidth", ke = .8, Ae = 2e7, je = 3e5;
|
|
602
|
+
function Me() {
|
|
603
|
+
return globalThis.navigator?.connection;
|
|
604
|
+
}
|
|
605
|
+
function Ne() {
|
|
606
|
+
let e = Me()?.type;
|
|
607
|
+
return typeof e == "string" && e !== "" && e !== "unknown" ? e : "any";
|
|
608
|
+
}
|
|
609
|
+
function Pe() {
|
|
610
|
+
let e = Me()?.downlink;
|
|
611
|
+
return typeof e == "number" && Number.isFinite(e) && e > 0 ? e * 1e6 : void 0;
|
|
612
|
+
}
|
|
613
|
+
function Fe() {
|
|
614
|
+
try {
|
|
615
|
+
let e = globalThis.localStorage?.getItem(k);
|
|
616
|
+
if (!e) return {};
|
|
617
|
+
let t = JSON.parse(e);
|
|
618
|
+
return t && typeof t == "object" && !Array.isArray(t) ? t : {};
|
|
619
|
+
} catch {
|
|
620
|
+
return {};
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
function Ie(e = Date.now()) {
|
|
624
|
+
let t = Fe()[Ne()];
|
|
625
|
+
if (!t || typeof t.bps != "number" || typeof t.at != "number" || !Number.isFinite(t.bps) || t.bps <= 0) return;
|
|
626
|
+
let n = e - t.at;
|
|
627
|
+
if (n < 0 || n > 2592e5) return;
|
|
628
|
+
let r = Pe(), i = r === void 0 ? t.bps : Math.min(t.bps, r);
|
|
629
|
+
return Math.round(Math.min(Ae, Math.max(je, i * ke)));
|
|
630
|
+
}
|
|
631
|
+
function Le(e, t = Date.now()) {
|
|
632
|
+
if (!Number.isFinite(e) || e <= 0) return;
|
|
633
|
+
let n = Fe();
|
|
634
|
+
n[Ne()] = {
|
|
635
|
+
bps: Math.round(e),
|
|
636
|
+
at: t
|
|
637
|
+
};
|
|
638
|
+
try {
|
|
639
|
+
globalThis.localStorage?.setItem(k, JSON.stringify(n));
|
|
640
|
+
} catch {}
|
|
641
|
+
}
|
|
642
|
+
function Re() {
|
|
643
|
+
try {
|
|
644
|
+
globalThis.localStorage?.removeItem(k);
|
|
645
|
+
} catch {}
|
|
646
|
+
}
|
|
647
|
+
//#endregion
|
|
600
648
|
//#region src/core/drm/cdm.ts
|
|
601
|
-
var
|
|
602
|
-
function
|
|
603
|
-
let n =
|
|
604
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
649
|
+
var ze = /* @__PURE__ */ new WeakMap();
|
|
650
|
+
function Be(e, t) {
|
|
651
|
+
let n = ze.get(e);
|
|
652
|
+
n || (n = /* @__PURE__ */ new Map(), ze.set(e, n));
|
|
605
653
|
let r = n.get(t.keySystem);
|
|
606
654
|
if (r) return r;
|
|
607
655
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -609,22 +657,22 @@ function Oe(e, t) {
|
|
|
609
657
|
});
|
|
610
658
|
return n.set(t.keySystem, i), i;
|
|
611
659
|
}
|
|
612
|
-
function
|
|
660
|
+
function A() {
|
|
613
661
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
614
662
|
}
|
|
615
|
-
var
|
|
616
|
-
function
|
|
663
|
+
var j = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
664
|
+
function Ve(e) {
|
|
617
665
|
return e.startsWith("com.widevine");
|
|
618
666
|
}
|
|
619
|
-
function
|
|
620
|
-
if (!
|
|
667
|
+
function M(e, t) {
|
|
668
|
+
if (!Ve(e)) return t;
|
|
621
669
|
let n = (e, t) => {
|
|
622
670
|
let n = e.videoCapabilities;
|
|
623
671
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
624
|
-
let n =
|
|
625
|
-
return n === -1 ||
|
|
672
|
+
let n = j.indexOf(e.robustness);
|
|
673
|
+
return n === -1 || j.indexOf(t) > n;
|
|
626
674
|
});
|
|
627
|
-
}, r =
|
|
675
|
+
}, r = j.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
628
676
|
...t,
|
|
629
677
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
630
678
|
...t,
|
|
@@ -633,53 +681,53 @@ function N(e, t) {
|
|
|
633
681
|
})));
|
|
634
682
|
return [...t, ...r];
|
|
635
683
|
}
|
|
636
|
-
function
|
|
637
|
-
return (t, n) =>
|
|
684
|
+
function He(e) {
|
|
685
|
+
return (t, n) => A() ? navigator.requestMediaKeySystemAccess(t, M(t, n)).then((t) => ({
|
|
638
686
|
keySystem: t.keySystem,
|
|
639
687
|
getConfiguration: () => t.getConfiguration(),
|
|
640
|
-
createMediaKeys: () =>
|
|
688
|
+
createMediaKeys: () => Be(e, t)
|
|
641
689
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
642
690
|
}
|
|
643
|
-
var
|
|
691
|
+
var N = {
|
|
644
692
|
video: "SW_SECURE_DECODE",
|
|
645
693
|
audio: "SW_SECURE_CRYPTO",
|
|
646
694
|
scheme: "cbcs"
|
|
647
695
|
};
|
|
648
|
-
function
|
|
649
|
-
if (!
|
|
696
|
+
function Ue(e) {
|
|
697
|
+
if (!A()) return;
|
|
650
698
|
let t = (e, t) => ({
|
|
651
699
|
contentType: e,
|
|
652
700
|
robustness: t,
|
|
653
|
-
encryptionScheme:
|
|
701
|
+
encryptionScheme: N.scheme
|
|
654
702
|
});
|
|
655
|
-
|
|
703
|
+
He(e)("com.widevine.alpha", [{
|
|
656
704
|
initDataTypes: ["cenc"],
|
|
657
705
|
distinctiveIdentifier: "optional",
|
|
658
706
|
persistentState: "optional",
|
|
659
707
|
sessionTypes: ["temporary"],
|
|
660
|
-
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"",
|
|
661
|
-
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"",
|
|
708
|
+
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", N.audio)],
|
|
709
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", N.video)]
|
|
662
710
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
663
711
|
}
|
|
664
|
-
function
|
|
665
|
-
let t =
|
|
712
|
+
function P(e) {
|
|
713
|
+
let t = F(e);
|
|
666
714
|
if (/^avc[13]/.test(t)) return "avc";
|
|
667
715
|
if (/^(hvc1|hev1)/.test(t)) return "hevc";
|
|
668
716
|
if (/^(dvh1|dvhe)/.test(t)) return "dv";
|
|
669
717
|
if (t.startsWith("av01")) return "av1";
|
|
670
718
|
if (/^vp0?9/.test(t)) return "vp9";
|
|
671
719
|
}
|
|
672
|
-
function
|
|
720
|
+
function F(e) {
|
|
673
721
|
return (e ?? "").trim().toLowerCase();
|
|
674
722
|
}
|
|
675
|
-
var
|
|
723
|
+
var We = {
|
|
676
724
|
hevc: "hvc1.1.6.L93.90",
|
|
677
725
|
dv: "dvh1.05.06",
|
|
678
726
|
av1: "av01.0.05M.08",
|
|
679
727
|
vp9: "vp09.00.10.08"
|
|
680
|
-
},
|
|
681
|
-
function
|
|
682
|
-
let t =
|
|
728
|
+
}, Ge = /* @__PURE__ */ new Map(), I = /* @__PURE__ */ new Map();
|
|
729
|
+
function Ke(e) {
|
|
730
|
+
let t = F(e), n = Ge.get(t);
|
|
683
731
|
if (n) return n;
|
|
684
732
|
let r = {
|
|
685
733
|
initDataTypes: ["cenc"],
|
|
@@ -688,32 +736,32 @@ function Me(e) {
|
|
|
688
736
|
sessionTypes: ["temporary"],
|
|
689
737
|
videoCapabilities: [{
|
|
690
738
|
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
691
|
-
robustness:
|
|
692
|
-
encryptionScheme:
|
|
739
|
+
robustness: N.video,
|
|
740
|
+
encryptionScheme: N.scheme
|
|
693
741
|
}]
|
|
694
742
|
}, i = (async () => {
|
|
695
743
|
try {
|
|
696
|
-
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha",
|
|
744
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", M("com.widevine.alpha", [r])), !0;
|
|
697
745
|
} catch {
|
|
698
746
|
return !1;
|
|
699
747
|
}
|
|
700
|
-
})().then((e) => (
|
|
701
|
-
return
|
|
748
|
+
})().then((e) => (I.set(t, e), e));
|
|
749
|
+
return Ge.set(t, i), i;
|
|
702
750
|
}
|
|
703
|
-
function
|
|
704
|
-
if (
|
|
751
|
+
function qe() {
|
|
752
|
+
if (A()) for (let e of Object.values(We)) Ke(e);
|
|
705
753
|
}
|
|
706
|
-
function
|
|
707
|
-
let t =
|
|
708
|
-
if (t) return t === "avc" ? !0 :
|
|
754
|
+
function Je(e) {
|
|
755
|
+
let t = P(e);
|
|
756
|
+
if (t) return t === "avc" ? !0 : I.get(F(e)) ?? I.get(F(We[t]));
|
|
709
757
|
}
|
|
710
758
|
//#endregion
|
|
711
759
|
//#region src/core/drm/support.ts
|
|
712
|
-
var
|
|
760
|
+
var Ye = 5e3, Xe = "video/mp4; codecs=\"avc1.42E01E\"", Ze = "audio/mp4; codecs=\"mp4a.40.2\"", Qe = {
|
|
713
761
|
widevine: ["com.widevine.alpha"],
|
|
714
762
|
fairplay: ["com.apple.fps"]
|
|
715
763
|
};
|
|
716
|
-
function
|
|
764
|
+
function $e(e) {
|
|
717
765
|
return e === "fairplay" ? [{
|
|
718
766
|
initDataTypes: [
|
|
719
767
|
"sinf",
|
|
@@ -721,30 +769,30 @@ function ze(e) {
|
|
|
721
769
|
"cenc"
|
|
722
770
|
],
|
|
723
771
|
videoCapabilities: [{
|
|
724
|
-
contentType:
|
|
772
|
+
contentType: Xe,
|
|
725
773
|
robustness: "",
|
|
726
774
|
encryptionScheme: "cbcs"
|
|
727
775
|
}],
|
|
728
776
|
audioCapabilities: [{
|
|
729
|
-
contentType:
|
|
777
|
+
contentType: Ze,
|
|
730
778
|
robustness: "",
|
|
731
779
|
encryptionScheme: "cbcs"
|
|
732
780
|
}]
|
|
733
|
-
}] :
|
|
781
|
+
}] : M("com.widevine.alpha", [{
|
|
734
782
|
initDataTypes: ["cenc"],
|
|
735
783
|
videoCapabilities: [{
|
|
736
|
-
contentType:
|
|
737
|
-
robustness:
|
|
738
|
-
encryptionScheme:
|
|
784
|
+
contentType: Xe,
|
|
785
|
+
robustness: N.video,
|
|
786
|
+
encryptionScheme: N.scheme
|
|
739
787
|
}],
|
|
740
788
|
audioCapabilities: [{
|
|
741
|
-
contentType:
|
|
742
|
-
robustness:
|
|
743
|
-
encryptionScheme:
|
|
789
|
+
contentType: Ze,
|
|
790
|
+
robustness: N.audio,
|
|
791
|
+
encryptionScheme: N.scheme
|
|
744
792
|
}]
|
|
745
793
|
}]);
|
|
746
794
|
}
|
|
747
|
-
function
|
|
795
|
+
function et(e, t) {
|
|
748
796
|
return new Promise((n, r) => {
|
|
749
797
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
750
798
|
e.then((e) => {
|
|
@@ -754,8 +802,8 @@ function Be(e, t) {
|
|
|
754
802
|
});
|
|
755
803
|
});
|
|
756
804
|
}
|
|
757
|
-
async function
|
|
758
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
805
|
+
async function tt(e = {}) {
|
|
806
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ye, r = {};
|
|
759
807
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
760
808
|
verdict: "insecure-context",
|
|
761
809
|
detail: r
|
|
@@ -767,7 +815,7 @@ async function Ve(e = {}) {
|
|
|
767
815
|
};
|
|
768
816
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
769
817
|
for (let e of t) {
|
|
770
|
-
let t =
|
|
818
|
+
let t = Qe[e];
|
|
771
819
|
if (!t) {
|
|
772
820
|
r[e] = "unknown system";
|
|
773
821
|
continue;
|
|
@@ -778,7 +826,7 @@ async function Ve(e = {}) {
|
|
|
778
826
|
break;
|
|
779
827
|
}
|
|
780
828
|
try {
|
|
781
|
-
return await
|
|
829
|
+
return await et((await et(i(n, $e(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
782
830
|
verdict: "supported",
|
|
783
831
|
system: e,
|
|
784
832
|
detail: r
|
|
@@ -802,37 +850,37 @@ async function Ve(e = {}) {
|
|
|
802
850
|
}
|
|
803
851
|
//#endregion
|
|
804
852
|
//#region src/core/manifest.ts
|
|
805
|
-
var
|
|
806
|
-
function
|
|
807
|
-
return
|
|
853
|
+
var nt = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
854
|
+
function rt(e) {
|
|
855
|
+
return nt.test(e);
|
|
808
856
|
}
|
|
809
857
|
//#endregion
|
|
810
858
|
//#region src/core/env.ts
|
|
811
|
-
var
|
|
859
|
+
var it = {
|
|
812
860
|
integration: "https://feed-dev.oddin-video.gg",
|
|
813
861
|
production: "https://feed.oddin-video.gg"
|
|
814
862
|
};
|
|
815
|
-
function
|
|
816
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
863
|
+
function L(e) {
|
|
864
|
+
let t = Object.prototype.hasOwnProperty.call(it, e) ? it[e] : void 0;
|
|
817
865
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
818
866
|
return t;
|
|
819
867
|
}
|
|
820
868
|
//#endregion
|
|
821
869
|
//#region src/core/stats.ts
|
|
822
|
-
var
|
|
823
|
-
function
|
|
870
|
+
var R = { droppedFrames: 0 };
|
|
871
|
+
function z(e) {
|
|
824
872
|
try {
|
|
825
873
|
return new URL(e).host;
|
|
826
874
|
} catch {
|
|
827
875
|
return "";
|
|
828
876
|
}
|
|
829
877
|
}
|
|
830
|
-
var
|
|
831
|
-
function
|
|
878
|
+
var at = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
879
|
+
function ot(e) {
|
|
832
880
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
833
881
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
834
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
835
|
-
let e =
|
|
882
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || at.test(i.name)) && i.startTime >= n) {
|
|
883
|
+
let e = z(i.name);
|
|
836
884
|
e && (t = e, n = i.startTime);
|
|
837
885
|
}
|
|
838
886
|
return t;
|
|
@@ -844,7 +892,7 @@ function B(e) {
|
|
|
844
892
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
845
893
|
};
|
|
846
894
|
}
|
|
847
|
-
var
|
|
895
|
+
var st = class {
|
|
848
896
|
video;
|
|
849
897
|
baseFrames = 0;
|
|
850
898
|
baseDropped = 0;
|
|
@@ -867,7 +915,7 @@ var Xe = class {
|
|
|
867
915
|
};
|
|
868
916
|
}
|
|
869
917
|
};
|
|
870
|
-
function
|
|
918
|
+
function ct(e, t) {
|
|
871
919
|
let n = [
|
|
872
920
|
["playing", () => t("playing")],
|
|
873
921
|
["waiting", () => t("buffering")],
|
|
@@ -884,8 +932,8 @@ function Ze(e, t) {
|
|
|
884
932
|
}
|
|
885
933
|
//#endregion
|
|
886
934
|
//#region src/core/engine/native.ts
|
|
887
|
-
var
|
|
888
|
-
function
|
|
935
|
+
var lt = 2e3, ut = 3, V = 500, dt = 6e3, ft = .25, pt = 250, mt = .05, ht = 4, gt = 12e3, _t = .25, vt = 1e3;
|
|
936
|
+
function yt(e) {
|
|
889
937
|
try {
|
|
890
938
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
891
939
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -901,7 +949,7 @@ function U() {
|
|
|
901
949
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
902
950
|
return e || t;
|
|
903
951
|
}
|
|
904
|
-
function
|
|
952
|
+
function bt() {
|
|
905
953
|
if (typeof navigator > "u" || !U()) return !1;
|
|
906
954
|
let e = navigator.userAgent ?? "";
|
|
907
955
|
return /iPhone|iPad|iPod/.test(e) ? !0 : /Macintosh/.test(e) && typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1;
|
|
@@ -936,7 +984,7 @@ var W = class {
|
|
|
936
984
|
frameCounter;
|
|
937
985
|
detachFrames = null;
|
|
938
986
|
constructor(e) {
|
|
939
|
-
this.deps = e, this.frameCounter = new
|
|
987
|
+
this.deps = e, this.frameCounter = new st(e.video), this.loadStarted = e.deferLoad !== !0, this.builtAt = typeof performance < "u" ? performance.now() : 0;
|
|
940
988
|
}
|
|
941
989
|
async load() {
|
|
942
990
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -957,7 +1005,7 @@ var W = class {
|
|
|
957
1005
|
type: "error",
|
|
958
1006
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
959
1007
|
fatal: !0
|
|
960
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
1008
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = St(t.manifestUrl, t.analytics?.sid), e.load();
|
|
961
1009
|
}
|
|
962
1010
|
startLoad() {
|
|
963
1011
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -979,7 +1027,7 @@ var W = class {
|
|
|
979
1027
|
});
|
|
980
1028
|
this.onEncrypted = (n) => {
|
|
981
1029
|
let i = n;
|
|
982
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
1030
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = yt(i.initData), (async () => {
|
|
983
1031
|
try {
|
|
984
1032
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
985
1033
|
initDataTypes: [i.initDataType],
|
|
@@ -1078,10 +1126,10 @@ var W = class {
|
|
|
1078
1126
|
droppedFrames: t.dropped,
|
|
1079
1127
|
decodedFrames: t.totalFrames
|
|
1080
1128
|
};
|
|
1081
|
-
if (this.cdnHost ||=
|
|
1129
|
+
if (this.cdnHost ||= ot(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity) {
|
|
1082
1130
|
n.isLive = !0;
|
|
1083
1131
|
let t = this.liveEdgeEstimate(), r = t == null ? NaN : t - e.currentTime;
|
|
1084
|
-
Number.isFinite(r) && (n.atLiveEdge = r <=
|
|
1132
|
+
Number.isFinite(r) && (n.atLiveEdge = r <= ht, !e.paused && r >= 0 && (n.latencySeconds = r));
|
|
1085
1133
|
} else Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1);
|
|
1086
1134
|
return n;
|
|
1087
1135
|
}
|
|
@@ -1099,7 +1147,7 @@ var W = class {
|
|
|
1099
1147
|
return;
|
|
1100
1148
|
}
|
|
1101
1149
|
let t = this.hiddenSince;
|
|
1102
|
-
this.hiddenSince = null, t != null && e - t >=
|
|
1150
|
+
this.hiddenSince = null, t != null && e - t >= lt && this.armRefocus();
|
|
1103
1151
|
}, this.onPageShow = (e) => {
|
|
1104
1152
|
e.persisted && this.armRefocus();
|
|
1105
1153
|
}, document.addEventListener("visibilitychange", this.onVisibility), typeof window < "u" && window.addEventListener("pageshow", this.onPageShow));
|
|
@@ -1109,7 +1157,7 @@ var W = class {
|
|
|
1109
1157
|
let e = this.liveEnd(), t = G, n = t(), r = 0, i = () => {
|
|
1110
1158
|
if (this.refocusTimer = null, Number.isFinite(this.deps.video.duration)) return;
|
|
1111
1159
|
r += V;
|
|
1112
|
-
let a = this.liveEnd(), o = a != null && (e == null || a >= e +
|
|
1160
|
+
let a = this.liveEnd(), o = a != null && (e == null || a >= e + ft), s = Math.max(r, t() - n) >= dt;
|
|
1113
1161
|
if (o || s && a != null) {
|
|
1114
1162
|
this.snapToLive();
|
|
1115
1163
|
return;
|
|
@@ -1129,9 +1177,9 @@ var W = class {
|
|
|
1129
1177
|
}, e.addEventListener("seeking", this.onEdgeReset), e.addEventListener("emptied", this.onEdgeReset), this.edgeTimer = setInterval(() => {
|
|
1130
1178
|
if (e.duration !== Infinity) return;
|
|
1131
1179
|
this.checkEndStale();
|
|
1132
|
-
let t =
|
|
1133
|
-
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >=
|
|
1134
|
-
},
|
|
1180
|
+
let t = xt(e, e.currentTime);
|
|
1181
|
+
t != null && ((this.lastBufferedEnd == null || Math.abs(t - this.lastBufferedEnd) >= mt) && (this.bufferedAdvancedAt = G()), this.lastBufferedEnd = t);
|
|
1182
|
+
}, pt);
|
|
1135
1183
|
}
|
|
1136
1184
|
checkEndStale() {
|
|
1137
1185
|
if (this.endedEmitted) return;
|
|
@@ -1139,14 +1187,14 @@ var W = class {
|
|
|
1139
1187
|
this.lastTickAt = e;
|
|
1140
1188
|
let n = this.liveEnd();
|
|
1141
1189
|
if (n == null) return;
|
|
1142
|
-
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >=
|
|
1190
|
+
let r = this.lastSeekableEnd == null || Math.abs(n - this.lastSeekableEnd) >= _t;
|
|
1143
1191
|
this.lastSeekableEnd = n;
|
|
1144
1192
|
let i = this.deps.video, a = typeof document < "u" && document.visibilityState === "hidden";
|
|
1145
|
-
if (r || t >
|
|
1193
|
+
if (r || t > vt || a || i.paused) {
|
|
1146
1194
|
this.edgeStampedAt = e;
|
|
1147
1195
|
return;
|
|
1148
1196
|
}
|
|
1149
|
-
e - (this.edgeStampedAt ?? e) >
|
|
1197
|
+
e - (this.edgeStampedAt ?? e) > gt && (this.endedEmitted = !0, this.deps.emit({
|
|
1150
1198
|
type: "ended",
|
|
1151
1199
|
reason: "stalled"
|
|
1152
1200
|
}));
|
|
@@ -1160,7 +1208,7 @@ var W = class {
|
|
|
1160
1208
|
liveEdgeEstimate() {
|
|
1161
1209
|
let e = this.deps.video;
|
|
1162
1210
|
if (e.duration !== Infinity) return null;
|
|
1163
|
-
let t = this.liveEnd(), n =
|
|
1211
|
+
let t = this.liveEnd(), n = xt(e, e.currentTime) ?? this.lastBufferedEnd;
|
|
1164
1212
|
if (n != null) {
|
|
1165
1213
|
let e = this.bufferedAdvancedAt, r = n + (e == null ? 0 : Math.max(0, (G() - e) / 1e3));
|
|
1166
1214
|
(t == null || r > t) && (t = r);
|
|
@@ -1176,7 +1224,7 @@ var W = class {
|
|
|
1176
1224
|
snapToLive() {
|
|
1177
1225
|
let e = this.deps.video, t = this.liveEnd();
|
|
1178
1226
|
if (t == null) return;
|
|
1179
|
-
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t -
|
|
1227
|
+
let n = e.seekable.start(e.seekable.length - 1), r = Math.min(e.currentTime, t), i = Math.max(n, t - ut, r);
|
|
1180
1228
|
try {
|
|
1181
1229
|
e.currentTime = i;
|
|
1182
1230
|
} catch {}
|
|
@@ -1197,7 +1245,7 @@ var W = class {
|
|
|
1197
1245
|
function G() {
|
|
1198
1246
|
return typeof performance < "u" ? performance.now() : Date.now();
|
|
1199
1247
|
}
|
|
1200
|
-
function
|
|
1248
|
+
function xt(e, t) {
|
|
1201
1249
|
let n = e.buffered;
|
|
1202
1250
|
if (!n || !Number.isFinite(t)) return null;
|
|
1203
1251
|
for (let e = 0; e < n.length; e += 1) if (n.start(e) <= t + .1 && n.end(e) > t) {
|
|
@@ -1206,7 +1254,7 @@ function ut(e, t) {
|
|
|
1206
1254
|
}
|
|
1207
1255
|
return null;
|
|
1208
1256
|
}
|
|
1209
|
-
function
|
|
1257
|
+
function St(e, t) {
|
|
1210
1258
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
1211
1259
|
}
|
|
1212
1260
|
//#endregion
|
|
@@ -1223,8 +1271,8 @@ function K(e, t = Date.now()) {
|
|
|
1223
1271
|
}
|
|
1224
1272
|
//#endregion
|
|
1225
1273
|
//#region src/core/engine/prefetch.ts
|
|
1226
|
-
var
|
|
1227
|
-
function
|
|
1274
|
+
var Ct = 15e3, wt = 5e3, Tt = 6;
|
|
1275
|
+
function Et(e) {
|
|
1228
1276
|
try {
|
|
1229
1277
|
let t = new URL(e);
|
|
1230
1278
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -1232,7 +1280,7 @@ function ht(e) {
|
|
|
1232
1280
|
return e;
|
|
1233
1281
|
}
|
|
1234
1282
|
}
|
|
1235
|
-
var
|
|
1283
|
+
var Dt = class {
|
|
1236
1284
|
cmcd;
|
|
1237
1285
|
entries = /* @__PURE__ */ new Map();
|
|
1238
1286
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1255,10 +1303,10 @@ var gt = class {
|
|
|
1255
1303
|
}
|
|
1256
1304
|
prefetch(e, t, n) {
|
|
1257
1305
|
if (!this.isActive(t)) return;
|
|
1258
|
-
let r =
|
|
1306
|
+
let r = Et(e);
|
|
1259
1307
|
if (this.entries.has(r)) return;
|
|
1260
1308
|
let i = this.perTrack.get(t) ?? 0;
|
|
1261
|
-
if (i >=
|
|
1309
|
+
if (i >= Tt) return;
|
|
1262
1310
|
this.perTrack.set(t, i + 1);
|
|
1263
1311
|
let a = new AbortController(), o = {
|
|
1264
1312
|
started: performance.now(),
|
|
@@ -1272,10 +1320,10 @@ var gt = class {
|
|
|
1272
1320
|
signal: a.signal
|
|
1273
1321
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1274
1322
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1275
|
-
},
|
|
1323
|
+
}, Ct);
|
|
1276
1324
|
}
|
|
1277
1325
|
take(e) {
|
|
1278
|
-
let t =
|
|
1326
|
+
let t = Et(e), n = this.entries.get(t);
|
|
1279
1327
|
return n && this.entries.delete(t), n;
|
|
1280
1328
|
}
|
|
1281
1329
|
destroy() {
|
|
@@ -1295,13 +1343,13 @@ var gt = class {
|
|
|
1295
1343
|
}
|
|
1296
1344
|
}
|
|
1297
1345
|
};
|
|
1298
|
-
function
|
|
1346
|
+
function Ot(t) {
|
|
1299
1347
|
let n = e.DefaultConfig?.loader;
|
|
1300
1348
|
if (typeof n != "function") return;
|
|
1301
1349
|
class r extends n {
|
|
1302
1350
|
served = !1;
|
|
1303
1351
|
cancelled = !1;
|
|
1304
|
-
stats =
|
|
1352
|
+
stats = kt();
|
|
1305
1353
|
load(e, n, r) {
|
|
1306
1354
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1307
1355
|
if (!i) {
|
|
@@ -1309,7 +1357,7 @@ function _t(t) {
|
|
|
1309
1357
|
return;
|
|
1310
1358
|
}
|
|
1311
1359
|
this.served = !0;
|
|
1312
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1360
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || wt, s = setTimeout(() => {
|
|
1313
1361
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1314
1362
|
}, o);
|
|
1315
1363
|
i.bytes.then((o) => {
|
|
@@ -1336,7 +1384,7 @@ function _t(t) {
|
|
|
1336
1384
|
}
|
|
1337
1385
|
return r;
|
|
1338
1386
|
}
|
|
1339
|
-
function
|
|
1387
|
+
function kt() {
|
|
1340
1388
|
return {
|
|
1341
1389
|
aborted: !1,
|
|
1342
1390
|
loaded: 0,
|
|
@@ -1360,10 +1408,10 @@ function vt() {
|
|
|
1360
1408
|
}
|
|
1361
1409
|
};
|
|
1362
1410
|
}
|
|
1363
|
-
function
|
|
1411
|
+
function At(e) {
|
|
1364
1412
|
return e === "audio" ? "audio" : "main";
|
|
1365
1413
|
}
|
|
1366
|
-
function
|
|
1414
|
+
function jt(e, t) {
|
|
1367
1415
|
let n = [];
|
|
1368
1416
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1369
1417
|
url: t.initSegment.url,
|
|
@@ -1382,24 +1430,24 @@ function yt(e, t) {
|
|
|
1382
1430
|
}
|
|
1383
1431
|
//#endregion
|
|
1384
1432
|
//#region src/core/engine/hls.ts
|
|
1385
|
-
function
|
|
1433
|
+
function Mt() {
|
|
1386
1434
|
return e.isSupported();
|
|
1387
1435
|
}
|
|
1388
|
-
var
|
|
1389
|
-
function
|
|
1436
|
+
var Nt = 1e6, Pt = 20, Ft = 1e4, It = 3, Lt = 5, Rt = 3, zt = 1e4, Bt = 3e4, Vt = 12e3, Ht = 3e3, Ut = .02, Wt = 6e3, Gt = .5, Kt = 3, qt = .5, Jt = 1.1, Yt = .25, Xt = 5e3, Zt = 4e3, Qt = 2, $t = 5, en = 2, tn = 2, nn = 4, rn = 4, an = 2e3, on = 3e4, sn = .2, cn = 30, ln = 2, un = 2, dn = 9, fn = .5, pn = 64;
|
|
1437
|
+
function mn(e) {
|
|
1390
1438
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1391
1439
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1392
1440
|
return;
|
|
1393
1441
|
}
|
|
1394
|
-
e.liveSyncDuration ??=
|
|
1395
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1396
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1442
|
+
e.liveSyncDuration ??= un;
|
|
1443
|
+
let t = Math.max(12, e.liveSyncDuration + dn);
|
|
1444
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), hn(e, e.liveSyncDuration);
|
|
1397
1445
|
}
|
|
1398
|
-
function
|
|
1446
|
+
function hn(e, t) {
|
|
1399
1447
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1400
1448
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1401
1449
|
}
|
|
1402
|
-
var
|
|
1450
|
+
var gn = class {
|
|
1403
1451
|
name = "hls";
|
|
1404
1452
|
hls = null;
|
|
1405
1453
|
deps;
|
|
@@ -1451,6 +1499,8 @@ var en = class {
|
|
|
1451
1499
|
starvedFrames = 0;
|
|
1452
1500
|
deadTicks = 0;
|
|
1453
1501
|
mainFragsSinceTick = 0;
|
|
1502
|
+
bwFragsLoaded = 0;
|
|
1503
|
+
bwSavedAt = 0;
|
|
1454
1504
|
recentMainFrags = [];
|
|
1455
1505
|
chaseSuspended = !1;
|
|
1456
1506
|
savedLiveMaxLatency;
|
|
@@ -1481,7 +1531,7 @@ var en = class {
|
|
|
1481
1531
|
frameCounter;
|
|
1482
1532
|
detachFrames = null;
|
|
1483
1533
|
constructor(e) {
|
|
1484
|
-
this.deps = e, this.frameCounter = new
|
|
1534
|
+
this.deps = e, this.frameCounter = new st(e.video), this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1485
1535
|
}
|
|
1486
1536
|
async load() {
|
|
1487
1537
|
this.detachFrames ??= this.frameCounter.attach();
|
|
@@ -1494,7 +1544,7 @@ var en = class {
|
|
|
1494
1544
|
});
|
|
1495
1545
|
return;
|
|
1496
1546
|
}
|
|
1497
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (
|
|
1547
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ue(r), qe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1498
1548
|
let e = this.hls;
|
|
1499
1549
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1500
1550
|
let t = e.liveSyncPosition;
|
|
@@ -1517,7 +1567,7 @@ var en = class {
|
|
|
1517
1567
|
}
|
|
1518
1568
|
this.loadSuspended = !0;
|
|
1519
1569
|
}
|
|
1520
|
-
},
|
|
1570
|
+
}, Xt));
|
|
1521
1571
|
}
|
|
1522
1572
|
resumeLoading() {
|
|
1523
1573
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.resetChaseWindow(), this.resetFrameDropWindow(), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1549,7 +1599,7 @@ var en = class {
|
|
|
1549
1599
|
let t = e.liveSyncPosition;
|
|
1550
1600
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1551
1601
|
let { video: n } = this.deps;
|
|
1552
|
-
n.currentTime <= t +
|
|
1602
|
+
n.currentTime <= t + fn || (n.currentTime = t);
|
|
1553
1603
|
}
|
|
1554
1604
|
reanchorPartTimeline(e, t) {
|
|
1555
1605
|
let { frag: n, part: r } = t;
|
|
@@ -1561,7 +1611,7 @@ var en = class {
|
|
|
1561
1611
|
let o = n.sn, s = i.fragments.find((e) => e && e.sn === o) ?? (i.fragmentHint?.sn === o ? i.fragmentHint : void 0);
|
|
1562
1612
|
if (!s) return;
|
|
1563
1613
|
let c = a.startPTS - s.start;
|
|
1564
|
-
if (!(!Number.isFinite(c) || Math.abs(c) <
|
|
1614
|
+
if (!(!Number.isFinite(c) || Math.abs(c) < Ut)) {
|
|
1565
1615
|
for (let e of i.fragments) e && e.setStart(e.start + c);
|
|
1566
1616
|
i.fragmentHint?.setStart(i.fragmentHint.start + c), this.deps.debug === !0 && console.info(`havik-player: LL-HLS timeline re-anchored by ${c >= 0 ? "+" : ""}${c.toFixed(3)}s at sn ${n.sn} (level ${n.level})`);
|
|
1567
1617
|
}
|
|
@@ -1577,19 +1627,19 @@ var en = class {
|
|
|
1577
1627
|
liveDurationInfinity: !0,
|
|
1578
1628
|
maxBufferHole: .5,
|
|
1579
1629
|
maxLiveSyncPlaybackRate: d ? 1 : 1.1,
|
|
1580
|
-
abrEwmaDefaultEstimate:
|
|
1630
|
+
abrEwmaDefaultEstimate: this.startEstimate(),
|
|
1581
1631
|
capLevelToPlayerSize: !1,
|
|
1582
1632
|
...this.loadStarted ? {} : { autoStartLoad: !1 },
|
|
1583
1633
|
...u ? {
|
|
1584
1634
|
emeEnabled: !0,
|
|
1585
1635
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1586
1636
|
drmSystemOptions: {
|
|
1587
|
-
videoRobustness:
|
|
1588
|
-
audioRobustness:
|
|
1589
|
-
videoEncryptionScheme:
|
|
1590
|
-
audioEncryptionScheme:
|
|
1637
|
+
videoRobustness: N.video,
|
|
1638
|
+
audioRobustness: N.audio,
|
|
1639
|
+
videoEncryptionScheme: N.scheme,
|
|
1640
|
+
audioEncryptionScheme: N.scheme
|
|
1591
1641
|
},
|
|
1592
|
-
...
|
|
1642
|
+
...A() ? { requestMediaKeySystemAccessFunc: He(t) } : {},
|
|
1593
1643
|
licenseXhrSetup: (e, t) => {
|
|
1594
1644
|
let o = performance.now(), s = () => {
|
|
1595
1645
|
e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a), this.licenseRequested = !0, e.addEventListener("loadend", () => {
|
|
@@ -1601,7 +1651,7 @@ var en = class {
|
|
|
1601
1651
|
return;
|
|
1602
1652
|
}
|
|
1603
1653
|
let l = this.hls, u, d = new Promise((e) => {
|
|
1604
|
-
u = setTimeout(() => e(void 0),
|
|
1654
|
+
u = setTimeout(() => e(void 0), zt);
|
|
1605
1655
|
});
|
|
1606
1656
|
return Promise.race([c().catch(() => void 0), d]).finally(() => clearTimeout(u)).then((e) => {
|
|
1607
1657
|
if (!this.hls || this.hls !== l) throw Error("havik-player: engine torn down during refresh");
|
|
@@ -1617,31 +1667,31 @@ var en = class {
|
|
|
1617
1667
|
...c
|
|
1618
1668
|
};
|
|
1619
1669
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !f.fLoader) {
|
|
1620
|
-
let e = new
|
|
1670
|
+
let e = new Dt({
|
|
1621
1671
|
sessionId: n.analytics?.sid,
|
|
1622
1672
|
contentId: n.matchUrn
|
|
1623
|
-
}), t =
|
|
1673
|
+
}), t = Ot(e);
|
|
1624
1674
|
t && (this.prefetch = e, f.fLoader = t);
|
|
1625
1675
|
}
|
|
1626
|
-
|
|
1676
|
+
mn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
|
|
1627
1677
|
let p = new e(f);
|
|
1628
1678
|
if (this.hls = p, p.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(p, t)), p.on(e.Events.MANIFEST_PARSED, () => {
|
|
1629
1679
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(p), this.measureLadder(p), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1630
1680
|
}), p.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1631
1681
|
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(() => {
|
|
1632
1682
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1633
|
-
},
|
|
1683
|
+
}, Bt)));
|
|
1634
1684
|
}), p.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1635
1685
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1636
1686
|
}), p.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
1637
|
-
t?.frag?.type === "main" && (this.mainFragsSinceTick += 1);
|
|
1687
|
+
t?.frag?.type === "main" && (this.mainFragsSinceTick += 1, this.bwFragsLoaded += 1, this.maybeRememberBandwidth(!1));
|
|
1638
1688
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1639
1689
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1640
1690
|
let i = n?.loading;
|
|
1641
|
-
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 >
|
|
1691
|
+
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 > pn && this.requestTimesMs.shift());
|
|
1642
1692
|
let a = t?.frag?.url;
|
|
1643
1693
|
if (a) {
|
|
1644
|
-
let e =
|
|
1694
|
+
let e = z(a);
|
|
1645
1695
|
e && (this.cdnHost = e);
|
|
1646
1696
|
}
|
|
1647
1697
|
}), p.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1655,15 +1705,15 @@ var en = class {
|
|
|
1655
1705
|
}), p.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1656
1706
|
let t = this.prefetch;
|
|
1657
1707
|
p.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1658
|
-
let r = n?.frag, i =
|
|
1659
|
-
if (r && t.isActive(i)) for (let e of
|
|
1660
|
-
}), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1708
|
+
let r = n?.frag, i = At(r?.type);
|
|
1709
|
+
if (r && t.isActive(i)) for (let e of jt(p, r)) t.prefetch(e.url, i, e.kind);
|
|
1710
|
+
}), p.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(At(n?.frag?.type)));
|
|
1661
1711
|
}
|
|
1662
1712
|
p.on(e.Events.KEY_LOADED, () => {
|
|
1663
1713
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1664
1714
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1665
1715
|
this.checkEndStale(), this.checkStarvation(), this.updateCatchUpBand(), this.checkFutileChase(), this.checkFrameDrops();
|
|
1666
|
-
},
|
|
1716
|
+
}, Ht), p.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1667
1717
|
this.renditionSwitches += 1;
|
|
1668
1718
|
let n = this.lastLevelIndex >= 0 ? p.levels[this.lastLevelIndex] : void 0, r = p.levels[t.level];
|
|
1669
1719
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1727,7 +1777,7 @@ var en = class {
|
|
|
1727
1777
|
return;
|
|
1728
1778
|
}
|
|
1729
1779
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1730
|
-
let t = e > this.sizeCapLevel ?
|
|
1780
|
+
let t = e > this.sizeCapLevel ? an : on;
|
|
1731
1781
|
this.capTimer = setTimeout(() => {
|
|
1732
1782
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1733
1783
|
}, t);
|
|
@@ -1737,9 +1787,9 @@ var en = class {
|
|
|
1737
1787
|
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;
|
|
1738
1788
|
}
|
|
1739
1789
|
dropLevelsWidevineCannotPlay(e) {
|
|
1740
|
-
this.removeLevelsWhere(e, (e) =>
|
|
1741
|
-
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e &&
|
|
1742
|
-
for (let n of t)
|
|
1790
|
+
this.removeLevelsWhere(e, (e) => Je(e) !== !0);
|
|
1791
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && P(e) !== "avc" && !!P(e)));
|
|
1792
|
+
for (let n of t) Ke(n).then((t) => {
|
|
1743
1793
|
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1744
1794
|
});
|
|
1745
1795
|
}
|
|
@@ -1747,10 +1797,10 @@ var en = class {
|
|
|
1747
1797
|
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1748
1798
|
if (n.forEach((e, n) => {
|
|
1749
1799
|
let a = e.videoCodec;
|
|
1750
|
-
a &&
|
|
1800
|
+
a && P(a) && t(a) && (r.push(n), i.add(a));
|
|
1751
1801
|
}), !r.length) return !1;
|
|
1752
1802
|
let a = [...i].join(", ");
|
|
1753
|
-
if (!n.some((e, t) => r.includes(t) ? !1 : !
|
|
1803
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !P(e.videoCodec) || Je(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1754
1804
|
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1755
1805
|
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1756
1806
|
}
|
|
@@ -1856,7 +1906,7 @@ var en = class {
|
|
|
1856
1906
|
return;
|
|
1857
1907
|
}
|
|
1858
1908
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1859
|
-
!this.chaseSuspended && e >
|
|
1909
|
+
!this.chaseSuspended && e > Wt && this.suspendChasing(), e > Vt && this.emitEnded("stalled");
|
|
1860
1910
|
}
|
|
1861
1911
|
resetStarvationWindow() {
|
|
1862
1912
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1871,7 +1921,7 @@ var en = class {
|
|
|
1871
1921
|
this.resetStarvationWindow();
|
|
1872
1922
|
return;
|
|
1873
1923
|
}
|
|
1874
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1924
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < Wt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > Zt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = B(t), c = o - s, l = c !== this.starvedFrames;
|
|
1875
1925
|
if (this.starvedFrames = c, !a || l) {
|
|
1876
1926
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1877
1927
|
return;
|
|
@@ -1880,12 +1930,12 @@ var en = class {
|
|
|
1880
1930
|
this.resetStarvationWindow();
|
|
1881
1931
|
return;
|
|
1882
1932
|
}
|
|
1883
|
-
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 >
|
|
1933
|
+
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 > nn && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= en && (this.clearKick(), this.starvationRebuilds < tn)) {
|
|
1884
1934
|
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");
|
|
1885
1935
|
return;
|
|
1886
1936
|
}
|
|
1887
|
-
let u = i && this.starvedTicks >=
|
|
1888
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1937
|
+
let u = i && this.starvedTicks >= Qt, d = !i && this.deadTicks >= nn && this.recentMainFrags.reduce((e, t) => e + t, 0) >= rn;
|
|
1938
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= $t))) {
|
|
1889
1939
|
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");
|
|
1890
1940
|
try {
|
|
1891
1941
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1900,7 +1950,7 @@ var en = class {
|
|
|
1900
1950
|
let t = e.latency, n = e.targetLatency;
|
|
1901
1951
|
if (typeof t != "number" || typeof n != "number" || !Number.isFinite(t)) return;
|
|
1902
1952
|
let r = t - n;
|
|
1903
|
-
!this.catchUpEngaged && r >
|
|
1953
|
+
!this.catchUpEngaged && r > Gt ? this.catchUpEngaged = !0 : this.catchUpEngaged && r <= Gt && this.deps.video.playbackRate === 1 && (this.catchUpEngaged = !1);
|
|
1904
1954
|
let i = this.catchUpEngaged ? this.catchUpRate : 1;
|
|
1905
1955
|
e.config.maxLiveSyncPlaybackRate !== i && (e.config.maxLiveSyncPlaybackRate = i);
|
|
1906
1956
|
}
|
|
@@ -1922,15 +1972,15 @@ var en = class {
|
|
|
1922
1972
|
return;
|
|
1923
1973
|
}
|
|
1924
1974
|
let { totalFrames: n, dropped: r } = B(t), i = this.fpsLastFrames < 0, a = n - this.fpsLastFrames, o = r - this.fpsLastDropped;
|
|
1925
|
-
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a <
|
|
1975
|
+
if (this.fpsLastFrames = n, this.fpsLastDropped = r, i || a < cn || o < 0) {
|
|
1926
1976
|
this.fpsBadTicks = 0;
|
|
1927
1977
|
return;
|
|
1928
1978
|
}
|
|
1929
|
-
if (o <=
|
|
1979
|
+
if (o <= sn * a) {
|
|
1930
1980
|
this.fpsBadTicks = 0;
|
|
1931
1981
|
return;
|
|
1932
1982
|
}
|
|
1933
|
-
if (this.fpsBadTicks += 1, this.fpsBadTicks <
|
|
1983
|
+
if (this.fpsBadTicks += 1, this.fpsBadTicks < ln) return;
|
|
1934
1984
|
this.fpsBadTicks = 0;
|
|
1935
1985
|
let s = e.levels, c = s[e.currentLevel];
|
|
1936
1986
|
if (!c) return;
|
|
@@ -1947,20 +1997,20 @@ var en = class {
|
|
|
1947
1997
|
return;
|
|
1948
1998
|
}
|
|
1949
1999
|
let n = e.latency, r = t.playbackRate, i = e.config.maxLiveSyncPlaybackRate;
|
|
1950
|
-
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(
|
|
2000
|
+
if (!(!t.paused && typeof i == "number" && i > 1 && r >= Math.min(Jt, i) && r <= i && typeof n == "number" && Number.isFinite(n))) {
|
|
1951
2001
|
this.resetChaseWindow();
|
|
1952
2002
|
return;
|
|
1953
2003
|
}
|
|
1954
|
-
if (this.chaseLatency < 0 || this.chaseLatency - n >=
|
|
2004
|
+
if (this.chaseLatency < 0 || this.chaseLatency - n >= qt) {
|
|
1955
2005
|
this.chaseLatency = n, this.chaseTicks = 0;
|
|
1956
2006
|
return;
|
|
1957
2007
|
}
|
|
1958
|
-
if (this.chaseTicks += 1, this.chaseTicks <
|
|
2008
|
+
if (this.chaseTicks += 1, this.chaseTicks < Kt) return;
|
|
1959
2009
|
this.resetChaseWindow();
|
|
1960
2010
|
let a = typeof e.config.liveMaxLatencyDuration == "number" ? e.config.liveMaxLatencyDuration : e.maxLatency;
|
|
1961
2011
|
if (!(a > 1)) return;
|
|
1962
2012
|
let o = typeof e.targetLatency == "number" ? e.targetLatency : 0, s = Math.min(n, a - 1);
|
|
1963
|
-
s < o +
|
|
2013
|
+
s < o + Yt || (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);
|
|
1964
2014
|
}
|
|
1965
2015
|
suspendChasing() {
|
|
1966
2016
|
let e = this.hls;
|
|
@@ -1989,8 +2039,18 @@ var en = class {
|
|
|
1989
2039
|
this.deps.video.pause();
|
|
1990
2040
|
} catch {}
|
|
1991
2041
|
}
|
|
2042
|
+
startEstimate() {
|
|
2043
|
+
return this.deps.rememberBandwidth === !1 ? Nt : Ie() ?? Nt;
|
|
2044
|
+
}
|
|
2045
|
+
maybeRememberBandwidth(e) {
|
|
2046
|
+
if (this.deps.rememberBandwidth === !1 || this.bwFragsLoaded < Pt) return;
|
|
2047
|
+
let t = Date.now();
|
|
2048
|
+
if (!e && t - this.bwSavedAt < Ft) return;
|
|
2049
|
+
let n = this.hls?.bandwidthEstimate;
|
|
2050
|
+
typeof n != "number" || !Number.isFinite(n) || n <= 0 || (this.bwSavedAt = t, Le(n));
|
|
2051
|
+
}
|
|
1992
2052
|
destroy() {
|
|
1993
|
-
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) {
|
|
2053
|
+
if (this.maybeRememberBandwidth(!0), 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) {
|
|
1994
2054
|
try {
|
|
1995
2055
|
this.hls.destroy();
|
|
1996
2056
|
} catch (e) {
|
|
@@ -2005,7 +2065,7 @@ var en = class {
|
|
|
2005
2065
|
scheduleLicenseRetry(t) {
|
|
2006
2066
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
2007
2067
|
let n = t.response?.code ?? 0;
|
|
2008
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
2068
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= Rt) return !1;
|
|
2009
2069
|
this.licenseRecoveries += 1;
|
|
2010
2070
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
2011
2071
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -2037,7 +2097,7 @@ var en = class {
|
|
|
2037
2097
|
return;
|
|
2038
2098
|
}
|
|
2039
2099
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
2040
|
-
if (this.networkRecoveries <
|
|
2100
|
+
if (this.networkRecoveries < Lt) {
|
|
2041
2101
|
this.networkRecoveries += 1;
|
|
2042
2102
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
2043
2103
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -2054,7 +2114,7 @@ var en = class {
|
|
|
2054
2114
|
return;
|
|
2055
2115
|
}
|
|
2056
2116
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
2057
|
-
if (this.mediaRecoveries <
|
|
2117
|
+
if (this.mediaRecoveries < It) {
|
|
2058
2118
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
2059
2119
|
return;
|
|
2060
2120
|
}
|
|
@@ -2078,19 +2138,19 @@ var en = class {
|
|
|
2078
2138
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
2079
2139
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
2080
2140
|
}
|
|
2081
|
-
},
|
|
2141
|
+
}, _n = 15e3, vn = 6e5, yn = 3e5, bn = 100, q = 1, xn = 1e3, Sn = 3e4, Cn = 1e3, wn = {
|
|
2082
2142
|
inline: "PRESENTATION_INLINE",
|
|
2083
2143
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2084
2144
|
pip: "PRESENTATION_PIP"
|
|
2085
|
-
},
|
|
2145
|
+
}, Tn = {
|
|
2086
2146
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2087
2147
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2088
2148
|
none: "KEY_SYSTEM_NONE"
|
|
2089
2149
|
};
|
|
2090
|
-
function
|
|
2150
|
+
function En(e, t) {
|
|
2091
2151
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
2092
2152
|
}
|
|
2093
|
-
var
|
|
2153
|
+
var Dn = /* @__PURE__ */ new Set([
|
|
2094
2154
|
"INVALID_URN",
|
|
2095
2155
|
"NOT_FOUND",
|
|
2096
2156
|
"GONE",
|
|
@@ -2100,7 +2160,7 @@ var fn = /* @__PURE__ */ new Set([
|
|
|
2100
2160
|
"FORBIDDEN",
|
|
2101
2161
|
"RATE_LIMITED",
|
|
2102
2162
|
"TIMEOUT"
|
|
2103
|
-
]),
|
|
2163
|
+
]), J = {
|
|
2104
2164
|
idle: "PLAYER_STATE_IDLE",
|
|
2105
2165
|
waiting: "PLAYER_STATE_WAITING",
|
|
2106
2166
|
loading: "PLAYER_STATE_LOADING",
|
|
@@ -2110,7 +2170,7 @@ var fn = /* @__PURE__ */ new Set([
|
|
|
2110
2170
|
ended: "PLAYER_STATE_ENDED",
|
|
2111
2171
|
error: "PLAYER_STATE_ERROR"
|
|
2112
2172
|
};
|
|
2113
|
-
function
|
|
2173
|
+
function On(e) {
|
|
2114
2174
|
try {
|
|
2115
2175
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2116
2176
|
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);
|
|
@@ -2118,8 +2178,8 @@ function pn(e) {
|
|
|
2118
2178
|
return;
|
|
2119
2179
|
}
|
|
2120
2180
|
}
|
|
2121
|
-
var
|
|
2122
|
-
function
|
|
2181
|
+
var kn = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), An = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), jn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2182
|
+
function Mn(e) {
|
|
2123
2183
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2124
2184
|
let t;
|
|
2125
2185
|
try {
|
|
@@ -2128,19 +2188,19 @@ function _n(e) {
|
|
|
2128
2188
|
} catch {
|
|
2129
2189
|
return;
|
|
2130
2190
|
}
|
|
2131
|
-
if (
|
|
2132
|
-
|
|
2133
|
-
for (let e of
|
|
2191
|
+
if (An.has(t) && !Y.has(t)) {
|
|
2192
|
+
Y.add(t), g(jn(new URL(t).origin));
|
|
2193
|
+
for (let e of X) e.noteCspBlocked();
|
|
2134
2194
|
}
|
|
2135
2195
|
}
|
|
2136
|
-
function
|
|
2196
|
+
function Nn(e, t) {
|
|
2137
2197
|
return g(t, e), { disabledReason: t };
|
|
2138
2198
|
}
|
|
2139
|
-
function
|
|
2140
|
-
if (n) return t && !
|
|
2199
|
+
function Pn(e, t, n) {
|
|
2200
|
+
if (n) return t && !kn(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2141
2201
|
if (t) return { endpoint: t };
|
|
2142
|
-
if (t !== void 0) return
|
|
2143
|
-
let r =
|
|
2202
|
+
if (t !== void 0) return Nn("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).");
|
|
2203
|
+
let r = On(e);
|
|
2144
2204
|
if (r) return { endpoint: r };
|
|
2145
2205
|
let i;
|
|
2146
2206
|
try {
|
|
@@ -2148,9 +2208,9 @@ function yn(e, t, n) {
|
|
|
2148
2208
|
} catch {
|
|
2149
2209
|
i = e;
|
|
2150
2210
|
}
|
|
2151
|
-
return
|
|
2211
|
+
return Nn(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).`);
|
|
2152
2212
|
}
|
|
2153
|
-
var
|
|
2213
|
+
var Fn = class {
|
|
2154
2214
|
opts;
|
|
2155
2215
|
url;
|
|
2156
2216
|
cspKey;
|
|
@@ -2232,8 +2292,8 @@ var bn = class {
|
|
|
2232
2292
|
constructor(e) {
|
|
2233
2293
|
this.opts = {
|
|
2234
2294
|
...e,
|
|
2235
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2236
|
-
idleMs: e.idleMs ??
|
|
2295
|
+
heartbeatMs: e.heartbeatMs ?? _n,
|
|
2296
|
+
idleMs: e.idleMs ?? vn
|
|
2237
2297
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2238
2298
|
try {
|
|
2239
2299
|
let e = new URL(this.url);
|
|
@@ -2250,11 +2310,11 @@ var bn = class {
|
|
|
2250
2310
|
sdkVersion: this.opts.sdkVersion,
|
|
2251
2311
|
...this.opts.environment
|
|
2252
2312
|
};
|
|
2253
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2313
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), xn), 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", Mn), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2254
2314
|
}
|
|
2255
2315
|
checkSuspension(e) {
|
|
2256
2316
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2257
|
-
let t = Math.max(this.opts.idleMs,
|
|
2317
|
+
let t = Math.max(this.opts.idleMs, yn);
|
|
2258
2318
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2259
2319
|
}
|
|
2260
2320
|
syncIdle(e) {
|
|
@@ -2268,21 +2328,21 @@ var bn = class {
|
|
|
2268
2328
|
noteStateChange(e, t, n, r) {
|
|
2269
2329
|
if (this.endedFlag || e === t) return;
|
|
2270
2330
|
let i = this.now();
|
|
2271
|
-
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(
|
|
2331
|
+
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(q, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(q, i - this.startupAnchorMs)), this.isMuted && this.mutedSinceMs === null && (this.mutedSinceMs = i)) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null, this.mutedSinceMs !== null && (this.mutedTotalMs += i - this.mutedSinceMs, this.mutedSinceMs = null)), this.isPlaying = t === "playing", this.syncActive(), t === "waiting" ? this.waitingSinceMs = i : this.waitingSinceMs !== null && (this.waitingTotalMs += i - this.waitingSinceMs, this.waitingSinceMs = null), t === "buffering" && e === "playing") {
|
|
2272
2332
|
this.stallIsSeekInduced = this.seekInduced(i);
|
|
2273
2333
|
let e = !this.isHidden && !this.stallIsSeekInduced;
|
|
2274
|
-
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(
|
|
2334
|
+
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(q, Math.round(this.playingTotalMs)));
|
|
2275
2335
|
} else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
|
|
2276
2336
|
this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
|
|
2277
2337
|
let a = {
|
|
2278
|
-
fromState:
|
|
2279
|
-
toState:
|
|
2280
|
-
presentation:
|
|
2338
|
+
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2339
|
+
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2340
|
+
presentation: wn[this.presentation]
|
|
2281
2341
|
}, o = this.causeOf(e, t, i);
|
|
2282
2342
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2283
2343
|
}
|
|
2284
2344
|
seekInduced(e) {
|
|
2285
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2345
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < Cn;
|
|
2286
2346
|
}
|
|
2287
2347
|
causeOf(e, t, n) {
|
|
2288
2348
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2319,25 +2379,25 @@ var bn = class {
|
|
|
2319
2379
|
}
|
|
2320
2380
|
this.muteChanges += 1;
|
|
2321
2381
|
let r = this.now();
|
|
2322
|
-
n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(
|
|
2382
|
+
n ? this.isPlaying && this.mutedSinceMs === null && (this.mutedSinceMs = r) : (this.mutedSinceMs !== null && (this.mutedTotalMs += r - this.mutedSinceMs, this.mutedSinceMs = null), this.firstAudioMs === 0 && this.isPlaying && (this.firstAudioMs = Math.max(q, r - this.startupAnchorMs))), this.isMuted = n, this.syncActive();
|
|
2323
2383
|
}
|
|
2324
2384
|
notePresentation(e) {
|
|
2325
2385
|
this.endedFlag || e === this.presentation || (this.closePresentation(), this.presentation = e);
|
|
2326
2386
|
}
|
|
2327
2387
|
notePlayIntent() {
|
|
2328
|
-
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs =
|
|
2388
|
+
this.endedFlag || this.startupTimeMs > 0 || (this.startupAnchorMs = this.now(), this.manifestLoadMs > 0 && (this.manifestLoadMs = q), this.firstPlaylistMs > 0 && (this.firstPlaylistMs = q), this.firstFragLoadMs > 0 && (this.firstFragLoadMs = q), this.drmSetupMs > 0 && (this.drmSetupMs = q));
|
|
2329
2389
|
}
|
|
2330
2390
|
noteReady() {
|
|
2331
|
-
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(
|
|
2391
|
+
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(q, this.now() - this.startupAnchorMs));
|
|
2332
2392
|
}
|
|
2333
2393
|
noteFirstPlaylist() {
|
|
2334
|
-
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(
|
|
2394
|
+
this.firstPlaylistMs === 0 && (this.firstPlaylistMs = Math.max(q, this.now() - this.startupAnchorMs));
|
|
2335
2395
|
}
|
|
2336
2396
|
noteDrmReady() {
|
|
2337
|
-
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(
|
|
2397
|
+
this.drmSetupMs === 0 && (this.drmSetupMs = Math.max(q, this.now() - this.startupAnchorMs));
|
|
2338
2398
|
}
|
|
2339
2399
|
noteFirstBytes() {
|
|
2340
|
-
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(
|
|
2400
|
+
this.sawFirstBytes = !0, this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(q, this.now() - this.startupAnchorMs));
|
|
2341
2401
|
}
|
|
2342
2402
|
noteSeek() {
|
|
2343
2403
|
this.endedFlag || (this.seekCount += 1, this.lastSeekMs = this.now());
|
|
@@ -2356,7 +2416,7 @@ var bn = class {
|
|
|
2356
2416
|
let r = n ?? "";
|
|
2357
2417
|
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";
|
|
2358
2418
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
2359
|
-
if (
|
|
2419
|
+
if (Dn.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2360
2420
|
let i = t ?? "";
|
|
2361
2421
|
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";
|
|
2362
2422
|
}
|
|
@@ -2388,7 +2448,7 @@ var bn = class {
|
|
|
2388
2448
|
let l = t.droppedFrames ?? 0;
|
|
2389
2449
|
l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
|
|
2390
2450
|
let u = t.renditionSwitches ?? 0;
|
|
2391
|
-
u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState =
|
|
2451
|
+
u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = J[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
|
|
2392
2452
|
let d = this.mutedTotalMs;
|
|
2393
2453
|
this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
|
|
2394
2454
|
let f = t.upshifts ?? 0;
|
|
@@ -2403,20 +2463,20 @@ var bn = class {
|
|
|
2403
2463
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2404
2464
|
o.requestCountDelta = _;
|
|
2405
2465
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2406
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2466
|
+
n.length > 0 && (o.requestTimeP50Ms = En(n, 50), o.requestTimeP95Ms = En(n, 95));
|
|
2407
2467
|
}
|
|
2408
2468
|
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();
|
|
2409
2469
|
}
|
|
2410
2470
|
maybeEmitMediaInfo(e) {
|
|
2411
2471
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2412
2472
|
let t = {};
|
|
2413
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2473
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Tn[e.keySystem]), e.drmSecurityLevel && (t.drmSecurityLevel = e.drmSecurityLevel), e.ladderHeights?.length && (t.ladderHeights = e.ladderHeights), e.ladderTopBitrateKbps && (t.ladderTopBitrateKbps = e.ladderTopBitrateKbps), e.lowLatency && (t.lowLatency = !0);
|
|
2414
2474
|
let n = JSON.stringify(t);
|
|
2415
2475
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2416
2476
|
}
|
|
2417
2477
|
end(e, t) {
|
|
2418
2478
|
if (this.endedFlag) return;
|
|
2419
|
-
this.endedFlag = !0,
|
|
2479
|
+
this.endedFlag = !0, X.delete(this);
|
|
2420
2480
|
let n = t ?? this.now();
|
|
2421
2481
|
this.playingSinceMs !== null && (this.playingTotalMs += n - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += n - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += n - this.bufferingSinceMs, this.bufferingSinceMs = null), this.mutedSinceMs !== null && (this.mutedTotalMs += n - this.mutedSinceMs, this.mutedSinceMs = null), this.waitingSinceMs !== null && (this.waitingTotalMs += n - this.waitingSinceMs, this.waitingSinceMs = null), this.isPlaying = !1, this.syncActive(n), this.closePresentation(n), this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.timer &&= (clearInterval(this.timer), null), this.idleTimer &&= (clearTimeout(this.idleTimer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), document.removeEventListener("freeze", this.onFreeze), document.removeEventListener("resume", this.onResume));
|
|
2422
2482
|
let r = this.safeSample();
|
|
@@ -2430,7 +2490,7 @@ var bn = class {
|
|
|
2430
2490
|
let c = r?.positionMs ?? 0;
|
|
2431
2491
|
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));
|
|
2432
2492
|
let l = e !== "END_REASON_ENDED";
|
|
2433
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2493
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= Sn && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Sn && (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);
|
|
2434
2494
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2435
2495
|
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");
|
|
2436
2496
|
}
|
|
@@ -2450,13 +2510,13 @@ var bn = class {
|
|
|
2450
2510
|
};
|
|
2451
2511
|
}
|
|
2452
2512
|
noteCspBlocked() {
|
|
2453
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2513
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(jn(new URL(this.url).origin)));
|
|
2454
2514
|
}
|
|
2455
2515
|
cspBlocked() {
|
|
2456
|
-
return !!this.cspKey &&
|
|
2516
|
+
return !!this.cspKey && Y.has(this.cspKey);
|
|
2457
2517
|
}
|
|
2458
2518
|
enqueue(e) {
|
|
2459
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2519
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > bn;) {
|
|
2460
2520
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2461
2521
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2462
2522
|
}
|
|
@@ -2483,7 +2543,7 @@ var bn = class {
|
|
|
2483
2543
|
};
|
|
2484
2544
|
//#endregion
|
|
2485
2545
|
//#region src/core/environment.ts
|
|
2486
|
-
function
|
|
2546
|
+
function In() {
|
|
2487
2547
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2488
2548
|
let e;
|
|
2489
2549
|
try {
|
|
@@ -2508,14 +2568,14 @@ function xn() {
|
|
|
2508
2568
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2509
2569
|
};
|
|
2510
2570
|
}
|
|
2511
|
-
function
|
|
2571
|
+
function Ln() {
|
|
2512
2572
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2513
2573
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2514
2574
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2515
2575
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2516
2576
|
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";
|
|
2517
2577
|
}
|
|
2518
|
-
function
|
|
2578
|
+
function Rn() {
|
|
2519
2579
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2520
2580
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2521
2581
|
let t = {
|
|
@@ -2534,17 +2594,17 @@ function Cn() {
|
|
|
2534
2594
|
}
|
|
2535
2595
|
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;
|
|
2536
2596
|
}
|
|
2537
|
-
function
|
|
2538
|
-
let t =
|
|
2539
|
-
deviceClass:
|
|
2597
|
+
function zn(e) {
|
|
2598
|
+
let t = In(), n = {
|
|
2599
|
+
deviceClass: Ln(),
|
|
2540
2600
|
integration: t.integration,
|
|
2541
|
-
...
|
|
2601
|
+
...Rn()
|
|
2542
2602
|
};
|
|
2543
2603
|
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);
|
|
2544
2604
|
let r = e.getBoundingClientRect?.();
|
|
2545
2605
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2546
2606
|
}
|
|
2547
|
-
async function
|
|
2607
|
+
async function Bn() {
|
|
2548
2608
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2549
2609
|
if (!e?.getHighEntropyValues) return {};
|
|
2550
2610
|
try {
|
|
@@ -2556,7 +2616,7 @@ async function Tn() {
|
|
|
2556
2616
|
}
|
|
2557
2617
|
//#endregion
|
|
2558
2618
|
//#region src/core/version.ts
|
|
2559
|
-
var
|
|
2619
|
+
var Vn = "2.18.0", Hn = {
|
|
2560
2620
|
accent: "#E1B600",
|
|
2561
2621
|
accentText: "#1B1C23",
|
|
2562
2622
|
background: "#0e0f13",
|
|
@@ -2567,7 +2627,7 @@ var En = "2.17.0", Dn = {
|
|
|
2567
2627
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2568
2628
|
radius: "8px",
|
|
2569
2629
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2570
|
-
},
|
|
2630
|
+
}, Un = {
|
|
2571
2631
|
accent: "--havik-accent",
|
|
2572
2632
|
accentText: "--havik-accent-text",
|
|
2573
2633
|
background: "--havik-bg",
|
|
@@ -2579,26 +2639,26 @@ var En = "2.17.0", Dn = {
|
|
|
2579
2639
|
radius: "--havik-radius",
|
|
2580
2640
|
fontFamily: "--havik-font"
|
|
2581
2641
|
};
|
|
2582
|
-
function
|
|
2642
|
+
function Wn(e, t) {
|
|
2583
2643
|
let n = {
|
|
2584
|
-
...
|
|
2644
|
+
...Hn,
|
|
2585
2645
|
...t
|
|
2586
2646
|
};
|
|
2587
|
-
for (let t of Object.keys(
|
|
2647
|
+
for (let t of Object.keys(Un)) e.style.setProperty(Un[t], n[t]);
|
|
2588
2648
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2589
2649
|
}
|
|
2590
2650
|
//#endregion
|
|
2591
2651
|
//#region src/ui/styles.ts
|
|
2592
|
-
var
|
|
2593
|
-
function
|
|
2594
|
-
let n = e.querySelector(`style#${
|
|
2595
|
-
if (n && (!t ||
|
|
2652
|
+
var Gn = "havik-player-styles", Kn = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", Z = /* @__PURE__ */ new WeakMap();
|
|
2653
|
+
function qn(e = document, t) {
|
|
2654
|
+
let n = e.querySelector(`style#${Gn}`);
|
|
2655
|
+
if (n && (!t || Z.get(n) === t)) return;
|
|
2596
2656
|
let r = e.createElement("style");
|
|
2597
|
-
r.id =
|
|
2657
|
+
r.id = Gn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = Kn, Z.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2598
2658
|
}
|
|
2599
2659
|
//#endregion
|
|
2600
2660
|
//#region src/ui/icons.ts
|
|
2601
|
-
var
|
|
2661
|
+
var Jn = {
|
|
2602
2662
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2603
2663
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2604
2664
|
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\"/>",
|
|
@@ -2612,20 +2672,20 @@ var Pn = {
|
|
|
2612
2672
|
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\"/>"
|
|
2613
2673
|
};
|
|
2614
2674
|
function Q(e) {
|
|
2615
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2675
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Jn[e]}</svg>`;
|
|
2616
2676
|
}
|
|
2617
2677
|
//#endregion
|
|
2618
2678
|
//#region src/ui/controls.ts
|
|
2619
|
-
var
|
|
2679
|
+
var Yn = 3e3, Xn = 250, Zn = /* @__PURE__ */ new Set([
|
|
2620
2680
|
"GONE",
|
|
2621
2681
|
"NOT_FOUND",
|
|
2622
2682
|
"INVALID_URN",
|
|
2623
2683
|
"UNAUTHORIZED"
|
|
2624
2684
|
]);
|
|
2625
|
-
function
|
|
2626
|
-
return new
|
|
2685
|
+
function Qn(e) {
|
|
2686
|
+
return new $n(e);
|
|
2627
2687
|
}
|
|
2628
|
-
var
|
|
2688
|
+
var $n = class {
|
|
2629
2689
|
root;
|
|
2630
2690
|
video;
|
|
2631
2691
|
player;
|
|
@@ -2672,7 +2732,7 @@ var zn = class {
|
|
|
2672
2732
|
scrubbing = !1;
|
|
2673
2733
|
offFns = [];
|
|
2674
2734
|
constructor(e) {
|
|
2675
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2735
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Yn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, qn(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");
|
|
2676
2736
|
let t = (e, t, n) => {
|
|
2677
2737
|
let r = this.doc.createElement(e);
|
|
2678
2738
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2758,7 +2818,7 @@ var zn = class {
|
|
|
2758
2818
|
let t = this.surfaceWasHidden;
|
|
2759
2819
|
this.tapTimer = setTimeout(() => {
|
|
2760
2820
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2761
|
-
},
|
|
2821
|
+
}, Xn);
|
|
2762
2822
|
}
|
|
2763
2823
|
toggleBar(e) {
|
|
2764
2824
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2793,7 +2853,7 @@ var zn = class {
|
|
|
2793
2853
|
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);
|
|
2794
2854
|
} else {
|
|
2795
2855
|
let r = this.doc.createElement("div");
|
|
2796
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2856
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !Zn.has(this.lastError.code)) {
|
|
2797
2857
|
let e = this.doc.createElement("button");
|
|
2798
2858
|
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);
|
|
2799
2859
|
}
|
|
@@ -2834,7 +2894,7 @@ var zn = class {
|
|
|
2834
2894
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2835
2895
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2836
2896
|
}
|
|
2837
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2897
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${er(this.video.currentTime)} / ${er(this.video.duration)}`);
|
|
2838
2898
|
}
|
|
2839
2899
|
syncLive() {
|
|
2840
2900
|
let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
|
|
@@ -2884,17 +2944,17 @@ var zn = class {
|
|
|
2884
2944
|
renderQualityMenu() {
|
|
2885
2945
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2886
2946
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2887
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2947
|
+
for (let n of e) this.menu.append(this.menuItem(tr(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2888
2948
|
}
|
|
2889
2949
|
renderAudioMenu() {
|
|
2890
2950
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2891
2951
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2892
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2952
|
+
for (let t of e) this.menu.append(this.menuItem(nr(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2893
2953
|
}
|
|
2894
2954
|
renderCcMenu() {
|
|
2895
2955
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2896
2956
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2897
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2957
|
+
for (let t of e) this.menu.append(this.menuItem(rr(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2898
2958
|
}
|
|
2899
2959
|
onTracksChanged() {
|
|
2900
2960
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2914,11 +2974,11 @@ var zn = class {
|
|
|
2914
2974
|
}
|
|
2915
2975
|
async toggleFullscreen() {
|
|
2916
2976
|
try {
|
|
2917
|
-
|
|
2977
|
+
x(this.video, this.root) ? await C(this.video, this.root) : await S(this.video, this.root);
|
|
2918
2978
|
} catch {}
|
|
2919
2979
|
}
|
|
2920
2980
|
syncFullscreen() {
|
|
2921
|
-
let e =
|
|
2981
|
+
let e = x(this.video, this.root);
|
|
2922
2982
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
2923
2983
|
}
|
|
2924
2984
|
poke() {
|
|
@@ -2995,41 +3055,41 @@ var zn = class {
|
|
|
2995
3055
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2996
3056
|
}
|
|
2997
3057
|
};
|
|
2998
|
-
function
|
|
3058
|
+
function er(e) {
|
|
2999
3059
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
3000
3060
|
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");
|
|
3001
3061
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
3002
3062
|
}
|
|
3003
|
-
function
|
|
3063
|
+
function tr(e) {
|
|
3004
3064
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
3005
3065
|
}
|
|
3006
|
-
function
|
|
3066
|
+
function nr(e) {
|
|
3007
3067
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3008
3068
|
}
|
|
3009
|
-
function
|
|
3069
|
+
function rr(e) {
|
|
3010
3070
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3011
3071
|
}
|
|
3012
3072
|
//#endregion
|
|
3013
3073
|
//#region src/managed/index.ts
|
|
3014
|
-
var
|
|
3015
|
-
function
|
|
3074
|
+
var ir = 6e3, ar = 45e3, or = 2e3, sr = 3, cr = 5e3, lr = 2e3, ur = 48e4, dr = "keySystemLicenseRequestFailed";
|
|
3075
|
+
function fr(e) {
|
|
3016
3076
|
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)})`);
|
|
3017
|
-
if (e.env !== void 0) return
|
|
3077
|
+
if (e.env !== void 0) return L(e.env);
|
|
3018
3078
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
3019
3079
|
return e.baseUrl;
|
|
3020
3080
|
}
|
|
3021
|
-
async function
|
|
3081
|
+
async function pr(e) {
|
|
3022
3082
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
3023
|
-
let t =
|
|
3083
|
+
let t = fr(e);
|
|
3024
3084
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
3025
3085
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
3026
|
-
let r = new
|
|
3086
|
+
let r = new mr({
|
|
3027
3087
|
...e,
|
|
3028
3088
|
baseUrl: t
|
|
3029
3089
|
});
|
|
3030
3090
|
return await r.start(), r;
|
|
3031
3091
|
}
|
|
3032
|
-
var
|
|
3092
|
+
var mr = class {
|
|
3033
3093
|
opts;
|
|
3034
3094
|
abort = new AbortController();
|
|
3035
3095
|
listeners = {};
|
|
@@ -3080,7 +3140,7 @@ var er = class {
|
|
|
3080
3140
|
this.opts.muted && (this.opts.video.muted = !0), this.opts.poster && (this.opts.video.poster = this.opts.poster), this.mountControls(), this.attachPipListeners(), this.attachEndedPlayGuard(), this.setState("loading");
|
|
3081
3141
|
let e = ++this.loadGen, t = this.resolveOptions();
|
|
3082
3142
|
try {
|
|
3083
|
-
let n = await
|
|
3143
|
+
let n = await v(t);
|
|
3084
3144
|
if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
|
|
3085
3145
|
let e = this._lastError;
|
|
3086
3146
|
throw this.destroy(), e;
|
|
@@ -3103,11 +3163,11 @@ var er = class {
|
|
|
3103
3163
|
};
|
|
3104
3164
|
}
|
|
3105
3165
|
beginArming(e, t, n = !1) {
|
|
3106
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
3166
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? T(this.opts.baseUrl);
|
|
3107
3167
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
3108
3168
|
}
|
|
3109
3169
|
beginArmingByPolling(e) {
|
|
3110
|
-
|
|
3170
|
+
y({
|
|
3111
3171
|
...this.resolveOptions(),
|
|
3112
3172
|
signal: this.abort.signal,
|
|
3113
3173
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -3124,7 +3184,7 @@ var er = class {
|
|
|
3124
3184
|
setTimeout(() => {
|
|
3125
3185
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3126
3186
|
phase: i ? "unavailable" : "tooEarly",
|
|
3127
|
-
retryInMs:
|
|
3187
|
+
retryInMs: ar,
|
|
3128
3188
|
attempt: 1,
|
|
3129
3189
|
elapsedMs: 0,
|
|
3130
3190
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3141,7 +3201,7 @@ var er = class {
|
|
|
3141
3201
|
}
|
|
3142
3202
|
}
|
|
3143
3203
|
}, h = () => {
|
|
3144
|
-
a || s || p() || (s = !0,
|
|
3204
|
+
a || s || p() || (s = !0, y({
|
|
3145
3205
|
...this.resolveOptions(),
|
|
3146
3206
|
signal: c.signal,
|
|
3147
3207
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -3149,7 +3209,7 @@ var er = class {
|
|
|
3149
3209
|
a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
|
|
3150
3210
|
}));
|
|
3151
3211
|
}, g = () => {
|
|
3152
|
-
a || p() ||
|
|
3212
|
+
a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
|
|
3153
3213
|
if (!(a || p())) {
|
|
3154
3214
|
if (e instanceof n && o(e.code)) {
|
|
3155
3215
|
h();
|
|
@@ -3163,13 +3223,13 @@ var er = class {
|
|
|
3163
3223
|
!a && !p() && h();
|
|
3164
3224
|
}, e);
|
|
3165
3225
|
};
|
|
3166
|
-
_(
|
|
3226
|
+
_(ir), this.armingSub = w({
|
|
3167
3227
|
eventsBaseUrl: t,
|
|
3168
3228
|
matchUrn: this.opts.matchUrn,
|
|
3169
3229
|
credential: this.opts.credential,
|
|
3170
|
-
onAlive: () => _(
|
|
3230
|
+
onAlive: () => _(ar),
|
|
3171
3231
|
onState: (e) => {
|
|
3172
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3232
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * or);
|
|
3173
3233
|
},
|
|
3174
3234
|
onError: () => h()
|
|
3175
3235
|
});
|
|
@@ -3192,7 +3252,7 @@ var er = class {
|
|
|
3192
3252
|
let n = await s(this.opts.credential);
|
|
3193
3253
|
if (this.destroyed || t !== this.loadGen) return;
|
|
3194
3254
|
this.setState("loading");
|
|
3195
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
3255
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = ct(this.opts.video, (e) => {
|
|
3196
3256
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
3197
3257
|
});
|
|
3198
3258
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -3214,26 +3274,26 @@ var er = class {
|
|
|
3214
3274
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3215
3275
|
let i = e.analytics?.sid;
|
|
3216
3276
|
if (!i) return;
|
|
3217
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3277
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Pn(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3218
3278
|
if (!o) {
|
|
3219
3279
|
s && setTimeout(() => {
|
|
3220
3280
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3221
3281
|
}, 0);
|
|
3222
3282
|
return;
|
|
3223
3283
|
}
|
|
3224
|
-
let c = this.opts.video, l = new
|
|
3284
|
+
let c = this.opts.video, l = new Fn({
|
|
3225
3285
|
endpoint: o,
|
|
3226
3286
|
sid: i,
|
|
3227
3287
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3228
|
-
sdkVersion:
|
|
3229
|
-
environment:
|
|
3288
|
+
sdkVersion: Vn,
|
|
3289
|
+
environment: zn(c),
|
|
3230
3290
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3231
3291
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3232
3292
|
onBlocked: (e) => setTimeout(() => {
|
|
3233
3293
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, e));
|
|
3234
3294
|
}, 0),
|
|
3235
3295
|
sample: () => {
|
|
3236
|
-
let e = this.engine?.getStats() ??
|
|
3296
|
+
let e = this.engine?.getStats() ?? R, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
3237
3297
|
return {
|
|
3238
3298
|
...e,
|
|
3239
3299
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -3247,7 +3307,7 @@ var er = class {
|
|
|
3247
3307
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3248
3308
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3249
3309
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3250
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3310
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), Bn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3251
3311
|
}
|
|
3252
3312
|
currentPresentation() {
|
|
3253
3313
|
let e = this.opts.video;
|
|
@@ -3262,10 +3322,11 @@ var er = class {
|
|
|
3262
3322
|
video: this.opts.video,
|
|
3263
3323
|
descriptor: e,
|
|
3264
3324
|
credential: t,
|
|
3265
|
-
deviceId:
|
|
3325
|
+
deviceId: O(),
|
|
3266
3326
|
userId: this.opts.userId,
|
|
3267
3327
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
3268
3328
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
3329
|
+
rememberBandwidth: this.opts.rememberBandwidth,
|
|
3269
3330
|
mediaDuringKey: this.opts.mediaDuringKey,
|
|
3270
3331
|
debug: this.opts.debug,
|
|
3271
3332
|
deferLoad: r,
|
|
@@ -3274,9 +3335,9 @@ var er = class {
|
|
|
3274
3335
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3275
3336
|
}, o = this.opts.engine ?? "auto";
|
|
3276
3337
|
if (o === "native") return new W(a);
|
|
3277
|
-
if (o === "hls") return new
|
|
3278
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled &&
|
|
3279
|
-
if (
|
|
3338
|
+
if (o === "hls") return new gn(a);
|
|
3339
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled && bt() && H(this.opts.video)) return new W(a);
|
|
3340
|
+
if (Mt()) return new gn(a);
|
|
3280
3341
|
if (H(this.opts.video)) return new W(a);
|
|
3281
3342
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3282
3343
|
}
|
|
@@ -3324,11 +3385,11 @@ var er = class {
|
|
|
3324
3385
|
}
|
|
3325
3386
|
startLiveState(e) {
|
|
3326
3387
|
if (this.opts.liveStateEvents === !1) return;
|
|
3327
|
-
let t = this.opts.eventsBaseUrl ??
|
|
3388
|
+
let t = this.opts.eventsBaseUrl ?? T(this.opts.baseUrl);
|
|
3328
3389
|
if (!t) return;
|
|
3329
3390
|
this.closeLiveState();
|
|
3330
3391
|
let r = 0, i = !1;
|
|
3331
|
-
this.liveStateSub =
|
|
3392
|
+
this.liveStateSub = w({
|
|
3332
3393
|
eventsBaseUrl: t,
|
|
3333
3394
|
matchUrn: this.opts.matchUrn,
|
|
3334
3395
|
credential: this.opts.credential,
|
|
@@ -3339,7 +3400,7 @@ var er = class {
|
|
|
3339
3400
|
r = 0, i = !1;
|
|
3340
3401
|
},
|
|
3341
3402
|
onError: () => {
|
|
3342
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
3403
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= sr && (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.`))));
|
|
3343
3404
|
}
|
|
3344
3405
|
});
|
|
3345
3406
|
}
|
|
@@ -3353,7 +3414,7 @@ var er = class {
|
|
|
3353
3414
|
return;
|
|
3354
3415
|
}
|
|
3355
3416
|
let e = this.hiddenAtMs;
|
|
3356
|
-
this.hiddenAtMs = null, e != null && Date.now() - e >=
|
|
3417
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= cr && this.resyncLiveState();
|
|
3357
3418
|
}, this.onReturnPageShow = (e) => {
|
|
3358
3419
|
e.persisted && this.resyncLiveState();
|
|
3359
3420
|
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
@@ -3385,7 +3446,7 @@ var er = class {
|
|
|
3385
3446
|
scheduleRejoin(e) {
|
|
3386
3447
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3387
3448
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3388
|
-
}, Math.random() *
|
|
3449
|
+
}, Math.random() * or));
|
|
3389
3450
|
}
|
|
3390
3451
|
cancelRejoin() {
|
|
3391
3452
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3409,7 +3470,7 @@ var er = class {
|
|
|
3409
3470
|
}
|
|
3410
3471
|
t.controls = !1;
|
|
3411
3472
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3412
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3473
|
+
r && r.insertBefore(n, t), n.appendChild(t), Wn(n, this.opts.theme), this.container = n, this.controlBar = Qn({
|
|
3413
3474
|
root: n,
|
|
3414
3475
|
video: t,
|
|
3415
3476
|
player: this,
|
|
@@ -3447,7 +3508,7 @@ var er = class {
|
|
|
3447
3508
|
}
|
|
3448
3509
|
startStats() {
|
|
3449
3510
|
this.stopStats();
|
|
3450
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3511
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? lr);
|
|
3451
3512
|
this.statsTimer = setInterval(() => {
|
|
3452
3513
|
if (!this.engine) return;
|
|
3453
3514
|
let e = this.engine.getStats();
|
|
@@ -3458,14 +3519,14 @@ var er = class {
|
|
|
3458
3519
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3459
3520
|
}
|
|
3460
3521
|
isStaleLicenseDenial(e) {
|
|
3461
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3522
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== dr || e.error.httpStatus !== 403 ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3462
3523
|
}
|
|
3463
3524
|
scheduleLicenseRefresh() {
|
|
3464
3525
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3465
3526
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3466
3527
|
document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3467
3528
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3468
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3529
|
+
let e = this.opts.licenseRefreshMs ?? ur;
|
|
3469
3530
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3470
3531
|
}
|
|
3471
3532
|
stopRefresh() {
|
|
@@ -3477,7 +3538,7 @@ var er = class {
|
|
|
3477
3538
|
if (this.refreshInFlight?.engine === e) return this.refreshInFlight.promise;
|
|
3478
3539
|
let t = (async () => {
|
|
3479
3540
|
try {
|
|
3480
|
-
let t = await
|
|
3541
|
+
let t = await v(this.resolveOptions());
|
|
3481
3542
|
if (this.destroyed || this.engine !== e) return;
|
|
3482
3543
|
let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
|
|
3483
3544
|
return (n || r) && (e.setLicenseUrls({
|
|
@@ -3522,7 +3583,7 @@ var er = class {
|
|
|
3522
3583
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
3523
3584
|
}
|
|
3524
3585
|
getStats() {
|
|
3525
|
-
return this.engine?.getStats() ??
|
|
3586
|
+
return this.engine?.getStats() ?? R;
|
|
3526
3587
|
}
|
|
3527
3588
|
getQualityLevels() {
|
|
3528
3589
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3561,10 +3622,10 @@ var er = class {
|
|
|
3561
3622
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
3562
3623
|
}
|
|
3563
3624
|
async enterFullscreen() {
|
|
3564
|
-
return !this.destroyed &&
|
|
3625
|
+
return !this.destroyed && S(this.opts.video, this.container ?? void 0);
|
|
3565
3626
|
}
|
|
3566
3627
|
async exitFullscreen() {
|
|
3567
|
-
await
|
|
3628
|
+
await C(this.opts.video, this.container ?? void 0);
|
|
3568
3629
|
}
|
|
3569
3630
|
retry() {
|
|
3570
3631
|
return this.reload();
|
|
@@ -3574,7 +3635,7 @@ var er = class {
|
|
|
3574
3635
|
let e = ++this.loadGen;
|
|
3575
3636
|
this.teardownPlayback();
|
|
3576
3637
|
try {
|
|
3577
|
-
let t = await
|
|
3638
|
+
let t = await y({
|
|
3578
3639
|
...this.resolveOptions(),
|
|
3579
3640
|
waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
|
|
3580
3641
|
});
|
|
@@ -3632,7 +3693,7 @@ function $(e) {
|
|
|
3632
3693
|
}
|
|
3633
3694
|
//#endregion
|
|
3634
3695
|
//#region src/embed/host.ts
|
|
3635
|
-
function
|
|
3696
|
+
function hr(e) {
|
|
3636
3697
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3637
3698
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3638
3699
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3691,15 +3752,15 @@ function tr(e) {
|
|
|
3691
3752
|
}
|
|
3692
3753
|
//#endregion
|
|
3693
3754
|
//#region src/embed/page.ts
|
|
3694
|
-
var
|
|
3695
|
-
function
|
|
3755
|
+
var gr = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3756
|
+
function _r(e) {
|
|
3696
3757
|
if (typeof e == "boolean") return e;
|
|
3697
3758
|
if (typeof e == "object" && e) {
|
|
3698
3759
|
let t = e.endpoint;
|
|
3699
3760
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3700
3761
|
}
|
|
3701
3762
|
}
|
|
3702
|
-
function
|
|
3763
|
+
function vr() {
|
|
3703
3764
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3704
3765
|
if (e) return {
|
|
3705
3766
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3709,7 +3770,7 @@ function ir() {
|
|
|
3709
3770
|
autoplay: e.autoplay ?? !0,
|
|
3710
3771
|
muted: e.muted ?? !0,
|
|
3711
3772
|
waitForLive: e.waitForLive ?? !0,
|
|
3712
|
-
analytics:
|
|
3773
|
+
analytics: _r(e.analytics)
|
|
3713
3774
|
};
|
|
3714
3775
|
let t = new URLSearchParams(location.search);
|
|
3715
3776
|
return {
|
|
@@ -3722,9 +3783,9 @@ function ir() {
|
|
|
3722
3783
|
waitForLive: !0
|
|
3723
3784
|
};
|
|
3724
3785
|
}
|
|
3725
|
-
async function
|
|
3726
|
-
let e =
|
|
3727
|
-
|
|
3786
|
+
async function yr() {
|
|
3787
|
+
let e = vr();
|
|
3788
|
+
xr();
|
|
3728
3789
|
let t = document.createElement("video");
|
|
3729
3790
|
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);
|
|
3730
3791
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3779,12 +3840,12 @@ async function ar() {
|
|
|
3779
3840
|
code: e.code,
|
|
3780
3841
|
message: e.message
|
|
3781
3842
|
})), e.on("autoplayblocked", () => {
|
|
3782
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3843
|
+
i({ type: "oddin:autoplayblocked" }), br(t, e);
|
|
3783
3844
|
});
|
|
3784
3845
|
}, s = async (r) => {
|
|
3785
3846
|
a?.destroy(), a = null;
|
|
3786
3847
|
try {
|
|
3787
|
-
let n = await
|
|
3848
|
+
let n = await pr({
|
|
3788
3849
|
video: t,
|
|
3789
3850
|
baseUrl: e.baseUrl,
|
|
3790
3851
|
matchUrn: r,
|
|
@@ -3846,7 +3907,7 @@ async function ar() {
|
|
|
3846
3907
|
a?.retry();
|
|
3847
3908
|
break;
|
|
3848
3909
|
case "oddin:load":
|
|
3849
|
-
typeof e.matchUrn == "string" &&
|
|
3910
|
+
typeof e.matchUrn == "string" && gr.test(e.matchUrn) && s(e.matchUrn);
|
|
3850
3911
|
break;
|
|
3851
3912
|
case "oddin:destroy": c();
|
|
3852
3913
|
}
|
|
@@ -3858,18 +3919,18 @@ async function ar() {
|
|
|
3858
3919
|
protocol: 1
|
|
3859
3920
|
});
|
|
3860
3921
|
}
|
|
3861
|
-
function
|
|
3922
|
+
function br(e, t) {
|
|
3862
3923
|
if (document.getElementById("havik-tap")) return;
|
|
3863
3924
|
let n = document.createElement("button");
|
|
3864
3925
|
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", () => {
|
|
3865
3926
|
n.remove(), t.play();
|
|
3866
3927
|
}), document.body.appendChild(n);
|
|
3867
3928
|
}
|
|
3868
|
-
function
|
|
3929
|
+
function xr() {
|
|
3869
3930
|
let e = document.createElement("style");
|
|
3870
3931
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3871
3932
|
}
|
|
3872
3933
|
//#endregion
|
|
3873
|
-
export {
|
|
3934
|
+
export { Hn as ODDIN_THEME, n as PlaybackError, Wn as applyTheme, L as baseUrlForEnv, yr as bootEmbed, Ee as clearDeviceId, Re as clearRememberedBandwidth, pr as createPlayer, T as deriveEventsBaseUrl, tt as detectDrmSupport, S as enterVideoFullscreen, C as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, O as getDeviceId, rt as isLowLatencyManifest, $ as isOddinMessage, Oe as licenseRequestHeaders, hr as mountEmbed, de as pollToLive, y as resolveStream, w as subscribeLiveState, x as videoFullscreenActive, we as watchStatus };
|
|
3874
3935
|
|
|
3875
3936
|
//# sourceMappingURL=index.js.map
|