@oddin-gg/havik-player 2.11.0 → 2.12.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 +26 -7
- package/dist/havik-player.global.js +18 -18
- 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.d.cts +33 -15
- package/dist/index.d.ts +33 -15
- package/dist/index.js +391 -304
- package/dist/index.js.map +1 -1
- package/docs/API.md +48 -43
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -110,42 +110,48 @@ function m(e) {
|
|
|
110
110
|
return e instanceof Error ? e.message : String(e);
|
|
111
111
|
}
|
|
112
112
|
//#endregion
|
|
113
|
+
//#region src/core/warnOnce.ts
|
|
114
|
+
var h = /* @__PURE__ */ new Set();
|
|
115
|
+
function g(e, t = e) {
|
|
116
|
+
h.has(t) || (h.add(t), console.warn(`havik-player: ${e}`));
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
113
119
|
//#region src/core/waitForLive.ts
|
|
114
|
-
var
|
|
120
|
+
var _ = 1e3, ee = 3e4, te = 6e5, ne = 3e5, re = 1e3, ie = {
|
|
115
121
|
TOO_EARLY: "tooEarly",
|
|
116
122
|
UNAVAILABLE: "unavailable",
|
|
117
123
|
RATE_LIMITED: "rateLimited",
|
|
118
124
|
NETWORK: "network"
|
|
119
125
|
};
|
|
120
|
-
function
|
|
121
|
-
let t = e === !0 || e === !1 ? {} : e, n = Math.max(
|
|
126
|
+
function ae(e) {
|
|
127
|
+
let t = e === !0 || e === !1 ? {} : e, n = Math.max(re, t.floorMs ?? _), r = Math.max(n, t.ceilMs ?? ee), i = Math.max(0, t.imminentMs ?? te), a = Math.max(r, t.sanityFloorMs ?? ne);
|
|
122
128
|
return {
|
|
123
129
|
timeoutMs: t.timeoutMs,
|
|
124
130
|
floorMs: n,
|
|
125
131
|
ceilMs: r,
|
|
126
132
|
imminentMs: i,
|
|
127
133
|
sanityFloorMs: a,
|
|
128
|
-
kickoffMs:
|
|
134
|
+
kickoffMs: oe(t.kickoffAt),
|
|
129
135
|
jitter: t.jitter ?? !0,
|
|
130
136
|
onState: t.onState
|
|
131
137
|
};
|
|
132
138
|
}
|
|
133
|
-
function
|
|
139
|
+
function oe(e) {
|
|
134
140
|
if (e == null) return;
|
|
135
141
|
if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
|
|
136
142
|
let t = Date.parse(e);
|
|
137
143
|
return Number.isFinite(t) ? t : void 0;
|
|
138
144
|
}
|
|
139
|
-
function
|
|
145
|
+
function se(e, t, n) {
|
|
140
146
|
return Math.min(n, Math.max(t, e));
|
|
141
147
|
}
|
|
142
|
-
function
|
|
148
|
+
function ce(e) {
|
|
143
149
|
return Math.round(e * (1 + .15 * Math.random()));
|
|
144
150
|
}
|
|
145
|
-
function
|
|
151
|
+
function le(e, t, n, r) {
|
|
146
152
|
let i = r ?? n.kickoffMs, a = i == null ? void 0 : Math.max(0, i - t), o = Math.max(n.floorMs, e ?? 0);
|
|
147
153
|
if (a == null || a <= n.imminentMs) return {
|
|
148
|
-
delay:
|
|
154
|
+
delay: se(e ?? n.floorMs, o, n.ceilMs),
|
|
149
155
|
ttkMs: a
|
|
150
156
|
};
|
|
151
157
|
let s = Math.min(Math.floor(a / 10), n.sanityFloorMs, a);
|
|
@@ -154,7 +160,7 @@ function se(e, t, n, r) {
|
|
|
154
160
|
ttkMs: a
|
|
155
161
|
};
|
|
156
162
|
}
|
|
157
|
-
function
|
|
163
|
+
function ue(e, t) {
|
|
158
164
|
return new Promise((r, i) => {
|
|
159
165
|
if (t?.aborted) {
|
|
160
166
|
i(new n("ABORTED", 0, "wait-for-live aborted"));
|
|
@@ -168,8 +174,8 @@ function ce(e, t) {
|
|
|
168
174
|
t?.addEventListener("abort", a, { once: !0 });
|
|
169
175
|
});
|
|
170
176
|
}
|
|
171
|
-
async function
|
|
172
|
-
let i =
|
|
177
|
+
async function de(e, t, r) {
|
|
178
|
+
let i = ae(t), a = Date.now(), s = i.timeoutMs == null ? Infinity : a + i.timeoutMs, c = 0, l;
|
|
173
179
|
for (;;) {
|
|
174
180
|
if (r?.aborted) throw new n("ABORTED", 0, "wait-for-live aborted");
|
|
175
181
|
try {
|
|
@@ -177,38 +183,38 @@ async function v(e, t, r) {
|
|
|
177
183
|
} catch (e) {
|
|
178
184
|
if (!(e instanceof n) || !o(e.code)) throw e;
|
|
179
185
|
c += 1, e.liveStartsAtMs != null && Number.isFinite(e.liveStartsAtMs) && (l = e.liveStartsAtMs);
|
|
180
|
-
let t = Date.now(), u =
|
|
181
|
-
if (i.jitter && (f =
|
|
186
|
+
let t = Date.now(), u = le(e.retryAfterMs, t, i, l), d = u.ttkMs, f = u.delay;
|
|
187
|
+
if (i.jitter && (f = ce(f)), t + f > s) throw new n("TIMEOUT", e.httpStatus, `timed out after ${i.timeoutMs}ms waiting for the stream to go live`, {
|
|
182
188
|
retryAfterMs: e.retryAfterMs,
|
|
183
189
|
cause: e
|
|
184
190
|
});
|
|
185
191
|
i.onState?.({
|
|
186
|
-
phase:
|
|
192
|
+
phase: ie[e.code] ?? "unavailable",
|
|
187
193
|
retryInMs: f,
|
|
188
194
|
attempt: c,
|
|
189
195
|
elapsedMs: t - a,
|
|
190
196
|
ttkMs: d
|
|
191
|
-
}), await
|
|
197
|
+
}), await ue(f, r);
|
|
192
198
|
}
|
|
193
199
|
}
|
|
194
200
|
}
|
|
195
201
|
//#endregion
|
|
196
202
|
//#region src/core/resolve.ts
|
|
197
|
-
async function
|
|
203
|
+
async function v(e) {
|
|
198
204
|
if (!e.matchUrn || typeof e.matchUrn != "string") throw new n("INVALID_URN", 0, "resolveStream: a non-empty matchUrn is required");
|
|
199
205
|
let t = await p(d(e.baseUrl, `/v1/playback/${encodeURIComponent(e.matchUrn)}`), {
|
|
200
206
|
credential: e.credential,
|
|
201
207
|
signal: e.signal,
|
|
202
208
|
apiHeaders: e.apiHeaders
|
|
203
209
|
});
|
|
204
|
-
if (!t.ok) throw await
|
|
205
|
-
return
|
|
210
|
+
if (!t.ok) throw await fe(t);
|
|
211
|
+
return he(await t.json(), e.matchUrn);
|
|
206
212
|
}
|
|
207
|
-
function
|
|
208
|
-
let t = () =>
|
|
209
|
-
return e.waitForLive ?
|
|
213
|
+
function y(e) {
|
|
214
|
+
let t = () => v(e);
|
|
215
|
+
return e.waitForLive ? de(t, e.waitForLive, e.signal) : t();
|
|
210
216
|
}
|
|
211
|
-
async function
|
|
217
|
+
async function fe(e) {
|
|
212
218
|
let t = f(e.headers.get("retry-after")), i = e.headers.get("x-request-id") ?? e.headers.get("x-amzn-requestid") ?? void 0, a = e.statusText || `HTTP ${e.status}`, o, s;
|
|
213
219
|
try {
|
|
214
220
|
let t = await e.json();
|
|
@@ -224,7 +230,7 @@ async function le(e) {
|
|
|
224
230
|
liveStartsAtMs: s
|
|
225
231
|
});
|
|
226
232
|
}
|
|
227
|
-
var
|
|
233
|
+
var pe = /* @__PURE__ */ new Set([
|
|
228
234
|
"matchUrn",
|
|
229
235
|
"protocol",
|
|
230
236
|
"drmEnabled",
|
|
@@ -235,7 +241,7 @@ var ue = /* @__PURE__ */ new Set([
|
|
|
235
241
|
"expiresAt",
|
|
236
242
|
"analytics"
|
|
237
243
|
]);
|
|
238
|
-
function
|
|
244
|
+
function b(e, t) {
|
|
239
245
|
let r;
|
|
240
246
|
try {
|
|
241
247
|
r = new URL(t);
|
|
@@ -245,57 +251,71 @@ function x(e, t) {
|
|
|
245
251
|
if (r.protocol !== "https:" && r.protocol !== "http:") throw new n("INTERNAL", 0, `playback ${e} has a disallowed scheme: ${r.protocol}`);
|
|
246
252
|
return t;
|
|
247
253
|
}
|
|
248
|
-
function
|
|
254
|
+
function me(e) {
|
|
255
|
+
if (e !== void 0) {
|
|
256
|
+
if (typeof e == "string" && !e.endsWith("/")) try {
|
|
257
|
+
let t = new URL(e);
|
|
258
|
+
if (t.protocol === "https:" && t.href === `${t.origin}/`) return t.origin;
|
|
259
|
+
} catch {}
|
|
260
|
+
g(`server analytics.endpoint ${JSON.stringify(e)} ignored: not a bare https origin.`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function he(e, t) {
|
|
249
264
|
if (!e.manifestUrl) throw new n("INTERNAL", 0, "playback response is missing manifestUrl");
|
|
250
265
|
let r = e.drmEnabled ?? !!e.drm, i = {
|
|
251
266
|
matchUrn: e.matchUrn ?? t,
|
|
252
267
|
protocol: "hls",
|
|
253
268
|
drmEnabled: r,
|
|
254
|
-
manifestUrl:
|
|
269
|
+
manifestUrl: b("manifestUrl", e.manifestUrl),
|
|
255
270
|
serverTime: e.serverTime ?? ""
|
|
256
271
|
};
|
|
257
|
-
if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid
|
|
272
|
+
if (e.liveStartsAt && (i.liveStartsAt = e.liveStartsAt), typeof e.analytics?.sid == "string" && e.analytics.sid) {
|
|
273
|
+
i.analytics = { sid: e.analytics.sid };
|
|
274
|
+
let t = me(e.analytics.endpoint);
|
|
275
|
+
t && (i.analytics.endpoint = t);
|
|
276
|
+
}
|
|
277
|
+
if (r && e.drm) {
|
|
258
278
|
let t = {};
|
|
259
|
-
e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl:
|
|
260
|
-
licenseUrl:
|
|
261
|
-
certificateUrl:
|
|
279
|
+
e.drm.widevine?.licenseUrl && (t.widevine = { licenseUrl: b("widevine licenseUrl", e.drm.widevine.licenseUrl) }), e.drm.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && (t.fairplay = {
|
|
280
|
+
licenseUrl: b("fairplay licenseUrl", e.drm.fairplay.licenseUrl),
|
|
281
|
+
certificateUrl: b("fairplay certificateUrl", e.drm.fairplay.certificateUrl)
|
|
262
282
|
}), (t.widevine || t.fairplay) && (i.drm = t);
|
|
263
283
|
}
|
|
264
284
|
let a = {};
|
|
265
|
-
for (let [t, n] of Object.entries(e))
|
|
285
|
+
for (let [t, n] of Object.entries(e)) pe.has(t) || (a[t] = n);
|
|
266
286
|
return Object.keys(a).length > 0 && (i.extensions = a), i;
|
|
267
287
|
}
|
|
268
288
|
//#endregion
|
|
269
289
|
//#region src/core/fullscreen.ts
|
|
270
|
-
function
|
|
290
|
+
function ge(e) {
|
|
271
291
|
return e.ownerDocument ?? document;
|
|
272
292
|
}
|
|
273
|
-
function
|
|
293
|
+
function _e(e) {
|
|
274
294
|
return e.fullscreenElement ?? e.webkitFullscreenElement ?? null;
|
|
275
295
|
}
|
|
276
|
-
function
|
|
277
|
-
let n =
|
|
296
|
+
function x(e, t) {
|
|
297
|
+
let n = _e(ge(e));
|
|
278
298
|
return n != null && (n === e || t != null && n === t) || e.webkitDisplayingFullscreen === !0;
|
|
279
299
|
}
|
|
280
|
-
async function
|
|
300
|
+
async function S(e, t) {
|
|
281
301
|
let n = t ?? e;
|
|
282
302
|
if (typeof n.requestFullscreen == "function") return await n.requestFullscreen(), !0;
|
|
283
303
|
if (typeof n.webkitRequestFullscreen == "function") return n.webkitRequestFullscreen(), !0;
|
|
284
304
|
let r = e;
|
|
285
305
|
return r.webkitSupportsFullscreen && typeof r.webkitEnterFullscreen == "function" ? (r.webkitEnterFullscreen(), !0) : !1;
|
|
286
306
|
}
|
|
287
|
-
async function
|
|
307
|
+
async function C(e, t) {
|
|
288
308
|
let n = e;
|
|
289
309
|
if (n.webkitDisplayingFullscreen) {
|
|
290
310
|
n.webkitExitFullscreen?.();
|
|
291
311
|
return;
|
|
292
312
|
}
|
|
293
|
-
let r =
|
|
313
|
+
let r = ge(e), i = _e(r);
|
|
294
314
|
i != null && (i === e || t != null && i === t) && (typeof r.exitFullscreen == "function" ? await r.exitFullscreen() : r.webkitExitFullscreen?.());
|
|
295
315
|
}
|
|
296
316
|
//#endregion
|
|
297
317
|
//#region src/core/catalog.ts
|
|
298
|
-
async function
|
|
318
|
+
async function ve(e) {
|
|
299
319
|
let t = new URLSearchParams();
|
|
300
320
|
e.status && t.set("status", Array.isArray(e.status) ? e.status.join(",") : e.status), e.sport && t.set("sport", e.sport);
|
|
301
321
|
let i = t.toString(), a = d(e.baseUrl, "/v1/catalog" + (i ? `?${i}` : "")), o = new Headers();
|
|
@@ -313,12 +333,12 @@ async function pe(e) {
|
|
|
313
333
|
};
|
|
314
334
|
if (!s.ok) throw new n(r(s.status), s.status, `catalog request failed (HTTP ${s.status})`);
|
|
315
335
|
return {
|
|
316
|
-
tournaments:
|
|
336
|
+
tournaments: ye(await s.json()),
|
|
317
337
|
etag: s.headers.get("etag") ?? void 0,
|
|
318
338
|
notModified: !1
|
|
319
339
|
};
|
|
320
340
|
}
|
|
321
|
-
function
|
|
341
|
+
function ye(e) {
|
|
322
342
|
return (e.tournaments ?? []).map((e) => {
|
|
323
343
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
324
344
|
return {
|
|
@@ -340,7 +360,7 @@ function me(e) {
|
|
|
340
360
|
};
|
|
341
361
|
});
|
|
342
362
|
}
|
|
343
|
-
async function
|
|
363
|
+
async function be(e) {
|
|
344
364
|
let t = d(e.baseUrl, `/v1/tournaments/${encodeURIComponent(e.urn)}`), i = new Headers();
|
|
345
365
|
e.etag && i.set("If-None-Match", e.etag);
|
|
346
366
|
let a = await p(t, {
|
|
@@ -360,13 +380,13 @@ async function he(e) {
|
|
|
360
380
|
};
|
|
361
381
|
if (!a.ok) throw new n(r(a.status), a.status, `tournament request failed (HTTP ${a.status})`);
|
|
362
382
|
return {
|
|
363
|
-
tournament:
|
|
383
|
+
tournament: xe(await a.json()),
|
|
364
384
|
etag: a.headers.get("etag") ?? void 0,
|
|
365
385
|
notModified: !1,
|
|
366
386
|
notFound: !1
|
|
367
387
|
};
|
|
368
388
|
}
|
|
369
|
-
function
|
|
389
|
+
function xe(e) {
|
|
370
390
|
let t = e.urn ?? "", n = e.name ?? "", r = e.sport ?? "";
|
|
371
391
|
return {
|
|
372
392
|
urn: t,
|
|
@@ -386,12 +406,12 @@ function ge(e) {
|
|
|
386
406
|
}))
|
|
387
407
|
};
|
|
388
408
|
}
|
|
389
|
-
function
|
|
409
|
+
function Se(e) {
|
|
390
410
|
return e.tournaments.flatMap((e) => e.matches);
|
|
391
411
|
}
|
|
392
412
|
//#endregion
|
|
393
413
|
//#region src/core/poll.ts
|
|
394
|
-
function
|
|
414
|
+
function Ce(e) {
|
|
395
415
|
let t = Math.max(2e3, e.intervalMs ?? 1e4), i = new AbortController(), a, o, s, u = !1, f = () => {
|
|
396
416
|
u || (a = setTimeout(m, t));
|
|
397
417
|
}, m = async () => {
|
|
@@ -433,9 +453,9 @@ function ve(e) {
|
|
|
433
453
|
}
|
|
434
454
|
//#endregion
|
|
435
455
|
//#region src/core/events.ts
|
|
436
|
-
var
|
|
437
|
-
function
|
|
438
|
-
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ??
|
|
456
|
+
var we = 45e3;
|
|
457
|
+
function w(e) {
|
|
458
|
+
let t = Math.max(250, e.minBackoffMs ?? 1e3), n = Math.max(t, e.maxBackoffMs ?? 15e3), r = e.idleTimeoutMs ?? we, i = Number.isFinite(r) && r > 0 ? r : 0, a = new AbortController(), o = !1, c = (e) => new Promise((t) => {
|
|
439
459
|
if (a.signal.aborted) return t();
|
|
440
460
|
let n = setTimeout(t, e);
|
|
441
461
|
a.signal.addEventListener("abort", () => {
|
|
@@ -516,7 +536,7 @@ function E(e) {
|
|
|
516
536
|
o || (o = !0, a.abort());
|
|
517
537
|
} };
|
|
518
538
|
}
|
|
519
|
-
function
|
|
539
|
+
function T(e) {
|
|
520
540
|
try {
|
|
521
541
|
let t = new URL(e);
|
|
522
542
|
return t.hostname = `events.${t.hostname}`, t.pathname = "", t.search = "", t.origin;
|
|
@@ -526,27 +546,27 @@ function D(e) {
|
|
|
526
546
|
}
|
|
527
547
|
//#endregion
|
|
528
548
|
//#region src/core/drm/deviceId.ts
|
|
529
|
-
var
|
|
530
|
-
function
|
|
531
|
-
if (
|
|
549
|
+
var E = "havik.player.deviceId", D;
|
|
550
|
+
function O() {
|
|
551
|
+
if (D) return D;
|
|
532
552
|
try {
|
|
533
|
-
let e = globalThis.localStorage?.getItem(
|
|
534
|
-
if (e) return
|
|
553
|
+
let e = globalThis.localStorage?.getItem(E);
|
|
554
|
+
if (e) return D = e, e;
|
|
535
555
|
} catch {}
|
|
536
|
-
let e =
|
|
537
|
-
|
|
556
|
+
let e = Ee();
|
|
557
|
+
D = e;
|
|
538
558
|
try {
|
|
539
|
-
globalThis.localStorage?.setItem(
|
|
559
|
+
globalThis.localStorage?.setItem(E, e);
|
|
540
560
|
} catch {}
|
|
541
561
|
return e;
|
|
542
562
|
}
|
|
543
|
-
function
|
|
544
|
-
|
|
563
|
+
function Te() {
|
|
564
|
+
D = void 0;
|
|
545
565
|
try {
|
|
546
|
-
globalThis.localStorage?.removeItem(
|
|
566
|
+
globalThis.localStorage?.removeItem(E);
|
|
547
567
|
} catch {}
|
|
548
568
|
}
|
|
549
|
-
function
|
|
569
|
+
function Ee() {
|
|
550
570
|
let e = globalThis.crypto;
|
|
551
571
|
if (e && typeof e.randomUUID == "function") return e.randomUUID();
|
|
552
572
|
let t = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -558,21 +578,21 @@ function xe() {
|
|
|
558
578
|
}
|
|
559
579
|
//#endregion
|
|
560
580
|
//#region src/core/drm/headers.ts
|
|
561
|
-
function
|
|
581
|
+
function De(e, t, n = {}) {
|
|
562
582
|
let r = {
|
|
563
583
|
"x-api-key": t.apiKey,
|
|
564
584
|
"X-Match-Urn": e.matchUrn,
|
|
565
|
-
"X-Device-Id": n.deviceId ??
|
|
585
|
+
"X-Device-Id": n.deviceId ?? O(),
|
|
566
586
|
"Content-Type": "application/octet-stream"
|
|
567
587
|
};
|
|
568
588
|
return n.userId && (r["X-User-Id"] = n.userId), r;
|
|
569
589
|
}
|
|
570
590
|
//#endregion
|
|
571
591
|
//#region src/core/drm/cdm.ts
|
|
572
|
-
var
|
|
573
|
-
function
|
|
574
|
-
let n =
|
|
575
|
-
n || (n = /* @__PURE__ */ new Map(),
|
|
592
|
+
var k = /* @__PURE__ */ new WeakMap();
|
|
593
|
+
function Oe(e, t) {
|
|
594
|
+
let n = k.get(e);
|
|
595
|
+
n || (n = /* @__PURE__ */ new Map(), k.set(e, n));
|
|
576
596
|
let r = n.get(t.keySystem);
|
|
577
597
|
if (r) return r;
|
|
578
598
|
let i = t.createMediaKeys().catch((e) => {
|
|
@@ -580,22 +600,22 @@ function Ce(e, t) {
|
|
|
580
600
|
});
|
|
581
601
|
return n.set(t.keySystem, i), i;
|
|
582
602
|
}
|
|
583
|
-
function
|
|
603
|
+
function A() {
|
|
584
604
|
return typeof navigator < "u" && typeof navigator.requestMediaKeySystemAccess == "function";
|
|
585
605
|
}
|
|
586
|
-
var
|
|
587
|
-
function
|
|
606
|
+
var j = ["SW_SECURE_DECODE", "SW_SECURE_CRYPTO"];
|
|
607
|
+
function ke(e) {
|
|
588
608
|
return e.startsWith("com.widevine");
|
|
589
609
|
}
|
|
590
|
-
function
|
|
591
|
-
if (!
|
|
610
|
+
function M(e, t) {
|
|
611
|
+
if (!ke(e)) return t;
|
|
592
612
|
let n = (e, t) => {
|
|
593
613
|
let n = e.videoCapabilities;
|
|
594
614
|
return !n?.length || !n.some((e) => e.robustness) ? !1 : n.every((e) => {
|
|
595
|
-
let n =
|
|
596
|
-
return n === -1 ||
|
|
615
|
+
let n = j.indexOf(e.robustness);
|
|
616
|
+
return n === -1 || j.indexOf(t) > n;
|
|
597
617
|
});
|
|
598
|
-
}, r =
|
|
618
|
+
}, r = j.flatMap((e) => t.filter((t) => n(t, e)).map((t) => ({
|
|
599
619
|
...t,
|
|
600
620
|
videoCapabilities: t.videoCapabilities?.map((t) => ({
|
|
601
621
|
...t,
|
|
@@ -604,41 +624,87 @@ function P(e, t) {
|
|
|
604
624
|
})));
|
|
605
625
|
return [...t, ...r];
|
|
606
626
|
}
|
|
607
|
-
function
|
|
608
|
-
return (t, n) =>
|
|
627
|
+
function N(e) {
|
|
628
|
+
return (t, n) => A() ? navigator.requestMediaKeySystemAccess(t, M(t, n)).then((t) => ({
|
|
609
629
|
keySystem: t.keySystem,
|
|
610
630
|
getConfiguration: () => t.getConfiguration(),
|
|
611
|
-
createMediaKeys: () =>
|
|
631
|
+
createMediaKeys: () => Oe(e, t)
|
|
612
632
|
})) : Promise.reject(/* @__PURE__ */ Error("navigator.requestMediaKeySystemAccess is unavailable — EME needs a secure context (https, or localhost)"));
|
|
613
633
|
}
|
|
614
|
-
var
|
|
634
|
+
var P = {
|
|
615
635
|
video: "SW_SECURE_DECODE",
|
|
616
636
|
audio: "SW_SECURE_CRYPTO",
|
|
617
637
|
scheme: "cbcs"
|
|
618
638
|
};
|
|
619
|
-
function
|
|
620
|
-
if (!
|
|
639
|
+
function Ae(e) {
|
|
640
|
+
if (!A()) return;
|
|
621
641
|
let t = (e, t) => ({
|
|
622
642
|
contentType: e,
|
|
623
643
|
robustness: t,
|
|
624
|
-
encryptionScheme:
|
|
644
|
+
encryptionScheme: P.scheme
|
|
625
645
|
});
|
|
626
|
-
|
|
646
|
+
N(e)("com.widevine.alpha", [{
|
|
627
647
|
initDataTypes: ["cenc"],
|
|
628
648
|
distinctiveIdentifier: "optional",
|
|
629
649
|
persistentState: "optional",
|
|
630
650
|
sessionTypes: ["temporary"],
|
|
631
|
-
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"",
|
|
632
|
-
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"",
|
|
651
|
+
audioCapabilities: [t("audio/mp4; codecs=\"mp4a.40.2\"", P.audio)],
|
|
652
|
+
videoCapabilities: [t("video/mp4; codecs=\"avc1.42e01e\"", P.video)]
|
|
633
653
|
}]).then((e) => e.createMediaKeys()).catch(() => {});
|
|
634
654
|
}
|
|
655
|
+
function F(e) {
|
|
656
|
+
let t = I(e);
|
|
657
|
+
if (/^avc[13]/.test(t)) return "avc";
|
|
658
|
+
if (/^(hvc1|hev1)/.test(t)) return "hevc";
|
|
659
|
+
if (/^(dvh1|dvhe)/.test(t)) return "dv";
|
|
660
|
+
if (t.startsWith("av01")) return "av1";
|
|
661
|
+
if (/^vp0?9/.test(t)) return "vp9";
|
|
662
|
+
}
|
|
663
|
+
function I(e) {
|
|
664
|
+
return (e ?? "").trim().toLowerCase();
|
|
665
|
+
}
|
|
666
|
+
var je = {
|
|
667
|
+
hevc: "hvc1.1.6.L93.90",
|
|
668
|
+
dv: "dvh1.05.06",
|
|
669
|
+
av1: "av01.0.05M.08",
|
|
670
|
+
vp9: "vp09.00.10.08"
|
|
671
|
+
}, Me = /* @__PURE__ */ new Map(), L = /* @__PURE__ */ new Map();
|
|
672
|
+
function Ne(e) {
|
|
673
|
+
let t = I(e), n = Me.get(t);
|
|
674
|
+
if (n) return n;
|
|
675
|
+
let r = {
|
|
676
|
+
initDataTypes: ["cenc"],
|
|
677
|
+
distinctiveIdentifier: "optional",
|
|
678
|
+
persistentState: "optional",
|
|
679
|
+
sessionTypes: ["temporary"],
|
|
680
|
+
videoCapabilities: [{
|
|
681
|
+
contentType: `video/mp4; codecs="${e.trim()}"`,
|
|
682
|
+
robustness: P.video,
|
|
683
|
+
encryptionScheme: P.scheme
|
|
684
|
+
}]
|
|
685
|
+
}, i = (async () => {
|
|
686
|
+
try {
|
|
687
|
+
return await navigator.requestMediaKeySystemAccess("com.widevine.alpha", M("com.widevine.alpha", [r])), !0;
|
|
688
|
+
} catch {
|
|
689
|
+
return !1;
|
|
690
|
+
}
|
|
691
|
+
})().then((e) => (L.set(t, e), e));
|
|
692
|
+
return Me.set(t, i), i;
|
|
693
|
+
}
|
|
694
|
+
function Pe() {
|
|
695
|
+
if (A()) for (let e of Object.values(je)) Ne(e);
|
|
696
|
+
}
|
|
697
|
+
function Fe(e) {
|
|
698
|
+
let t = F(e);
|
|
699
|
+
if (t) return t === "avc" ? !0 : L.get(I(e)) ?? L.get(I(je[t]));
|
|
700
|
+
}
|
|
635
701
|
//#endregion
|
|
636
702
|
//#region src/core/drm/support.ts
|
|
637
|
-
var
|
|
703
|
+
var Ie = 5e3, R = "video/mp4; codecs=\"avc1.42E01E\"", z = "audio/mp4; codecs=\"mp4a.40.2\"", Le = {
|
|
638
704
|
widevine: ["com.widevine.alpha"],
|
|
639
705
|
fairplay: ["com.apple.fps"]
|
|
640
706
|
};
|
|
641
|
-
function
|
|
707
|
+
function Re(e) {
|
|
642
708
|
return e === "fairplay" ? [{
|
|
643
709
|
initDataTypes: [
|
|
644
710
|
"sinf",
|
|
@@ -646,30 +712,30 @@ function je(e) {
|
|
|
646
712
|
"cenc"
|
|
647
713
|
],
|
|
648
714
|
videoCapabilities: [{
|
|
649
|
-
contentType:
|
|
715
|
+
contentType: R,
|
|
650
716
|
robustness: "",
|
|
651
717
|
encryptionScheme: "cbcs"
|
|
652
718
|
}],
|
|
653
719
|
audioCapabilities: [{
|
|
654
|
-
contentType:
|
|
720
|
+
contentType: z,
|
|
655
721
|
robustness: "",
|
|
656
722
|
encryptionScheme: "cbcs"
|
|
657
723
|
}]
|
|
658
|
-
}] :
|
|
724
|
+
}] : M("com.widevine.alpha", [{
|
|
659
725
|
initDataTypes: ["cenc"],
|
|
660
726
|
videoCapabilities: [{
|
|
661
|
-
contentType:
|
|
662
|
-
robustness:
|
|
663
|
-
encryptionScheme:
|
|
727
|
+
contentType: R,
|
|
728
|
+
robustness: P.video,
|
|
729
|
+
encryptionScheme: P.scheme
|
|
664
730
|
}],
|
|
665
731
|
audioCapabilities: [{
|
|
666
|
-
contentType:
|
|
667
|
-
robustness:
|
|
668
|
-
encryptionScheme:
|
|
732
|
+
contentType: z,
|
|
733
|
+
robustness: P.audio,
|
|
734
|
+
encryptionScheme: P.scheme
|
|
669
735
|
}]
|
|
670
736
|
}]);
|
|
671
737
|
}
|
|
672
|
-
function
|
|
738
|
+
function B(e, t) {
|
|
673
739
|
return new Promise((n, r) => {
|
|
674
740
|
let i = setTimeout(() => r(/* @__PURE__ */ Error("probe-timeout")), t);
|
|
675
741
|
e.then((e) => {
|
|
@@ -679,8 +745,8 @@ function Me(e, t) {
|
|
|
679
745
|
});
|
|
680
746
|
});
|
|
681
747
|
}
|
|
682
|
-
async function
|
|
683
|
-
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ??
|
|
748
|
+
async function ze(e = {}) {
|
|
749
|
+
let t = e.systems ?? ["widevine", "fairplay"], n = e.timeoutMs ?? Ie, r = {};
|
|
684
750
|
if (typeof window < "u" && window.isSecureContext === !1) return {
|
|
685
751
|
verdict: "insecure-context",
|
|
686
752
|
detail: r
|
|
@@ -692,7 +758,7 @@ async function Ne(e = {}) {
|
|
|
692
758
|
};
|
|
693
759
|
let a = !1, o = !1, s = Date.now() + n, c = () => Math.max(1, s - Date.now());
|
|
694
760
|
for (let e of t) {
|
|
695
|
-
let t =
|
|
761
|
+
let t = Le[e];
|
|
696
762
|
if (!t) {
|
|
697
763
|
r[e] = "unknown system";
|
|
698
764
|
continue;
|
|
@@ -703,7 +769,7 @@ async function Ne(e = {}) {
|
|
|
703
769
|
break;
|
|
704
770
|
}
|
|
705
771
|
try {
|
|
706
|
-
return await
|
|
772
|
+
return await B((await B(i(n, Re(e)), c())).createMediaKeys(), c()), r[e] = `ok (${n})`, {
|
|
707
773
|
verdict: "supported",
|
|
708
774
|
system: e,
|
|
709
775
|
detail: r
|
|
@@ -727,49 +793,49 @@ async function Ne(e = {}) {
|
|
|
727
793
|
}
|
|
728
794
|
//#endregion
|
|
729
795
|
//#region src/core/manifest.ts
|
|
730
|
-
var
|
|
731
|
-
function
|
|
732
|
-
return
|
|
796
|
+
var Be = /^#EXT-X-(PART-INF|PART|PRELOAD-HINT)[:\s]/m;
|
|
797
|
+
function Ve(e) {
|
|
798
|
+
return Be.test(e);
|
|
733
799
|
}
|
|
734
800
|
//#endregion
|
|
735
801
|
//#region src/core/env.ts
|
|
736
|
-
var
|
|
802
|
+
var V = {
|
|
737
803
|
integration: "https://feed-dev.oddin-video.gg",
|
|
738
804
|
production: "https://feed.oddin-video.gg"
|
|
739
805
|
};
|
|
740
|
-
function
|
|
741
|
-
let t = Object.prototype.hasOwnProperty.call(
|
|
806
|
+
function H(e) {
|
|
807
|
+
let t = Object.prototype.hasOwnProperty.call(V, e) ? V[e] : void 0;
|
|
742
808
|
if (!t) throw new n("INTERNAL", 0, `unknown env ${JSON.stringify(e)} — expected 'integration' or 'production'`);
|
|
743
809
|
return t;
|
|
744
810
|
}
|
|
745
811
|
//#endregion
|
|
746
812
|
//#region src/core/stats.ts
|
|
747
|
-
var
|
|
748
|
-
function
|
|
813
|
+
var U = { droppedFrames: 0 };
|
|
814
|
+
function W(e) {
|
|
749
815
|
try {
|
|
750
816
|
return new URL(e).host;
|
|
751
817
|
} catch {
|
|
752
818
|
return "";
|
|
753
819
|
}
|
|
754
820
|
}
|
|
755
|
-
var
|
|
756
|
-
function
|
|
821
|
+
var He = /\.(m3u8|ts|m4s|mp4|cmfv|cmfa)(\?|$)/i;
|
|
822
|
+
function Ue(e) {
|
|
757
823
|
if (typeof performance > "u" || typeof performance.getEntriesByType != "function") return "";
|
|
758
824
|
let t = "", n = -1, r = performance.getEntriesByType("resource");
|
|
759
|
-
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" ||
|
|
760
|
-
let e =
|
|
825
|
+
for (let i of r) if (!(i.startTime < e) && (i.initiatorType === "video" || i.initiatorType === "audio" || He.test(i.name)) && i.startTime >= n) {
|
|
826
|
+
let e = W(i.name);
|
|
761
827
|
e && (t = e, n = i.startTime);
|
|
762
828
|
}
|
|
763
829
|
return t;
|
|
764
830
|
}
|
|
765
|
-
function
|
|
831
|
+
function G(e) {
|
|
766
832
|
let t = e.getVideoPlaybackQuality?.();
|
|
767
833
|
return {
|
|
768
834
|
dropped: t?.droppedVideoFrames ?? 0,
|
|
769
835
|
totalFrames: t?.totalVideoFrames ?? 0
|
|
770
836
|
};
|
|
771
837
|
}
|
|
772
|
-
function
|
|
838
|
+
function We(e, t) {
|
|
773
839
|
let n = [
|
|
774
840
|
["playing", () => t("playing")],
|
|
775
841
|
["waiting", () => t("buffering")],
|
|
@@ -786,7 +852,7 @@ function Re(e, t) {
|
|
|
786
852
|
}
|
|
787
853
|
//#endregion
|
|
788
854
|
//#region src/core/engine/native.ts
|
|
789
|
-
function
|
|
855
|
+
function Ge(e) {
|
|
790
856
|
try {
|
|
791
857
|
let t = new TextDecoder("utf-8").decode(new Uint8Array(e));
|
|
792
858
|
return /^skd:\/\/[0-9a-fA-F-]{36}:([0-9a-fA-F]{32})$/.exec(t)?.[1];
|
|
@@ -794,15 +860,15 @@ function ze(e) {
|
|
|
794
860
|
return;
|
|
795
861
|
}
|
|
796
862
|
}
|
|
797
|
-
function
|
|
863
|
+
function K(e) {
|
|
798
864
|
return !!(e ?? (typeof document < "u" ? document.createElement("video") : void 0))?.canPlayType("application/vnd.apple.mpegurl");
|
|
799
865
|
}
|
|
800
|
-
function
|
|
866
|
+
function q() {
|
|
801
867
|
if (typeof window > "u") return !1;
|
|
802
868
|
let e = "WebKitMediaKeys" in window || typeof HTMLMediaElement < "u" && "webkitSetMediaKeys" in HTMLMediaElement.prototype, t = typeof navigator < "u" && /Apple/i.test(navigator.vendor ?? "");
|
|
803
869
|
return e || t;
|
|
804
870
|
}
|
|
805
|
-
var
|
|
871
|
+
var J = class {
|
|
806
872
|
name = "native";
|
|
807
873
|
deps;
|
|
808
874
|
onLoaded;
|
|
@@ -838,7 +904,7 @@ var U = class {
|
|
|
838
904
|
type: "error",
|
|
839
905
|
error: new n("INTERNAL", 0, "native HLS playback error"),
|
|
840
906
|
fatal: !0
|
|
841
|
-
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src =
|
|
907
|
+
}), this.onLoaded && e.addEventListener("loadedmetadata", this.onLoaded, { once: !0 }), e.addEventListener("error", this.onError), e.src = Ke(t.manifestUrl, t.analytics?.sid), e.load();
|
|
842
908
|
}
|
|
843
909
|
startLoad() {
|
|
844
910
|
this.loadStarted || (this.loadStarted = !0, this.restorePreload());
|
|
@@ -860,7 +926,7 @@ var U = class {
|
|
|
860
926
|
});
|
|
861
927
|
this.onEncrypted = (n) => {
|
|
862
928
|
let i = n;
|
|
863
|
-
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV =
|
|
929
|
+
i.initData && !this.fairplayArmed && (this.fairplayArmed = !0, this.fairplayKeyIV = Ge(i.initData), (async () => {
|
|
864
930
|
try {
|
|
865
931
|
let n = await (await navigator.requestMediaKeySystemAccess("com.apple.fps", [{
|
|
866
932
|
initDataTypes: [i.initDataType],
|
|
@@ -955,11 +1021,11 @@ var U = class {
|
|
|
955
1021
|
e.seekable.length > 0 && (e.currentTime = e.seekable.end(e.seekable.length - 1));
|
|
956
1022
|
}
|
|
957
1023
|
getStats() {
|
|
958
|
-
let e = this.deps.video, t =
|
|
1024
|
+
let e = this.deps.video, t = G(e), n = {
|
|
959
1025
|
droppedFrames: t.dropped,
|
|
960
1026
|
decodedFrames: t.totalFrames
|
|
961
1027
|
};
|
|
962
|
-
return this.cdnHost ||=
|
|
1028
|
+
return this.cdnHost ||= Ue(this.builtAt), this.cdnHost && (n.cdnHost = this.cdnHost), this.deps.descriptor.drmEnabled && (n.keySystem = "fairplay"), e.duration === Infinity ? (n.isLive = !0, e.seekable.length > 0 && (n.atLiveEdge = e.currentTime >= e.seekable.end(e.seekable.length - 1) - 2)) : Number.isFinite(e.duration) && e.duration > 0 && (n.isLive = !1), n;
|
|
963
1029
|
}
|
|
964
1030
|
stop() {
|
|
965
1031
|
try {
|
|
@@ -978,13 +1044,13 @@ var U = class {
|
|
|
978
1044
|
} catch {}
|
|
979
1045
|
}
|
|
980
1046
|
};
|
|
981
|
-
function
|
|
1047
|
+
function Ke(e, t) {
|
|
982
1048
|
return t ? `${e}${e.includes("?") ? "&" : "?"}CMCD=${encodeURIComponent(`sid="${t}"`)}` : e;
|
|
983
1049
|
}
|
|
984
1050
|
//#endregion
|
|
985
1051
|
//#region src/core/engine/prefetch.ts
|
|
986
|
-
var
|
|
987
|
-
function
|
|
1052
|
+
var qe = 15e3, Je = 5e3, Ye = 6;
|
|
1053
|
+
function Xe(e) {
|
|
988
1054
|
try {
|
|
989
1055
|
let t = new URL(e);
|
|
990
1056
|
return t.searchParams.delete("CMCD"), t.toString();
|
|
@@ -992,7 +1058,7 @@ function W(e) {
|
|
|
992
1058
|
return e;
|
|
993
1059
|
}
|
|
994
1060
|
}
|
|
995
|
-
var
|
|
1061
|
+
var Ze = class {
|
|
996
1062
|
cmcd;
|
|
997
1063
|
entries = /* @__PURE__ */ new Map();
|
|
998
1064
|
keyed = /* @__PURE__ */ new Set();
|
|
@@ -1015,10 +1081,10 @@ var We = class {
|
|
|
1015
1081
|
}
|
|
1016
1082
|
prefetch(e, t, n) {
|
|
1017
1083
|
if (!this.isActive(t)) return;
|
|
1018
|
-
let r =
|
|
1084
|
+
let r = Xe(e);
|
|
1019
1085
|
if (this.entries.has(r)) return;
|
|
1020
1086
|
let i = this.perTrack.get(t) ?? 0;
|
|
1021
|
-
if (i >=
|
|
1087
|
+
if (i >= Ye) return;
|
|
1022
1088
|
this.perTrack.set(t, i + 1);
|
|
1023
1089
|
let a = new AbortController(), o = {
|
|
1024
1090
|
started: performance.now(),
|
|
@@ -1032,10 +1098,10 @@ var We = class {
|
|
|
1032
1098
|
signal: a.signal
|
|
1033
1099
|
}).then(async (e) => (o.first = performance.now(), e.ok ? e.arrayBuffer() : null)).catch(() => null), this.entries.set(r, o), this.stats.started += 1, setTimeout(() => {
|
|
1034
1100
|
this.entries.get(r) === o && (this.entries.delete(r), a.abort(), this.stats.expired += 1);
|
|
1035
|
-
},
|
|
1101
|
+
}, qe);
|
|
1036
1102
|
}
|
|
1037
1103
|
take(e) {
|
|
1038
|
-
let t =
|
|
1104
|
+
let t = Xe(e), n = this.entries.get(t);
|
|
1039
1105
|
return n && this.entries.delete(t), n;
|
|
1040
1106
|
}
|
|
1041
1107
|
destroy() {
|
|
@@ -1055,13 +1121,13 @@ var We = class {
|
|
|
1055
1121
|
}
|
|
1056
1122
|
}
|
|
1057
1123
|
};
|
|
1058
|
-
function
|
|
1124
|
+
function Qe(t) {
|
|
1059
1125
|
let n = e.DefaultConfig?.loader;
|
|
1060
1126
|
if (typeof n != "function") return;
|
|
1061
1127
|
class r extends n {
|
|
1062
1128
|
served = !1;
|
|
1063
1129
|
cancelled = !1;
|
|
1064
|
-
stats =
|
|
1130
|
+
stats = $e();
|
|
1065
1131
|
load(e, n, r) {
|
|
1066
1132
|
let i = e.rangeEnd ? void 0 : t.take(e.url);
|
|
1067
1133
|
if (!i) {
|
|
@@ -1069,7 +1135,7 @@ function Ge(t) {
|
|
|
1069
1135
|
return;
|
|
1070
1136
|
}
|
|
1071
1137
|
this.served = !0;
|
|
1072
|
-
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs ||
|
|
1138
|
+
let a = performance.now(), o = n?.loadPolicy?.maxTimeToFirstByteMs || Je, s = setTimeout(() => {
|
|
1073
1139
|
!this.cancelled && this.served && (i.abort.abort(), t.stats.failed += 1, this.served = !1, super.load(e, n, r));
|
|
1074
1140
|
}, o);
|
|
1075
1141
|
i.bytes.then((o) => {
|
|
@@ -1096,7 +1162,7 @@ function Ge(t) {
|
|
|
1096
1162
|
}
|
|
1097
1163
|
return r;
|
|
1098
1164
|
}
|
|
1099
|
-
function
|
|
1165
|
+
function $e() {
|
|
1100
1166
|
return {
|
|
1101
1167
|
aborted: !1,
|
|
1102
1168
|
loaded: 0,
|
|
@@ -1120,10 +1186,10 @@ function Ke() {
|
|
|
1120
1186
|
}
|
|
1121
1187
|
};
|
|
1122
1188
|
}
|
|
1123
|
-
function
|
|
1189
|
+
function et(e) {
|
|
1124
1190
|
return e === "audio" ? "audio" : "main";
|
|
1125
1191
|
}
|
|
1126
|
-
function
|
|
1192
|
+
function tt(e, t) {
|
|
1127
1193
|
let n = [];
|
|
1128
1194
|
t.initSegment?.url && !t.initSegment.data && n.push({
|
|
1129
1195
|
url: t.initSegment.url,
|
|
@@ -1142,24 +1208,24 @@ function qe(e, t) {
|
|
|
1142
1208
|
}
|
|
1143
1209
|
//#endregion
|
|
1144
1210
|
//#region src/core/engine/hls.ts
|
|
1145
|
-
function
|
|
1211
|
+
function nt() {
|
|
1146
1212
|
return e.isSupported();
|
|
1147
1213
|
}
|
|
1148
|
-
var
|
|
1149
|
-
function
|
|
1214
|
+
var rt = 3, it = 5, at = 3, ot = 3e4, st = 12e3, ct = 3e3, lt = 6e3, ut = 5e3, dt = 4e3, ft = 2, pt = 5, mt = 2, ht = 2, gt = 4, _t = 4, vt = 2e3, yt = 3e4, bt = 2, xt = 9, St = .5, Ct = 64;
|
|
1215
|
+
function wt(e) {
|
|
1150
1216
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1151
1217
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1152
1218
|
return;
|
|
1153
1219
|
}
|
|
1154
|
-
e.liveSyncDuration ??=
|
|
1155
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1156
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1220
|
+
e.liveSyncDuration ??= bt;
|
|
1221
|
+
let t = Math.max(12, e.liveSyncDuration + xt);
|
|
1222
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Tt(e, e.liveSyncDuration);
|
|
1157
1223
|
}
|
|
1158
|
-
function
|
|
1224
|
+
function Tt(e, t) {
|
|
1159
1225
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1160
1226
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1161
1227
|
}
|
|
1162
|
-
var
|
|
1228
|
+
var Et = class {
|
|
1163
1229
|
name = "hls";
|
|
1164
1230
|
hls = null;
|
|
1165
1231
|
deps;
|
|
@@ -1227,7 +1293,7 @@ var J = class {
|
|
|
1227
1293
|
this.deps = e, this.licenseUrl = e.descriptor.drm?.widevine?.licenseUrl, this.loadStarted = e.deferLoad !== !0;
|
|
1228
1294
|
}
|
|
1229
1295
|
async load() {
|
|
1230
|
-
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a =
|
|
1296
|
+
let { descriptor: e, snapToLiveOnRefocus: t, video: r, emit: i } = this.deps, a = K(r) && q(), o = !!e.drm?.widevine?.licenseUrl && !a;
|
|
1231
1297
|
if (e.drmEnabled && !o) {
|
|
1232
1298
|
i({
|
|
1233
1299
|
type: "error",
|
|
@@ -1236,7 +1302,7 @@ var J = class {
|
|
|
1236
1302
|
});
|
|
1237
1303
|
return;
|
|
1238
1304
|
}
|
|
1239
|
-
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc &&
|
|
1305
|
+
e.drmEnabled && o && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && (Ae(r), Pe()), this.startHls(), t !== !1 && typeof document < "u" && (this.onVisibility = () => {
|
|
1240
1306
|
let e = this.hls;
|
|
1241
1307
|
if (document.visibilityState !== "visible" || !e) return;
|
|
1242
1308
|
let t = e.liveSyncPosition;
|
|
@@ -1259,7 +1325,7 @@ var J = class {
|
|
|
1259
1325
|
}
|
|
1260
1326
|
this.loadSuspended = !0;
|
|
1261
1327
|
}
|
|
1262
|
-
},
|
|
1328
|
+
}, ut));
|
|
1263
1329
|
}
|
|
1264
1330
|
resumeLoading() {
|
|
1265
1331
|
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
@@ -1291,7 +1357,7 @@ var J = class {
|
|
|
1291
1357
|
let t = e.liveSyncPosition;
|
|
1292
1358
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1293
1359
|
let { video: n } = this.deps;
|
|
1294
|
-
n.currentTime <= t +
|
|
1360
|
+
n.currentTime <= t + St || (n.currentTime = t);
|
|
1295
1361
|
}
|
|
1296
1362
|
startHls() {
|
|
1297
1363
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1310,12 +1376,12 @@ var J = class {
|
|
|
1310
1376
|
emeEnabled: !0,
|
|
1311
1377
|
drmSystems: { ...this.licenseUrl ? { "com.widevine.alpha": { licenseUrl: this.licenseUrl } } : {} },
|
|
1312
1378
|
drmSystemOptions: {
|
|
1313
|
-
videoRobustness:
|
|
1314
|
-
audioRobustness:
|
|
1315
|
-
videoEncryptionScheme:
|
|
1316
|
-
audioEncryptionScheme:
|
|
1379
|
+
videoRobustness: P.video,
|
|
1380
|
+
audioRobustness: P.audio,
|
|
1381
|
+
videoEncryptionScheme: P.scheme,
|
|
1382
|
+
audioEncryptionScheme: P.scheme
|
|
1317
1383
|
},
|
|
1318
|
-
...
|
|
1384
|
+
...A() ? { requestMediaKeySystemAccessFunc: N(t) } : {},
|
|
1319
1385
|
licenseXhrSetup: (e, t) => {
|
|
1320
1386
|
e.open("POST", this.licenseUrl ?? t, !0), e.setRequestHeader("x-api-key", r.apiKey), e.setRequestHeader("X-Match-Urn", n.matchUrn), e.setRequestHeader("X-Device-Id", i), a && e.setRequestHeader("X-User-Id", a), this.licenseRequested = !0;
|
|
1321
1387
|
let o = performance.now();
|
|
@@ -1332,22 +1398,20 @@ var J = class {
|
|
|
1332
1398
|
...c
|
|
1333
1399
|
};
|
|
1334
1400
|
if (this.prefetch?.destroy(), this.prefetch = null, u && this.deps.mediaDuringKey !== !1 && !d.fLoader) {
|
|
1335
|
-
let e = new
|
|
1401
|
+
let e = new Ze({
|
|
1336
1402
|
sessionId: n.analytics?.sid,
|
|
1337
1403
|
contentId: n.matchUrn
|
|
1338
|
-
}), t =
|
|
1404
|
+
}), t = Qe(e);
|
|
1339
1405
|
t && (this.prefetch = e, d.fLoader = t);
|
|
1340
1406
|
}
|
|
1341
|
-
|
|
1407
|
+
wt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
|
|
1342
1408
|
let f = new e(d);
|
|
1343
1409
|
if (this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1344
|
-
this.mediaRecoveries = 0, this.networkRecoveries = 0;
|
|
1345
|
-
let e = f.levels.map((e) => e.height).filter((e) => !!e);
|
|
1346
|
-
this.ladderHeights = e.length ? [...new Set(e)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = f.levels.length ? Math.round(Math.max(...f.levels.map((e) => e.bitrate)) / 1e3) : 0, this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1410
|
+
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(f), this.measureLadder(f), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
1347
1411
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1348
1412
|
t?.frag?.type === "main" && (this.kickKind !== "dead" && this.clearKick(), (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
1349
1413
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
1350
|
-
},
|
|
1414
|
+
}, ot)));
|
|
1351
1415
|
}), f.on(e.Events.FRAG_LOADING, (e, t) => {
|
|
1352
1416
|
t?.frag?.type === "main" && (this.lastFragLoadingMs = Date.now());
|
|
1353
1417
|
}), f.on(e.Events.FRAG_LOADED, (e, t) => {
|
|
@@ -1355,10 +1419,10 @@ var J = class {
|
|
|
1355
1419
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1356
1420
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1357
1421
|
let i = n?.loading;
|
|
1358
|
-
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length >
|
|
1422
|
+
i && i.end > 0 && i.start > 0 && (this.requestCount += 1, this.requestTimesMs.push(Math.max(0, Math.round(i.end - i.start))), this.requestTimesMs.length > Ct && this.requestTimesMs.shift());
|
|
1359
1423
|
let a = t?.frag?.url;
|
|
1360
1424
|
if (a) {
|
|
1361
|
-
let e =
|
|
1425
|
+
let e = W(a);
|
|
1362
1426
|
e && (this.cdnHost = e);
|
|
1363
1427
|
}
|
|
1364
1428
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => {
|
|
@@ -1372,15 +1436,15 @@ var J = class {
|
|
|
1372
1436
|
}), f.on(e.Events.LEVEL_LOADED, (e, t) => this.trackEnd(t)), this.prefetch) {
|
|
1373
1437
|
let t = this.prefetch;
|
|
1374
1438
|
f.on(e.Events.KEY_LOADING, (e, n) => {
|
|
1375
|
-
let r = n?.frag, i =
|
|
1376
|
-
if (r && t.isActive(i)) for (let e of
|
|
1377
|
-
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(
|
|
1439
|
+
let r = n?.frag, i = et(r?.type);
|
|
1440
|
+
if (r && t.isActive(i)) for (let e of tt(f, r)) t.prefetch(e.url, i, e.kind);
|
|
1441
|
+
}), f.on(e.Events.KEY_LOADED, (e, n) => t.keyUsable(et(n?.frag?.type)));
|
|
1378
1442
|
}
|
|
1379
1443
|
f.on(e.Events.KEY_LOADED, () => {
|
|
1380
1444
|
u && !this.reportedDrmReady && (this.reportedDrmReady = !0, l({ type: "drmReady" }));
|
|
1381
1445
|
}), this.endWatchdog && clearInterval(this.endWatchdog), this.endWatchdog = setInterval(() => {
|
|
1382
1446
|
this.checkEndStale(), this.checkStarvation();
|
|
1383
|
-
},
|
|
1447
|
+
}, ct), f.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1384
1448
|
this.renditionSwitches += 1;
|
|
1385
1449
|
let n = this.lastLevelIndex >= 0 ? f.levels[this.lastLevelIndex] : void 0, r = f.levels[t.level];
|
|
1386
1450
|
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
@@ -1444,11 +1508,33 @@ var J = class {
|
|
|
1444
1508
|
return;
|
|
1445
1509
|
}
|
|
1446
1510
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1447
|
-
let t = e > this.sizeCapLevel ?
|
|
1511
|
+
let t = e > this.sizeCapLevel ? vt : yt;
|
|
1448
1512
|
this.capTimer = setTimeout(() => {
|
|
1449
1513
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1450
1514
|
}, t);
|
|
1451
1515
|
}
|
|
1516
|
+
measureLadder(e) {
|
|
1517
|
+
let t = e.levels.map((e) => e.height).filter((e) => !!e);
|
|
1518
|
+
this.ladderHeights = t.length ? [...new Set(t)].sort((e, t) => e - t) : void 0, this.ladderTopBitrateKbps = e.levels.length ? Math.round(Math.max(...e.levels.map((e) => e.bitrate)) / 1e3) : 0;
|
|
1519
|
+
}
|
|
1520
|
+
dropLevelsWidevineCannotPlay(e) {
|
|
1521
|
+
this.removeLevelsWhere(e, (e) => Fe(e) !== !0);
|
|
1522
|
+
let t = new Set(e.levels.map((e) => e.videoCodec).filter((e) => !!e && F(e) !== "avc" && !!F(e)));
|
|
1523
|
+
for (let n of t) Ne(n).then((t) => {
|
|
1524
|
+
t || this.hls !== e || this.removeLevelsWhere(e, (e) => e === n) && (this.measureLadder(e), this.applySizeCap());
|
|
1525
|
+
});
|
|
1526
|
+
}
|
|
1527
|
+
removeLevelsWhere(e, t) {
|
|
1528
|
+
let n = e.levels ?? [], r = [], i = /* @__PURE__ */ new Set();
|
|
1529
|
+
if (n.forEach((e, n) => {
|
|
1530
|
+
let a = e.videoCodec;
|
|
1531
|
+
a && F(a) && t(a) && (r.push(n), i.add(a));
|
|
1532
|
+
}), !r.length) return !1;
|
|
1533
|
+
let a = [...i].join(", ");
|
|
1534
|
+
if (!n.some((e, t) => r.includes(t) ? !1 : !F(e.videoCodec) || Fe(e.videoCodec) === !0)) return console.warn(`havik-player: every rendition is ${a}, which Widevine may not play on this browser; keeping them`), !1;
|
|
1535
|
+
for (let t = r.length - 1; t >= 0; --t) e.removeLevel(r[t]);
|
|
1536
|
+
return console.info(`havik-player: skipped ${r.length} rendition(s) Widevine cannot play on this browser (${a})`), !0;
|
|
1537
|
+
}
|
|
1452
1538
|
applySizeCap() {
|
|
1453
1539
|
if (!this.sizeCapManaged) return;
|
|
1454
1540
|
this.capTimer &&= (clearTimeout(this.capTimer), null);
|
|
@@ -1491,7 +1577,7 @@ var J = class {
|
|
|
1491
1577
|
e.widevine && (this.licenseUrl = e.widevine);
|
|
1492
1578
|
}
|
|
1493
1579
|
getStats() {
|
|
1494
|
-
let e = this.hls, t =
|
|
1580
|
+
let e = this.hls, t = G(this.deps.video), n = {
|
|
1495
1581
|
droppedFrames: t.dropped,
|
|
1496
1582
|
decodedFrames: t.totalFrames,
|
|
1497
1583
|
lowLatency: this.detectedLowLatency,
|
|
@@ -1537,7 +1623,7 @@ var J = class {
|
|
|
1537
1623
|
return;
|
|
1538
1624
|
}
|
|
1539
1625
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1540
|
-
!this.chaseSuspended && e >
|
|
1626
|
+
!this.chaseSuspended && e > lt && this.suspendChasing(), e > st && this.emitEnded("stalled");
|
|
1541
1627
|
}
|
|
1542
1628
|
resetStarvationWindow() {
|
|
1543
1629
|
this.starvedTicks = 0, this.deadTicks = 0, this.mainFragsSinceTick = 0, this.recentMainFrags = [];
|
|
@@ -1552,7 +1638,7 @@ var J = class {
|
|
|
1552
1638
|
this.resetStarvationWindow();
|
|
1553
1639
|
return;
|
|
1554
1640
|
}
|
|
1555
|
-
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs <
|
|
1641
|
+
let n = Date.now(), r = this.lastAdvanceMs !== 0 && n - this.lastAdvanceMs < lt, i = this.lastFragLoadingMs !== 0 && n - this.lastFragLoadingMs > dt, a = t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused, { totalFrames: o, dropped: s } = G(t), c = o - s, l = c !== this.starvedFrames;
|
|
1556
1642
|
if (this.starvedFrames = c, !a || l) {
|
|
1557
1643
|
(t.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA || l) && this.clearKick(), this.resetStarvationWindow();
|
|
1558
1644
|
return;
|
|
@@ -1561,12 +1647,12 @@ var J = class {
|
|
|
1561
1647
|
this.resetStarvationWindow();
|
|
1562
1648
|
return;
|
|
1563
1649
|
}
|
|
1564
|
-
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length >
|
|
1650
|
+
if (this.kickPending && (this.kickKind === "dead" || i) && (this.kickTicks += 1), this.starvedTicks = i ? this.starvedTicks + 1 : 0, this.deadTicks += 1, this.recentMainFrags.push(this.mainFragsSinceTick), this.mainFragsSinceTick = 0, this.recentMainFrags.length > gt && this.recentMainFrags.shift(), this.clearRecoveryReset(), this.kickPending && this.kickTicks >= mt && (this.clearKick(), this.starvationRebuilds < ht)) {
|
|
1565
1651
|
this.starvationRebuilds += 1, this.resetStarvationWindow(), this.clearRecoveryReset(), console.warn("havik-player: restarting the load did not resume video (the wedge is in hls.js state that only a rebuild clears) — rebuilding the player"), this.rebuildInstance("starvation rebuild");
|
|
1566
1652
|
return;
|
|
1567
1653
|
}
|
|
1568
|
-
let u = i && this.starvedTicks >=
|
|
1569
|
-
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >=
|
|
1654
|
+
let u = i && this.starvedTicks >= ft, d = !i && this.deadTicks >= gt && this.recentMainFrags.reduce((e, t) => e + t, 0) >= _t;
|
|
1655
|
+
if ((u || d) && (this.resetStarvationWindow(), !(this.starvationKicks >= pt))) {
|
|
1570
1656
|
this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, this.kickKind = d ? "dead" : "quiet", this.clearRecoveryReset(), console.warn(d ? "havik-player: video starved while hls.js keeps loading media it never plays (dead pipeline at the live edge) — restarting the load" : "havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
|
|
1571
1657
|
try {
|
|
1572
1658
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1615,7 +1701,7 @@ var J = class {
|
|
|
1615
1701
|
scheduleLicenseRetry(t) {
|
|
1616
1702
|
if (t.details !== e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED && t.details !== e.ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED) return !1;
|
|
1617
1703
|
let n = t.response?.code ?? 0;
|
|
1618
|
-
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >=
|
|
1704
|
+
if (!(n === 0 || n === 408 || n === 429 || n >= 500) || this.licenseRecoveries >= at) return !1;
|
|
1619
1705
|
this.licenseRecoveries += 1;
|
|
1620
1706
|
let r = Math.min(8e3, 500 * 2 ** (this.licenseRecoveries - 1));
|
|
1621
1707
|
return this.licenseRetryTimer = setTimeout(() => {
|
|
@@ -1647,7 +1733,7 @@ var J = class {
|
|
|
1647
1733
|
return;
|
|
1648
1734
|
}
|
|
1649
1735
|
if (t.type === e.ErrorTypes.NETWORK_ERROR) {
|
|
1650
|
-
if (this.networkRecoveries <
|
|
1736
|
+
if (this.networkRecoveries < it) {
|
|
1651
1737
|
this.networkRecoveries += 1;
|
|
1652
1738
|
let e = Math.min(8e3, 1e3 * 2 ** (this.networkRecoveries - 1));
|
|
1653
1739
|
this.networkRetryTimer = setTimeout(() => {
|
|
@@ -1664,7 +1750,7 @@ var J = class {
|
|
|
1664
1750
|
return;
|
|
1665
1751
|
}
|
|
1666
1752
|
if (t.type === e.ErrorTypes.MEDIA_ERROR) {
|
|
1667
|
-
if (this.mediaRecoveries <
|
|
1753
|
+
if (this.mediaRecoveries < rt) {
|
|
1668
1754
|
this.mediaRecoveries += 1, n.recoverMediaError();
|
|
1669
1755
|
return;
|
|
1670
1756
|
}
|
|
@@ -1688,19 +1774,19 @@ var J = class {
|
|
|
1688
1774
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1689
1775
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1690
1776
|
}
|
|
1691
|
-
},
|
|
1777
|
+
}, Dt = 15e3, Ot = 6e5, kt = 3e5, At = 100, Y = 1, jt = 1e3, Mt = 3e4, Nt = 1e3, Pt = {
|
|
1692
1778
|
inline: "PRESENTATION_INLINE",
|
|
1693
1779
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1694
1780
|
pip: "PRESENTATION_PIP"
|
|
1695
|
-
},
|
|
1781
|
+
}, Ft = {
|
|
1696
1782
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1697
1783
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1698
1784
|
none: "KEY_SYSTEM_NONE"
|
|
1699
1785
|
};
|
|
1700
|
-
function
|
|
1786
|
+
function It(e, t) {
|
|
1701
1787
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1702
1788
|
}
|
|
1703
|
-
var
|
|
1789
|
+
var Lt = /* @__PURE__ */ new Set([
|
|
1704
1790
|
"INVALID_URN",
|
|
1705
1791
|
"NOT_FOUND",
|
|
1706
1792
|
"GONE",
|
|
@@ -1720,7 +1806,7 @@ var Et = /* @__PURE__ */ new Set([
|
|
|
1720
1806
|
ended: "PLAYER_STATE_ENDED",
|
|
1721
1807
|
error: "PLAYER_STATE_ERROR"
|
|
1722
1808
|
};
|
|
1723
|
-
function
|
|
1809
|
+
function Rt(e) {
|
|
1724
1810
|
try {
|
|
1725
1811
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1726
1812
|
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);
|
|
@@ -1728,24 +1814,25 @@ function Dt(e) {
|
|
|
1728
1814
|
return;
|
|
1729
1815
|
}
|
|
1730
1816
|
}
|
|
1731
|
-
var
|
|
1732
|
-
function
|
|
1733
|
-
return
|
|
1817
|
+
var zt = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase();
|
|
1818
|
+
function Bt(e, t) {
|
|
1819
|
+
return g(t, e), { disabledReason: t };
|
|
1734
1820
|
}
|
|
1735
|
-
function
|
|
1821
|
+
function Vt(e, t, n) {
|
|
1822
|
+
if (n) return t && !zt(t, n) && g(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
1736
1823
|
if (t) return { endpoint: t };
|
|
1737
|
-
if (t !== void 0) return
|
|
1738
|
-
let
|
|
1739
|
-
if (
|
|
1740
|
-
let
|
|
1824
|
+
if (t !== void 0) return Bt("empty-endpoint", "analytics is disabled: no QoE beacons will be sent. analytics.endpoint was supplied but empty. Pass a real beacons origin, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, or omit the option to derive it from baseUrl (or analytics: false to opt out).");
|
|
1825
|
+
let r = Rt(e);
|
|
1826
|
+
if (r) return { endpoint: r };
|
|
1827
|
+
let i;
|
|
1741
1828
|
try {
|
|
1742
|
-
|
|
1829
|
+
i = new URL(e).hostname || e;
|
|
1743
1830
|
} catch {
|
|
1744
|
-
|
|
1831
|
+
i = e;
|
|
1745
1832
|
}
|
|
1746
|
-
return
|
|
1833
|
+
return Bt(i, `analytics is disabled: no QoE beacons will be sent. The beacons endpoint cannot be derived from the baseUrl host "${i}" — the convention is feed[-dev].<domain> → beacons[-dev].<domain>. Pass an explicit endpoint, analytics: { endpoint: 'https://beacons[-dev].<domain>' }, to createPlayer (or analytics: false to opt out deliberately).`);
|
|
1747
1834
|
}
|
|
1748
|
-
var
|
|
1835
|
+
var Ht = class {
|
|
1749
1836
|
opts;
|
|
1750
1837
|
url;
|
|
1751
1838
|
now;
|
|
@@ -1825,8 +1912,8 @@ var jt = class {
|
|
|
1825
1912
|
constructor(e) {
|
|
1826
1913
|
this.opts = {
|
|
1827
1914
|
...e,
|
|
1828
|
-
heartbeatMs: e.heartbeatMs ??
|
|
1829
|
-
idleMs: e.idleMs ??
|
|
1915
|
+
heartbeatMs: e.heartbeatMs ?? Dt,
|
|
1916
|
+
idleMs: e.idleMs ?? Ot
|
|
1830
1917
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`, this.now = e.now ?? (() => Date.now()), this.bornMs = this.now(), this.presentationSinceMs = this.bornMs, this.startupAnchorMs = this.bornMs;
|
|
1831
1918
|
}
|
|
1832
1919
|
start() {
|
|
@@ -1836,11 +1923,11 @@ var jt = class {
|
|
|
1836
1923
|
sdkVersion: this.opts.sdkVersion,
|
|
1837
1924
|
...this.opts.environment
|
|
1838
1925
|
};
|
|
1839
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
1926
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), jt), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.onVisibility());
|
|
1840
1927
|
}
|
|
1841
1928
|
checkSuspension(e) {
|
|
1842
1929
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
1843
|
-
let t = Math.max(this.opts.idleMs,
|
|
1930
|
+
let t = Math.max(this.opts.idleMs, kt);
|
|
1844
1931
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
1845
1932
|
}
|
|
1846
1933
|
syncIdle(e) {
|
|
@@ -1863,12 +1950,12 @@ var jt = class {
|
|
|
1863
1950
|
let a = {
|
|
1864
1951
|
fromState: X[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1865
1952
|
toState: X[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1866
|
-
presentation:
|
|
1953
|
+
presentation: Pt[this.presentation]
|
|
1867
1954
|
}, o = this.causeOf(e, t, i);
|
|
1868
1955
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
1869
1956
|
}
|
|
1870
1957
|
seekInduced(e) {
|
|
1871
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
1958
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < Nt;
|
|
1872
1959
|
}
|
|
1873
1960
|
causeOf(e, t, n) {
|
|
1874
1961
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -1942,7 +2029,7 @@ var jt = class {
|
|
|
1942
2029
|
let r = n ?? "";
|
|
1943
2030
|
if (r !== "") return /^fragLoad/i.test(r) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /^(manifest|level|audioTrack|subtitleTrack)/i.test(r) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(r) ? "ERROR_STAGE_DRM" : /parsing|append|buffer|remux|decrypt|media/i.test(r) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
|
|
1944
2031
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
1945
|
-
if (
|
|
2032
|
+
if (Lt.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
1946
2033
|
let i = t ?? "";
|
|
1947
2034
|
return /frag|segment/i.test(i) ? this.sawFirstBytes ? "ERROR_STAGE_SEGMENT" : "ERROR_STAGE_FIRST_SEGMENT" : /manifest|level|playlist/i.test(i) ? "ERROR_STAGE_MANIFEST" : /key|licen[cs]e/i.test(i) ? "ERROR_STAGE_DRM" : /buffer|decode|media|append/i.test(i) ? "ERROR_STAGE_DECODE" : "ERROR_STAGE_OTHER";
|
|
1948
2035
|
}
|
|
@@ -1989,14 +2076,14 @@ var jt = class {
|
|
|
1989
2076
|
if (this.lastRequestCount = g, _ > 0) {
|
|
1990
2077
|
o.requestCountDelta = _;
|
|
1991
2078
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
1992
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2079
|
+
n.length > 0 && (o.requestTimeP50Ms = It(n, 50), o.requestTimeP95Ms = It(n, 95));
|
|
1993
2080
|
}
|
|
1994
2081
|
typeof t.latencySeconds == "number" && typeof t.targetLatencySeconds == "number" && (o.driftMs = Math.round((t.latencySeconds - t.targetLatencySeconds) * 1e3)), typeof t.playbackRate == "number" && t.playbackRate > 0 && (o.playbackRate = t.playbackRate), t.qualityPinned === !0 && (o.qualityPinned = !0), t.cdnHost && (o.cdnHost = t.cdnHost), this.maybeEmitMediaInfo(t), this.enqueue({ heartbeat: o }), this.flush(), s > 0 && this.noteFirstBytes();
|
|
1995
2082
|
}
|
|
1996
2083
|
maybeEmitMediaInfo(e) {
|
|
1997
2084
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
1998
2085
|
let t = {};
|
|
1999
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2086
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Ft[e.keySystem]), e.drmSecurityLevel && (t.drmSecurityLevel = e.drmSecurityLevel), e.ladderHeights?.length && (t.ladderHeights = e.ladderHeights), e.ladderTopBitrateKbps && (t.ladderTopBitrateKbps = e.ladderTopBitrateKbps), e.lowLatency && (t.lowLatency = !0);
|
|
2000
2087
|
let n = JSON.stringify(t);
|
|
2001
2088
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2002
2089
|
}
|
|
@@ -2016,7 +2103,7 @@ var jt = class {
|
|
|
2016
2103
|
let c = r?.positionMs ?? 0;
|
|
2017
2104
|
c > 0 && (i.exitPositionMs = Math.round(c)), this.activeTotalMs > 0 && (i.activeWatchTimeMs = Math.round(this.activeTotalMs)), this.mutedTotalMs > 0 && (i.mutedTimeMs = Math.round(this.mutedTotalMs));
|
|
2018
2105
|
let l = e !== "END_REASON_ENDED";
|
|
2019
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2106
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= Mt && (i.abandonAfterStallMs = Math.max(Y, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= Mt && (i.abandonAfterErrorMs = Math.max(Y, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
|
|
2020
2107
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2021
2108
|
u > 0 && (i.decodedFramesTotal = u), e === "END_REASON_STOPPED" && this.startupTimeMs === 0 && this.lastErrorStage === null && (e = "END_REASON_ABORTED", i.reason = e), this.startupTimeMs === 0 && e !== "END_REASON_ABORTED" && (i.failedStage = this.lastErrorStage ?? (this.manifestLoadMs === 0 ? "ERROR_STAGE_MANIFEST" : this.firstFragLoadMs === 0 ? "ERROR_STAGE_FIRST_SEGMENT" : "ERROR_STAGE_OTHER")), this.pending.push(this.wrap({ sessionEnd: i })), this.flush(e === "END_REASON_PAGEHIDE");
|
|
2022
2109
|
}
|
|
@@ -2036,7 +2123,7 @@ var jt = class {
|
|
|
2036
2123
|
};
|
|
2037
2124
|
}
|
|
2038
2125
|
enqueue(e) {
|
|
2039
|
-
for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2126
|
+
for (this.pending.push(this.wrap(e)); this.pending.length > At;) {
|
|
2040
2127
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2041
2128
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2042
2129
|
}
|
|
@@ -2059,7 +2146,7 @@ var jt = class {
|
|
|
2059
2146
|
};
|
|
2060
2147
|
//#endregion
|
|
2061
2148
|
//#region src/core/environment.ts
|
|
2062
|
-
function
|
|
2149
|
+
function Ut() {
|
|
2063
2150
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2064
2151
|
let e;
|
|
2065
2152
|
try {
|
|
@@ -2084,14 +2171,14 @@ function Mt() {
|
|
|
2084
2171
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2085
2172
|
};
|
|
2086
2173
|
}
|
|
2087
|
-
function
|
|
2174
|
+
function Wt() {
|
|
2088
2175
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2089
2176
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2090
2177
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2091
2178
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2092
2179
|
return e?.mobile ?? (typeof navigator.maxTouchPoints == "number" && navigator.maxTouchPoints > 1 && n > 0 && n < 900) ? n >= 600 ? "DEVICE_CLASS_TABLET" : "DEVICE_CLASS_PHONE" : e || n >= 900 || /mac|win|linux|chrome os/i.test(t) ? "DEVICE_CLASS_DESKTOP" : "DEVICE_CLASS_OTHER";
|
|
2093
2180
|
}
|
|
2094
|
-
function
|
|
2181
|
+
function Gt() {
|
|
2095
2182
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2096
2183
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2097
2184
|
let t = {
|
|
@@ -2110,17 +2197,17 @@ function Pt() {
|
|
|
2110
2197
|
}
|
|
2111
2198
|
return typeof e.downlink == "number" && e.downlink > 0 && (i.downlinkKbps = Math.round(e.downlink * 1e3)), typeof e.rtt == "number" && e.rtt > 0 && (i.rttMs = Math.round(e.rtt)), e.saveData && (i.saveData = !0), i;
|
|
2112
2199
|
}
|
|
2113
|
-
function
|
|
2114
|
-
let t =
|
|
2115
|
-
deviceClass:
|
|
2200
|
+
function Kt(e) {
|
|
2201
|
+
let t = Ut(), n = {
|
|
2202
|
+
deviceClass: Wt(),
|
|
2116
2203
|
integration: t.integration,
|
|
2117
|
-
...
|
|
2204
|
+
...Gt()
|
|
2118
2205
|
};
|
|
2119
2206
|
t.host && (n.host = t.host), typeof screen < "u" && screen.width > 0 && (n.screenWidth = screen.width, n.screenHeight = screen.height), typeof window < "u" && window.devicePixelRatio > 0 && (n.devicePixelRatio = Math.round(window.devicePixelRatio * 100) / 100);
|
|
2120
2207
|
let r = e.getBoundingClientRect?.();
|
|
2121
2208
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2122
2209
|
}
|
|
2123
|
-
async function
|
|
2210
|
+
async function qt() {
|
|
2124
2211
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2125
2212
|
if (!e?.getHighEntropyValues) return {};
|
|
2126
2213
|
try {
|
|
@@ -2132,7 +2219,7 @@ async function It() {
|
|
|
2132
2219
|
}
|
|
2133
2220
|
//#endregion
|
|
2134
2221
|
//#region src/core/version.ts
|
|
2135
|
-
var
|
|
2222
|
+
var Jt = "2.12.0", Yt = {
|
|
2136
2223
|
accent: "#E1B600",
|
|
2137
2224
|
accentText: "#1B1C23",
|
|
2138
2225
|
background: "#0e0f13",
|
|
@@ -2143,7 +2230,7 @@ var Lt = "2.11.0", Rt = {
|
|
|
2143
2230
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2144
2231
|
radius: "8px",
|
|
2145
2232
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2146
|
-
},
|
|
2233
|
+
}, Xt = {
|
|
2147
2234
|
accent: "--havik-accent",
|
|
2148
2235
|
accentText: "--havik-accent-text",
|
|
2149
2236
|
background: "--havik-bg",
|
|
@@ -2155,25 +2242,25 @@ var Lt = "2.11.0", Rt = {
|
|
|
2155
2242
|
radius: "--havik-radius",
|
|
2156
2243
|
fontFamily: "--havik-font"
|
|
2157
2244
|
};
|
|
2158
|
-
function
|
|
2245
|
+
function Zt(e, t) {
|
|
2159
2246
|
let n = {
|
|
2160
|
-
...
|
|
2247
|
+
...Yt,
|
|
2161
2248
|
...t
|
|
2162
2249
|
};
|
|
2163
|
-
for (let t of Object.keys(
|
|
2250
|
+
for (let t of Object.keys(Xt)) e.style.setProperty(Xt[t], n[t]);
|
|
2164
2251
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2165
2252
|
}
|
|
2166
2253
|
//#endregion
|
|
2167
2254
|
//#region src/ui/styles.ts
|
|
2168
|
-
var
|
|
2169
|
-
function
|
|
2170
|
-
if (e.getElementById(
|
|
2255
|
+
var Qt = "havik-player-styles", $t = "\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/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
|
|
2256
|
+
function en(e = document) {
|
|
2257
|
+
if (e.getElementById(Qt)) return;
|
|
2171
2258
|
let t = e.createElement("style");
|
|
2172
|
-
t.id =
|
|
2259
|
+
t.id = Qt, t.textContent = $t, e.head.appendChild(t);
|
|
2173
2260
|
}
|
|
2174
2261
|
//#endregion
|
|
2175
2262
|
//#region src/ui/icons.ts
|
|
2176
|
-
var
|
|
2263
|
+
var tn = {
|
|
2177
2264
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2178
2265
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2179
2266
|
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\"/>",
|
|
@@ -2186,21 +2273,21 @@ var Ut = {
|
|
|
2186
2273
|
liveDot: "<circle cx=\"12\" cy=\"12\" r=\"6\"/>",
|
|
2187
2274
|
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\"/>"
|
|
2188
2275
|
};
|
|
2189
|
-
function
|
|
2190
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2276
|
+
function Z(e) {
|
|
2277
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${tn[e]}</svg>`;
|
|
2191
2278
|
}
|
|
2192
2279
|
//#endregion
|
|
2193
2280
|
//#region src/ui/controls.ts
|
|
2194
|
-
var
|
|
2281
|
+
var nn = 3e3, rn = /* @__PURE__ */ new Set([
|
|
2195
2282
|
"GONE",
|
|
2196
2283
|
"NOT_FOUND",
|
|
2197
2284
|
"INVALID_URN",
|
|
2198
2285
|
"UNAUTHORIZED"
|
|
2199
2286
|
]);
|
|
2200
|
-
function
|
|
2201
|
-
return new
|
|
2287
|
+
function an(e) {
|
|
2288
|
+
return new on(e);
|
|
2202
2289
|
}
|
|
2203
|
-
var
|
|
2290
|
+
var on = class {
|
|
2204
2291
|
root;
|
|
2205
2292
|
video;
|
|
2206
2293
|
player;
|
|
@@ -2242,7 +2329,7 @@ var qt = class {
|
|
|
2242
2329
|
scrubbing = !1;
|
|
2243
2330
|
offFns = [];
|
|
2244
2331
|
constructor(e) {
|
|
2245
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2332
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? nn, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, en(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");
|
|
2246
2333
|
let t = (e, t, n) => {
|
|
2247
2334
|
let r = this.doc.createElement(e);
|
|
2248
2335
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2253,12 +2340,12 @@ var qt = class {
|
|
|
2253
2340
|
"aria-label": r,
|
|
2254
2341
|
title: r
|
|
2255
2342
|
});
|
|
2256
|
-
return i.innerHTML =
|
|
2343
|
+
return i.innerHTML = Z(n), i;
|
|
2257
2344
|
};
|
|
2258
2345
|
this.overlay = t("div", "havik-overlay"), this.center = t("button", "havik-center", {
|
|
2259
2346
|
type: "button",
|
|
2260
2347
|
"aria-label": "Play"
|
|
2261
|
-
}), this.center.innerHTML =
|
|
2348
|
+
}), this.center.innerHTML = Z("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", {
|
|
2262
2349
|
role: "slider",
|
|
2263
2350
|
"aria-label": "Seek",
|
|
2264
2351
|
"aria-valuemin": "0",
|
|
@@ -2276,7 +2363,7 @@ var qt = class {
|
|
|
2276
2363
|
"aria-label": "Volume"
|
|
2277
2364
|
});
|
|
2278
2365
|
let a = t("div", "havik-vol");
|
|
2279
|
-
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML =
|
|
2366
|
+
a.append(this.muteBtn, this.volSlider), this.live = t("div", "havik-live"), this.live.innerHTML = Z("liveDot");
|
|
2280
2367
|
let o = this.doc.createElement("span");
|
|
2281
2368
|
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";
|
|
2282
2369
|
let s = t("div", "havik-spacer");
|
|
@@ -2330,12 +2417,12 @@ var qt = class {
|
|
|
2330
2417
|
}
|
|
2331
2418
|
if (e === "preplay") {
|
|
2332
2419
|
let e = this.doc.createElement("button");
|
|
2333
|
-
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML =
|
|
2420
|
+
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Z("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
|
|
2334
2421
|
} else {
|
|
2335
2422
|
let r = this.doc.createElement("div");
|
|
2336
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2423
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !rn.has(this.lastError.code)) {
|
|
2337
2424
|
let e = this.doc.createElement("button");
|
|
2338
|
-
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${
|
|
2425
|
+
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Z("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
2339
2426
|
}
|
|
2340
2427
|
}
|
|
2341
2428
|
this.root.append(n), this.statusBox = n, this.show();
|
|
@@ -2374,7 +2461,7 @@ var qt = class {
|
|
|
2374
2461
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2375
2462
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2376
2463
|
}
|
|
2377
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2464
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Q(this.video.currentTime)} / ${Q(this.video.duration)}`);
|
|
2378
2465
|
}
|
|
2379
2466
|
syncLive() {
|
|
2380
2467
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2424,17 +2511,17 @@ var qt = class {
|
|
|
2424
2511
|
renderQualityMenu() {
|
|
2425
2512
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2426
2513
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2427
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2514
|
+
for (let n of e) this.menu.append(this.menuItem(sn(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2428
2515
|
}
|
|
2429
2516
|
renderAudioMenu() {
|
|
2430
2517
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2431
2518
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2432
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2519
|
+
for (let t of e) this.menu.append(this.menuItem(cn(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2433
2520
|
}
|
|
2434
2521
|
renderCcMenu() {
|
|
2435
2522
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2436
2523
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2437
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2524
|
+
for (let t of e) this.menu.append(this.menuItem(ln(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2438
2525
|
}
|
|
2439
2526
|
onTracksChanged() {
|
|
2440
2527
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2454,11 +2541,11 @@ var qt = class {
|
|
|
2454
2541
|
}
|
|
2455
2542
|
async toggleFullscreen() {
|
|
2456
2543
|
try {
|
|
2457
|
-
|
|
2544
|
+
x(this.video, this.root) ? await C(this.video, this.root) : await S(this.video, this.root);
|
|
2458
2545
|
} catch {}
|
|
2459
2546
|
}
|
|
2460
2547
|
syncFullscreen() {
|
|
2461
|
-
let e =
|
|
2548
|
+
let e = x(this.video, this.root);
|
|
2462
2549
|
this.setIcon(this.fsBtn, e ? "fullscreenExit" : "fullscreen"), this.fsBtn.setAttribute("aria-label", e ? "Exit fullscreen" : "Fullscreen");
|
|
2463
2550
|
}
|
|
2464
2551
|
poke() {
|
|
@@ -2517,7 +2604,7 @@ var qt = class {
|
|
|
2517
2604
|
}
|
|
2518
2605
|
}
|
|
2519
2606
|
setIcon(e, t) {
|
|
2520
|
-
e.innerHTML =
|
|
2607
|
+
e.innerHTML = Z(t);
|
|
2521
2608
|
}
|
|
2522
2609
|
destroy() {
|
|
2523
2610
|
this.hideTimer && clearTimeout(this.hideTimer);
|
|
@@ -2534,41 +2621,41 @@ var qt = class {
|
|
|
2534
2621
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2535
2622
|
}
|
|
2536
2623
|
};
|
|
2537
|
-
function
|
|
2624
|
+
function Q(e) {
|
|
2538
2625
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2539
2626
|
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");
|
|
2540
2627
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2541
2628
|
}
|
|
2542
|
-
function
|
|
2629
|
+
function sn(e) {
|
|
2543
2630
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2544
2631
|
}
|
|
2545
|
-
function
|
|
2632
|
+
function cn(e) {
|
|
2546
2633
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2547
2634
|
}
|
|
2548
|
-
function
|
|
2635
|
+
function ln(e) {
|
|
2549
2636
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2550
2637
|
}
|
|
2551
2638
|
//#endregion
|
|
2552
2639
|
//#region src/managed/index.ts
|
|
2553
|
-
var
|
|
2554
|
-
function
|
|
2640
|
+
var un = 6e3, dn = 45e3, fn = 2e3, pn = 3, mn = 2e3, hn = 48e4;
|
|
2641
|
+
function gn(e) {
|
|
2555
2642
|
if (e.env !== void 0 && e.baseUrl !== void 0) throw new n("INTERNAL", 0, `createPlayer: pass env OR baseUrl, not both (got env=${JSON.stringify(e.env)} and baseUrl=${JSON.stringify(e.baseUrl)})`);
|
|
2556
|
-
if (e.env !== void 0) return
|
|
2643
|
+
if (e.env !== void 0) return H(e.env);
|
|
2557
2644
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
2558
2645
|
return e.baseUrl;
|
|
2559
2646
|
}
|
|
2560
|
-
async function
|
|
2647
|
+
async function _n(e) {
|
|
2561
2648
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2562
|
-
let t =
|
|
2649
|
+
let t = gn(e);
|
|
2563
2650
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2564
2651
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2565
|
-
let r = new
|
|
2652
|
+
let r = new vn({
|
|
2566
2653
|
...e,
|
|
2567
2654
|
baseUrl: t
|
|
2568
2655
|
});
|
|
2569
2656
|
return await r.start(), r;
|
|
2570
2657
|
}
|
|
2571
|
-
var
|
|
2658
|
+
var vn = class {
|
|
2572
2659
|
opts;
|
|
2573
2660
|
abort = new AbortController();
|
|
2574
2661
|
listeners = {};
|
|
@@ -2612,7 +2699,7 @@ var sn = class {
|
|
|
2612
2699
|
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");
|
|
2613
2700
|
let e = ++this.loadGen, t = this.resolveOptions();
|
|
2614
2701
|
try {
|
|
2615
|
-
let n = await
|
|
2702
|
+
let n = await v(t);
|
|
2616
2703
|
if (await this.onResolved(n, e), e === this.loadGen && this._state === "error" && this._lastError) {
|
|
2617
2704
|
let e = this._lastError;
|
|
2618
2705
|
throw this.destroy(), e;
|
|
@@ -2635,11 +2722,11 @@ var sn = class {
|
|
|
2635
2722
|
};
|
|
2636
2723
|
}
|
|
2637
2724
|
beginArming(e, t, n = !1) {
|
|
2638
|
-
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ??
|
|
2725
|
+
let r = this.opts.liveStateEvents === !1 ? void 0 : this.opts.eventsBaseUrl ?? T(this.opts.baseUrl);
|
|
2639
2726
|
r ? this.armWithSse(e, r, t, n) : this.beginArmingByPolling(e);
|
|
2640
2727
|
}
|
|
2641
2728
|
beginArmingByPolling(e) {
|
|
2642
|
-
|
|
2729
|
+
y({
|
|
2643
2730
|
...this.resolveOptions(),
|
|
2644
2731
|
signal: this.abort.signal,
|
|
2645
2732
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -2656,7 +2743,7 @@ var sn = class {
|
|
|
2656
2743
|
setTimeout(() => {
|
|
2657
2744
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
2658
2745
|
phase: i ? "unavailable" : "tooEarly",
|
|
2659
|
-
retryInMs:
|
|
2746
|
+
retryInMs: dn,
|
|
2660
2747
|
attempt: 1,
|
|
2661
2748
|
elapsedMs: 0,
|
|
2662
2749
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -2673,7 +2760,7 @@ var sn = class {
|
|
|
2673
2760
|
}
|
|
2674
2761
|
}
|
|
2675
2762
|
}, h = () => {
|
|
2676
|
-
a || s || p() || (s = !0,
|
|
2763
|
+
a || s || p() || (s = !0, y({
|
|
2677
2764
|
...this.resolveOptions(),
|
|
2678
2765
|
signal: c.signal,
|
|
2679
2766
|
waitForLive: this.buildWaitConfig(e)
|
|
@@ -2681,7 +2768,7 @@ var sn = class {
|
|
|
2681
2768
|
a || p() || c.signal.aborted || (a = !0, this.closeArming(), this.fail(e instanceof n ? e : new n("INTERNAL", 0, String(e))));
|
|
2682
2769
|
}));
|
|
2683
2770
|
}, g = () => {
|
|
2684
|
-
a || p() ||
|
|
2771
|
+
a || p() || v(this.resolveOptions()).then((e) => m(e)).catch((e) => {
|
|
2685
2772
|
if (!(a || p())) {
|
|
2686
2773
|
if (e instanceof n && o(e.code)) {
|
|
2687
2774
|
h();
|
|
@@ -2695,13 +2782,13 @@ var sn = class {
|
|
|
2695
2782
|
!a && !p() && h();
|
|
2696
2783
|
}, e);
|
|
2697
2784
|
};
|
|
2698
|
-
_(
|
|
2785
|
+
_(un), this.armingSub = w({
|
|
2699
2786
|
eventsBaseUrl: t,
|
|
2700
2787
|
matchUrn: this.opts.matchUrn,
|
|
2701
2788
|
credential: this.opts.credential,
|
|
2702
|
-
onAlive: () => _(
|
|
2789
|
+
onAlive: () => _(dn),
|
|
2703
2790
|
onState: (e) => {
|
|
2704
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
2791
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * fn);
|
|
2705
2792
|
},
|
|
2706
2793
|
onError: () => h()
|
|
2707
2794
|
});
|
|
@@ -2724,7 +2811,7 @@ var sn = class {
|
|
|
2724
2811
|
let n = await s(this.opts.credential);
|
|
2725
2812
|
if (this.destroyed || t !== this.loadGen) return;
|
|
2726
2813
|
this.setState("loading");
|
|
2727
|
-
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a =
|
|
2814
|
+
let r = this.opts.autoplay === !1 && !this.playRequested, i = this.createEngine(e, n, r), a = We(this.opts.video, (e) => {
|
|
2728
2815
|
this._state !== "ended" && this._state !== "error" && this.setState(e);
|
|
2729
2816
|
});
|
|
2730
2817
|
if (await i.load(), this.destroyed || t !== this.loadGen) {
|
|
@@ -2746,23 +2833,23 @@ var sn = class {
|
|
|
2746
2833
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
2747
2834
|
let i = e.analytics?.sid;
|
|
2748
2835
|
if (!i) return;
|
|
2749
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
2836
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Vt(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
2750
2837
|
if (!o) {
|
|
2751
2838
|
s && setTimeout(() => {
|
|
2752
2839
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
2753
2840
|
}, 0);
|
|
2754
2841
|
return;
|
|
2755
2842
|
}
|
|
2756
|
-
let c = this.opts.video, l = new
|
|
2843
|
+
let c = this.opts.video, l = new Ht({
|
|
2757
2844
|
endpoint: o,
|
|
2758
2845
|
sid: i,
|
|
2759
2846
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
2760
|
-
sdkVersion:
|
|
2761
|
-
environment:
|
|
2847
|
+
sdkVersion: Jt,
|
|
2848
|
+
environment: Kt(c),
|
|
2762
2849
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
2763
2850
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
2764
2851
|
sample: () => {
|
|
2765
|
-
let e = this.engine?.getStats() ??
|
|
2852
|
+
let e = this.engine?.getStats() ?? U, t = c.buffered.length ? Math.max(0, c.buffered.end(c.buffered.length - 1) - c.currentTime) : 0;
|
|
2766
2853
|
return {
|
|
2767
2854
|
...e,
|
|
2768
2855
|
bufferedMs: Math.round(t * 1e3),
|
|
@@ -2776,7 +2863,7 @@ var sn = class {
|
|
|
2776
2863
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
2777
2864
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
2778
2865
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
2779
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
2866
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), qt().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
2780
2867
|
}
|
|
2781
2868
|
currentPresentation() {
|
|
2782
2869
|
let e = this.opts.video;
|
|
@@ -2791,7 +2878,7 @@ var sn = class {
|
|
|
2791
2878
|
video: this.opts.video,
|
|
2792
2879
|
descriptor: e,
|
|
2793
2880
|
credential: t,
|
|
2794
|
-
deviceId:
|
|
2881
|
+
deviceId: O(),
|
|
2795
2882
|
userId: this.opts.userId,
|
|
2796
2883
|
lowLatency: this.opts.lowLatency === void 0 || this.opts.lowLatency === "auto" || this.opts.lowLatency,
|
|
2797
2884
|
snapToLiveOnRefocus: this.opts.snapToLiveOnRefocus,
|
|
@@ -2801,11 +2888,11 @@ var sn = class {
|
|
|
2801
2888
|
hlsConfig: i,
|
|
2802
2889
|
emit: (e) => this.onEngineEvent(e)
|
|
2803
2890
|
}, o = this.opts.engine ?? "auto";
|
|
2804
|
-
if (o === "native") return new
|
|
2805
|
-
if (o === "hls") return new
|
|
2806
|
-
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl &&
|
|
2807
|
-
if (
|
|
2808
|
-
if (
|
|
2891
|
+
if (o === "native") return new J(a);
|
|
2892
|
+
if (o === "hls") return new Et(a);
|
|
2893
|
+
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && K(this.opts.video) && q()) return new J(a);
|
|
2894
|
+
if (nt()) return new Et(a);
|
|
2895
|
+
if (K(this.opts.video)) return new J(a);
|
|
2809
2896
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
2810
2897
|
}
|
|
2811
2898
|
onEngineEvent(e) {
|
|
@@ -2842,11 +2929,11 @@ var sn = class {
|
|
|
2842
2929
|
}
|
|
2843
2930
|
startLiveState(e) {
|
|
2844
2931
|
if (this.opts.liveStateEvents === !1) return;
|
|
2845
|
-
let t = this.opts.eventsBaseUrl ??
|
|
2932
|
+
let t = this.opts.eventsBaseUrl ?? T(this.opts.baseUrl);
|
|
2846
2933
|
if (!t) return;
|
|
2847
2934
|
this.closeLiveState();
|
|
2848
2935
|
let r = 0, i = !1;
|
|
2849
|
-
this.liveStateSub =
|
|
2936
|
+
this.liveStateSub = w({
|
|
2850
2937
|
eventsBaseUrl: t,
|
|
2851
2938
|
matchUrn: this.opts.matchUrn,
|
|
2852
2939
|
credential: this.opts.credential,
|
|
@@ -2857,7 +2944,7 @@ var sn = class {
|
|
|
2857
2944
|
r = 0, i = !1;
|
|
2858
2945
|
},
|
|
2859
2946
|
onError: () => {
|
|
2860
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
2947
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= pn && (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.`))));
|
|
2861
2948
|
}
|
|
2862
2949
|
});
|
|
2863
2950
|
}
|
|
@@ -2879,7 +2966,7 @@ var sn = class {
|
|
|
2879
2966
|
scheduleRejoin(e) {
|
|
2880
2967
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
2881
2968
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
2882
|
-
}, Math.random() *
|
|
2969
|
+
}, Math.random() * fn));
|
|
2883
2970
|
}
|
|
2884
2971
|
cancelRejoin() {
|
|
2885
2972
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -2903,7 +2990,7 @@ var sn = class {
|
|
|
2903
2990
|
}
|
|
2904
2991
|
t.controls = !1;
|
|
2905
2992
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
2906
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
2993
|
+
r && r.insertBefore(n, t), n.appendChild(t), Zt(n, this.opts.theme), this.container = n, this.controlBar = an({
|
|
2907
2994
|
root: n,
|
|
2908
2995
|
video: t,
|
|
2909
2996
|
player: this,
|
|
@@ -2933,7 +3020,7 @@ var sn = class {
|
|
|
2933
3020
|
}
|
|
2934
3021
|
startStats() {
|
|
2935
3022
|
this.stopStats();
|
|
2936
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3023
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? mn);
|
|
2937
3024
|
this.statsTimer = setInterval(() => {
|
|
2938
3025
|
if (!this.engine) return;
|
|
2939
3026
|
let e = this.engine.getStats();
|
|
@@ -2945,7 +3032,7 @@ var sn = class {
|
|
|
2945
3032
|
}
|
|
2946
3033
|
scheduleLicenseRefresh() {
|
|
2947
3034
|
this.stopRefresh();
|
|
2948
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3035
|
+
let e = this.opts.licenseRefreshMs ?? hn;
|
|
2949
3036
|
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
2950
3037
|
}
|
|
2951
3038
|
stopRefresh() {
|
|
@@ -2954,7 +3041,7 @@ var sn = class {
|
|
|
2954
3041
|
async refreshLicense() {
|
|
2955
3042
|
let e = this.engine;
|
|
2956
3043
|
if (!this.destroyed && e) try {
|
|
2957
|
-
let t = await
|
|
3044
|
+
let t = await v(this.resolveOptions());
|
|
2958
3045
|
if (this.destroyed || this.engine !== e) return;
|
|
2959
3046
|
let n = t.drm?.widevine?.licenseUrl, r = t.drm?.fairplay?.licenseUrl;
|
|
2960
3047
|
(n || r) && (e.setLicenseUrls({
|
|
@@ -2990,7 +3077,7 @@ var sn = class {
|
|
|
2990
3077
|
this.destroyed || (this.opts.video.volume = Math.min(1, Math.max(0, e)));
|
|
2991
3078
|
}
|
|
2992
3079
|
getStats() {
|
|
2993
|
-
return this.engine?.getStats() ??
|
|
3080
|
+
return this.engine?.getStats() ?? U;
|
|
2994
3081
|
}
|
|
2995
3082
|
getQualityLevels() {
|
|
2996
3083
|
return this.engine?.getQualityLevels() ?? [];
|
|
@@ -3029,10 +3116,10 @@ var sn = class {
|
|
|
3029
3116
|
e.pictureInPictureElement === this.opts.video && typeof e.exitPictureInPicture == "function" && await e.exitPictureInPicture();
|
|
3030
3117
|
}
|
|
3031
3118
|
async enterFullscreen() {
|
|
3032
|
-
return !this.destroyed &&
|
|
3119
|
+
return !this.destroyed && S(this.opts.video, this.container ?? void 0);
|
|
3033
3120
|
}
|
|
3034
3121
|
async exitFullscreen() {
|
|
3035
|
-
await
|
|
3122
|
+
await C(this.opts.video, this.container ?? void 0);
|
|
3036
3123
|
}
|
|
3037
3124
|
retry() {
|
|
3038
3125
|
return this.reload();
|
|
@@ -3042,7 +3129,7 @@ var sn = class {
|
|
|
3042
3129
|
let e = ++this.loadGen;
|
|
3043
3130
|
this.teardownPlayback();
|
|
3044
3131
|
try {
|
|
3045
|
-
let t = await
|
|
3132
|
+
let t = await y({
|
|
3046
3133
|
...this.resolveOptions(),
|
|
3047
3134
|
waitForLive: this.opts.waitForLive ? this.buildWaitConfig(e) : void 0
|
|
3048
3135
|
});
|
|
@@ -3100,7 +3187,7 @@ function $(e) {
|
|
|
3100
3187
|
}
|
|
3101
3188
|
//#endregion
|
|
3102
3189
|
//#region src/embed/host.ts
|
|
3103
|
-
function
|
|
3190
|
+
function yn(e) {
|
|
3104
3191
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3105
3192
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3106
3193
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3159,15 +3246,15 @@ function cn(e) {
|
|
|
3159
3246
|
}
|
|
3160
3247
|
//#endregion
|
|
3161
3248
|
//#region src/embed/page.ts
|
|
3162
|
-
var
|
|
3163
|
-
function
|
|
3249
|
+
var bn = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3250
|
+
function xn(e) {
|
|
3164
3251
|
if (typeof e == "boolean") return e;
|
|
3165
3252
|
if (typeof e == "object" && e) {
|
|
3166
3253
|
let t = e.endpoint;
|
|
3167
3254
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3168
3255
|
}
|
|
3169
3256
|
}
|
|
3170
|
-
function
|
|
3257
|
+
function Sn() {
|
|
3171
3258
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3172
3259
|
if (e) return {
|
|
3173
3260
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3177,7 +3264,7 @@ function dn() {
|
|
|
3177
3264
|
autoplay: e.autoplay ?? !0,
|
|
3178
3265
|
muted: e.muted ?? !0,
|
|
3179
3266
|
waitForLive: e.waitForLive ?? !0,
|
|
3180
|
-
analytics:
|
|
3267
|
+
analytics: xn(e.analytics)
|
|
3181
3268
|
};
|
|
3182
3269
|
let t = new URLSearchParams(location.search);
|
|
3183
3270
|
return {
|
|
@@ -3190,9 +3277,9 @@ function dn() {
|
|
|
3190
3277
|
waitForLive: !0
|
|
3191
3278
|
};
|
|
3192
3279
|
}
|
|
3193
|
-
async function
|
|
3194
|
-
let e =
|
|
3195
|
-
|
|
3280
|
+
async function Cn() {
|
|
3281
|
+
let e = Sn();
|
|
3282
|
+
Tn();
|
|
3196
3283
|
let t = document.createElement("video");
|
|
3197
3284
|
t.setAttribute("playsinline", ""), t.muted = e.muted ?? !0, t.style.cssText = "width:100%;height:100%;object-fit:contain;background:#000;aspect-ratio:auto", document.body.appendChild(t);
|
|
3198
3285
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3247,12 +3334,12 @@ async function fn() {
|
|
|
3247
3334
|
code: e.code,
|
|
3248
3335
|
message: e.message
|
|
3249
3336
|
})), e.on("autoplayblocked", () => {
|
|
3250
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3337
|
+
i({ type: "oddin:autoplayblocked" }), wn(t, e);
|
|
3251
3338
|
});
|
|
3252
3339
|
}, s = async (r) => {
|
|
3253
3340
|
a?.destroy(), a = null;
|
|
3254
3341
|
try {
|
|
3255
|
-
let n = await
|
|
3342
|
+
let n = await _n({
|
|
3256
3343
|
video: t,
|
|
3257
3344
|
baseUrl: e.baseUrl,
|
|
3258
3345
|
matchUrn: r,
|
|
@@ -3314,7 +3401,7 @@ async function fn() {
|
|
|
3314
3401
|
a?.retry();
|
|
3315
3402
|
break;
|
|
3316
3403
|
case "oddin:load":
|
|
3317
|
-
typeof e.matchUrn == "string" &&
|
|
3404
|
+
typeof e.matchUrn == "string" && bn.test(e.matchUrn) && s(e.matchUrn);
|
|
3318
3405
|
break;
|
|
3319
3406
|
case "oddin:destroy": c();
|
|
3320
3407
|
}
|
|
@@ -3326,18 +3413,18 @@ async function fn() {
|
|
|
3326
3413
|
protocol: 1
|
|
3327
3414
|
});
|
|
3328
3415
|
}
|
|
3329
|
-
function
|
|
3416
|
+
function wn(e, t) {
|
|
3330
3417
|
if (document.getElementById("havik-tap")) return;
|
|
3331
3418
|
let n = document.createElement("button");
|
|
3332
3419
|
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", () => {
|
|
3333
3420
|
n.remove(), t.play();
|
|
3334
3421
|
}), document.body.appendChild(n);
|
|
3335
3422
|
}
|
|
3336
|
-
function
|
|
3423
|
+
function Tn() {
|
|
3337
3424
|
let e = document.createElement("style");
|
|
3338
3425
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
3339
3426
|
}
|
|
3340
3427
|
//#endregion
|
|
3341
|
-
export {
|
|
3428
|
+
export { Yt as ODDIN_THEME, n as PlaybackError, Zt as applyTheme, H as baseUrlForEnv, Cn as bootEmbed, Te as clearDeviceId, _n as createPlayer, T as deriveEventsBaseUrl, ze as detectDrmSupport, S as enterVideoFullscreen, C as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, O as getDeviceId, Ve as isLowLatencyManifest, $ as isOddinMessage, De as licenseRequestHeaders, yn as mountEmbed, de as pollToLive, y as resolveStream, w as subscribeLiveState, x as videoFullscreenActive, Ce as watchStatus };
|
|
3342
3429
|
|
|
3343
3430
|
//# sourceMappingURL=index.js.map
|