@oddin-gg/havik-player 1.16.0 → 1.17.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/README.md +28 -14
- package/dist/havik-player.global.js +2 -2
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +193 -174
- package/dist/index.js.map +1 -1
- package/docs/API.md +1270 -0
- package/docs/STABILITY.md +56 -0
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +4 -5
package/dist/index.js
CHANGED
|
@@ -85,13 +85,13 @@ function d(e) {
|
|
|
85
85
|
}
|
|
86
86
|
//#endregion
|
|
87
87
|
//#region src/core/waitForLive.ts
|
|
88
|
-
var f = 1e3, p = 3e4, m = 6e5, h = 3e5, g = 1e3,
|
|
88
|
+
var f = 1e3, p = 3e4, m = 6e5, h = 3e5, g = 1e3, _ = {
|
|
89
89
|
TOO_EARLY: "tooEarly",
|
|
90
90
|
UNAVAILABLE: "unavailable",
|
|
91
91
|
RATE_LIMITED: "rateLimited",
|
|
92
92
|
NETWORK: "network"
|
|
93
93
|
};
|
|
94
|
-
function
|
|
94
|
+
function ee(e) {
|
|
95
95
|
let t = e === !0 || e === !1 ? {} : e, n = Math.max(g, t.floorMs ?? f), r = Math.max(n, t.ceilMs ?? p), i = Math.max(0, t.imminentMs ?? m), a = Math.max(r, t.sanityFloorMs ?? h);
|
|
96
96
|
return {
|
|
97
97
|
timeoutMs: t.timeoutMs,
|
|
@@ -99,27 +99,27 @@ function te(e) {
|
|
|
99
99
|
ceilMs: r,
|
|
100
100
|
imminentMs: i,
|
|
101
101
|
sanityFloorMs: a,
|
|
102
|
-
kickoffMs:
|
|
102
|
+
kickoffMs: te(t.kickoffAt),
|
|
103
103
|
jitter: t.jitter ?? !0,
|
|
104
104
|
onState: t.onState
|
|
105
105
|
};
|
|
106
106
|
}
|
|
107
|
-
function
|
|
107
|
+
function te(e) {
|
|
108
108
|
if (e == null) return;
|
|
109
109
|
if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
|
|
110
110
|
let t = Date.parse(e);
|
|
111
111
|
return Number.isFinite(t) ? t : void 0;
|
|
112
112
|
}
|
|
113
|
-
function
|
|
113
|
+
function ne(e, t, n) {
|
|
114
114
|
return Math.min(n, Math.max(t, e));
|
|
115
115
|
}
|
|
116
|
-
function
|
|
116
|
+
function re(e) {
|
|
117
117
|
return Math.round(e * (1 + .15 * Math.random()));
|
|
118
118
|
}
|
|
119
|
-
function
|
|
119
|
+
function ie(e, t, n, r) {
|
|
120
120
|
let i = r ?? n.kickoffMs, a = i == null ? void 0 : Math.max(0, i - t), o = Math.max(n.floorMs, e ?? 0);
|
|
121
121
|
if (a == null || a <= n.imminentMs) return {
|
|
122
|
-
delay:
|
|
122
|
+
delay: ne(e ?? n.floorMs, o, n.ceilMs),
|
|
123
123
|
ttkMs: a
|
|
124
124
|
};
|
|
125
125
|
let s = Math.min(Math.floor(a / 10), n.sanityFloorMs, a);
|
|
@@ -128,7 +128,7 @@ function ae(e, t, n, r) {
|
|
|
128
128
|
ttkMs: a
|
|
129
129
|
};
|
|
130
130
|
}
|
|
131
|
-
function
|
|
131
|
+
function ae(e, t) {
|
|
132
132
|
return new Promise((r, i) => {
|
|
133
133
|
if (t?.aborted) {
|
|
134
134
|
i(new n("ABORTED", 0, "wait-for-live aborted"));
|
|
@@ -142,8 +142,8 @@ function oe(e, t) {
|
|
|
142
142
|
t?.addEventListener("abort", a, { once: !0 });
|
|
143
143
|
});
|
|
144
144
|
}
|
|
145
|
-
async function
|
|
146
|
-
let i =
|
|
145
|
+
async function v(e, t, r) {
|
|
146
|
+
let i = ee(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
|
|
147
147
|
for (;;) {
|
|
148
148
|
if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
|
|
149
149
|
try {
|
|
@@ -151,38 +151,38 @@ async function _(e, t, r) {
|
|
|
151
151
|
} catch (e) {
|
|
152
152
|
if (!(e instanceof n) || !o(e.code)) throw e;
|
|
153
153
|
c += 1, e.liveStartsAtMs != null && Number.isFinite(e.liveStartsAtMs) && (l = e.liveStartsAtMs);
|
|
154
|
-
let t = Date.now(), u =
|
|
155
|
-
if (i.jitter && (f =
|
|
154
|
+
let t = Date.now(), u = ie(e.retryAfterMs, t, i, l), d = u.ttkMs, f = u.delay;
|
|
155
|
+
if (i.jitter && (f = re(f)), t + f > s) throw new n("TIMEOUT", e.httpStatus, `timed out after ${i.timeoutMs}ms waiting for the stream to go live`, {
|
|
156
156
|
retryAfterMs: e.retryAfterMs,
|
|
157
157
|
cause: e
|
|
158
158
|
});
|
|
159
159
|
i.onState?.({
|
|
160
|
-
phase:
|
|
160
|
+
phase: _[e.code] ?? "unavailable",
|
|
161
161
|
retryInMs: f,
|
|
162
162
|
attempt: c,
|
|
163
163
|
elapsedMs: t - a,
|
|
164
164
|
ttkMs: d
|
|
165
|
-
}), await
|
|
165
|
+
}), await ae(f, r);
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
//#endregion
|
|
170
170
|
//#region src/core/resolve.ts
|
|
171
|
-
async function
|
|
171
|
+
async function y(e) {
|
|
172
172
|
if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
|
|
173
173
|
let t = await u(c(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
|
|
174
174
|
credential: e.credential,
|
|
175
175
|
signal: e.signal,
|
|
176
176
|
apiHeaders: e.apiHeaders
|
|
177
177
|
});
|
|
178
|
-
if (!t.ok) throw await
|
|
179
|
-
return
|
|
178
|
+
if (!t.ok) throw await oe(t);
|
|
179
|
+
return ce(await t.json(), e.matchUrn);
|
|
180
180
|
}
|
|
181
|
-
function
|
|
182
|
-
let t = () =>
|
|
183
|
-
return e.waitForLive ?
|
|
181
|
+
function b(e) {
|
|
182
|
+
let t = () => y(e);
|
|
183
|
+
return e.waitForLive ? v(t, e.waitForLive, e.signal) : t();
|
|
184
184
|
}
|
|
185
|
-
async function
|
|
185
|
+
async function oe(e) {
|
|
186
186
|
let t = l(e.headers.get("retry-after")), i = e.headers.get("x-request-id") ?? e.headers.get("x-amzn-requestid") ?? void 0, a = e.statusText || `HTTP ${e.status}`, o, s;
|
|
187
187
|
try {
|
|
188
188
|
let t = await e.json();
|
|
@@ -198,7 +198,7 @@ async function se(e) {
|
|
|
198
198
|
liveStartsAtMs: s
|
|
199
199
|
});
|
|
200
200
|
}
|
|
201
|
-
var
|
|
201
|
+
var se = /* @__PURE__ */ new Set([
|
|
202
202
|
"matchUrn",
|
|
203
203
|
"protocol",
|
|
204
204
|
"drmEnabled",
|
|
@@ -209,7 +209,7 @@ var ce = /* @__PURE__ */ new Set([
|
|
|
209
209
|
"expiresAt",
|
|
210
210
|
"analytics"
|
|
211
211
|
]);
|
|
212
|
-
function
|
|
212
|
+
function x(e, t) {
|
|
213
213
|
let r;
|
|
214
214
|
try {
|
|
215
215
|
r = new URL(t);
|
|
@@ -219,57 +219,57 @@ function b(e, t) {
|
|
|
219
219
|
if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
|
|
220
220
|
return t;
|
|
221
221
|
}
|
|
222
|
-
function
|
|
222
|
+
function ce(e, t) {
|
|
223
223
|
if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
|
|
224
224
|
let r = e.drmEnabled ?? !!e.drm, i = {
|
|
225
225
|
matchUrn: e.matchUrn ?? t,
|
|
226
226
|
protocol: "hls",
|
|
227
227
|
drmEnabled: r,
|
|
228
|
-
manifestUrl:
|
|
228
|
+
manifestUrl: x("manifestUrl", e.manifestUrl),
|
|
229
229
|
serverTime: e.serverTime ?? ""
|
|
230
230
|
};
|
|
231
231
|
if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid && (i.analytics = { sid: e.analytics.sid }), r && e.drm) {
|
|
232
232
|
let t = {};
|
|
233
|
-
e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl:
|
|
234
|
-
licenseUrl:
|
|
235
|
-
certificateUrl:
|
|
233
|
+
e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: x("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
|
|
234
|
+
licenseUrl: x("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
|
|
235
|
+
certificateUrl: x("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
|
|
236
236
|
}), (t.widevine || t.fairplay) && (i.drm = t);
|
|
237
237
|
}
|
|
238
238
|
let a = {};
|
|
239
|
-
for (let [t, n] of Object.entries(e))
|
|
239
|
+
for (let [t, n] of Object.entries(e)) se.has(t) || (a[t] = n);
|
|
240
240
|
return Object.keys(a).length > 0 && (i.extensions = a), i;
|
|
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 C(e) {
|
|
248
248
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
249
249
|
}
|
|
250
|
-
function
|
|
251
|
-
let n = S(
|
|
250
|
+
function w(e, t) {
|
|
251
|
+
let n = C(S(e));
|
|
252
252
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
253
253
|
}
|
|
254
|
-
async function
|
|
254
|
+
async function T(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 E(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 = C(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 le(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 ue(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: ue(await s.json()),
|
|
291
291
|
etag: s.headers.get("etag") ?? void 0,
|
|
292
292
|
notModified: !1
|
|
293
293
|
};
|
|
294
294
|
}
|
|
295
|
-
function
|
|
295
|
+
function ue(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 de(e) {
|
|
|
312
312
|
};
|
|
313
313
|
});
|
|
314
314
|
}
|
|
315
|
-
async function
|
|
315
|
+
async function de(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 fe(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: fe(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 fe(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 pe(e) {
|
|
|
356
356
|
}))
|
|
357
357
|
};
|
|
358
358
|
}
|
|
359
|
-
function
|
|
359
|
+
function pe(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 me(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 he(e) {
|
|
|
397
397
|
}
|
|
398
398
|
//#endregion
|
|
399
399
|
//#region src/core/events.ts
|
|
400
|
-
function
|
|
400
|
+
function D(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 E(e) {
|
|
|
464
464
|
i || (i = !0, r.abort());
|
|
465
465
|
} };
|
|
466
466
|
}
|
|
467
|
-
function
|
|
467
|
+
function O(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 D(e) {
|
|
|
474
474
|
}
|
|
475
475
|
//#endregion
|
|
476
476
|
//#region src/core/drm/deviceId.ts
|
|
477
|
-
var
|
|
478
|
-
function
|
|
479
|
-
if (
|
|
477
|
+
var k = "havik.player.deviceId", A;
|
|
478
|
+
function j() {
|
|
479
|
+
if (A) return A;
|
|
480
480
|
try {
|
|
481
|
-
let e = globalThis.localStorage?.getItem(
|
|
482
|
-
if (e) return
|
|
481
|
+
let e = globalThis.localStorage?.getItem(k);
|
|
482
|
+
if (e) return A = e, e;
|
|
483
483
|
} catch {}
|
|
484
|
-
let e =
|
|
485
|
-
|
|
484
|
+
let e = ge();
|
|
485
|
+
A = e;
|
|
486
486
|
try {
|
|
487
|
-
globalThis.localStorage?.setItem(
|
|
487
|
+
globalThis.localStorage?.setItem(k, e);
|
|
488
488
|
} catch {}
|
|
489
489
|
return e;
|
|
490
490
|
}
|
|
491
|
-
function
|
|
492
|
-
|
|
491
|
+
function he() {
|
|
492
|
+
A = void 0;
|
|
493
493
|
try {
|
|
494
|
-
globalThis.localStorage?.removeItem(
|
|
494
|
+
globalThis.localStorage?.removeItem(k);
|
|
495
495
|
} catch {}
|
|
496
496
|
}
|
|
497
|
-
function
|
|
497
|
+
function ge() {
|
|
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,22 +506,22 @@ function _e() {
|
|
|
506
506
|
}
|
|
507
507
|
//#endregion
|
|
508
508
|
//#region src/core/drm/headers.ts
|
|
509
|
-
function
|
|
509
|
+
function _e(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 ?? j(),
|
|
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/support.ts
|
|
520
|
-
var
|
|
520
|
+
var ve = 5e3, M = "video/mp4; codecs=\"avc1.42E01E\"", N = "audio/mp4; codecs=\"mp4a.40.2\"", ye = {
|
|
521
521
|
widevine: ["com.widevine.alpha"],
|
|
522
522
|
fairplay: ["com.apple.fps"]
|
|
523
523
|
};
|
|
524
|
-
function
|
|
524
|
+
function be(e) {
|
|
525
525
|
return e === "fairplay" ? [{
|
|
526
526
|
initDataTypes: [
|
|
527
527
|
"sinf",
|
|
@@ -529,24 +529,24 @@ function N(e) {
|
|
|
529
529
|
"cenc"
|
|
530
530
|
],
|
|
531
531
|
videoCapabilities: [{
|
|
532
|
-
contentType:
|
|
532
|
+
contentType: M,
|
|
533
533
|
robustness: "",
|
|
534
534
|
encryptionScheme: "cbcs"
|
|
535
535
|
}],
|
|
536
536
|
audioCapabilities: [{
|
|
537
|
-
contentType:
|
|
537
|
+
contentType: N,
|
|
538
538
|
robustness: "",
|
|
539
539
|
encryptionScheme: "cbcs"
|
|
540
540
|
}]
|
|
541
541
|
}] : [{
|
|
542
542
|
initDataTypes: ["cenc"],
|
|
543
543
|
videoCapabilities: [{
|
|
544
|
-
contentType:
|
|
544
|
+
contentType: M,
|
|
545
545
|
robustness: "SW_SECURE_DECODE",
|
|
546
546
|
encryptionScheme: "cbcs"
|
|
547
547
|
}],
|
|
548
548
|
audioCapabilities: [{
|
|
549
|
-
contentType:
|
|
549
|
+
contentType: N,
|
|
550
550
|
robustness: "SW_SECURE_CRYPTO",
|
|
551
551
|
encryptionScheme: "cbcs"
|
|
552
552
|
}]
|
|
@@ -563,7 +563,7 @@ function P(e, t) {
|
|
|
563
563
|
});
|
|
564
564
|
}
|
|
565
565
|
async function xe(e = {}) {
|
|
566
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
566
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? ve, r = {};
|
|
567
567
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
568
568
|
verdict: "insecure-context",
|
|
569
569
|
detail: r
|
|
@@ -575,7 +575,7 @@ async function xe(e = {}) {
|
|
|
575
575
|
};
|
|
576
576
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
577
577
|
for (let e of t) {
|
|
578
|
-
let t =
|
|
578
|
+
let t = ye[e];
|
|
579
579
|
if (!t) {
|
|
580
580
|
r[e] = "unknown system";
|
|
581
581
|
continue;
|
|
@@ -586,7 +586,7 @@ async function xe(e = {}) {
|
|
|
586
586
|
break;
|
|
587
587
|
}
|
|
588
588
|
try {
|
|
589
|
-
return await P((await P(i(n,
|
|
589
|
+
return await P((await P(i(n, be(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
590
590
|
verdict: "supported",
|
|
591
591
|
system: e,
|
|
592
592
|
detail: r
|
|
@@ -819,21 +819,21 @@ function Ee(e, t) {
|
|
|
819
819
|
function De() {
|
|
820
820
|
return e.isSupported();
|
|
821
821
|
}
|
|
822
|
-
var Oe = 3, ke = 5, Ae = 3, je = 3e4, Me = 12e3, Ne = 3e3, B = 6e3, Pe = 4e3, Fe = 2, Ie = 5, Le = 2e3, Re = 3e4, ze = 2, Be = 9,
|
|
823
|
-
function
|
|
822
|
+
var Oe = 3, ke = 5, Ae = 3, je = 3e4, Me = 12e3, Ne = 3e3, B = 6e3, Pe = 4e3, Fe = 2, Ie = 5, Le = 2e3, Re = 3e4, ze = 2, Be = 9, Ve = .5;
|
|
823
|
+
function He(e) {
|
|
824
824
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
825
825
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
826
826
|
return;
|
|
827
827
|
}
|
|
828
828
|
e.liveSyncDuration ??= ze;
|
|
829
829
|
let t = Math.max(12, e.liveSyncDuration + Be);
|
|
830
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
830
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Ue(e, e.liveSyncDuration);
|
|
831
831
|
}
|
|
832
|
-
function
|
|
832
|
+
function Ue(e, t) {
|
|
833
833
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
834
834
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
835
835
|
}
|
|
836
|
-
var
|
|
836
|
+
var V = class {
|
|
837
837
|
name = "hls";
|
|
838
838
|
hls = null;
|
|
839
839
|
deps;
|
|
@@ -910,7 +910,7 @@ var H = class {
|
|
|
910
910
|
let t = e.liveSyncPosition;
|
|
911
911
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
912
912
|
let { video: n } = this.deps;
|
|
913
|
-
n.currentTime <= t +
|
|
913
|
+
n.currentTime <= t + Ve || (n.currentTime = t);
|
|
914
914
|
}
|
|
915
915
|
startHls() {
|
|
916
916
|
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 = {
|
|
@@ -946,7 +946,7 @@ var H = class {
|
|
|
946
946
|
} } : {},
|
|
947
947
|
...c
|
|
948
948
|
};
|
|
949
|
-
|
|
949
|
+
He(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0;
|
|
950
950
|
let f = new e(d);
|
|
951
951
|
this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
952
952
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.applySizeCap(), l({ type: "ready" });
|
|
@@ -1241,7 +1241,7 @@ var H = class {
|
|
|
1241
1241
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1242
1242
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1243
1243
|
}
|
|
1244
|
-
},
|
|
1244
|
+
}, We = 15e3, Ge = 100, H = 1, U = {
|
|
1245
1245
|
idle: "PLAYER_STATE_IDLE",
|
|
1246
1246
|
waiting: "PLAYER_STATE_WAITING",
|
|
1247
1247
|
loading: "PLAYER_STATE_LOADING",
|
|
@@ -1251,7 +1251,7 @@ var H = class {
|
|
|
1251
1251
|
ended: "PLAYER_STATE_ENDED",
|
|
1252
1252
|
error: "PLAYER_STATE_ERROR"
|
|
1253
1253
|
};
|
|
1254
|
-
function
|
|
1254
|
+
function Ke(e) {
|
|
1255
1255
|
try {
|
|
1256
1256
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1257
1257
|
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);
|
|
@@ -1259,7 +1259,7 @@ function Ge(e) {
|
|
|
1259
1259
|
return;
|
|
1260
1260
|
}
|
|
1261
1261
|
}
|
|
1262
|
-
var
|
|
1262
|
+
var qe = class {
|
|
1263
1263
|
opts;
|
|
1264
1264
|
url;
|
|
1265
1265
|
now;
|
|
@@ -1294,7 +1294,7 @@ var Ke = class {
|
|
|
1294
1294
|
constructor(e) {
|
|
1295
1295
|
this.opts = {
|
|
1296
1296
|
...e,
|
|
1297
|
-
heartbeatMs: e.heartbeatMs ??
|
|
1297
|
+
heartbeatMs: e.heartbeatMs ?? We
|
|
1298
1298
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now();
|
|
1299
1299
|
}
|
|
1300
1300
|
start() {
|
|
@@ -1306,18 +1306,18 @@ var Ke = class {
|
|
|
1306
1306
|
noteStateChange(e, t, n, r) {
|
|
1307
1307
|
if (this.endedFlag || e === t) return;
|
|
1308
1308
|
let i = this.now();
|
|
1309
|
-
t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(
|
|
1309
|
+
t === "playing" ? (this.playingSinceMs === null && (this.playingSinceMs = i), this.startupTimeMs === 0 && (this.startupTimeMs = Math.max(H, i - this.bornMs))) : this.playingSinceMs !== null && (this.playingTotalMs += i - this.playingSinceMs, this.playingSinceMs = null), t === "buffering" && e === "playing" ? (this.rebufferCount += 1, this.bufferingSinceMs = i) : e === "buffering" && this.bufferingSinceMs !== null && (this.rebufferTotalMs += i - this.bufferingSinceMs, this.bufferingSinceMs = null), t === "paused" && (this.pauseCount += 1);
|
|
1310
1310
|
let a = {
|
|
1311
|
-
fromState:
|
|
1312
|
-
toState:
|
|
1311
|
+
fromState: U[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1312
|
+
toState: U[t] ?? "PLAYER_STATE_UNSPECIFIED"
|
|
1313
1313
|
};
|
|
1314
1314
|
n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
1315
1315
|
}
|
|
1316
1316
|
noteReady() {
|
|
1317
|
-
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(
|
|
1317
|
+
this.manifestLoadMs === 0 && (this.manifestLoadMs = Math.max(H, this.now() - this.bornMs));
|
|
1318
1318
|
}
|
|
1319
1319
|
noteFirstBytes() {
|
|
1320
|
-
this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(
|
|
1320
|
+
this.firstFragLoadMs === 0 && (this.firstFragLoadMs = Math.max(H, this.now() - this.bornMs));
|
|
1321
1321
|
}
|
|
1322
1322
|
noteSeek() {
|
|
1323
1323
|
this.endedFlag || (this.seekCount += 1);
|
|
@@ -1352,7 +1352,7 @@ var Ke = class {
|
|
|
1352
1352
|
let c = e.renditionSwitches ?? 0;
|
|
1353
1353
|
c > this.lastSwitches && (i.renditionSwitchesDelta = c - this.lastSwitches), this.lastSwitches = c, n > this.lastHbPlayingMs && (i.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (i.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, typeof e.latencySeconds == "number" && (i.latencyMs = Math.round(e.latencySeconds * 1e3)), typeof e.targetLatencySeconds == "number" && (i.targetLatencyMs = Math.round(e.targetLatencySeconds * 1e3)), typeof e.bandwidthKbps == "number" && (i.bandwidthEstKbps = e.bandwidthKbps), typeof e.levelHeight == "number" && (i.renditionHeight = e.levelHeight), typeof e.renditionBitrateKbps == "number" && (i.renditionBitrateKbps = e.renditionBitrateKbps), e.atLiveEdge === !0 && (i.atLiveEdge = !0);
|
|
1354
1354
|
let l = this.bufferedMsFrom(e);
|
|
1355
|
-
l > 0 && (i.bufferedMs = l), i.playerState =
|
|
1355
|
+
l > 0 && (i.bufferedMs = l), i.playerState = U[e.state] ?? "PLAYER_STATE_UNSPECIFIED", this.enqueue({ heartbeat: i }), this.flush(), a > 0 && this.noteFirstBytes();
|
|
1356
1356
|
}
|
|
1357
1357
|
bufferedMsFrom(e) {
|
|
1358
1358
|
let t = e;
|
|
@@ -1386,7 +1386,7 @@ var Ke = class {
|
|
|
1386
1386
|
};
|
|
1387
1387
|
}
|
|
1388
1388
|
enqueue(e) {
|
|
1389
|
-
for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
1389
|
+
for (this.pending.push(this.wrap(e)); this.pending.length > Ge;) {
|
|
1390
1390
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
1391
1391
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
1392
1392
|
}
|
|
@@ -1408,7 +1408,7 @@ var Ke = class {
|
|
|
1408
1408
|
keepalive: !0
|
|
1409
1409
|
}).catch(() => {});
|
|
1410
1410
|
}
|
|
1411
|
-
},
|
|
1411
|
+
}, Je = "1.17.0", W = {
|
|
1412
1412
|
accent: "#E1B600",
|
|
1413
1413
|
accentText: "#1B1C23",
|
|
1414
1414
|
background: "#0e0f13",
|
|
@@ -1419,7 +1419,7 @@ var Ke = class {
|
|
|
1419
1419
|
border: "rgba(255, 255, 255, 0.1)",
|
|
1420
1420
|
radius: "8px",
|
|
1421
1421
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
1422
|
-
},
|
|
1422
|
+
}, G = {
|
|
1423
1423
|
accent: "--havik-accent",
|
|
1424
1424
|
accentText: "--havik-accent-text",
|
|
1425
1425
|
background: "--havik-bg",
|
|
@@ -1431,25 +1431,25 @@ var Ke = class {
|
|
|
1431
1431
|
radius: "--havik-radius",
|
|
1432
1432
|
fontFamily: "--havik-font"
|
|
1433
1433
|
};
|
|
1434
|
-
function
|
|
1434
|
+
function K(e, t) {
|
|
1435
1435
|
let n = {
|
|
1436
|
-
...
|
|
1436
|
+
...W,
|
|
1437
1437
|
...t
|
|
1438
1438
|
};
|
|
1439
|
-
for (let t of Object.keys(
|
|
1439
|
+
for (let t of Object.keys(G)) e.style.setProperty(G[t], n[t]);
|
|
1440
1440
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
1441
1441
|
}
|
|
1442
1442
|
//#endregion
|
|
1443
1443
|
//#region src/ui/styles.ts
|
|
1444
|
-
var
|
|
1445
|
-
function
|
|
1446
|
-
if (e.getElementById(
|
|
1444
|
+
var q = "havik-player-styles", Ye = "\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";
|
|
1445
|
+
function Xe(e = document) {
|
|
1446
|
+
if (e.getElementById(q)) return;
|
|
1447
1447
|
let t = e.createElement("style");
|
|
1448
|
-
t.id =
|
|
1448
|
+
t.id = q, t.textContent = Ye, e.head.appendChild(t);
|
|
1449
1449
|
}
|
|
1450
1450
|
//#endregion
|
|
1451
1451
|
//#region src/ui/icons.ts
|
|
1452
|
-
var
|
|
1452
|
+
var Ze = {
|
|
1453
1453
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
1454
1454
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
1455
1455
|
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\"/>",
|
|
@@ -1462,21 +1462,21 @@ var Xe = {
|
|
|
1462
1462
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
1463
1463
|
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\"/>"
|
|
1464
1464
|
};
|
|
1465
|
-
function
|
|
1466
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
1465
|
+
function J(e) {
|
|
1466
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${Ze[e]}</svg>`;
|
|
1467
1467
|
}
|
|
1468
1468
|
//#endregion
|
|
1469
1469
|
//#region src/ui/controls.ts
|
|
1470
|
-
var
|
|
1470
|
+
var Qe = 3e3, $e = /* @__PURE__ */ new Set([
|
|
1471
1471
|
"GONE",
|
|
1472
1472
|
"NOT_FOUND",
|
|
1473
1473
|
"INVALID_URN",
|
|
1474
1474
|
"UNAUTHORIZED"
|
|
1475
1475
|
]);
|
|
1476
|
-
function
|
|
1477
|
-
return new
|
|
1476
|
+
function et(e) {
|
|
1477
|
+
return new tt(e);
|
|
1478
1478
|
}
|
|
1479
|
-
var
|
|
1479
|
+
var tt = class {
|
|
1480
1480
|
root;
|
|
1481
1481
|
video;
|
|
1482
1482
|
player;
|
|
@@ -1516,7 +1516,7 @@ var et = class {
|
|
|
1516
1516
|
scrubbing = !1;
|
|
1517
1517
|
offFns = [];
|
|
1518
1518
|
constructor(e) {
|
|
1519
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
1519
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Qe, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.errorMessage = e.errorMessage, Xe(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");
|
|
1520
1520
|
let t = (e, t, n) => {
|
|
1521
1521
|
let r = this.doc.createElement(e);
|
|
1522
1522
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -1527,12 +1527,12 @@ var et = class {
|
|
|
1527
1527
|
"aria-label": r,
|
|
1528
1528
|
title: r
|
|
1529
1529
|
});
|
|
1530
|
-
return i.innerHTML =
|
|
1530
|
+
return i.innerHTML = J(n), i;
|
|
1531
1531
|
};
|
|
1532
1532
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
1533
1533
|
type: "button",
|
|
1534
1534
|
"aria-label": "Play"
|
|
1535
|
-
}), this.center.innerHTML =
|
|
1535
|
+
}), this.center.innerHTML = J("play"), this.spinner = t("div", "havik-spinner"), this.spinner.style.display = "none", this.overlay.append(this.center, this.spinner), this.gradient = t("div", "havik-gradient"), this.bar = t("div", "havik-bar"), this.seek = t("div", "havik-seek", {
|
|
1536
1536
|
role: "slider",
|
|
1537
1537
|
"aria-label": "Seek",
|
|
1538
1538
|
"aria-valuemin": "0",
|
|
@@ -1550,7 +1550,7 @@ var et = class {
|
|
|
1550
1550
|
"aria-label": "Volume"
|
|
1551
1551
|
});
|
|
1552
1552
|
let a = t("div", "havik-vol");
|
|
1553
|
-
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML =
|
|
1553
|
+
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = J("liveDot");
|
|
1554
1554
|
let o = this.doc.createElement("span");
|
|
1555
1555
|
o.textContent = "LIVE", this.liveGo = t("button", "havik-live__go", { type: "button" }), this.liveGo.textContent = "Go live", this.live.append(o, this.liveGo), this.time = t("div", "havik-time"), this.time.textContent = "0:00", this.time.style.display = "none";
|
|
1556
1556
|
let s = t("div", "havik-spacer");
|
|
@@ -1600,12 +1600,12 @@ var et = class {
|
|
|
1600
1600
|
}
|
|
1601
1601
|
if (e === "preplay") {
|
|
1602
1602
|
let e = this.doc.createElement("button");
|
|
1603
|
-
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML =
|
|
1603
|
+
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);
|
|
1604
1604
|
} else {
|
|
1605
1605
|
let n = this.doc.createElement("div");
|
|
1606
|
-
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 &&
|
|
1606
|
+
if (n.className = "havik-status__msg", n.textContent = e === "ended" ? this.endedMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : this.errorMessage ?? this.lastError?.message ?? "Playback unavailable", t.append(n), e === "error" && this.lastError && !$e.has(this.lastError.code)) {
|
|
1607
1607
|
let e = this.doc.createElement("button");
|
|
1608
|
-
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${
|
|
1608
|
+
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);
|
|
1609
1609
|
}
|
|
1610
1610
|
}
|
|
1611
1611
|
this.root.append(t), this.statusBox = t, this.show();
|
|
@@ -1644,7 +1644,7 @@ var et = class {
|
|
|
1644
1644
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
1645
1645
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
1646
1646
|
}
|
|
1647
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
1647
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Y(this.video.currentTime)} / ${Y(this.video.duration)}`);
|
|
1648
1648
|
}
|
|
1649
1649
|
syncLive() {
|
|
1650
1650
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -1694,17 +1694,17 @@ var et = class {
|
|
|
1694
1694
|
renderQualityMenu() {
|
|
1695
1695
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
1696
1696
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
1697
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
1697
|
+
for (let n of e) this.menu.append(this.menuItem(nt(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
1698
1698
|
}
|
|
1699
1699
|
renderAudioMenu() {
|
|
1700
1700
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
1701
1701
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
1702
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
1702
|
+
for (let t of e) this.menu.append(this.menuItem(rt(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
1703
1703
|
}
|
|
1704
1704
|
renderCcMenu() {
|
|
1705
1705
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
1706
1706
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
1707
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
1707
|
+
for (let t of e) this.menu.append(this.menuItem(it(t), !1, () => this.player.setTextTrack(t.id)));
|
|
1708
1708
|
}
|
|
1709
1709
|
onTracksChanged() {
|
|
1710
1710
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -1724,11 +1724,11 @@ var et = class {
|
|
|
1724
1724
|
}
|
|
1725
1725
|
async toggleFullscreen() {
|
|
1726
1726
|
try {
|
|
1727
|
-
|
|
1727
|
+
w(this.video, this.root) ? await E(this.video, this.root) : await T(this.video, this.root);
|
|
1728
1728
|
} catch {}
|
|
1729
1729
|
}
|
|
1730
1730
|
syncFullscreen() {
|
|
1731
|
-
let e =
|
|
1731
|
+
let e = w(this.video, this.root);
|
|
1732
1732
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
1733
1733
|
}
|
|
1734
1734
|
poke() {
|
|
@@ -1787,7 +1787,7 @@ var et = class {
|
|
|
1787
1787
|
}
|
|
1788
1788
|
}
|
|
1789
1789
|
setIcon(e, t) {
|
|
1790
|
-
e.innerHTML =
|
|
1790
|
+
e.innerHTML = J(t);
|
|
1791
1791
|
}
|
|
1792
1792
|
destroy() {
|
|
1793
1793
|
this.hideTimer && clearTimeout(this.hideTimer);
|
|
@@ -1804,23 +1804,23 @@ var et = class {
|
|
|
1804
1804
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
1805
1805
|
}
|
|
1806
1806
|
};
|
|
1807
|
-
function
|
|
1807
|
+
function Y(e) {
|
|
1808
1808
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
1809
1809
|
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");
|
|
1810
1810
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
1811
1811
|
}
|
|
1812
|
-
function
|
|
1812
|
+
function nt(e) {
|
|
1813
1813
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
1814
1814
|
}
|
|
1815
|
-
function
|
|
1815
|
+
function rt(e) {
|
|
1816
1816
|
return e.name || e.lang || `Track ${e.id}`;
|
|
1817
1817
|
}
|
|
1818
|
-
function
|
|
1818
|
+
function it(e) {
|
|
1819
1819
|
return e.name || e.lang || `Track ${e.id}`;
|
|
1820
1820
|
}
|
|
1821
1821
|
//#endregion
|
|
1822
1822
|
//#region src/managed/index.ts
|
|
1823
|
-
var
|
|
1823
|
+
var at = 6e3, X = 45e3, Z = 2e3, ot = 3, st = 2e3, ct = 48e4;
|
|
1824
1824
|
async function Q(e) {
|
|
1825
1825
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
1826
1826
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: baseUrl is required");
|
|
@@ -1846,6 +1846,7 @@ var lt = class {
|
|
|
1846
1846
|
loadGen = 0;
|
|
1847
1847
|
liveStateSub = null;
|
|
1848
1848
|
endedHandled = !1;
|
|
1849
|
+
rejoinTimer = null;
|
|
1849
1850
|
armingSub = null;
|
|
1850
1851
|
armSseTimer = null;
|
|
1851
1852
|
armFallbackCtrl = null;
|
|
@@ -1865,7 +1866,7 @@ var lt = class {
|
|
|
1865
1866
|
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");
|
|
1866
1867
|
let e = ++this.loadGen, t = this.resolveOptions();
|
|
1867
1868
|
try {
|
|
1868
|
-
let n = await
|
|
1869
|
+
let n = await y(t);
|
|
1869
1870
|
if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
|
|
1870
1871
|
let e = this._lastError;
|
|
1871
1872
|
throw this.destroy(), e;
|
|
@@ -1887,12 +1888,12 @@ var lt = class {
|
|
|
1887
1888
|
apiHeaders: this.opts.apiHeaders
|
|
1888
1889
|
};
|
|
1889
1890
|
}
|
|
1890
|
-
beginArming(e, t) {
|
|
1891
|
-
let
|
|
1892
|
-
|
|
1891
|
+
beginArming(e, t, n = !1) {
|
|
1892
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
|
|
1893
|
+
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
1893
1894
|
}
|
|
1894
1895
|
beginArmingByPolling(e) {
|
|
1895
|
-
|
|
1896
|
+
b({
|
|
1896
1897
|
...this.resolveOptions(),
|
|
1897
1898
|
signal: this.abort.signal,
|
|
1898
1899
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -1902,55 +1903,55 @@ var lt = class {
|
|
|
1902
1903
|
this.destroyed || this.abort.signal.aborted || e !== this.loadGen || this.fail(t instanceof n ? t : new n("INTERNAL", 0, String(t)));
|
|
1903
1904
|
});
|
|
1904
1905
|
}
|
|
1905
|
-
armWithSse(e, t, r) {
|
|
1906
|
-
let
|
|
1907
|
-
this.armFallbackCtrl =
|
|
1908
|
-
let
|
|
1906
|
+
armWithSse(e, t, r, i = !1) {
|
|
1907
|
+
let a = !1, s = !1, c = new AbortController();
|
|
1908
|
+
this.armFallbackCtrl = c, this.setState("waiting");
|
|
1909
|
+
let l = this.opts.waitForLive, u = l && l !== !0 ? l.kickoffAt : void 0, d = typeof u == "number" ? u : typeof u == "string" ? Date.parse(u) : NaN, f = r ?? (Number.isFinite(d) ? d : void 0);
|
|
1909
1910
|
setTimeout(() => {
|
|
1910
|
-
|
|
1911
|
-
phase: "tooEarly",
|
|
1912
|
-
retryInMs:
|
|
1911
|
+
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
1912
|
+
phase: i ? "unavailable" : "tooEarly",
|
|
1913
|
+
retryInMs: X,
|
|
1913
1914
|
attempt: 1,
|
|
1914
1915
|
elapsedMs: 0,
|
|
1915
|
-
|
|
1916
|
+
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
1916
1917
|
});
|
|
1917
1918
|
}, 0);
|
|
1918
|
-
let
|
|
1919
|
-
if (!(
|
|
1920
|
-
|
|
1919
|
+
let p = () => this.destroyed || this.abort.signal.aborted || e !== this.loadGen, m = async (t) => {
|
|
1920
|
+
if (!(a || p())) {
|
|
1921
|
+
a = !0, this.closeArming(), c.abort();
|
|
1921
1922
|
try {
|
|
1922
1923
|
await this.onResolved(t, e);
|
|
1923
1924
|
} catch (e) {
|
|
1924
|
-
if (
|
|
1925
|
+
if (p()) return;
|
|
1925
1926
|
this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e)));
|
|
1926
1927
|
}
|
|
1927
1928
|
}
|
|
1928
|
-
},
|
|
1929
|
-
|
|
1929
|
+
}, h = () => {
|
|
1930
|
+
a || s || p() || (s = !0, b({
|
|
1930
1931
|
...this.resolveOptions(),
|
|
1931
|
-
signal:
|
|
1932
|
+
signal: c.signal,
|
|
1932
1933
|
waitForLive: this.buildWaitConfig(e)
|
|
1933
|
-
}).then((e) =>
|
|
1934
|
-
|
|
1934
|
+
}).then((e) => m(e)).catch((e) => {
|
|
1935
|
+
a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
|
|
1935
1936
|
}));
|
|
1936
|
-
},
|
|
1937
|
-
|
|
1938
|
-
|
|
1937
|
+
}, g = () => {
|
|
1938
|
+
a || p() || y(this.resolveOptions()).then((e) => m(e)).catch((e) => {
|
|
1939
|
+
a || p() || e instanceof n && o(e.code) || (a = !0, this.closeArming(), c.abort(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
|
|
1939
1940
|
});
|
|
1940
|
-
},
|
|
1941
|
+
}, _ = (e) => {
|
|
1941
1942
|
this.armSseTimer && clearTimeout(this.armSseTimer), this.armSseTimer = setTimeout(() => {
|
|
1942
|
-
!
|
|
1943
|
+
!a && !p() && h();
|
|
1943
1944
|
}, e);
|
|
1944
1945
|
};
|
|
1945
|
-
|
|
1946
|
+
_(at), this.armingSub = D({
|
|
1946
1947
|
eventsBaseUrl: t,
|
|
1947
1948
|
matchUrn: this.opts.matchUrn,
|
|
1948
1949
|
credential: this.opts.credential,
|
|
1949
|
-
onAlive: () =>
|
|
1950
|
+
onAlive: () => _(X),
|
|
1950
1951
|
onState: (e) => {
|
|
1951
|
-
|
|
1952
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Z);
|
|
1952
1953
|
},
|
|
1953
|
-
onError: () =>
|
|
1954
|
+
onError: () => h()
|
|
1954
1955
|
});
|
|
1955
1956
|
}
|
|
1956
1957
|
closeArming() {
|
|
@@ -1988,14 +1989,14 @@ var lt = class {
|
|
|
1988
1989
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachSeekListener?.(), this.opts.analytics === !1) return;
|
|
1989
1990
|
let r = e.analytics?.sid;
|
|
1990
1991
|
if (!r) return;
|
|
1991
|
-
let i = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ??
|
|
1992
|
+
let i = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ?? Ke(this.opts.baseUrl);
|
|
1992
1993
|
if (!i) return;
|
|
1993
|
-
let a = this.opts.video, o = new
|
|
1994
|
+
let a = this.opts.video, o = new qe({
|
|
1994
1995
|
endpoint: i,
|
|
1995
1996
|
sid: r,
|
|
1996
1997
|
apiKey: n,
|
|
1997
1998
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
1998
|
-
sdkVersion:
|
|
1999
|
+
sdkVersion: Je,
|
|
1999
2000
|
sample: () => {
|
|
2000
2001
|
let e = this.engine?.getStats() ?? F, t = a.buffered.length ? Math.max(0, a.buffered.end(a.buffered.length - 1) - a.currentTime) : 0;
|
|
2001
2002
|
return {
|
|
@@ -2017,7 +2018,7 @@ var lt = class {
|
|
|
2017
2018
|
video: this.opts.video,
|
|
2018
2019
|
descriptor: e,
|
|
2019
2020
|
credential: t,
|
|
2020
|
-
deviceId:
|
|
2021
|
+
deviceId: j(),
|
|
2021
2022
|
userId: this.opts.userId,
|
|
2022
2023
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
2023
2024
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -2026,9 +2027,9 @@ var lt = class {
|
|
|
2026
2027
|
emit: (e) => this.onEngineEvent(e)
|
|
2027
2028
|
}, a = this.opts.engine ?? "auto";
|
|
2028
2029
|
if (a === "native") return new z(i);
|
|
2029
|
-
if (a === "hls") return new
|
|
2030
|
+
if (a === "hls") return new V(i);
|
|
2030
2031
|
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && L(this.opts.video) && R()) return new z(i);
|
|
2031
|
-
if (De()) return new
|
|
2032
|
+
if (De()) return new V(i);
|
|
2032
2033
|
if (L(this.opts.video)) return new z(i);
|
|
2033
2034
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
2034
2035
|
}
|
|
@@ -2057,30 +2058,48 @@ var lt = class {
|
|
|
2057
2058
|
}
|
|
2058
2059
|
startLiveState(e) {
|
|
2059
2060
|
if (this.opts.liveStateEvents === !1) return;
|
|
2060
|
-
let t = this.opts.eventsBaseUrl ??
|
|
2061
|
+
let t = this.opts.eventsBaseUrl ?? O(this.opts.baseUrl);
|
|
2061
2062
|
if (!t) return;
|
|
2062
2063
|
this.closeLiveState();
|
|
2063
2064
|
let r = 0, i = !1;
|
|
2064
|
-
this.liveStateSub =
|
|
2065
|
+
this.liveStateSub = D({
|
|
2065
2066
|
eventsBaseUrl: t,
|
|
2066
2067
|
matchUrn: this.opts.matchUrn,
|
|
2067
2068
|
credential: this.opts.credential,
|
|
2068
2069
|
onState: (t) => {
|
|
2069
|
-
this.destroyed || e !== this.loadGen || (t.state === "
|
|
2070
|
+
this.destroyed || e !== this.loadGen || (t.state === "gone" ? this.onStreamEnded(!0) : t.state === "ended" ? this.onStreamEnded() : t.state === "live" && this.endedHandled && this.scheduleRejoin(e));
|
|
2070
2071
|
},
|
|
2071
2072
|
onAlive: () => {
|
|
2072
2073
|
r = 0, i = !1;
|
|
2073
2074
|
},
|
|
2074
2075
|
onError: () => {
|
|
2075
|
-
this.destroyed || e !== this.loadGen || i || (r += 1, r >= ot && (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.`))));
|
|
2076
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= ot && (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.`))));
|
|
2076
2077
|
}
|
|
2077
2078
|
});
|
|
2078
2079
|
}
|
|
2079
2080
|
closeLiveState() {
|
|
2080
2081
|
this.liveStateSub?.close(), this.liveStateSub = null;
|
|
2081
2082
|
}
|
|
2082
|
-
onStreamEnded() {
|
|
2083
|
-
this.destroyed || this.endedHandled
|
|
2083
|
+
onStreamEnded(e = !1) {
|
|
2084
|
+
this.destroyed || ((e || !this.rejoinEnabled()) && (this.cancelRejoin(), this.closeLiveState()), !this.endedHandled && (this.endedHandled = !0, this.stopRefresh(), this.engine?.stop(), this.setState("ended")));
|
|
2085
|
+
}
|
|
2086
|
+
rejoinEnabled() {
|
|
2087
|
+
return this.opts.rejoinOnLive !== !1 && this.opts.liveStateEvents !== !1;
|
|
2088
|
+
}
|
|
2089
|
+
scheduleRejoin(e) {
|
|
2090
|
+
!this.rejoinEnabled() || this.rejoinTimer || (this.rejoinTimer = setTimeout(() => {
|
|
2091
|
+
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
2092
|
+
}, Math.random() * Z));
|
|
2093
|
+
}
|
|
2094
|
+
cancelRejoin() {
|
|
2095
|
+
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
2096
|
+
}
|
|
2097
|
+
rejoin() {
|
|
2098
|
+
let e = ++this.loadGen;
|
|
2099
|
+
this.teardownPlayback(), this.setState("waiting"), this.beginArming(e, void 0, !0);
|
|
2100
|
+
}
|
|
2101
|
+
teardownPlayback() {
|
|
2102
|
+
this.stopStats(), this.stopRefresh(), this.cancelRejoin(), this.closeArming(), this.closeLiveState(), this.detachMedia?.(), this.engine?.destroy(), this.engine = null;
|
|
2084
2103
|
}
|
|
2085
2104
|
mountControls() {
|
|
2086
2105
|
let e = this.opts.controls ?? "custom", t = this.opts.video;
|
|
@@ -2094,7 +2113,7 @@ var lt = class {
|
|
|
2094
2113
|
}
|
|
2095
2114
|
t.controls = !1;
|
|
2096
2115
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
2097
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
2116
|
+
r && r.insertBefore(n, t), n.appendChild(t), K(n, this.opts.theme), this.container = n, this.controlBar = et({
|
|
2098
2117
|
root: n,
|
|
2099
2118
|
video: t,
|
|
2100
2119
|
player: this,
|
|
@@ -2138,7 +2157,7 @@ var lt = class {
|
|
|
2138
2157
|
async refreshLicense() {
|
|
2139
2158
|
let e = this.engine;
|
|
2140
2159
|
if (!(this.destroyed || !e)) try {
|
|
2141
|
-
let t = await
|
|
2160
|
+
let t = await y(this.resolveOptions());
|
|
2142
2161
|
if (this.destroyed || this.engine !== e) return;
|
|
2143
2162
|
let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
|
|
2144
2163
|
(n || r) && (e.setLicenseUrls({
|
|
@@ -2205,10 +2224,10 @@ var lt = class {
|
|
|
2205
2224
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
2206
2225
|
}
|
|
2207
2226
|
async enterFullscreen() {
|
|
2208
|
-
return !this.destroyed &&
|
|
2227
|
+
return !this.destroyed && T(this.opts.video, this.container ?? void 0);
|
|
2209
2228
|
}
|
|
2210
2229
|
async exitFullscreen() {
|
|
2211
|
-
await
|
|
2230
|
+
await E(this.opts.video, this.container ?? void 0);
|
|
2212
2231
|
}
|
|
2213
2232
|
retry() {
|
|
2214
2233
|
return this.reload();
|
|
@@ -2216,9 +2235,9 @@ var lt = class {
|
|
|
2216
2235
|
async reload() {
|
|
2217
2236
|
if (this.destroyed) return;
|
|
2218
2237
|
let e = ++this.loadGen;
|
|
2219
|
-
this.
|
|
2238
|
+
this.teardownPlayback();
|
|
2220
2239
|
try {
|
|
2221
|
-
let t = await
|
|
2240
|
+
let t = await b({
|
|
2222
2241
|
...this.resolveOptions(),
|
|
2223
2242
|
waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
|
|
2224
2243
|
});
|
|
@@ -2233,7 +2252,7 @@ var lt = class {
|
|
|
2233
2252
|
return n.add(t), () => n.delete(t);
|
|
2234
2253
|
}
|
|
2235
2254
|
destroy() {
|
|
2236
|
-
this.destroyed || (this.destroyed = !0, this.loadGen += 1, this.abort.abort(), this.stopStats(), this.stopRefresh(), this.unmountControls(), this.closeArming(), this.closeLiveState(), this.detachMedia?.(), this.detachPip?.(), this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachSeekListener?.(), this.engine?.destroy(), this.engine = null, this.setState("idle"), this.clearListeners());
|
|
2255
|
+
this.destroyed || (this.destroyed = !0, this.loadGen += 1, this.abort.abort(), this.stopStats(), this.stopRefresh(), this.unmountControls(), this.cancelRejoin(), this.closeArming(), this.closeLiveState(), this.detachMedia?.(), this.detachPip?.(), this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachSeekListener?.(), this.engine?.destroy(), this.engine = null, this.setState("idle"), this.clearListeners());
|
|
2237
2256
|
}
|
|
2238
2257
|
clearListeners() {
|
|
2239
2258
|
for (let e of Object.keys(this.listeners)) this.listeners[e]?.clear();
|
|
@@ -2505,6 +2524,6 @@ function ht() {
|
|
|
2505
2524
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
2506
2525
|
}
|
|
2507
2526
|
//#endregion
|
|
2508
|
-
export {
|
|
2527
|
+
export { W as ODDIN_THEME, n as PlaybackError, K as applyTheme, pt as bootEmbed, he as clearDeviceId, Q as createPlayer, O as deriveEventsBaseUrl, xe as detectDrmSupport, T as enterVideoFullscreen, E as exitVideoFullscreen, le as fetchCatalog, de as fetchTournament, pe as flattenMatches, j as getDeviceId, Ce as isLowLatencyManifest, $ as isOddinMessage, _e as licenseRequestHeaders, ut as mountEmbed, v as pollToLive, b as resolveStream, D as subscribeLiveState, w as videoFullscreenActive, me as watchStatus };
|
|
2509
2528
|
|
|
2510
2529
|
//# sourceMappingURL=index.js.map
|