@oddin-gg/havik-player 2.3.0 → 2.4.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 +11 -11
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +175 -162
- package/dist/index.js.map +1 -1
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -241,35 +241,35 @@ function ce(e, t) {
|
|
|
241
241
|
}
|
|
242
242
|
//#endregion
|
|
243
243
|
//#region src/core/fullscreen.ts
|
|
244
|
-
function
|
|
244
|
+
function S(e) {
|
|
245
245
|
return e.ownerDocument ?? document;
|
|
246
246
|
}
|
|
247
|
-
function
|
|
247
|
+
function le(e) {
|
|
248
248
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
249
249
|
}
|
|
250
|
-
function
|
|
251
|
-
let n =
|
|
250
|
+
function C(e, t) {
|
|
251
|
+
let n = le(S(e));
|
|
252
252
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
253
253
|
}
|
|
254
|
-
async function
|
|
254
|
+
async function w(e, t) {
|
|
255
255
|
let n = t ?? e;
|
|
256
256
|
if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
|
|
257
257
|
if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
|
|
258
258
|
let r = e;
|
|
259
259
|
return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
|
|
260
260
|
}
|
|
261
|
-
async function
|
|
261
|
+
async function T(e, t) {
|
|
262
262
|
let n = e;
|
|
263
263
|
if (n.webkitDisplayingFullscreen) {
|
|
264
264
|
n.webkitExitFullscreen?.();
|
|
265
265
|
return;
|
|
266
266
|
}
|
|
267
|
-
let r =
|
|
267
|
+
let r = S(e), i = le(r);
|
|
268
268
|
i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
|
|
269
269
|
}
|
|
270
270
|
//#endregion
|
|
271
271
|
//#region src/core/catalog.ts
|
|
272
|
-
async function
|
|
272
|
+
async function ue(e) {
|
|
273
273
|
let t = new URLSearchParams();
|
|
274
274
|
e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
|
|
275
275
|
let i = t.toString(), a = c(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
|
|
@@ -287,12 +287,12 @@ async function de(e) {
|
|
|
287
287
|
};
|
|
288
288
|
if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
|
|
289
289
|
return {
|
|
290
|
-
tournaments:
|
|
290
|
+
tournaments: de(await s.json()),
|
|
291
291
|
etag: s.headers.get("etag") ?? void 0,
|
|
292
292
|
notModified: !1
|
|
293
293
|
};
|
|
294
294
|
}
|
|
295
|
-
function
|
|
295
|
+
function de(e) {
|
|
296
296
|
return (e.tournaments ?? []).map((e) => {
|
|
297
297
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
298
298
|
return {
|
|
@@ -312,7 +312,7 @@ function fe(e) {
|
|
|
312
312
|
};
|
|
313
313
|
});
|
|
314
314
|
}
|
|
315
|
-
async function
|
|
315
|
+
async function fe(e) {
|
|
316
316
|
let t = c(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
317
317
|
e.etag && i.set("If-None-Match", e.etag);
|
|
318
318
|
let a = await u(t, {
|
|
@@ -332,13 +332,13 @@ async function pe(e) {
|
|
|
332
332
|
};
|
|
333
333
|
if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
334
334
|
return {
|
|
335
|
-
tournament:
|
|
335
|
+
tournament: pe(await a.json()),
|
|
336
336
|
etag: a.headers.get("etag") ?? void 0,
|
|
337
337
|
notModified: !1,
|
|
338
338
|
notFound: !1
|
|
339
339
|
};
|
|
340
340
|
}
|
|
341
|
-
function
|
|
341
|
+
function pe(e) {
|
|
342
342
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
343
343
|
return {
|
|
344
344
|
urn: t,
|
|
@@ -356,12 +356,12 @@ function me(e) {
|
|
|
356
356
|
}))
|
|
357
357
|
};
|
|
358
358
|
}
|
|
359
|
-
function
|
|
359
|
+
function me(e) {
|
|
360
360
|
return e.tournaments.flatMap((e) => e.matches);
|
|
361
361
|
}
|
|
362
362
|
//#endregion
|
|
363
363
|
//#region src/core/poll.ts
|
|
364
|
-
function
|
|
364
|
+
function he(e) {
|
|
365
365
|
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, l = !1, d = () => {
|
|
366
366
|
l || (a = setTimeout(f, t));
|
|
367
367
|
}, f = async () => {
|
|
@@ -397,7 +397,7 @@ function ge(e) {
|
|
|
397
397
|
}
|
|
398
398
|
//#endregion
|
|
399
399
|
//#region src/core/events.ts
|
|
400
|
-
function
|
|
400
|
+
function E(e) {
|
|
401
401
|
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = new AbortController(), i = !1, a = (e) => new Promise((t) => {
|
|
402
402
|
if (r.signal.aborted) return t();
|
|
403
403
|
let n = setTimeout(t, e);
|
|
@@ -464,7 +464,7 @@ function T(e) {
|
|
|
464
464
|
i || (i = !0, r.abort());
|
|
465
465
|
} };
|
|
466
466
|
}
|
|
467
|
-
function
|
|
467
|
+
function D(e) {
|
|
468
468
|
try {
|
|
469
469
|
let t = new URL(e);
|
|
470
470
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -474,27 +474,27 @@ function E(e) {
|
|
|
474
474
|
}
|
|
475
475
|
//#endregion
|
|
476
476
|
//#region src/core/drm/deviceId.ts
|
|
477
|
-
var
|
|
478
|
-
function
|
|
479
|
-
if (
|
|
477
|
+
var O = "havik.player.deviceId", k;
|
|
478
|
+
function A() {
|
|
479
|
+
if (k) return k;
|
|
480
480
|
try {
|
|
481
|
-
let e = globalThis.localStorage?.getItem(
|
|
482
|
-
if (e) return
|
|
481
|
+
let e = globalThis.localStorage?.getItem(O);
|
|
482
|
+
if (e) return k = e, e;
|
|
483
483
|
} catch {}
|
|
484
|
-
let e =
|
|
485
|
-
|
|
484
|
+
let e = _e();
|
|
485
|
+
k = e;
|
|
486
486
|
try {
|
|
487
|
-
globalThis.localStorage?.setItem(
|
|
487
|
+
globalThis.localStorage?.setItem(O, e);
|
|
488
488
|
} catch {}
|
|
489
489
|
return e;
|
|
490
490
|
}
|
|
491
|
-
function
|
|
492
|
-
|
|
491
|
+
function ge() {
|
|
492
|
+
k = void 0;
|
|
493
493
|
try {
|
|
494
|
-
globalThis.localStorage?.removeItem(
|
|
494
|
+
globalThis.localStorage?.removeItem(O);
|
|
495
495
|
} catch {}
|
|
496
496
|
}
|
|
497
|
-
function
|
|
497
|
+
function _e() {
|
|
498
498
|
let e = globalThis.crypto;
|
|
499
499
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
500
500
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -506,21 +506,21 @@ function ve() {
|
|
|
506
506
|
}
|
|
507
507
|
//#endregion
|
|
508
508
|
//#region src/core/drm/headers.ts
|
|
509
|
-
function
|
|
509
|
+
function ve(e, t, n = {}) {
|
|
510
510
|
let r = {
|
|
511
511
|
"x-api-key": t.apiKey,
|
|
512
512
|
"X-Match-Urn": e.matchUrn,
|
|
513
|
-
"X-Device-Id": n.deviceId ??
|
|
513
|
+
"X-Device-Id": n.deviceId ?? A(),
|
|
514
514
|
"Content-Type": "application/octet-stream"
|
|
515
515
|
};
|
|
516
516
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
517
517
|
}
|
|
518
518
|
//#endregion
|
|
519
519
|
//#region src/core/drm/cdm.ts
|
|
520
|
-
var
|
|
521
|
-
function
|
|
522
|
-
let n =
|
|
523
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
520
|
+
var j = /* @__PURE__ */ new WeakMap();
|
|
521
|
+
function ye(e, t) {
|
|
522
|
+
let n = j.get(e);
|
|
523
|
+
n || (n = /* @__PURE__ */ new Map(), j.set(e, n));
|
|
524
524
|
let r = n.get(t.keySystem);
|
|
525
525
|
if (r) return r;
|
|
526
526
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -528,22 +528,22 @@ function be(e, t) {
|
|
|
528
528
|
});
|
|
529
529
|
return n.set(t.keySystem, i), i;
|
|
530
530
|
}
|
|
531
|
-
function
|
|
531
|
+
function M() {
|
|
532
532
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
533
533
|
}
|
|
534
|
-
var
|
|
535
|
-
function
|
|
534
|
+
var N = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
535
|
+
function be(e) {
|
|
536
536
|
return e.startsWith("com.widevine");
|
|
537
537
|
}
|
|
538
|
-
function
|
|
539
|
-
if (!
|
|
538
|
+
function P(e, t) {
|
|
539
|
+
if (!be(e)) return t;
|
|
540
540
|
let n = (e, t) => {
|
|
541
541
|
let n = e.videoCapabilities;
|
|
542
542
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
543
|
-
let n =
|
|
544
|
-
return n === -1 ||
|
|
543
|
+
let n = N.indexOf(e.robustness);
|
|
544
|
+
return n === -1 || N.indexOf(t) > n;
|
|
545
545
|
});
|
|
546
|
-
}, r =
|
|
546
|
+
}, r = N.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
547
547
|
...t,
|
|
548
548
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
549
549
|
...t,
|
|
@@ -552,16 +552,16 @@ function N(e, t) {
|
|
|
552
552
|
})));
|
|
553
553
|
return [...t, ...r];
|
|
554
554
|
}
|
|
555
|
-
function
|
|
556
|
-
return (t, n) =>
|
|
555
|
+
function xe(e) {
|
|
556
|
+
return (t, n) => M() ? navigator.requestMediaKeySystemAccess(t, P(t, n)).then((t) => ({
|
|
557
557
|
keySystem: t.keySystem,
|
|
558
558
|
getConfiguration: () => t.getConfiguration(),
|
|
559
|
-
createMediaKeys: () =>
|
|
559
|
+
createMediaKeys: () => ye(e, t)
|
|
560
560
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
561
561
|
}
|
|
562
562
|
//#endregion
|
|
563
563
|
//#region src/core/drm/support.ts
|
|
564
|
-
var
|
|
564
|
+
var Se = 5e3, Ce = "video/mp4; codecs=\"avc1.42E01E\"", we = "audio/mp4; codecs=\"mp4a.40.2\"", Te = {
|
|
565
565
|
widevine: ["com.widevine.alpha"],
|
|
566
566
|
fairplay: ["com.apple.fps"]
|
|
567
567
|
};
|
|
@@ -573,24 +573,24 @@ function Ee(e) {
|
|
|
573
573
|
"cenc"
|
|
574
574
|
],
|
|
575
575
|
videoCapabilities: [{
|
|
576
|
-
contentType:
|
|
576
|
+
contentType: Ce,
|
|
577
577
|
robustness: "",
|
|
578
578
|
encryptionScheme: "cbcs"
|
|
579
579
|
}],
|
|
580
580
|
audioCapabilities: [{
|
|
581
|
-
contentType:
|
|
581
|
+
contentType: we,
|
|
582
582
|
robustness: "",
|
|
583
583
|
encryptionScheme: "cbcs"
|
|
584
584
|
}]
|
|
585
|
-
}] :
|
|
585
|
+
}] : P("com.widevine.alpha", [{
|
|
586
586
|
initDataTypes: ["cenc"],
|
|
587
587
|
videoCapabilities: [{
|
|
588
|
-
contentType:
|
|
588
|
+
contentType: Ce,
|
|
589
589
|
robustness: "SW_SECURE_DECODE",
|
|
590
590
|
encryptionScheme: "cbcs"
|
|
591
591
|
}],
|
|
592
592
|
audioCapabilities: [{
|
|
593
|
-
contentType:
|
|
593
|
+
contentType: we,
|
|
594
594
|
robustness: "SW_SECURE_CRYPTO",
|
|
595
595
|
encryptionScheme: "cbcs"
|
|
596
596
|
}]
|
|
@@ -607,7 +607,7 @@ function F(e, t) {
|
|
|
607
607
|
});
|
|
608
608
|
}
|
|
609
609
|
async function De(e = {}) {
|
|
610
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
610
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Se, r = {};
|
|
611
611
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
612
612
|
verdict: "insecure-context",
|
|
613
613
|
detail: r
|
|
@@ -672,7 +672,7 @@ var Ae = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
|
672
672
|
function je(e) {
|
|
673
673
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
674
674
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
675
|
-
for (let i of r) if (!(i.startTime < e) &&
|
|
675
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || Ae.test(i.name)) && i.startTime >= n) {
|
|
676
676
|
let e = L(i.name);
|
|
677
677
|
e && (t = e, n = i.startTime);
|
|
678
678
|
}
|
|
@@ -776,7 +776,7 @@ var V = class {
|
|
|
776
776
|
});
|
|
777
777
|
this.onEncrypted = (n) => {
|
|
778
778
|
let i = n;
|
|
779
|
-
|
|
779
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Ne(i.initData), (async () => {
|
|
780
780
|
try {
|
|
781
781
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
782
782
|
initDataTypes: [i.initDataType],
|
|
@@ -1034,7 +1034,7 @@ var U = class {
|
|
|
1034
1034
|
videoEncryptionScheme: "cbcs",
|
|
1035
1035
|
audioEncryptionScheme: "cbcs"
|
|
1036
1036
|
},
|
|
1037
|
-
...
|
|
1037
|
+
...M() ? { requestMediaKeySystemAccessFunc: xe(t) } : {},
|
|
1038
1038
|
licenseXhrSetup: (e, t) => {
|
|
1039
1039
|
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;
|
|
1040
1040
|
let o = performance.now();
|
|
@@ -1377,11 +1377,11 @@ var U = class {
|
|
|
1377
1377
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1378
1378
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1379
1379
|
}
|
|
1380
|
-
}, tt = 15e3, nt = 100, W = 1, rt = 1e3, G = 3e4, it = {
|
|
1380
|
+
}, tt = 15e3, nt = 100, W = 1, rt = 1e3, G = 3e4, it = 1e3, at = {
|
|
1381
1381
|
inline: "PRESENTATION_INLINE",
|
|
1382
1382
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1383
1383
|
pip: "PRESENTATION_PIP"
|
|
1384
|
-
},
|
|
1384
|
+
}, ot = {
|
|
1385
1385
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1386
1386
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1387
1387
|
none: "KEY_SYSTEM_NONE"
|
|
@@ -1389,7 +1389,7 @@ var U = class {
|
|
|
1389
1389
|
function K(e, t) {
|
|
1390
1390
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1391
1391
|
}
|
|
1392
|
-
var
|
|
1392
|
+
var st = /* @__PURE__ */ new Set([
|
|
1393
1393
|
"INVALID_URN",
|
|
1394
1394
|
"NOT_FOUND",
|
|
1395
1395
|
"GONE",
|
|
@@ -1409,7 +1409,7 @@ var ot = /* @__PURE__ */ new Set([
|
|
|
1409
1409
|
ended: "PLAYER_STATE_ENDED",
|
|
1410
1410
|
error: "PLAYER_STATE_ERROR"
|
|
1411
1411
|
};
|
|
1412
|
-
function
|
|
1412
|
+
function ct(e) {
|
|
1413
1413
|
try {
|
|
1414
1414
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1415
1415
|
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);
|
|
@@ -1417,7 +1417,7 @@ function st(e) {
|
|
|
1417
1417
|
return;
|
|
1418
1418
|
}
|
|
1419
1419
|
}
|
|
1420
|
-
var
|
|
1420
|
+
var lt = class {
|
|
1421
1421
|
opts;
|
|
1422
1422
|
url;
|
|
1423
1423
|
now;
|
|
@@ -1435,6 +1435,8 @@ var ct = class {
|
|
|
1435
1435
|
hiddenTotalMs = 0;
|
|
1436
1436
|
lastHbPlayingMs = 0;
|
|
1437
1437
|
lastHbHiddenMs = 0;
|
|
1438
|
+
lastHbRebufferMs = 0;
|
|
1439
|
+
lastHbRebufferCount = 0;
|
|
1438
1440
|
rebufferCount = 0;
|
|
1439
1441
|
rebufferTotalMs = 0;
|
|
1440
1442
|
bufferingSinceMs = null;
|
|
@@ -1462,7 +1464,8 @@ var ct = class {
|
|
|
1462
1464
|
timeToFirstStallMs = 0;
|
|
1463
1465
|
lastStallMs = 0;
|
|
1464
1466
|
lastErrorMs = 0;
|
|
1465
|
-
lastSeekMs =
|
|
1467
|
+
lastSeekMs = -1;
|
|
1468
|
+
stallIsSeekInduced = !1;
|
|
1466
1469
|
lastErrorStage = null;
|
|
1467
1470
|
sawFirstBytes = !1;
|
|
1468
1471
|
mediaInfoSignature = "";
|
|
@@ -1500,17 +1503,25 @@ var ct = class {
|
|
|
1500
1503
|
noteStateChange(e, t, n, r) {
|
|
1501
1504
|
if (this.endedFlag || e === t) return;
|
|
1502
1505
|
let i = this.now();
|
|
1503
|
-
t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(W, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(W, 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"
|
|
1506
|
+
if (t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(W, i - this.startupAnchorMs)), this.firstAudioMs === 0 && !this.isMuted && (this.firstAudioMs = Math.max(W, 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") {
|
|
1507
|
+
this.stallIsSeekInduced = this.seekInduced(i);
|
|
1508
|
+
let e = !this.isHidden && !this.stallIsSeekInduced;
|
|
1509
|
+
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(W, Math.round(this.playingTotalMs)));
|
|
1510
|
+
} else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
|
|
1511
|
+
this.syncBuffering(), t === "paused" && (this.pauseCount += 1);
|
|
1504
1512
|
let a = {
|
|
1505
1513
|
fromState: q[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1506
1514
|
toState: q[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1507
|
-
presentation:
|
|
1515
|
+
presentation: at[this.presentation]
|
|
1508
1516
|
}, o = this.causeOf(e, t, i);
|
|
1509
1517
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
1510
1518
|
}
|
|
1519
|
+
seekInduced(e) {
|
|
1520
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < it;
|
|
1521
|
+
}
|
|
1511
1522
|
causeOf(e, t, n) {
|
|
1512
1523
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
1513
|
-
if (t === "buffering") return
|
|
1524
|
+
if (t === "buffering") return this.seekInduced(n) ? "TRANSITION_CAUSE_SEEK" : "TRANSITION_CAUSE_NETWORK_STALL";
|
|
1514
1525
|
if (t === "paused" || t === "playing" && e === "paused") return "TRANSITION_CAUSE_USER";
|
|
1515
1526
|
}
|
|
1516
1527
|
syncActive() {
|
|
@@ -1518,7 +1529,7 @@ var ct = class {
|
|
|
1518
1529
|
e && this.activeSinceMs === null ? this.activeSinceMs = this.now() : !e && this.activeSinceMs !== null && (this.activeTotalMs += this.now() - this.activeSinceMs, this.activeSinceMs = null);
|
|
1519
1530
|
}
|
|
1520
1531
|
syncBuffering() {
|
|
1521
|
-
let e = this.isBuffering && !this.isHidden;
|
|
1532
|
+
let e = this.isBuffering && !this.isHidden && !this.stallIsSeekInduced;
|
|
1522
1533
|
e && this.bufferingSinceMs === null ? this.bufferingSinceMs = this.now() : !e && this.bufferingSinceMs !== null && (this.rebufferTotalMs += this.now() - this.bufferingSinceMs, this.bufferingSinceMs = null);
|
|
1523
1534
|
}
|
|
1524
1535
|
closePresentation() {
|
|
@@ -1574,7 +1585,7 @@ var ct = class {
|
|
|
1574
1585
|
let r = n ?? "";
|
|
1575
1586
|
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";
|
|
1576
1587
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
1577
|
-
if (
|
|
1588
|
+
if (st.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
1578
1589
|
let i = t ?? "";
|
|
1579
1590
|
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";
|
|
1580
1591
|
}
|
|
@@ -1593,36 +1604,38 @@ var ct = class {
|
|
|
1593
1604
|
this.playingSinceMs !== null && (n += t - this.playingSinceMs);
|
|
1594
1605
|
let r = this.hiddenTotalMs;
|
|
1595
1606
|
this.hiddenSinceMs !== null && (r += t - this.hiddenSinceMs);
|
|
1596
|
-
let i =
|
|
1597
|
-
|
|
1598
|
-
let o = e.
|
|
1599
|
-
o > this.
|
|
1600
|
-
let s = e.
|
|
1601
|
-
s > this.
|
|
1602
|
-
let c = e.
|
|
1603
|
-
c > this.
|
|
1604
|
-
let l =
|
|
1605
|
-
this.
|
|
1606
|
-
let u =
|
|
1607
|
-
u > this.
|
|
1608
|
-
let d = e.
|
|
1609
|
-
d > this.
|
|
1610
|
-
let f = e.
|
|
1611
|
-
f > this.
|
|
1612
|
-
let p = e.
|
|
1613
|
-
p > this.
|
|
1614
|
-
let m = e.
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1607
|
+
let i = this.rebufferTotalMs;
|
|
1608
|
+
this.bufferingSinceMs !== null && (i += t - this.bufferingSinceMs);
|
|
1609
|
+
let a = {}, o = e.bytesLoaded ?? 0;
|
|
1610
|
+
o > this.lastBytes && (a.bytesDownloadedDelta = o - this.lastBytes), this.lastBytes = o;
|
|
1611
|
+
let s = e.playlistBytesLoaded ?? 0;
|
|
1612
|
+
s > this.lastPlaylistBytes && (a.playlistBytesDelta = s - this.lastPlaylistBytes), this.lastPlaylistBytes = s;
|
|
1613
|
+
let c = e.droppedFrames ?? 0;
|
|
1614
|
+
c > this.lastDropped && (a.droppedFramesDelta = c - this.lastDropped), this.lastDropped = c;
|
|
1615
|
+
let l = e.renditionSwitches ?? 0;
|
|
1616
|
+
l > this.lastSwitches && (a.renditionSwitchesDelta = l - this.lastSwitches), this.lastSwitches = l, n > this.lastHbPlayingMs && (a.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (a.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (a.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (a.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, typeof e.latencySeconds == "number" && (a.latencyMs = Math.round(e.latencySeconds * 1e3)), typeof e.targetLatencySeconds == "number" && (a.targetLatencyMs = Math.round(e.targetLatencySeconds * 1e3)), typeof e.bandwidthKbps == "number" && (a.bandwidthEstKbps = e.bandwidthKbps), typeof e.levelHeight == "number" && (a.renditionHeight = e.levelHeight), typeof e.renditionBitrateKbps == "number" && (a.renditionBitrateKbps = e.renditionBitrateKbps), e.atLiveEdge === !0 && (a.atLiveEdge = !0), typeof e.bufferedMs == "number" && e.bufferedMs > 0 && (a.bufferedMs = Math.round(e.bufferedMs)), a.playerState = q[e.state] ?? "PLAYER_STATE_UNSPECIFIED";
|
|
1617
|
+
let u = this.mutedTotalMs;
|
|
1618
|
+
this.mutedSinceMs !== null && (u += t - this.mutedSinceMs), u > this.lastHbMutedMs && (a.mutedMsDelta = Math.round(u - this.lastHbMutedMs)), this.lastHbMutedMs = u;
|
|
1619
|
+
let d = e.upshifts ?? 0;
|
|
1620
|
+
d > this.lastUpshifts && (a.upshiftsDelta = d - this.lastUpshifts), this.lastUpshifts = d;
|
|
1621
|
+
let f = e.downshifts ?? 0;
|
|
1622
|
+
f > this.lastDownshifts && (a.downshiftsDelta = f - this.lastDownshifts), this.lastDownshifts = f;
|
|
1623
|
+
let p = e.decodedFrames ?? 0;
|
|
1624
|
+
p > this.lastDecoded && (a.decodedFramesDelta = p - this.lastDecoded), this.lastDecoded = p;
|
|
1625
|
+
let m = e.requestErrors ?? 0;
|
|
1626
|
+
m > this.lastRequestErrors && (a.requestErrorsDelta = m - this.lastRequestErrors), this.lastRequestErrors = m;
|
|
1627
|
+
let h = e.requestCount ?? 0, g = h - this.lastRequestCount;
|
|
1628
|
+
if (this.lastRequestCount = h, g > 0) {
|
|
1629
|
+
a.requestCountDelta = g;
|
|
1630
|
+
let t = e.requestTimesMs ?? [], n = t.slice(Math.max(0, t.length - g)).sort((e, t) => e - t);
|
|
1631
|
+
n.length > 0 && (a.requestTimeP50Ms = K(n, 50), a.requestTimeP95Ms = K(n, 95));
|
|
1619
1632
|
}
|
|
1620
|
-
typeof e.latencySeconds == "number" && typeof e.targetLatencySeconds == "number" && (
|
|
1633
|
+
typeof e.latencySeconds == "number" && typeof e.targetLatencySeconds == "number" && (a.driftMs = Math.round((e.latencySeconds - e.targetLatencySeconds) * 1e3)), typeof e.playbackRate == "number" && e.playbackRate > 0 && (a.playbackRate = e.playbackRate), e.qualityPinned === !0 && (a.qualityPinned = !0), e.cdnHost && (a.cdnHost = e.cdnHost), this.maybeEmitMediaInfo(e), this.enqueue({ heartbeat: a }), this.flush(), o > 0 && this.noteFirstBytes();
|
|
1621
1634
|
}
|
|
1622
1635
|
maybeEmitMediaInfo(e) {
|
|
1623
1636
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
1624
1637
|
let t = {};
|
|
1625
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
1638
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = ot[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);
|
|
1626
1639
|
let n = JSON.stringify(t);
|
|
1627
1640
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
1628
1641
|
}
|
|
@@ -1687,7 +1700,7 @@ var ct = class {
|
|
|
1687
1700
|
};
|
|
1688
1701
|
//#endregion
|
|
1689
1702
|
//#region src/core/environment.ts
|
|
1690
|
-
function
|
|
1703
|
+
function ut() {
|
|
1691
1704
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
1692
1705
|
let e;
|
|
1693
1706
|
try {
|
|
@@ -1712,14 +1725,14 @@ function lt() {
|
|
|
1712
1725
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
1713
1726
|
};
|
|
1714
1727
|
}
|
|
1715
|
-
function
|
|
1728
|
+
function dt() {
|
|
1716
1729
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
1717
1730
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
1718
1731
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
1719
1732
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
1720
1733
|
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";
|
|
1721
1734
|
}
|
|
1722
|
-
function
|
|
1735
|
+
function ft() {
|
|
1723
1736
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
1724
1737
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
1725
1738
|
let t = { connectionType: e.type ? {
|
|
@@ -1729,17 +1742,17 @@ function dt() {
|
|
|
1729
1742
|
}[e.type] ?? "CONNECTION_TYPE_OTHER" : "CONNECTION_TYPE_UNKNOWN" };
|
|
1730
1743
|
return typeof e.downlink == "number" && e.downlink > 0 && (t.downlinkKbps = Math.round(e.downlink * 1e3)), e.saveData && (t.saveData = !0), t;
|
|
1731
1744
|
}
|
|
1732
|
-
function
|
|
1733
|
-
let t =
|
|
1734
|
-
deviceClass:
|
|
1745
|
+
function pt(e) {
|
|
1746
|
+
let t = ut(), n = {
|
|
1747
|
+
deviceClass: dt(),
|
|
1735
1748
|
integration: t.integration,
|
|
1736
|
-
...
|
|
1749
|
+
...ft()
|
|
1737
1750
|
};
|
|
1738
1751
|
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);
|
|
1739
1752
|
let r = e.getBoundingClientRect?.();
|
|
1740
1753
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
1741
1754
|
}
|
|
1742
|
-
async function
|
|
1755
|
+
async function mt() {
|
|
1743
1756
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
1744
1757
|
if (!e?.getHighEntropyValues) return {};
|
|
1745
1758
|
try {
|
|
@@ -1751,7 +1764,7 @@ async function pt() {
|
|
|
1751
1764
|
}
|
|
1752
1765
|
//#endregion
|
|
1753
1766
|
//#region src/core/version.ts
|
|
1754
|
-
var
|
|
1767
|
+
var ht = "2.4.0", J = {
|
|
1755
1768
|
accent: "#E1B600",
|
|
1756
1769
|
accentText: "#1B1C23",
|
|
1757
1770
|
background: "#0e0f13",
|
|
@@ -1784,15 +1797,15 @@ function X(e, t) {
|
|
|
1784
1797
|
}
|
|
1785
1798
|
//#endregion
|
|
1786
1799
|
//#region src/ui/styles.ts
|
|
1787
|
-
var Z = "havik-player-styles",
|
|
1788
|
-
function
|
|
1800
|
+
var Z = "havik-player-styles", gt = "\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.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.havik-spinner{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";
|
|
1801
|
+
function _t(e = document) {
|
|
1789
1802
|
if (e.getElementById(Z)) return;
|
|
1790
1803
|
let t = e.createElement("style");
|
|
1791
|
-
t.id = Z, t.textContent =
|
|
1804
|
+
t.id = Z, t.textContent = gt, e.head.appendChild(t);
|
|
1792
1805
|
}
|
|
1793
1806
|
//#endregion
|
|
1794
1807
|
//#region src/ui/icons.ts
|
|
1795
|
-
var
|
|
1808
|
+
var vt = {
|
|
1796
1809
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
1797
1810
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
1798
1811
|
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\"/>",
|
|
@@ -1806,20 +1819,20 @@ var _t = {
|
|
|
1806
1819
|
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\"/>"
|
|
1807
1820
|
};
|
|
1808
1821
|
function Q(e) {
|
|
1809
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
1822
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${vt[e]}</svg>`;
|
|
1810
1823
|
}
|
|
1811
1824
|
//#endregion
|
|
1812
1825
|
//#region src/ui/controls.ts
|
|
1813
|
-
var
|
|
1826
|
+
var yt = 3e3, bt = /* @__PURE__ */ new Set([
|
|
1814
1827
|
"GONE",
|
|
1815
1828
|
"NOT_FOUND",
|
|
1816
1829
|
"INVALID_URN",
|
|
1817
1830
|
"UNAUTHORIZED"
|
|
1818
1831
|
]);
|
|
1819
|
-
function
|
|
1820
|
-
return new
|
|
1832
|
+
function xt(e) {
|
|
1833
|
+
return new St(e);
|
|
1821
1834
|
}
|
|
1822
|
-
var
|
|
1835
|
+
var St = class {
|
|
1823
1836
|
root;
|
|
1824
1837
|
video;
|
|
1825
1838
|
player;
|
|
@@ -1861,7 +1874,7 @@ var xt = class {
|
|
|
1861
1874
|
scrubbing = !1;
|
|
1862
1875
|
offFns = [];
|
|
1863
1876
|
constructor(e) {
|
|
1864
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
1877
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? yt, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, _t(this.doc), 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");
|
|
1865
1878
|
let t = (e, t, n) => {
|
|
1866
1879
|
let r = this.doc.createElement(e);
|
|
1867
1880
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -1952,7 +1965,7 @@ var xt = class {
|
|
|
1952
1965
|
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);
|
|
1953
1966
|
} else {
|
|
1954
1967
|
let r = this.doc.createElement("div");
|
|
1955
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
1968
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !bt.has(this.lastError.code)) {
|
|
1956
1969
|
let e = this.doc.createElement("button");
|
|
1957
1970
|
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);
|
|
1958
1971
|
}
|
|
@@ -1993,7 +2006,7 @@ var xt = class {
|
|
|
1993
2006
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
1994
2007
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
1995
2008
|
}
|
|
1996
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2009
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Ct(this.video.currentTime)} / ${Ct(this.video.duration)}`);
|
|
1997
2010
|
}
|
|
1998
2011
|
syncLive() {
|
|
1999
2012
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2043,17 +2056,17 @@ var xt = class {
|
|
|
2043
2056
|
renderQualityMenu() {
|
|
2044
2057
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2045
2058
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2046
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2059
|
+
for (let n of e) this.menu.append(this.menuItem(wt(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2047
2060
|
}
|
|
2048
2061
|
renderAudioMenu() {
|
|
2049
2062
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2050
2063
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2051
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2064
|
+
for (let t of e) this.menu.append(this.menuItem(Tt(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2052
2065
|
}
|
|
2053
2066
|
renderCcMenu() {
|
|
2054
2067
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2055
2068
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2056
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2069
|
+
for (let t of e) this.menu.append(this.menuItem(Et(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2057
2070
|
}
|
|
2058
2071
|
onTracksChanged() {
|
|
2059
2072
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2073,11 +2086,11 @@ var xt = class {
|
|
|
2073
2086
|
}
|
|
2074
2087
|
async toggleFullscreen() {
|
|
2075
2088
|
try {
|
|
2076
|
-
|
|
2089
|
+
C(this.video, this.root) ? await T(this.video, this.root) : await w(this.video, this.root);
|
|
2077
2090
|
} catch {}
|
|
2078
2091
|
}
|
|
2079
2092
|
syncFullscreen() {
|
|
2080
|
-
let e =
|
|
2093
|
+
let e = C(this.video, this.root);
|
|
2081
2094
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
2082
2095
|
}
|
|
2083
2096
|
poke() {
|
|
@@ -2153,32 +2166,32 @@ var xt = class {
|
|
|
2153
2166
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2154
2167
|
}
|
|
2155
2168
|
};
|
|
2156
|
-
function
|
|
2169
|
+
function Ct(e) {
|
|
2157
2170
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2158
2171
|
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");
|
|
2159
2172
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2160
2173
|
}
|
|
2161
|
-
function
|
|
2174
|
+
function wt(e) {
|
|
2162
2175
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2163
2176
|
}
|
|
2164
|
-
function
|
|
2177
|
+
function Tt(e) {
|
|
2165
2178
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2166
2179
|
}
|
|
2167
|
-
function
|
|
2180
|
+
function Et(e) {
|
|
2168
2181
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2169
2182
|
}
|
|
2170
2183
|
//#endregion
|
|
2171
2184
|
//#region src/managed/index.ts
|
|
2172
|
-
var
|
|
2173
|
-
async function
|
|
2185
|
+
var Dt = 6e3, Ot = 45e3, kt = 2e3, At = 3, jt = 2e3, Mt = 48e4;
|
|
2186
|
+
async function Nt(e) {
|
|
2174
2187
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2175
2188
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: baseUrl is required");
|
|
2176
2189
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2177
2190
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2178
|
-
let t = new
|
|
2191
|
+
let t = new Pt(e);
|
|
2179
2192
|
return await t.start(), t;
|
|
2180
2193
|
}
|
|
2181
|
-
var
|
|
2194
|
+
var Pt = class {
|
|
2182
2195
|
opts;
|
|
2183
2196
|
abort = new AbortController();
|
|
2184
2197
|
listeners = {};
|
|
@@ -2244,7 +2257,7 @@ var Nt = class {
|
|
|
2244
2257
|
};
|
|
2245
2258
|
}
|
|
2246
2259
|
beginArming(e, t, n = !1) {
|
|
2247
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
2260
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
|
|
2248
2261
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
2249
2262
|
}
|
|
2250
2263
|
beginArmingByPolling(e) {
|
|
@@ -2265,7 +2278,7 @@ var Nt = class {
|
|
|
2265
2278
|
setTimeout(() => {
|
|
2266
2279
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
2267
2280
|
phase: i ? "unavailable" : "tooEarly",
|
|
2268
|
-
retryInMs:
|
|
2281
|
+
retryInMs: Ot,
|
|
2269
2282
|
attempt: 1,
|
|
2270
2283
|
elapsedMs: 0,
|
|
2271
2284
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -2304,13 +2317,13 @@ var Nt = class {
|
|
|
2304
2317
|
!a && !p() && h();
|
|
2305
2318
|
}, e);
|
|
2306
2319
|
};
|
|
2307
|
-
_(
|
|
2320
|
+
_(Dt), this.armingSub = E({
|
|
2308
2321
|
eventsBaseUrl: t,
|
|
2309
2322
|
matchUrn: this.opts.matchUrn,
|
|
2310
2323
|
credential: this.opts.credential,
|
|
2311
|
-
onAlive: () => _(
|
|
2324
|
+
onAlive: () => _(Ot),
|
|
2312
2325
|
onState: (e) => {
|
|
2313
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
2326
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * kt);
|
|
2314
2327
|
},
|
|
2315
2328
|
onError: () => h()
|
|
2316
2329
|
});
|
|
@@ -2352,15 +2365,15 @@ var Nt = class {
|
|
|
2352
2365
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
2353
2366
|
let r = e.analytics?.sid;
|
|
2354
2367
|
if (!r) return;
|
|
2355
|
-
let i = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ??
|
|
2368
|
+
let i = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ?? ct(this.opts.baseUrl);
|
|
2356
2369
|
if (!i) return;
|
|
2357
|
-
let a = this.opts.video, o = new
|
|
2370
|
+
let a = this.opts.video, o = new lt({
|
|
2358
2371
|
endpoint: i,
|
|
2359
2372
|
sid: r,
|
|
2360
2373
|
apiKey: n,
|
|
2361
2374
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
2362
|
-
sdkVersion:
|
|
2363
|
-
environment:
|
|
2375
|
+
sdkVersion: ht,
|
|
2376
|
+
environment: pt(a),
|
|
2364
2377
|
sample: () => {
|
|
2365
2378
|
let e = this.engine?.getStats() ?? I, t = a.buffered.length ? Math.max(0, a.buffered.end(a.buffered.length - 1) - a.currentTime) : 0;
|
|
2366
2379
|
return {
|
|
@@ -2376,7 +2389,7 @@ var Nt = class {
|
|
|
2376
2389
|
let s = () => o.noteSeek(), c = () => o.noteVolume(a.muted, a.volume);
|
|
2377
2390
|
a.addEventListener("seeking", s), a.addEventListener("volumechange", c), this.detachMediaListeners = () => {
|
|
2378
2391
|
a.removeEventListener("seeking", s), a.removeEventListener("volumechange", c);
|
|
2379
|
-
}, o.start(), o.seedVolume(a.muted, a.volume), o.notePresentation(this.currentPresentation()),
|
|
2392
|
+
}, o.start(), o.seedVolume(a.muted, a.volume), o.notePresentation(this.currentPresentation()), mt().then((e) => o.noteEnvironment(e)), this.opts.autoplay === !1 && o.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
2380
2393
|
}
|
|
2381
2394
|
currentPresentation() {
|
|
2382
2395
|
let e = this.opts.video;
|
|
@@ -2391,7 +2404,7 @@ var Nt = class {
|
|
|
2391
2404
|
video: this.opts.video,
|
|
2392
2405
|
descriptor: e,
|
|
2393
2406
|
credential: t,
|
|
2394
|
-
deviceId:
|
|
2407
|
+
deviceId: A(),
|
|
2395
2408
|
userId: this.opts.userId,
|
|
2396
2409
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
2397
2410
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -2432,11 +2445,11 @@ var Nt = class {
|
|
|
2432
2445
|
}
|
|
2433
2446
|
startLiveState(e) {
|
|
2434
2447
|
if (this.opts.liveStateEvents === !1) return;
|
|
2435
|
-
let t = this.opts.eventsBaseUrl ??
|
|
2448
|
+
let t = this.opts.eventsBaseUrl ?? D(this.opts.baseUrl);
|
|
2436
2449
|
if (!t) return;
|
|
2437
2450
|
this.closeLiveState();
|
|
2438
2451
|
let r = 0, i = !1;
|
|
2439
|
-
this.liveStateSub =
|
|
2452
|
+
this.liveStateSub = E({
|
|
2440
2453
|
eventsBaseUrl: t,
|
|
2441
2454
|
matchUrn: this.opts.matchUrn,
|
|
2442
2455
|
credential: this.opts.credential,
|
|
@@ -2447,7 +2460,7 @@ var Nt = class {
|
|
|
2447
2460
|
r = 0, i = !1;
|
|
2448
2461
|
},
|
|
2449
2462
|
onError: () => {
|
|
2450
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
2463
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= At && (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.`))));
|
|
2451
2464
|
}
|
|
2452
2465
|
});
|
|
2453
2466
|
}
|
|
@@ -2467,9 +2480,9 @@ var Nt = class {
|
|
|
2467
2480
|
return this.opts.rejoinOnLive !== !1 && this.opts.liveStateEvents !== !1;
|
|
2468
2481
|
}
|
|
2469
2482
|
scheduleRejoin(e) {
|
|
2470
|
-
|
|
2483
|
+
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
2471
2484
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
2472
|
-
}, Math.random() *
|
|
2485
|
+
}, Math.random() * kt));
|
|
2473
2486
|
}
|
|
2474
2487
|
cancelRejoin() {
|
|
2475
2488
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -2493,7 +2506,7 @@ var Nt = class {
|
|
|
2493
2506
|
}
|
|
2494
2507
|
t.controls = !1;
|
|
2495
2508
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
2496
|
-
r && r.insertBefore(n, t), n.appendChild(t), X(n, this.opts.theme), this.container = n, this.controlBar =
|
|
2509
|
+
r && r.insertBefore(n, t), n.appendChild(t), X(n, this.opts.theme), this.container = n, this.controlBar = xt({
|
|
2497
2510
|
root: n,
|
|
2498
2511
|
video: t,
|
|
2499
2512
|
player: this,
|
|
@@ -2523,7 +2536,7 @@ var Nt = class {
|
|
|
2523
2536
|
}
|
|
2524
2537
|
startStats() {
|
|
2525
2538
|
this.stopStats();
|
|
2526
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
2539
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? jt);
|
|
2527
2540
|
this.statsTimer = setInterval(() => {
|
|
2528
2541
|
if (!this.engine) return;
|
|
2529
2542
|
let e = this.engine.getStats();
|
|
@@ -2535,15 +2548,15 @@ var Nt = class {
|
|
|
2535
2548
|
}
|
|
2536
2549
|
scheduleLicenseRefresh() {
|
|
2537
2550
|
this.stopRefresh();
|
|
2538
|
-
let e = this.opts.licenseRefreshMs ??
|
|
2539
|
-
|
|
2551
|
+
let e = this.opts.licenseRefreshMs ?? Mt;
|
|
2552
|
+
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
2540
2553
|
}
|
|
2541
2554
|
stopRefresh() {
|
|
2542
2555
|
this.refreshTimer && clearInterval(this.refreshTimer), this.refreshTimer = void 0;
|
|
2543
2556
|
}
|
|
2544
2557
|
async refreshLicense() {
|
|
2545
2558
|
let e = this.engine;
|
|
2546
|
-
if (!
|
|
2559
|
+
if (!this.destroyed && e) try {
|
|
2547
2560
|
let t = await y(this.resolveOptions());
|
|
2548
2561
|
if (this.destroyed || this.engine !== e) return;
|
|
2549
2562
|
let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
|
|
@@ -2616,10 +2629,10 @@ var Nt = class {
|
|
|
2616
2629
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
2617
2630
|
}
|
|
2618
2631
|
async enterFullscreen() {
|
|
2619
|
-
return !this.destroyed &&
|
|
2632
|
+
return !this.destroyed && w(this.opts.video, this.container ?? void 0);
|
|
2620
2633
|
}
|
|
2621
2634
|
async exitFullscreen() {
|
|
2622
|
-
await
|
|
2635
|
+
await T(this.opts.video, this.container ?? void 0);
|
|
2623
2636
|
}
|
|
2624
2637
|
retry() {
|
|
2625
2638
|
return this.reload();
|
|
@@ -2687,7 +2700,7 @@ function $(e) {
|
|
|
2687
2700
|
}
|
|
2688
2701
|
//#endregion
|
|
2689
2702
|
//#region src/embed/host.ts
|
|
2690
|
-
function
|
|
2703
|
+
function Ft(e) {
|
|
2691
2704
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
2692
2705
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
2693
2706
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -2746,8 +2759,8 @@ function Pt(e) {
|
|
|
2746
2759
|
}
|
|
2747
2760
|
//#endregion
|
|
2748
2761
|
//#region src/embed/page.ts
|
|
2749
|
-
var
|
|
2750
|
-
function
|
|
2762
|
+
var It = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
2763
|
+
function Lt() {
|
|
2751
2764
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
2752
2765
|
if (e) return {
|
|
2753
2766
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -2769,9 +2782,9 @@ function It() {
|
|
|
2769
2782
|
waitForLive: !0
|
|
2770
2783
|
};
|
|
2771
2784
|
}
|
|
2772
|
-
async function
|
|
2773
|
-
let e =
|
|
2774
|
-
|
|
2785
|
+
async function Rt() {
|
|
2786
|
+
let e = Lt();
|
|
2787
|
+
Bt();
|
|
2775
2788
|
let t = document.createElement("video");
|
|
2776
2789
|
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);
|
|
2777
2790
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -2826,12 +2839,12 @@ async function Lt() {
|
|
|
2826
2839
|
code: e.code,
|
|
2827
2840
|
message: e.message
|
|
2828
2841
|
})), e.on("autoplayblocked", () => {
|
|
2829
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
2842
|
+
i({ type: "oddin:autoplayblocked" }), zt(t, e);
|
|
2830
2843
|
});
|
|
2831
2844
|
}, s = async (r) => {
|
|
2832
2845
|
a?.destroy(), a = null;
|
|
2833
2846
|
try {
|
|
2834
|
-
let n = await
|
|
2847
|
+
let n = await Nt({
|
|
2835
2848
|
video: t,
|
|
2836
2849
|
baseUrl: e.baseUrl,
|
|
2837
2850
|
matchUrn: r,
|
|
@@ -2892,30 +2905,30 @@ async function Lt() {
|
|
|
2892
2905
|
a?.retry();
|
|
2893
2906
|
break;
|
|
2894
2907
|
case "oddin:load":
|
|
2895
|
-
typeof e.matchUrn == "string" &&
|
|
2908
|
+
typeof e.matchUrn == "string" && It.test(e.matchUrn) && s(e.matchUrn);
|
|
2896
2909
|
break;
|
|
2897
2910
|
case "oddin:destroy": c();
|
|
2898
2911
|
}
|
|
2899
2912
|
}, u = (e) => {
|
|
2900
|
-
|
|
2913
|
+
r && e.origin === r && $(e.data) && l(e.data);
|
|
2901
2914
|
};
|
|
2902
2915
|
r && window.addEventListener("message", u), window.addEventListener("pagehide", c, { once: !0 }), await s(e.matchUrn), i({
|
|
2903
2916
|
type: "oddin:ready",
|
|
2904
2917
|
protocol: 1
|
|
2905
2918
|
});
|
|
2906
2919
|
}
|
|
2907
|
-
function
|
|
2920
|
+
function zt(e, t) {
|
|
2908
2921
|
if (document.getElementById("havik-tap")) return;
|
|
2909
2922
|
let n = document.createElement("button");
|
|
2910
2923
|
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", () => {
|
|
2911
2924
|
n.remove(), t.play();
|
|
2912
2925
|
}), document.body.appendChild(n);
|
|
2913
2926
|
}
|
|
2914
|
-
function
|
|
2927
|
+
function Bt() {
|
|
2915
2928
|
let e = document.createElement("style");
|
|
2916
2929
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
2917
2930
|
}
|
|
2918
2931
|
//#endregion
|
|
2919
|
-
export { J as ODDIN_THEME, n as PlaybackError, X as applyTheme,
|
|
2932
|
+
export { J as ODDIN_THEME, n as PlaybackError, X as applyTheme, Rt as bootEmbed, ge as clearDeviceId, Nt as createPlayer, D as deriveEventsBaseUrl, De as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ue as fetchCatalog, fe as fetchTournament, me as flattenMatches, A as getDeviceId, ke as isLowLatencyManifest, $ as isOddinMessage, ve as licenseRequestHeaders, Ft as mountEmbed, v as pollToLive, b as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, he as watchStatus };
|
|
2920
2933
|
|
|
2921
2934
|
//# sourceMappingURL=index.js.map
|