@oddin-gg/havik-player 1.8.3 → 1.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/havik-player.global.js +2 -2
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +173 -145
- package/dist/index.js.map +1 -1
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -112,7 +112,7 @@ function te(e, t, n) {
|
|
|
112
112
|
function ne(e) {
|
|
113
113
|
return Math.round(e * (1 + .15 * Math.random()));
|
|
114
114
|
}
|
|
115
|
-
function
|
|
115
|
+
function re(e, t, n, r) {
|
|
116
116
|
let i = r ?? n.kickoffMs, a = i == null ? void 0 : Math.max(0, i - t), o = Math.max(n.floorMs, e ?? 0);
|
|
117
117
|
if (a == null || a <= n.imminentMs) return {
|
|
118
118
|
delay: te(e ?? n.floorMs, o, n.ceilMs),
|
|
@@ -124,7 +124,7 @@ function _(e, t, n, r) {
|
|
|
124
124
|
ttkMs: a
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
|
-
function
|
|
127
|
+
function ie(e, n) {
|
|
128
128
|
return new Promise((r, i) => {
|
|
129
129
|
if (n?.aborted) {
|
|
130
130
|
i(new t("ABORTED", 0, "wait-for-live aborted"));
|
|
@@ -138,7 +138,7 @@ function re(e, n) {
|
|
|
138
138
|
n?.addEventListener("abort", a, { once: !0 });
|
|
139
139
|
});
|
|
140
140
|
}
|
|
141
|
-
async function
|
|
141
|
+
async function _(e, n, r) {
|
|
142
142
|
let a = g(n), o = Date.now(), s = a.timeoutMs == null ? Infinity : o + a.timeoutMs, c = 0, l;
|
|
143
143
|
for (;;) {
|
|
144
144
|
if (r?.aborted) throw new t("ABORTED", 0, "wait-for-live aborted");
|
|
@@ -147,7 +147,7 @@ async function v(e, n, r) {
|
|
|
147
147
|
} catch (e) {
|
|
148
148
|
if (!(e instanceof t) || !i(e.code)) throw e;
|
|
149
149
|
c += 1, e.liveStartsAtMs != null && Number.isFinite(e.liveStartsAtMs) && (l = e.liveStartsAtMs);
|
|
150
|
-
let n = Date.now(), u =
|
|
150
|
+
let n = Date.now(), u = re(e.retryAfterMs, n, a, l), d = u.ttkMs, f = u.delay;
|
|
151
151
|
if (a.jitter && (f = ne(f)), n + f > s) throw new t("TIMEOUT", e.httpStatus, `timed out after ${a.timeoutMs}ms waiting for the stream to go live`, {
|
|
152
152
|
retryAfterMs: e.retryAfterMs,
|
|
153
153
|
cause: e
|
|
@@ -158,26 +158,26 @@ async function v(e, n, r) {
|
|
|
158
158
|
attempt: c,
|
|
159
159
|
elapsedMs: n - o,
|
|
160
160
|
ttkMs: d
|
|
161
|
-
}), await
|
|
161
|
+
}), await ie(f, r);
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
//#endregion
|
|
166
166
|
//#region src/core/resolve.ts
|
|
167
|
-
async function
|
|
167
|
+
async function v(e) {
|
|
168
168
|
if (!e.matchUrn || typeof e.matchUrn != "string") throw new t("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
|
|
169
169
|
let n = await c(o(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
|
|
170
170
|
credential: e.credential,
|
|
171
171
|
signal: e.signal
|
|
172
172
|
});
|
|
173
|
-
if (!n.ok) throw await
|
|
174
|
-
return
|
|
173
|
+
if (!n.ok) throw await ae(n);
|
|
174
|
+
return x(await n.json(), e.matchUrn);
|
|
175
175
|
}
|
|
176
|
-
function
|
|
177
|
-
let t = () =>
|
|
178
|
-
return e.waitForLive ?
|
|
176
|
+
function y(e) {
|
|
177
|
+
let t = () => v(e);
|
|
178
|
+
return e.waitForLive ? _(t, e.waitForLive, e.signal) : t();
|
|
179
179
|
}
|
|
180
|
-
async function
|
|
180
|
+
async function ae(e) {
|
|
181
181
|
let r = s(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, c;
|
|
182
182
|
try {
|
|
183
183
|
let t = await e.json();
|
|
@@ -193,7 +193,7 @@ async function ie(e) {
|
|
|
193
193
|
liveStartsAtMs: c
|
|
194
194
|
});
|
|
195
195
|
}
|
|
196
|
-
var
|
|
196
|
+
var oe = /* @__PURE__ */ new Set([
|
|
197
197
|
"matchUrn",
|
|
198
198
|
"protocol",
|
|
199
199
|
"drmEnabled",
|
|
@@ -203,7 +203,7 @@ var ae = /* @__PURE__ */ new Set([
|
|
|
203
203
|
"liveStartsAt",
|
|
204
204
|
"expiresAt"
|
|
205
205
|
]);
|
|
206
|
-
function
|
|
206
|
+
function b(e, n) {
|
|
207
207
|
let r;
|
|
208
208
|
try {
|
|
209
209
|
r = new URL(n);
|
|
@@ -213,29 +213,29 @@ function x(e, n) {
|
|
|
213
213
|
if (r.protocol !== "https:" && r.protocol !== "http:") throw new t("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
|
|
214
214
|
return n;
|
|
215
215
|
}
|
|
216
|
-
function
|
|
216
|
+
function x(e, n) {
|
|
217
217
|
if (!e.manifestUrl) throw new t("INTERNAL", 0, "playback response is missing manifestUrl");
|
|
218
218
|
let r = e.drmEnabled ?? !!e.drm, i = {
|
|
219
219
|
matchUrn: e.matchUrn ?? n,
|
|
220
220
|
protocol: "hls",
|
|
221
221
|
drmEnabled: r,
|
|
222
|
-
manifestUrl:
|
|
222
|
+
manifestUrl: b("manifestUrl", e.manifestUrl),
|
|
223
223
|
serverTime: e.serverTime ?? ""
|
|
224
224
|
};
|
|
225
225
|
if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), r && e.drm) {
|
|
226
226
|
let t = {};
|
|
227
|
-
e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl:
|
|
228
|
-
licenseUrl:
|
|
229
|
-
certificateUrl:
|
|
227
|
+
e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: b("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
|
|
228
|
+
licenseUrl: b("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
|
|
229
|
+
certificateUrl: b("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
|
|
230
230
|
}), (t.widevine || t.fairplay) && (i.drm = t);
|
|
231
231
|
}
|
|
232
232
|
let a = {};
|
|
233
|
-
for (let [t, n] of Object.entries(e))
|
|
233
|
+
for (let [t, n] of Object.entries(e)) oe.has(t) || (a[t] = n);
|
|
234
234
|
return Object.keys(a).length > 0 && (i.extensions = a), i;
|
|
235
235
|
}
|
|
236
236
|
//#endregion
|
|
237
237
|
//#region src/core/catalog.ts
|
|
238
|
-
async function
|
|
238
|
+
async function S(e) {
|
|
239
239
|
let r = new URLSearchParams();
|
|
240
240
|
e.status && r.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && r.set("sport", e.sport);
|
|
241
241
|
let i = r.toString(), a = o(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), s = new Headers();
|
|
@@ -252,12 +252,12 @@ async function C(e) {
|
|
|
252
252
|
};
|
|
253
253
|
if (!l.ok) throw new t(n(l.status), l.status, `catalog request failed (HTTP ${l.status})`);
|
|
254
254
|
return {
|
|
255
|
-
tournaments:
|
|
255
|
+
tournaments: se(await l.json()),
|
|
256
256
|
etag: l.headers.get("etag") ?? void 0,
|
|
257
257
|
notModified: !1
|
|
258
258
|
};
|
|
259
259
|
}
|
|
260
|
-
function
|
|
260
|
+
function se(e) {
|
|
261
261
|
return (e.tournaments ?? []).map((e) => {
|
|
262
262
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
263
263
|
return {
|
|
@@ -277,7 +277,7 @@ function oe(e) {
|
|
|
277
277
|
};
|
|
278
278
|
});
|
|
279
279
|
}
|
|
280
|
-
async function
|
|
280
|
+
async function ce(e) {
|
|
281
281
|
let r = o(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
282
282
|
e.etag && i.set("If-None-Match", e.etag);
|
|
283
283
|
let a = await c(r, {
|
|
@@ -296,13 +296,13 @@ async function se(e) {
|
|
|
296
296
|
};
|
|
297
297
|
if (!a.ok) throw new t(n(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
298
298
|
return {
|
|
299
|
-
tournament:
|
|
299
|
+
tournament: le(await a.json()),
|
|
300
300
|
etag: a.headers.get("etag") ?? void 0,
|
|
301
301
|
notModified: !1,
|
|
302
302
|
notFound: !1
|
|
303
303
|
};
|
|
304
304
|
}
|
|
305
|
-
function
|
|
305
|
+
function le(e) {
|
|
306
306
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
307
307
|
return {
|
|
308
308
|
urn: t,
|
|
@@ -320,12 +320,12 @@ function ce(e) {
|
|
|
320
320
|
}))
|
|
321
321
|
};
|
|
322
322
|
}
|
|
323
|
-
function
|
|
323
|
+
function ue(e) {
|
|
324
324
|
return e.tournaments.flatMap((e) => e.matches);
|
|
325
325
|
}
|
|
326
326
|
//#endregion
|
|
327
327
|
//#region src/core/poll.ts
|
|
328
|
-
function
|
|
328
|
+
function de(e) {
|
|
329
329
|
let r = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, s, l, u = !1, d = () => {
|
|
330
330
|
u || (a = setTimeout(f, r));
|
|
331
331
|
}, f = async () => {
|
|
@@ -360,7 +360,7 @@ function ue(e) {
|
|
|
360
360
|
}
|
|
361
361
|
//#endregion
|
|
362
362
|
//#region src/core/events.ts
|
|
363
|
-
function
|
|
363
|
+
function C(e) {
|
|
364
364
|
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = new AbortController(), i = !1, s = (e) => new Promise((t) => {
|
|
365
365
|
if (r.signal.aborted) return t();
|
|
366
366
|
let n = setTimeout(t, e);
|
|
@@ -427,7 +427,7 @@ function w(e) {
|
|
|
427
427
|
i || (i = !0, r.abort());
|
|
428
428
|
} };
|
|
429
429
|
}
|
|
430
|
-
function
|
|
430
|
+
function w(e) {
|
|
431
431
|
try {
|
|
432
432
|
let t = new URL(e);
|
|
433
433
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -437,27 +437,27 @@ function T(e) {
|
|
|
437
437
|
}
|
|
438
438
|
//#endregion
|
|
439
439
|
//#region src/core/drm/deviceId.ts
|
|
440
|
-
var
|
|
441
|
-
function
|
|
442
|
-
if (
|
|
440
|
+
var T = "havik.player.deviceId", E;
|
|
441
|
+
function D() {
|
|
442
|
+
if (E) return E;
|
|
443
443
|
try {
|
|
444
|
-
let e = globalThis.localStorage?.getItem(
|
|
445
|
-
if (e) return
|
|
444
|
+
let e = globalThis.localStorage?.getItem(T);
|
|
445
|
+
if (e) return E = e, e;
|
|
446
446
|
} catch {}
|
|
447
|
-
let e =
|
|
448
|
-
|
|
447
|
+
let e = pe();
|
|
448
|
+
E = e;
|
|
449
449
|
try {
|
|
450
|
-
globalThis.localStorage?.setItem(
|
|
450
|
+
globalThis.localStorage?.setItem(T, e);
|
|
451
451
|
} catch {}
|
|
452
452
|
return e;
|
|
453
453
|
}
|
|
454
|
-
function
|
|
455
|
-
|
|
454
|
+
function fe() {
|
|
455
|
+
E = void 0;
|
|
456
456
|
try {
|
|
457
|
-
globalThis.localStorage?.removeItem(
|
|
457
|
+
globalThis.localStorage?.removeItem(T);
|
|
458
458
|
} catch {}
|
|
459
459
|
}
|
|
460
|
-
function
|
|
460
|
+
function pe() {
|
|
461
461
|
let e = globalThis.crypto;
|
|
462
462
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
463
463
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -469,22 +469,22 @@ function fe() {
|
|
|
469
469
|
}
|
|
470
470
|
//#endregion
|
|
471
471
|
//#region src/core/drm/headers.ts
|
|
472
|
-
function
|
|
472
|
+
function me(e, t, n = {}) {
|
|
473
473
|
let r = {
|
|
474
474
|
"x-api-key": t.apiKey,
|
|
475
475
|
"X-Match-Urn": e.matchUrn,
|
|
476
|
-
"X-Device-Id": n.deviceId ??
|
|
476
|
+
"X-Device-Id": n.deviceId ?? D(),
|
|
477
477
|
"Content-Type": "application/octet-stream"
|
|
478
478
|
};
|
|
479
479
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
480
480
|
}
|
|
481
481
|
//#endregion
|
|
482
482
|
//#region src/core/drm/support.ts
|
|
483
|
-
var
|
|
483
|
+
var he = 5e3, O = "video/mp4; codecs=\"avc1.42E01E\"", k = "audio/mp4; codecs=\"mp4a.40.2\"", A = {
|
|
484
484
|
widevine: ["com.widevine.alpha"],
|
|
485
485
|
fairplay: ["com.apple.fps"]
|
|
486
486
|
};
|
|
487
|
-
function
|
|
487
|
+
function j(e) {
|
|
488
488
|
return e === "fairplay" ? [{
|
|
489
489
|
initDataTypes: [
|
|
490
490
|
"sinf",
|
|
@@ -492,30 +492,30 @@ function M(e) {
|
|
|
492
492
|
"cenc"
|
|
493
493
|
],
|
|
494
494
|
videoCapabilities: [{
|
|
495
|
-
contentType:
|
|
495
|
+
contentType: O,
|
|
496
496
|
robustness: "",
|
|
497
497
|
encryptionScheme: "cbcs"
|
|
498
498
|
}],
|
|
499
499
|
audioCapabilities: [{
|
|
500
|
-
contentType:
|
|
500
|
+
contentType: k,
|
|
501
501
|
robustness: "",
|
|
502
502
|
encryptionScheme: "cbcs"
|
|
503
503
|
}]
|
|
504
504
|
}] : [{
|
|
505
505
|
initDataTypes: ["cenc"],
|
|
506
506
|
videoCapabilities: [{
|
|
507
|
-
contentType:
|
|
507
|
+
contentType: O,
|
|
508
508
|
robustness: "SW_SECURE_DECODE",
|
|
509
509
|
encryptionScheme: "cbcs"
|
|
510
510
|
}],
|
|
511
511
|
audioCapabilities: [{
|
|
512
|
-
contentType:
|
|
512
|
+
contentType: k,
|
|
513
513
|
robustness: "SW_SECURE_CRYPTO",
|
|
514
514
|
encryptionScheme: "cbcs"
|
|
515
515
|
}]
|
|
516
516
|
}];
|
|
517
517
|
}
|
|
518
|
-
function
|
|
518
|
+
function M(e, t) {
|
|
519
519
|
return new Promise((n, r) => {
|
|
520
520
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
521
521
|
e.then((e) => {
|
|
@@ -525,8 +525,8 @@ function N(e, t) {
|
|
|
525
525
|
});
|
|
526
526
|
});
|
|
527
527
|
}
|
|
528
|
-
async function
|
|
529
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
528
|
+
async function N(e = {}) {
|
|
529
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? he, r = {};
|
|
530
530
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
531
531
|
verdict: "insecure-context",
|
|
532
532
|
detail: r
|
|
@@ -538,7 +538,7 @@ async function P(e = {}) {
|
|
|
538
538
|
};
|
|
539
539
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
540
540
|
for (let e of t) {
|
|
541
|
-
let t =
|
|
541
|
+
let t = A[e];
|
|
542
542
|
if (!t) {
|
|
543
543
|
r[e] = "unknown system";
|
|
544
544
|
continue;
|
|
@@ -549,7 +549,7 @@ async function P(e = {}) {
|
|
|
549
549
|
break;
|
|
550
550
|
}
|
|
551
551
|
try {
|
|
552
|
-
return await
|
|
552
|
+
return await M((await M(i(n, j(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
553
553
|
verdict: "supported",
|
|
554
554
|
system: e,
|
|
555
555
|
detail: r
|
|
@@ -573,17 +573,17 @@ async function P(e = {}) {
|
|
|
573
573
|
}
|
|
574
574
|
//#endregion
|
|
575
575
|
//#region src/core/manifest.ts
|
|
576
|
-
var
|
|
577
|
-
function
|
|
578
|
-
return
|
|
576
|
+
var P = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
577
|
+
function F(e) {
|
|
578
|
+
return P.test(e);
|
|
579
579
|
}
|
|
580
580
|
//#endregion
|
|
581
581
|
//#region src/core/stats.ts
|
|
582
|
-
var
|
|
583
|
-
function
|
|
582
|
+
var I = { droppedFrames: 0 };
|
|
583
|
+
function L(e) {
|
|
584
584
|
return e.getVideoPlaybackQuality?.()?.droppedVideoFrames ?? 0;
|
|
585
585
|
}
|
|
586
|
-
function
|
|
586
|
+
function R(e, t) {
|
|
587
587
|
let n = [
|
|
588
588
|
["playing", () => t("playing")],
|
|
589
589
|
["waiting", () => t("buffering")],
|
|
@@ -600,7 +600,7 @@ function z(e, t) {
|
|
|
600
600
|
}
|
|
601
601
|
//#endregion
|
|
602
602
|
//#region src/core/engine/native.ts
|
|
603
|
-
function
|
|
603
|
+
function ge(e) {
|
|
604
604
|
try {
|
|
605
605
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
606
606
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -608,15 +608,15 @@ function he(e) {
|
|
|
608
608
|
return;
|
|
609
609
|
}
|
|
610
610
|
}
|
|
611
|
-
function
|
|
611
|
+
function z(e) {
|
|
612
612
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
613
613
|
}
|
|
614
|
-
function
|
|
614
|
+
function B() {
|
|
615
615
|
if (typeof window > "u") return !1;
|
|
616
616
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
617
617
|
return e || t;
|
|
618
618
|
}
|
|
619
|
-
var
|
|
619
|
+
var V = class {
|
|
620
620
|
name = "native";
|
|
621
621
|
deps;
|
|
622
622
|
onLoaded;
|
|
@@ -659,7 +659,7 @@ var H = class {
|
|
|
659
659
|
});
|
|
660
660
|
this.onEncrypted = (t) => {
|
|
661
661
|
let o = t;
|
|
662
|
-
!o.initData || this.fairplayArmed || (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
662
|
+
!o.initData || this.fairplayArmed || (this.fairplayArmed = !0, this.fairplayKeyIV = ge(o.initData), (async () => {
|
|
663
663
|
try {
|
|
664
664
|
let t = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
665
665
|
initDataTypes: [o.initDataType],
|
|
@@ -751,7 +751,7 @@ var H = class {
|
|
|
751
751
|
e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
|
|
752
752
|
}
|
|
753
753
|
getStats() {
|
|
754
|
-
let e = this.deps.video, t = { droppedFrames:
|
|
754
|
+
let e = this.deps.video, t = { droppedFrames: L(e) };
|
|
755
755
|
return e.duration === Infinity && (t.isLive = !0, e.seekable.length > 0 && (t.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)), t;
|
|
756
756
|
}
|
|
757
757
|
stop() {
|
|
@@ -773,20 +773,20 @@ var H = class {
|
|
|
773
773
|
};
|
|
774
774
|
//#endregion
|
|
775
775
|
//#region src/core/engine/hls.ts
|
|
776
|
-
function
|
|
776
|
+
function _e() {
|
|
777
777
|
return e.isSupported();
|
|
778
778
|
}
|
|
779
|
-
var
|
|
780
|
-
function
|
|
779
|
+
var ve = 3, ye = 5, be = 3, xe = 3e4, Se = 12e3, Ce = 3e3, H = 6e3, we = 4e3, Te = 2, Ee = 5, De = 2, Oe = 9, ke = .5;
|
|
780
|
+
function Ae(e) {
|
|
781
781
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
782
782
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
783
783
|
return;
|
|
784
784
|
}
|
|
785
|
-
e.liveSyncDuration ??=
|
|
786
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
787
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
785
|
+
e.liveSyncDuration ??= De;
|
|
786
|
+
let t = Math.max(12, e.liveSyncDuration + Oe);
|
|
787
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), je(e, e.liveSyncDuration);
|
|
788
788
|
}
|
|
789
|
-
function
|
|
789
|
+
function je(e, t) {
|
|
790
790
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
791
791
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
792
792
|
}
|
|
@@ -809,6 +809,9 @@ var U = class {
|
|
|
809
809
|
lastAdvanceMs = 0;
|
|
810
810
|
endWatchdog = null;
|
|
811
811
|
endedEmitted = !1;
|
|
812
|
+
lastFragLoadingMs = 0;
|
|
813
|
+
starvedTicks = 0;
|
|
814
|
+
starvationKicks = 0;
|
|
812
815
|
chaseSuspended = !1;
|
|
813
816
|
savedLiveMaxLatency;
|
|
814
817
|
savedMaxSyncRate;
|
|
@@ -816,7 +819,7 @@ var U = class {
|
|
|
816
819
|
this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl;
|
|
817
820
|
}
|
|
818
821
|
async load() {
|
|
819
|
-
let { descriptor: e, snapToLiveOnRefocus: n, video: r, emit: i } = this.deps, a =
|
|
822
|
+
let { descriptor: e, snapToLiveOnRefocus: n, video: r, emit: i } = this.deps, a = z(r) && B(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
820
823
|
if (e.drmEnabled && !o) {
|
|
821
824
|
i({
|
|
822
825
|
type: "error",
|
|
@@ -840,7 +843,7 @@ var U = class {
|
|
|
840
843
|
let t = e.liveSyncPosition;
|
|
841
844
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
842
845
|
let { video: n } = this.deps;
|
|
843
|
-
n.currentTime <= t +
|
|
846
|
+
n.currentTime <= t + ke || (n.currentTime = t);
|
|
844
847
|
}
|
|
845
848
|
startHls() {
|
|
846
849
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps, u = n.drmEnabled && !!(n.drm?.widevine?.licenseUrl || n.drm?.fairplay?.licenseUrl), d = {
|
|
@@ -867,14 +870,16 @@ var U = class {
|
|
|
867
870
|
} : {},
|
|
868
871
|
...c
|
|
869
872
|
};
|
|
870
|
-
|
|
873
|
+
Ae(d);
|
|
871
874
|
let f = new e(d);
|
|
872
875
|
this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
873
876
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, l({ type: "ready" });
|
|
874
|
-
}), f.on(e.Events.FRAG_BUFFERED, () => {
|
|
875
|
-
(this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
876
|
-
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.recoveryResetTimer = null;
|
|
877
|
-
},
|
|
877
|
+
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
878
|
+
t?.frag?.type === "main" && (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
879
|
+
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.recoveryResetTimer = null;
|
|
880
|
+
}, xe));
|
|
881
|
+
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
882
|
+
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
878
883
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
879
884
|
if (this.detectedLowLatency) return;
|
|
880
885
|
let n = t.details;
|
|
@@ -882,7 +887,9 @@ var U = class {
|
|
|
882
887
|
type: "lowLatencyDetected",
|
|
883
888
|
value: !0
|
|
884
889
|
}));
|
|
885
|
-
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog = setInterval(() =>
|
|
890
|
+
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.endWatchdog = setInterval(() => {
|
|
891
|
+
this.checkEndStale(), this.checkStarvation();
|
|
892
|
+
}, Ce), f.on(e.Events.LEVEL_SWITCHED, (e, t) => l({
|
|
886
893
|
type: "qualitychange",
|
|
887
894
|
index: t.level
|
|
888
895
|
})), f.on(e.Events.AUDIO_TRACK_SWITCHED, (e, t) => l({
|
|
@@ -951,7 +958,7 @@ var U = class {
|
|
|
951
958
|
}
|
|
952
959
|
getStats() {
|
|
953
960
|
let e = this.hls, t = {
|
|
954
|
-
droppedFrames:
|
|
961
|
+
droppedFrames: L(this.deps.video),
|
|
955
962
|
lowLatency: this.detectedLowLatency
|
|
956
963
|
};
|
|
957
964
|
if (e) {
|
|
@@ -980,7 +987,28 @@ var U = class {
|
|
|
980
987
|
return;
|
|
981
988
|
}
|
|
982
989
|
let e = Date.now() - this.lastAdvanceMs;
|
|
983
|
-
!this.chaseSuspended && e >
|
|
990
|
+
!this.chaseSuspended && e > H && this.suspendChasing(), e > Se && this.emitEnded("stalled");
|
|
991
|
+
}
|
|
992
|
+
checkStarvation() {
|
|
993
|
+
let e = this.hls, { video: t } = this.deps;
|
|
994
|
+
if (!e || this.endedEmitted || !this.sawLive || this.chaseSuspended) return;
|
|
995
|
+
if (typeof document < "u" && document.hidden) {
|
|
996
|
+
this.starvedTicks = 0;
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
999
|
+
let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < H, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > we;
|
|
1000
|
+
if (!(t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused && n && r)) {
|
|
1001
|
+
this.starvedTicks = 0;
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
if (!(++this.starvedTicks < Te) && (this.starvedTicks = 0, !(this.starvationKicks >= Ee))) {
|
|
1005
|
+
this.starvationKicks += 1, console.warn("havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting load at the live edge");
|
|
1006
|
+
try {
|
|
1007
|
+
e.stopLoad(), e.startLoad(-1);
|
|
1008
|
+
} catch (e) {
|
|
1009
|
+
console.warn("havik-player: starvation kick failed", e);
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
984
1012
|
}
|
|
985
1013
|
suspendChasing() {
|
|
986
1014
|
let e = this.hls;
|
|
@@ -1022,7 +1050,7 @@ var U = class {
|
|
|
1022
1050
|
scheduleLicenseRetry(t) {
|
|
1023
1051
|
if (!(t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED || t.details === e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED)) return !1;
|
|
1024
1052
|
let n = t.response?.code ?? 0;
|
|
1025
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1053
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= be) return !1;
|
|
1026
1054
|
this.licenseRecoveries += 1;
|
|
1027
1055
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1028
1056
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1050,7 +1078,7 @@ var U = class {
|
|
|
1050
1078
|
return;
|
|
1051
1079
|
}
|
|
1052
1080
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1053
|
-
if (this.networkRecoveries <
|
|
1081
|
+
if (this.networkRecoveries < ye) {
|
|
1054
1082
|
this.networkRecoveries += 1;
|
|
1055
1083
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1056
1084
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1066,7 +1094,7 @@ var U = class {
|
|
|
1066
1094
|
return;
|
|
1067
1095
|
}
|
|
1068
1096
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1069
|
-
if (this.mediaRecoveries <
|
|
1097
|
+
if (this.mediaRecoveries < ve) {
|
|
1070
1098
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1071
1099
|
return;
|
|
1072
1100
|
}
|
|
@@ -1121,15 +1149,15 @@ function K(e, t) {
|
|
|
1121
1149
|
}
|
|
1122
1150
|
//#endregion
|
|
1123
1151
|
//#region src/ui/styles.ts
|
|
1124
|
-
var q = "havik-player-styles",
|
|
1125
|
-
function
|
|
1152
|
+
var q = "havik-player-styles", Me = "\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";
|
|
1153
|
+
function Ne(e = document) {
|
|
1126
1154
|
if (e.getElementById(q)) return;
|
|
1127
1155
|
let t = e.createElement("style");
|
|
1128
|
-
t.id = q, t.textContent =
|
|
1156
|
+
t.id = q, t.textContent = Me, e.head.appendChild(t);
|
|
1129
1157
|
}
|
|
1130
1158
|
//#endregion
|
|
1131
1159
|
//#region src/ui/icons.ts
|
|
1132
|
-
var
|
|
1160
|
+
var Pe = {
|
|
1133
1161
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
1134
1162
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
1135
1163
|
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\"/>",
|
|
@@ -1143,20 +1171,20 @@ var je = {
|
|
|
1143
1171
|
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\"/>"
|
|
1144
1172
|
};
|
|
1145
1173
|
function J(e) {
|
|
1146
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
1174
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Pe[e]}</svg>`;
|
|
1147
1175
|
}
|
|
1148
1176
|
//#endregion
|
|
1149
1177
|
//#region src/ui/controls.ts
|
|
1150
|
-
var
|
|
1178
|
+
var Fe = 3e3, Ie = /* @__PURE__ */ new Set([
|
|
1151
1179
|
"GONE",
|
|
1152
1180
|
"NOT_FOUND",
|
|
1153
1181
|
"INVALID_URN",
|
|
1154
1182
|
"UNAUTHORIZED"
|
|
1155
1183
|
]);
|
|
1156
|
-
function
|
|
1157
|
-
return new
|
|
1184
|
+
function Le(e) {
|
|
1185
|
+
return new Re(e);
|
|
1158
1186
|
}
|
|
1159
|
-
var
|
|
1187
|
+
var Re = class {
|
|
1160
1188
|
root;
|
|
1161
1189
|
video;
|
|
1162
1190
|
player;
|
|
@@ -1196,7 +1224,7 @@ var Fe = class {
|
|
|
1196
1224
|
scrubbing = !1;
|
|
1197
1225
|
offFns = [];
|
|
1198
1226
|
constructor(e) {
|
|
1199
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
1227
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Fe, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.errorMessage = e.errorMessage, Ne(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");
|
|
1200
1228
|
let t = (e, t, n) => {
|
|
1201
1229
|
let r = this.doc.createElement(e);
|
|
1202
1230
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -1283,7 +1311,7 @@ var Fe = class {
|
|
|
1283
1311
|
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = J("play"), e.addEventListener("click", () => void this.player.play()), t.append(e);
|
|
1284
1312
|
} else {
|
|
1285
1313
|
let n = this.doc.createElement("div");
|
|
1286
|
-
if (n.className = "havik-status__msg", n.textContent = e === "ended" ? this.endedMessage : e === "waiting" ? "Starting soon…" : this.errorMessage ?? this.lastError?.message ?? "Playback unavailable", t.append(n), e === "error" && this.lastError && !
|
|
1314
|
+
if (n.className = "havik-status__msg", n.textContent = e === "ended" ? this.endedMessage : e === "waiting" ? "Starting soon…" : this.errorMessage ?? this.lastError?.message ?? "Playback unavailable", t.append(n), e === "error" && this.lastError && !Ie.has(this.lastError.code)) {
|
|
1287
1315
|
let e = this.doc.createElement("button");
|
|
1288
1316
|
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${J("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), t.append(e);
|
|
1289
1317
|
}
|
|
@@ -1374,17 +1402,17 @@ var Fe = class {
|
|
|
1374
1402
|
renderQualityMenu() {
|
|
1375
1403
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
1376
1404
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
1377
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
1405
|
+
for (let n of e) this.menu.append(this.menuItem(ze(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
1378
1406
|
}
|
|
1379
1407
|
renderAudioMenu() {
|
|
1380
1408
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
1381
1409
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
1382
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
1410
|
+
for (let t of e) this.menu.append(this.menuItem(Be(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
1383
1411
|
}
|
|
1384
1412
|
renderCcMenu() {
|
|
1385
1413
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
1386
1414
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
1387
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
1415
|
+
for (let t of e) this.menu.append(this.menuItem(Ve(t), !1, () => this.player.setTextTrack(t.id)));
|
|
1388
1416
|
}
|
|
1389
1417
|
onTracksChanged() {
|
|
1390
1418
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -1490,27 +1518,27 @@ function Y(e) {
|
|
|
1490
1518
|
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");
|
|
1491
1519
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
1492
1520
|
}
|
|
1493
|
-
function
|
|
1521
|
+
function ze(e) {
|
|
1494
1522
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
1495
1523
|
}
|
|
1496
|
-
function
|
|
1524
|
+
function Be(e) {
|
|
1497
1525
|
return e.name || e.lang || `Track ${e.id}`;
|
|
1498
1526
|
}
|
|
1499
|
-
function
|
|
1527
|
+
function Ve(e) {
|
|
1500
1528
|
return e.name || e.lang || `Track ${e.id}`;
|
|
1501
1529
|
}
|
|
1502
1530
|
//#endregion
|
|
1503
1531
|
//#region src/managed/index.ts
|
|
1504
|
-
var
|
|
1505
|
-
async function
|
|
1532
|
+
var He = 6e3, X = 45e3, Ue = 2e3, Z = 3, We = 2e3, Ge = 480 * 1e3;
|
|
1533
|
+
async function Q(e) {
|
|
1506
1534
|
if (!e.video || typeof e.video.play != "function") throw new t("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
1507
1535
|
if (!e.baseUrl) throw new t("INTERNAL", 0, "createPlayer: baseUrl is required");
|
|
1508
1536
|
if (!e.matchUrn) throw new t("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
1509
1537
|
if (!e.credential) throw new t("INTERNAL", 0, "createPlayer: credential is required");
|
|
1510
|
-
let n = new
|
|
1538
|
+
let n = new Ke(e);
|
|
1511
1539
|
return await n.start(), n;
|
|
1512
1540
|
}
|
|
1513
|
-
var
|
|
1541
|
+
var Ke = class {
|
|
1514
1542
|
opts;
|
|
1515
1543
|
abort = new AbortController();
|
|
1516
1544
|
listeners = {};
|
|
@@ -1544,7 +1572,7 @@ var We = class {
|
|
|
1544
1572
|
this.opts.muted && (this.opts.video.muted = !0), this.opts.poster && (this.opts.video.poster = this.opts.poster), this.mountControls(), this.attachPipListeners(), this.setState("loading");
|
|
1545
1573
|
let e = ++this.loadGen, n = this.resolveOptions();
|
|
1546
1574
|
try {
|
|
1547
|
-
let t = await
|
|
1575
|
+
let t = await v(n);
|
|
1548
1576
|
if (await this.onResolved(t, e), e === this.loadGen && this._state === "error" && this._lastError) {
|
|
1549
1577
|
let e = this._lastError;
|
|
1550
1578
|
throw this.destroy(), e;
|
|
@@ -1566,11 +1594,11 @@ var We = class {
|
|
|
1566
1594
|
};
|
|
1567
1595
|
}
|
|
1568
1596
|
beginArming(e, t) {
|
|
1569
|
-
let n = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
1597
|
+
let n = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? w(this.opts.baseUrl);
|
|
1570
1598
|
n ? this.armWithSse(e, n, t) : this.beginArmingByPolling(e);
|
|
1571
1599
|
}
|
|
1572
1600
|
beginArmingByPolling(e) {
|
|
1573
|
-
|
|
1601
|
+
y({
|
|
1574
1602
|
...this.resolveOptions(),
|
|
1575
1603
|
signal: this.abort.signal,
|
|
1576
1604
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -1604,7 +1632,7 @@ var We = class {
|
|
|
1604
1632
|
}
|
|
1605
1633
|
}
|
|
1606
1634
|
}, m = () => {
|
|
1607
|
-
a || o || f() || (o = !0,
|
|
1635
|
+
a || o || f() || (o = !0, y({
|
|
1608
1636
|
...this.resolveOptions(),
|
|
1609
1637
|
signal: s.signal,
|
|
1610
1638
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -1612,7 +1640,7 @@ var We = class {
|
|
|
1612
1640
|
a || f() || s.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof t ? e : new t("INTERNAL", 0, String(e))));
|
|
1613
1641
|
}));
|
|
1614
1642
|
}, h = () => {
|
|
1615
|
-
a || f() ||
|
|
1643
|
+
a || f() || v(this.resolveOptions()).then((e) => p(e)).catch((e) => {
|
|
1616
1644
|
a || f() || e instanceof t && i(e.code) || (a = !0, this.closeArming(), s.abort(), this.fail(e instanceof t ? e : new t("INTERNAL", 0, String(e))));
|
|
1617
1645
|
});
|
|
1618
1646
|
}, g = (e) => {
|
|
@@ -1620,13 +1648,13 @@ var We = class {
|
|
|
1620
1648
|
!a && !f() && m();
|
|
1621
1649
|
}, e);
|
|
1622
1650
|
};
|
|
1623
|
-
g(
|
|
1651
|
+
g(He), this.armingSub = C({
|
|
1624
1652
|
eventsBaseUrl: n,
|
|
1625
1653
|
matchUrn: this.opts.matchUrn,
|
|
1626
1654
|
credential: this.opts.credential,
|
|
1627
1655
|
onAlive: () => g(X),
|
|
1628
1656
|
onState: (e) => {
|
|
1629
|
-
a || f() || (e.state === "live" || e.state === "gone") && setTimeout(h, Math.random() *
|
|
1657
|
+
a || f() || (e.state === "live" || e.state === "gone") && setTimeout(h, Math.random() * Ue);
|
|
1630
1658
|
},
|
|
1631
1659
|
onError: () => m()
|
|
1632
1660
|
});
|
|
@@ -1649,7 +1677,7 @@ var We = class {
|
|
|
1649
1677
|
let n = await a(this.opts.credential);
|
|
1650
1678
|
if (this.destroyed || t !== this.loadGen) return;
|
|
1651
1679
|
this.setState("loading");
|
|
1652
|
-
let r = this.createEngine(e, n), i =
|
|
1680
|
+
let r = this.createEngine(e, n), i = R(this.opts.video, (e) => {
|
|
1653
1681
|
this._state === "ended" || this._state === "error" || this.setState(e);
|
|
1654
1682
|
});
|
|
1655
1683
|
if (await r.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -1669,7 +1697,7 @@ var We = class {
|
|
|
1669
1697
|
video: this.opts.video,
|
|
1670
1698
|
descriptor: e,
|
|
1671
1699
|
credential: n,
|
|
1672
|
-
deviceId:
|
|
1700
|
+
deviceId: D(),
|
|
1673
1701
|
userId: this.opts.userId,
|
|
1674
1702
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
1675
1703
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -1677,11 +1705,11 @@ var We = class {
|
|
|
1677
1705
|
hlsConfig: r,
|
|
1678
1706
|
emit: (e) => this.onEngineEvent(e)
|
|
1679
1707
|
}, a = this.opts.engine ?? "auto";
|
|
1680
|
-
if (a === "native") return new
|
|
1708
|
+
if (a === "native") return new V(i);
|
|
1681
1709
|
if (a === "hls") return new U(i);
|
|
1682
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
1683
|
-
if (
|
|
1684
|
-
if (
|
|
1710
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && z(this.opts.video) && B()) return new V(i);
|
|
1711
|
+
if (_e()) return new U(i);
|
|
1712
|
+
if (z(this.opts.video)) return new V(i);
|
|
1685
1713
|
throw new t("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
1686
1714
|
}
|
|
1687
1715
|
onEngineEvent(e) {
|
|
@@ -1711,11 +1739,11 @@ var We = class {
|
|
|
1711
1739
|
}
|
|
1712
1740
|
startLiveState(e) {
|
|
1713
1741
|
if (this.opts.liveStateEvents === !1) return;
|
|
1714
|
-
let n = this.opts.eventsBaseUrl ??
|
|
1742
|
+
let n = this.opts.eventsBaseUrl ?? w(this.opts.baseUrl);
|
|
1715
1743
|
if (!n) return;
|
|
1716
1744
|
this.closeLiveState();
|
|
1717
1745
|
let r = 0, i = !1;
|
|
1718
|
-
this.liveStateSub =
|
|
1746
|
+
this.liveStateSub = C({
|
|
1719
1747
|
eventsBaseUrl: n,
|
|
1720
1748
|
matchUrn: this.opts.matchUrn,
|
|
1721
1749
|
credential: this.opts.credential,
|
|
@@ -1726,7 +1754,7 @@ var We = class {
|
|
|
1726
1754
|
r = 0, i = !1;
|
|
1727
1755
|
},
|
|
1728
1756
|
onError: () => {
|
|
1729
|
-
this.destroyed || e !== this.loadGen || i || (r += 1, r >=
|
|
1757
|
+
this.destroyed || e !== this.loadGen || i || (r += 1, r >= Z && (i = !0, this.emit("warning", new t("NETWORK", 0, `live-state events unreachable at ${n} 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.`))));
|
|
1730
1758
|
}
|
|
1731
1759
|
});
|
|
1732
1760
|
}
|
|
@@ -1748,7 +1776,7 @@ var We = class {
|
|
|
1748
1776
|
}
|
|
1749
1777
|
t.controls = !1;
|
|
1750
1778
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
1751
|
-
r && r.insertBefore(n, t), n.appendChild(t), K(n, this.opts.theme), this.container = n, this.controlBar =
|
|
1779
|
+
r && r.insertBefore(n, t), n.appendChild(t), K(n, this.opts.theme), this.container = n, this.controlBar = Le({
|
|
1752
1780
|
root: n,
|
|
1753
1781
|
video: t,
|
|
1754
1782
|
player: this,
|
|
@@ -1771,7 +1799,7 @@ var We = class {
|
|
|
1771
1799
|
}
|
|
1772
1800
|
startStats() {
|
|
1773
1801
|
this.stopStats();
|
|
1774
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
1802
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? We);
|
|
1775
1803
|
this.statsTimer = setInterval(() => {
|
|
1776
1804
|
this.engine && this.emit("stats", this.engine.getStats());
|
|
1777
1805
|
}, e);
|
|
@@ -1781,7 +1809,7 @@ var We = class {
|
|
|
1781
1809
|
}
|
|
1782
1810
|
scheduleLicenseRefresh() {
|
|
1783
1811
|
this.stopRefresh();
|
|
1784
|
-
let e = this.opts.licenseRefreshMs ??
|
|
1812
|
+
let e = this.opts.licenseRefreshMs ?? Ge;
|
|
1785
1813
|
!e || !this._descriptor?.drmEnabled || (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
1786
1814
|
}
|
|
1787
1815
|
stopRefresh() {
|
|
@@ -1790,7 +1818,7 @@ var We = class {
|
|
|
1790
1818
|
async refreshLicense() {
|
|
1791
1819
|
let e = this.engine;
|
|
1792
1820
|
if (!(this.destroyed || !e)) try {
|
|
1793
|
-
let t = await
|
|
1821
|
+
let t = await v(this.resolveOptions());
|
|
1794
1822
|
if (this.destroyed || this.engine !== e) return;
|
|
1795
1823
|
let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
|
|
1796
1824
|
(n || r) && (e.setLicenseUrls({
|
|
@@ -1818,7 +1846,7 @@ var We = class {
|
|
|
1818
1846
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
1819
1847
|
}
|
|
1820
1848
|
getStats() {
|
|
1821
|
-
return this.engine?.getStats() ??
|
|
1849
|
+
return this.engine?.getStats() ?? I;
|
|
1822
1850
|
}
|
|
1823
1851
|
getQualityLevels() {
|
|
1824
1852
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -1864,7 +1892,7 @@ var We = class {
|
|
|
1864
1892
|
let e = ++this.loadGen;
|
|
1865
1893
|
this.stopStats(), this.stopRefresh(), this.closeArming(), this.closeLiveState(), this.detachMedia?.(), this.engine?.destroy(), this.engine = null;
|
|
1866
1894
|
try {
|
|
1867
|
-
let t = await
|
|
1895
|
+
let t = await y({
|
|
1868
1896
|
...this.resolveOptions(),
|
|
1869
1897
|
waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
|
|
1870
1898
|
});
|
|
@@ -1914,12 +1942,12 @@ var We = class {
|
|
|
1914
1942
|
};
|
|
1915
1943
|
//#endregion
|
|
1916
1944
|
//#region src/embed/protocol.ts
|
|
1917
|
-
function
|
|
1945
|
+
function $(e) {
|
|
1918
1946
|
return !!e && typeof e == "object" && typeof e.type == "string" && e.type.startsWith("oddin:");
|
|
1919
1947
|
}
|
|
1920
1948
|
//#endregion
|
|
1921
1949
|
//#region src/embed/host.ts
|
|
1922
|
-
function
|
|
1950
|
+
function qe(e) {
|
|
1923
1951
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
1924
1952
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
1925
1953
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -1928,7 +1956,7 @@ function $(e) {
|
|
|
1928
1956
|
let r = document.createElement("iframe");
|
|
1929
1957
|
r.src = t.toString(), r.allow = "autoplay; encrypted-media; fullscreen", r.setAttribute("allowfullscreen", ""), r.referrerPolicy = "no-referrer", r.setAttribute("sandbox", e.sandbox ?? "allow-scripts allow-same-origin allow-presentation"), r.style.cssText = "border:0;width:100%;height:100%;display:block", e.container.appendChild(r);
|
|
1930
1958
|
let i = /* @__PURE__ */ new Set(), a = (t) => {
|
|
1931
|
-
if (t.source !== r.contentWindow || t.origin !== n ||
|
|
1959
|
+
if (t.source !== r.contentWindow || t.origin !== n || !$(t.data)) return;
|
|
1932
1960
|
let a = t.data;
|
|
1933
1961
|
a.type === "oddin:ready" && a.protocol !== 1 && console.warn(`havik-player: embed protocol v${a.protocol} != host v1. Pin the embed page version to the SDK version to avoid skew.`), e.onEvent?.(a), i.forEach((e) => e(a));
|
|
1934
1962
|
};
|
|
@@ -1978,8 +2006,8 @@ function $(e) {
|
|
|
1978
2006
|
}
|
|
1979
2007
|
//#endregion
|
|
1980
2008
|
//#region src/embed/page.ts
|
|
1981
|
-
var
|
|
1982
|
-
function
|
|
2009
|
+
var Je = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
2010
|
+
function Ye() {
|
|
1983
2011
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
1984
2012
|
if (e) return {
|
|
1985
2013
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -2001,9 +2029,9 @@ function Ke() {
|
|
|
2001
2029
|
waitForLive: !0
|
|
2002
2030
|
};
|
|
2003
2031
|
}
|
|
2004
|
-
async function
|
|
2005
|
-
let e =
|
|
2006
|
-
|
|
2032
|
+
async function Xe() {
|
|
2033
|
+
let e = Ye();
|
|
2034
|
+
Qe();
|
|
2007
2035
|
let n = document.createElement("video");
|
|
2008
2036
|
n.setAttribute("playsinline", ""), n.muted = e.muted ?? !0, n.style.cssText = "width:100%;height:100%;object-fit:contain;background:#000;aspect-ratio:auto", document.body.appendChild(n);
|
|
2009
2037
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -2058,12 +2086,12 @@ async function qe() {
|
|
|
2058
2086
|
code: e.code,
|
|
2059
2087
|
message: e.message
|
|
2060
2088
|
})), e.on("autoplayblocked", () => {
|
|
2061
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
2089
|
+
i({ type: "oddin:autoplayblocked" }), Ze(n, e);
|
|
2062
2090
|
});
|
|
2063
2091
|
}, s = async (r) => {
|
|
2064
2092
|
a?.destroy(), a = null;
|
|
2065
2093
|
try {
|
|
2066
|
-
let t = await
|
|
2094
|
+
let t = await Q({
|
|
2067
2095
|
video: n,
|
|
2068
2096
|
baseUrl: e.baseUrl,
|
|
2069
2097
|
matchUrn: r,
|
|
@@ -2124,32 +2152,32 @@ async function qe() {
|
|
|
2124
2152
|
a?.retry();
|
|
2125
2153
|
break;
|
|
2126
2154
|
case "oddin:load":
|
|
2127
|
-
typeof e.matchUrn == "string" &&
|
|
2155
|
+
typeof e.matchUrn == "string" && Je.test(e.matchUrn) && s(e.matchUrn);
|
|
2128
2156
|
break;
|
|
2129
2157
|
case "oddin:destroy":
|
|
2130
2158
|
c();
|
|
2131
2159
|
break;
|
|
2132
2160
|
}
|
|
2133
2161
|
}, u = (e) => {
|
|
2134
|
-
!r || e.origin !== r ||
|
|
2162
|
+
!r || e.origin !== r || $(e.data) && l(e.data);
|
|
2135
2163
|
};
|
|
2136
2164
|
r && window.addEventListener("message", u), window.addEventListener("pagehide", c, { once: !0 }), await s(e.matchUrn), i({
|
|
2137
2165
|
type: "oddin:ready",
|
|
2138
2166
|
protocol: 1
|
|
2139
2167
|
});
|
|
2140
2168
|
}
|
|
2141
|
-
function
|
|
2169
|
+
function Ze(e, t) {
|
|
2142
2170
|
if (document.getElementById("havik-tap")) return;
|
|
2143
2171
|
let n = document.createElement("button");
|
|
2144
2172
|
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", () => {
|
|
2145
2173
|
n.remove(), t.play();
|
|
2146
2174
|
}), document.body.appendChild(n);
|
|
2147
2175
|
}
|
|
2148
|
-
function
|
|
2176
|
+
function Qe() {
|
|
2149
2177
|
let e = document.createElement("style");
|
|
2150
2178
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
2151
2179
|
}
|
|
2152
2180
|
//#endregion
|
|
2153
|
-
export { W as ODDIN_THEME, t as PlaybackError, K as applyTheme,
|
|
2181
|
+
export { W as ODDIN_THEME, t as PlaybackError, K as applyTheme, Xe as bootEmbed, fe as clearDeviceId, Q as createPlayer, w as deriveEventsBaseUrl, N as detectDrmSupport, S as fetchCatalog, ce as fetchTournament, ue as flattenMatches, D as getDeviceId, F as isLowLatencyManifest, $ as isOddinMessage, me as licenseRequestHeaders, qe as mountEmbed, _ as pollToLive, y as resolveStream, C as subscribeLiveState, de as watchStatus };
|
|
2154
2182
|
|
|
2155
2183
|
//# sourceMappingURL=index.js.map
|