@oddin-gg/havik-player 2.22.0 → 2.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/havik-player.global.js +2 -2
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +121 -113
- package/dist/index.js.map +1 -1
- package/docs/API.md +3 -1
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1494,21 +1494,21 @@ function pn(e, t, n) {
|
|
|
1494
1494
|
for (let t = 0; t < n && a + 1 < e.length; t++) a = i(a + 1);
|
|
1495
1495
|
return a;
|
|
1496
1496
|
}
|
|
1497
|
-
var mn = .2, hn = 30, gn = 2, _n = 2, vn =
|
|
1498
|
-
function
|
|
1497
|
+
var mn = .2, hn = 30, gn = 2, _n = 2, vn = 2, yn = 9, bn = .5, xn = 64;
|
|
1498
|
+
function Sn(e) {
|
|
1499
1499
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
1500
1500
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
1501
1501
|
return;
|
|
1502
1502
|
}
|
|
1503
|
-
e.liveSyncDuration ??=
|
|
1504
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
1505
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
1503
|
+
e.liveSyncDuration ??= vn;
|
|
1504
|
+
let t = Math.max(12, e.liveSyncDuration + yn);
|
|
1505
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), Cn(e, e.liveSyncDuration);
|
|
1506
1506
|
}
|
|
1507
|
-
function
|
|
1507
|
+
function Cn(e, t) {
|
|
1508
1508
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
1509
1509
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
1510
1510
|
}
|
|
1511
|
-
var
|
|
1511
|
+
var wn = class {
|
|
1512
1512
|
name = "hls";
|
|
1513
1513
|
hls = null;
|
|
1514
1514
|
deps;
|
|
@@ -1584,6 +1584,7 @@ var Cn = class {
|
|
|
1584
1584
|
fpsLastFrames = -1;
|
|
1585
1585
|
fpsLastDropped = -1;
|
|
1586
1586
|
fpsBadTicks = 0;
|
|
1587
|
+
fpsGraceTicks = 0;
|
|
1587
1588
|
fpsDownCaps = 0;
|
|
1588
1589
|
sizeCapManaged = !0;
|
|
1589
1590
|
dprMedia = null;
|
|
@@ -1660,7 +1661,7 @@ var Cn = class {
|
|
|
1660
1661
|
let t = e.liveSyncPosition;
|
|
1661
1662
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1662
1663
|
let { video: n } = this.deps;
|
|
1663
|
-
n.currentTime <= t +
|
|
1664
|
+
n.currentTime <= t + bn || (n.currentTime = t);
|
|
1664
1665
|
}
|
|
1665
1666
|
reanchorPartTimeline(e, t) {
|
|
1666
1667
|
let { frag: n, part: r } = t;
|
|
@@ -1734,7 +1735,7 @@ var Cn = class {
|
|
|
1734
1735
|
}), t = Mt(e);
|
|
1735
1736
|
t && (this.prefetch = e, f.fLoader = t);
|
|
1736
1737
|
}
|
|
1737
|
-
|
|
1738
|
+
Sn(f), this.catchUpRate = typeof f.maxLiveSyncPlaybackRate == "number" ? f.maxLiveSyncPlaybackRate : 1, this.catchUpEngaged = !1, this.catchUpRate > 1 && (f.maxLiveSyncPlaybackRate = 1), this.sizeCapManaged = f.capLevelToPlayerSize !== !0, this.fpsCapManaged = !(c && "capLevelOnFPSDrop" in c), this.loadStarted = f.autoStartLoad !== !1;
|
|
1738
1739
|
let p = new e(f);
|
|
1739
1740
|
if (this.hls = p, p.on(e.Events.FRAG_PARSED, (e, t) => this.reanchorPartTimeline(p, t)), p.on(e.Events.MANIFEST_PARSED, () => {
|
|
1740
1741
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, u && !this.deps.hlsConfig?.requestMediaKeySystemAccessFunc && this.dropLevelsWidevineCannotPlay(p), this.measureLadder(p), this.applySizeCap(), this.loadSuspended = !1, t.paused && this.schedulePauseSuspend(), l({ type: "ready" });
|
|
@@ -1749,7 +1750,7 @@ var Cn = class {
|
|
|
1749
1750
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1750
1751
|
typeof r == "number" && (this.bytesLoaded += r), !this.reportedFirstBytes && typeof r == "number" && r > 0 && (this.reportedFirstBytes = !0, l({ type: "firstBytes" }));
|
|
1751
1752
|
let i = n?.loading;
|
|
1752
|
-
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 >
|
|
1753
|
+
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 > xn && this.requestTimesMs.shift());
|
|
1753
1754
|
let a = t?.frag?.url;
|
|
1754
1755
|
if (a) {
|
|
1755
1756
|
let e = ot(a);
|
|
@@ -1777,7 +1778,7 @@ var Cn = class {
|
|
|
1777
1778
|
}, Kt), p.on(e.Events.LEVEL_SWITCHED, (e, t) => {
|
|
1778
1779
|
this.renditionSwitches += 1;
|
|
1779
1780
|
let n = this.lastLevelIndex >= 0 ? p.levels[this.lastLevelIndex] : void 0, r = p.levels[t.level];
|
|
1780
|
-
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, l({
|
|
1781
|
+
n && r && r.bitrate !== n.bitrate && (r.bitrate > n.bitrate ? this.upshifts += 1 : this.downshifts += 1), this.lastLevelIndex = t.level, this.armFrameDropGrace(), l({
|
|
1781
1782
|
type: "qualitychange",
|
|
1782
1783
|
index: t.level
|
|
1783
1784
|
});
|
|
@@ -2027,6 +2028,9 @@ var Cn = class {
|
|
|
2027
2028
|
e.bitrate <= this.fpsCapBitrate && i && (n = r);
|
|
2028
2029
|
}), n < 0 ? 0 : n;
|
|
2029
2030
|
}
|
|
2031
|
+
armFrameDropGrace() {
|
|
2032
|
+
this.fpsGraceTicks > 0 || (this.fpsGraceTicks = _n, this.fpsBadTicks = 0);
|
|
2033
|
+
}
|
|
2030
2034
|
resetFrameDropWindow() {
|
|
2031
2035
|
this.fpsLastFrames = -1, this.fpsLastDropped = -1, this.fpsBadTicks = 0;
|
|
2032
2036
|
}
|
|
@@ -2041,6 +2045,10 @@ var Cn = class {
|
|
|
2041
2045
|
this.fpsBadTicks = 0;
|
|
2042
2046
|
return;
|
|
2043
2047
|
}
|
|
2048
|
+
if (this.fpsGraceTicks > 0) {
|
|
2049
|
+
--this.fpsGraceTicks, this.fpsBadTicks = 0;
|
|
2050
|
+
return;
|
|
2051
|
+
}
|
|
2044
2052
|
if (o <= mn * a) {
|
|
2045
2053
|
this.fpsBadTicks = 0;
|
|
2046
2054
|
return;
|
|
@@ -2144,7 +2152,7 @@ var Cn = class {
|
|
|
2144
2152
|
} catch (t) {
|
|
2145
2153
|
console.warn(`havik-player: hls.js destroy() threw during ${e}`, t);
|
|
2146
2154
|
}
|
|
2147
|
-
this.hls = null, this.startHls();
|
|
2155
|
+
this.hls = null, this.startHls(), this.armFrameDropGrace();
|
|
2148
2156
|
}
|
|
2149
2157
|
}
|
|
2150
2158
|
onError(t) {
|
|
@@ -2203,19 +2211,19 @@ var Cn = class {
|
|
|
2203
2211
|
let o = t.response?.code ?? 0, s = t.details ?? t.type, c = t.reason ?? t.error?.message ?? "", l = r === "DRM" && o === 403 && t.details === e.ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED ? i(Et(t.networkDetails)) : void 0;
|
|
2204
2212
|
return new n(r === "DRM" ? a(o, l) : o === 401 ? "UNAUTHORIZED" : o === 403 ? "FORBIDDEN" : "INTERNAL", o, `${r} error: ${s}${c ? ` (${c})` : ""}`, l ? { serverCode: l } : void 0);
|
|
2205
2213
|
}
|
|
2206
|
-
},
|
|
2214
|
+
}, Tn = 15e3, En = 6e5, Dn = 3e5, On = 100, q = 1, kn = 1e3, An = 3e4, jn = 1e3, Mn = {
|
|
2207
2215
|
inline: "PRESENTATION_INLINE",
|
|
2208
2216
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
2209
2217
|
pip: "PRESENTATION_PIP"
|
|
2210
|
-
},
|
|
2218
|
+
}, Nn = {
|
|
2211
2219
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
2212
2220
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
2213
2221
|
none: "KEY_SYSTEM_NONE"
|
|
2214
2222
|
};
|
|
2215
|
-
function
|
|
2223
|
+
function Pn(e, t) {
|
|
2216
2224
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
2217
2225
|
}
|
|
2218
|
-
var
|
|
2226
|
+
var Fn = /* @__PURE__ */ new Set([
|
|
2219
2227
|
"INVALID_URN",
|
|
2220
2228
|
"NOT_FOUND",
|
|
2221
2229
|
"GEO_DENIED",
|
|
@@ -2236,7 +2244,7 @@ var Pn = /* @__PURE__ */ new Set([
|
|
|
2236
2244
|
ended: "PLAYER_STATE_ENDED",
|
|
2237
2245
|
error: "PLAYER_STATE_ERROR"
|
|
2238
2246
|
};
|
|
2239
|
-
function
|
|
2247
|
+
function In(e) {
|
|
2240
2248
|
try {
|
|
2241
2249
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
2242
2250
|
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);
|
|
@@ -2244,8 +2252,8 @@ function Fn(e) {
|
|
|
2244
2252
|
return;
|
|
2245
2253
|
}
|
|
2246
2254
|
}
|
|
2247
|
-
var
|
|
2248
|
-
function
|
|
2255
|
+
var Ln = (e, t) => e.replace(/\/$/, "").toLowerCase() === t.replace(/\/$/, "").toLowerCase(), Rn = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), X = /* @__PURE__ */ new Set(), zn = (e) => `this page's Content-Security-Policy blocks QoE beacons. Add ${e} to connect-src; until then none are sent.`;
|
|
2256
|
+
function Bn(e) {
|
|
2249
2257
|
if (e.disposition !== "enforce" || e.effectiveDirective !== "connect-src") return;
|
|
2250
2258
|
let t;
|
|
2251
2259
|
try {
|
|
@@ -2254,19 +2262,19 @@ function zn(e) {
|
|
|
2254
2262
|
} catch {
|
|
2255
2263
|
return;
|
|
2256
2264
|
}
|
|
2257
|
-
if (
|
|
2258
|
-
Y.add(t), _(
|
|
2265
|
+
if (Rn.has(t) && !Y.has(t)) {
|
|
2266
|
+
Y.add(t), _(zn(new URL(t).origin));
|
|
2259
2267
|
for (let e of X) e.noteCspBlocked();
|
|
2260
2268
|
}
|
|
2261
2269
|
}
|
|
2262
2270
|
function Z(e, t) {
|
|
2263
2271
|
return _(t, e), { disabledReason: t };
|
|
2264
2272
|
}
|
|
2265
|
-
function
|
|
2266
|
-
if (n) return t && !
|
|
2273
|
+
function Vn(e, t, n) {
|
|
2274
|
+
if (n) return t && !Ln(t, n) && _(`analytics.endpoint "${t}" ignored; the server named "${n}".`), { endpoint: n };
|
|
2267
2275
|
if (t) return { endpoint: t };
|
|
2268
2276
|
if (t !== void 0) return Z("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).");
|
|
2269
|
-
let r =
|
|
2277
|
+
let r = In(e);
|
|
2270
2278
|
if (r) return { endpoint: r };
|
|
2271
2279
|
let i;
|
|
2272
2280
|
try {
|
|
@@ -2276,7 +2284,7 @@ function Bn(e, t, n) {
|
|
|
2276
2284
|
}
|
|
2277
2285
|
return Z(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).`);
|
|
2278
2286
|
}
|
|
2279
|
-
var
|
|
2287
|
+
var Hn = class {
|
|
2280
2288
|
opts;
|
|
2281
2289
|
url;
|
|
2282
2290
|
cspKey;
|
|
@@ -2358,8 +2366,8 @@ var Vn = class {
|
|
|
2358
2366
|
constructor(e) {
|
|
2359
2367
|
this.opts = {
|
|
2360
2368
|
...e,
|
|
2361
|
-
heartbeatMs: e.heartbeatMs ??
|
|
2362
|
-
idleMs: e.idleMs ??
|
|
2369
|
+
heartbeatMs: e.heartbeatMs ?? Tn,
|
|
2370
|
+
idleMs: e.idleMs ?? En
|
|
2363
2371
|
}, this.url = `${e.endpoint.replace(/\/$/, "")}/v1/beacons`;
|
|
2364
2372
|
try {
|
|
2365
2373
|
let e = new URL(this.url);
|
|
@@ -2376,11 +2384,11 @@ var Vn = class {
|
|
|
2376
2384
|
sdkVersion: this.opts.sdkVersion,
|
|
2377
2385
|
...this.opts.environment
|
|
2378
2386
|
};
|
|
2379
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
2387
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), kn), this.lastTickMs = this.now(), this.timer = setInterval(() => this.heartbeat(), this.opts.heartbeatMs), typeof window < "u" && window.addEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.addEventListener("visibilitychange", this.onVisibility), document.addEventListener("freeze", this.onFreeze), document.addEventListener("resume", this.onResume), this.cspKey && Rn.add(this.cspKey), document.addEventListener("securitypolicyviolation", Bn), X.add(this), this.noteCspBlocked(), this.onVisibility());
|
|
2380
2388
|
}
|
|
2381
2389
|
checkSuspension(e) {
|
|
2382
2390
|
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
2383
|
-
let t = Math.max(this.opts.idleMs,
|
|
2391
|
+
let t = Math.max(this.opts.idleMs, Dn);
|
|
2384
2392
|
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
2385
2393
|
}
|
|
2386
2394
|
syncIdle(e) {
|
|
@@ -2403,12 +2411,12 @@ var Vn = class {
|
|
|
2403
2411
|
let a = {
|
|
2404
2412
|
fromState: J[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2405
2413
|
toState: J[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
2406
|
-
presentation:
|
|
2414
|
+
presentation: Mn[this.presentation]
|
|
2407
2415
|
}, o = this.causeOf(e, t, i);
|
|
2408
2416
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
2409
2417
|
}
|
|
2410
2418
|
seekInduced(e) {
|
|
2411
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
2419
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < jn;
|
|
2412
2420
|
}
|
|
2413
2421
|
causeOf(e, t, n) {
|
|
2414
2422
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
@@ -2482,7 +2490,7 @@ var Vn = class {
|
|
|
2482
2490
|
let r = n ?? "";
|
|
2483
2491
|
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";
|
|
2484
2492
|
if (e === "DRM_CLIENT" || e === "DRM_DEVICE_REVOKED") return "ERROR_STAGE_DRM";
|
|
2485
|
-
if (
|
|
2493
|
+
if (Fn.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
2486
2494
|
let i = t ?? "";
|
|
2487
2495
|
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";
|
|
2488
2496
|
}
|
|
@@ -2529,14 +2537,14 @@ var Vn = class {
|
|
|
2529
2537
|
if (this.lastRequestCount = g, _ > 0) {
|
|
2530
2538
|
o.requestCountDelta = _;
|
|
2531
2539
|
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
2532
|
-
n.length > 0 && (o.requestTimeP50Ms =
|
|
2540
|
+
n.length > 0 && (o.requestTimeP50Ms = Pn(n, 50), o.requestTimeP95Ms = Pn(n, 95));
|
|
2533
2541
|
}
|
|
2534
2542
|
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();
|
|
2535
2543
|
}
|
|
2536
2544
|
maybeEmitMediaInfo(e) {
|
|
2537
2545
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
2538
2546
|
let t = {};
|
|
2539
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
2547
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = Nn[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);
|
|
2540
2548
|
let n = JSON.stringify(t);
|
|
2541
2549
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
2542
2550
|
}
|
|
@@ -2556,7 +2564,7 @@ var Vn = class {
|
|
|
2556
2564
|
let c = r?.positionMs ?? 0;
|
|
2557
2565
|
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));
|
|
2558
2566
|
let l = e !== "END_REASON_ENDED";
|
|
2559
|
-
l && this.lastStallMs > 0 && n - this.lastStallMs <=
|
|
2567
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= An && (i.abandonAfterStallMs = Math.max(q, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= An && (i.abandonAfterErrorMs = Math.max(q, Math.round(n - this.lastErrorMs))), this.fullscreenTotalMs > 0 && (i.fullscreenTimeMs = Math.round(this.fullscreenTotalMs)), this.pipTotalMs > 0 && (i.pipTimeMs = Math.round(this.pipTotalMs)), this.volumeChanges > 0 && (i.volumeChanges = this.volumeChanges), this.muteChanges > 0 && (i.muteChanges = this.muteChanges);
|
|
2560
2568
|
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
2561
2569
|
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");
|
|
2562
2570
|
}
|
|
@@ -2576,13 +2584,13 @@ var Vn = class {
|
|
|
2576
2584
|
};
|
|
2577
2585
|
}
|
|
2578
2586
|
noteCspBlocked() {
|
|
2579
|
-
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(
|
|
2587
|
+
this.cspBlockedNoted || this.endedFlag || !this.cspBlocked() || (this.cspBlockedNoted = !0, this.opts.onBlocked?.(zn(new URL(this.url).origin)));
|
|
2580
2588
|
}
|
|
2581
2589
|
cspBlocked() {
|
|
2582
2590
|
return !!this.cspKey && Y.has(this.cspKey);
|
|
2583
2591
|
}
|
|
2584
2592
|
enqueue(e) {
|
|
2585
|
-
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
2593
|
+
if (!this.cspBlocked()) for (this.pending.push(this.wrap(e)); this.pending.length > On;) {
|
|
2586
2594
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
2587
2595
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
2588
2596
|
}
|
|
@@ -2609,7 +2617,7 @@ var Vn = class {
|
|
|
2609
2617
|
};
|
|
2610
2618
|
//#endregion
|
|
2611
2619
|
//#region src/core/environment.ts
|
|
2612
|
-
function
|
|
2620
|
+
function Un() {
|
|
2613
2621
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
2614
2622
|
let e;
|
|
2615
2623
|
try {
|
|
@@ -2634,14 +2642,14 @@ function Hn() {
|
|
|
2634
2642
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
2635
2643
|
};
|
|
2636
2644
|
}
|
|
2637
|
-
function
|
|
2645
|
+
function Wn() {
|
|
2638
2646
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
2639
2647
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
2640
2648
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
2641
2649
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
2642
2650
|
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";
|
|
2643
2651
|
}
|
|
2644
|
-
function
|
|
2652
|
+
function Gn() {
|
|
2645
2653
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
2646
2654
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
2647
2655
|
let t = {
|
|
@@ -2660,17 +2668,17 @@ function Wn() {
|
|
|
2660
2668
|
}
|
|
2661
2669
|
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;
|
|
2662
2670
|
}
|
|
2663
|
-
function
|
|
2664
|
-
let t =
|
|
2665
|
-
deviceClass:
|
|
2671
|
+
function Kn(e) {
|
|
2672
|
+
let t = Un(), n = {
|
|
2673
|
+
deviceClass: Wn(),
|
|
2666
2674
|
integration: t.integration,
|
|
2667
|
-
...
|
|
2675
|
+
...Gn()
|
|
2668
2676
|
};
|
|
2669
2677
|
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);
|
|
2670
2678
|
let r = e.getBoundingClientRect?.();
|
|
2671
2679
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
2672
2680
|
}
|
|
2673
|
-
async function
|
|
2681
|
+
async function qn() {
|
|
2674
2682
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
2675
2683
|
if (!e?.getHighEntropyValues) return {};
|
|
2676
2684
|
try {
|
|
@@ -2682,7 +2690,7 @@ async function Kn() {
|
|
|
2682
2690
|
}
|
|
2683
2691
|
//#endregion
|
|
2684
2692
|
//#region src/core/version.ts
|
|
2685
|
-
var
|
|
2693
|
+
var Jn = "2.22.1", Yn = {
|
|
2686
2694
|
accent: "#E1B600",
|
|
2687
2695
|
accentText: "#1B1C23",
|
|
2688
2696
|
background: "#0e0f13",
|
|
@@ -2693,7 +2701,7 @@ var qn = "2.22.0", Jn = {
|
|
|
2693
2701
|
border: "rgba(255, 255, 255, 0.1)",
|
|
2694
2702
|
radius: "8px",
|
|
2695
2703
|
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
|
|
2696
|
-
},
|
|
2704
|
+
}, Xn = {
|
|
2697
2705
|
accent: "--havik-accent",
|
|
2698
2706
|
accentText: "--havik-accent-text",
|
|
2699
2707
|
background: "--havik-bg",
|
|
@@ -2705,26 +2713,26 @@ var qn = "2.22.0", Jn = {
|
|
|
2705
2713
|
radius: "--havik-radius",
|
|
2706
2714
|
fontFamily: "--havik-font"
|
|
2707
2715
|
};
|
|
2708
|
-
function
|
|
2716
|
+
function Zn(e, t) {
|
|
2709
2717
|
let n = {
|
|
2710
|
-
...
|
|
2718
|
+
...Yn,
|
|
2711
2719
|
...t
|
|
2712
2720
|
};
|
|
2713
|
-
for (let t of Object.keys(
|
|
2721
|
+
for (let t of Object.keys(Xn)) e.style.setProperty(Xn[t], n[t]);
|
|
2714
2722
|
n.logoUrl && e.style.setProperty("--havik-logo", `url("${n.logoUrl}")`);
|
|
2715
2723
|
}
|
|
2716
2724
|
//#endregion
|
|
2717
2725
|
//#region src/ui/styles.ts
|
|
2718
|
-
var
|
|
2719
|
-
function
|
|
2720
|
-
let n = e.querySelector(`style#${
|
|
2721
|
-
if (n && (!t ||
|
|
2726
|
+
var Qn = "havik-player-styles", $n = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer;\n touch-action:manipulation}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n/* Absolutely centred, NOT a flex sibling of .havik-center: the hidden center\n button (.havik-gone) still occupies its 74px in the row, which pushed an\n in-flow spinner 37px right of centre. */\n.havik-spinner{position:absolute;inset:0;margin:auto;width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n", er = /* @__PURE__ */ new WeakMap();
|
|
2727
|
+
function tr(e = document, t) {
|
|
2728
|
+
let n = e.querySelector(`style#${Qn}`);
|
|
2729
|
+
if (n && (!t || er.get(n) === t)) return;
|
|
2722
2730
|
let r = e.createElement("style");
|
|
2723
|
-
r.id =
|
|
2731
|
+
r.id = Qn, t && (r.nonce = t, r.setAttribute("nonce", t)), r.textContent = $n, er.set(r, t), n ? n.replaceWith(r) : e.head.appendChild(r);
|
|
2724
2732
|
}
|
|
2725
2733
|
//#endregion
|
|
2726
2734
|
//#region src/ui/icons.ts
|
|
2727
|
-
var
|
|
2735
|
+
var nr = {
|
|
2728
2736
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
2729
2737
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
2730
2738
|
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\"/>",
|
|
@@ -2738,11 +2746,11 @@ var tr = {
|
|
|
2738
2746
|
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\"/>"
|
|
2739
2747
|
};
|
|
2740
2748
|
function Q(e) {
|
|
2741
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
2749
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${nr[e]}</svg>`;
|
|
2742
2750
|
}
|
|
2743
2751
|
//#endregion
|
|
2744
2752
|
//#region src/ui/controls.ts
|
|
2745
|
-
var
|
|
2753
|
+
var rr = 3e3, ir = 250, ar = /* @__PURE__ */ new Set([
|
|
2746
2754
|
"GONE",
|
|
2747
2755
|
"NOT_FOUND",
|
|
2748
2756
|
"GEO_DENIED",
|
|
@@ -2750,15 +2758,15 @@ var nr = 3e3, rr = 250, ir = /* @__PURE__ */ new Set([
|
|
|
2750
2758
|
"UNAUTHORIZED",
|
|
2751
2759
|
"DRM_DEVICE_REVOKED"
|
|
2752
2760
|
]);
|
|
2753
|
-
function
|
|
2761
|
+
function or(e) {
|
|
2754
2762
|
let t = "This match isn't available in your country";
|
|
2755
2763
|
return e ? `${t} (${e})` : t;
|
|
2756
2764
|
}
|
|
2757
|
-
var
|
|
2758
|
-
function
|
|
2759
|
-
return new
|
|
2765
|
+
var sr = "This device can't play protected video";
|
|
2766
|
+
function cr(e) {
|
|
2767
|
+
return new lr(e);
|
|
2760
2768
|
}
|
|
2761
|
-
var
|
|
2769
|
+
var lr = class {
|
|
2762
2770
|
root;
|
|
2763
2771
|
video;
|
|
2764
2772
|
player;
|
|
@@ -2806,7 +2814,7 @@ var cr = class {
|
|
|
2806
2814
|
scrubbing = !1;
|
|
2807
2815
|
offFns = [];
|
|
2808
2816
|
constructor(e) {
|
|
2809
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
2817
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? rr, this.logoUrl = e.logoUrl, this.statusOverlays = e.statusOverlays !== !1, this.streamEnded = e.streamEnded ?? (() => !1), this.endedMessage = e.endedMessage ?? "This stream has ended", this.interruptedMessage = e.interruptedMessage ?? "Reconnecting — please stand by", this.errorMessage = e.errorMessage, tr(this.doc, e.cspNonce), this.root.classList.add("havik-player"), this.root.hasAttribute("tabindex") || (this.root.tabIndex = 0), this.root.setAttribute("role", "region"), this.root.setAttribute("aria-label", "Video player");
|
|
2810
2818
|
let t = (e, t, n) => {
|
|
2811
2819
|
let r = this.doc.createElement(e);
|
|
2812
2820
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -2892,7 +2900,7 @@ var cr = class {
|
|
|
2892
2900
|
let t = this.surfaceWasHidden;
|
|
2893
2901
|
this.tapTimer = setTimeout(() => {
|
|
2894
2902
|
this.tapTimer = void 0, this.toggleBar(t);
|
|
2895
|
-
},
|
|
2903
|
+
}, ir);
|
|
2896
2904
|
}
|
|
2897
2905
|
toggleBar(e) {
|
|
2898
2906
|
e ? this.poke() : this.hideIfIdle();
|
|
@@ -2912,7 +2920,7 @@ var cr = class {
|
|
|
2912
2920
|
this.statusOverlays && (e === "ended" ? t = "ended" : e === "error" ? t = "error" : e === "waiting" ? t = "waiting" : !this.hasPlayed && (e === "idle" || e === "paused") && (t = "preplay")), this.renderStatus(t);
|
|
2913
2921
|
}
|
|
2914
2922
|
statusMessageFor(e) {
|
|
2915
|
-
return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ?
|
|
2923
|
+
return e === "ended" ? this.player.endedReason === "interrupted" ? this.interruptedMessage : this.endedMessage : e === "waiting" ? this.hasPlayed ? "Reconnecting — please stand by" : "Starting soon…" : e === "error" ? this.errorMessage === void 0 ? this.lastError?.code === "GEO_DENIED" ? or(this.lastError.country) : this.lastError?.code === "DRM_DEVICE_REVOKED" ? sr : this.lastError?.message ?? "Playback unavailable" : this.errorMessage : null;
|
|
2916
2924
|
}
|
|
2917
2925
|
renderStatus(e) {
|
|
2918
2926
|
let t = this.statusMessageFor(e);
|
|
@@ -2927,7 +2935,7 @@ var cr = class {
|
|
|
2927
2935
|
e.type = "button", e.className = "havik-status__btn havik-status__btn--play", e.setAttribute("aria-label", "Play"), e.innerHTML = Q("play"), e.addEventListener("click", () => void this.player.play()), n.append(e);
|
|
2928
2936
|
} else {
|
|
2929
2937
|
let r = this.doc.createElement("div");
|
|
2930
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2938
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !ar.has(this.lastError.code)) {
|
|
2931
2939
|
let e = this.doc.createElement("button");
|
|
2932
2940
|
e.type = "button", e.className = "havik-status__btn", e.innerHTML = `${Q("retry")}<span>Retry</span>`, e.addEventListener("click", () => void this.player.retry()), n.append(e);
|
|
2933
2941
|
}
|
|
@@ -2968,7 +2976,7 @@ var cr = class {
|
|
|
2968
2976
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2969
2977
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2970
2978
|
}
|
|
2971
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2979
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${ur(this.video.currentTime)} / ${ur(this.video.duration)}`);
|
|
2972
2980
|
}
|
|
2973
2981
|
syncLive() {
|
|
2974
2982
|
let e = this.player.getStats(), t = e.isLive !== !1, n = this.player.state === "ended", r = !t && !this.streamEnded();
|
|
@@ -3018,17 +3026,17 @@ var cr = class {
|
|
|
3018
3026
|
renderQualityMenu() {
|
|
3019
3027
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
3020
3028
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
3021
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
3029
|
+
for (let n of e) this.menu.append(this.menuItem(dr(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
3022
3030
|
}
|
|
3023
3031
|
renderAudioMenu() {
|
|
3024
3032
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
3025
3033
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
3026
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3034
|
+
for (let t of e) this.menu.append(this.menuItem(fr(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
3027
3035
|
}
|
|
3028
3036
|
renderCcMenu() {
|
|
3029
3037
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
3030
3038
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
3031
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
3039
|
+
for (let t of e) this.menu.append(this.menuItem(pr(t), !1, () => this.player.setTextTrack(t.id)));
|
|
3032
3040
|
}
|
|
3033
3041
|
onTracksChanged() {
|
|
3034
3042
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -3133,41 +3141,41 @@ var cr = class {
|
|
|
3133
3141
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
3134
3142
|
}
|
|
3135
3143
|
};
|
|
3136
|
-
function
|
|
3144
|
+
function ur(e) {
|
|
3137
3145
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
3138
3146
|
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");
|
|
3139
3147
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
3140
3148
|
}
|
|
3141
|
-
function
|
|
3149
|
+
function dr(e) {
|
|
3142
3150
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
3143
3151
|
}
|
|
3144
|
-
function
|
|
3152
|
+
function fr(e) {
|
|
3145
3153
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3146
3154
|
}
|
|
3147
|
-
function
|
|
3155
|
+
function pr(e) {
|
|
3148
3156
|
return e.name || e.lang || `Track ${e.id}`;
|
|
3149
3157
|
}
|
|
3150
3158
|
//#endregion
|
|
3151
3159
|
//#region src/managed/index.ts
|
|
3152
|
-
var
|
|
3153
|
-
function
|
|
3160
|
+
var mr = 6e3, hr = 45e3, gr = 2e3, _r = 3, vr = 5e3, yr = 2e3, br = 48e4, xr = "keySystemLicenseRequestFailed";
|
|
3161
|
+
function Sr(e) {
|
|
3154
3162
|
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)})`);
|
|
3155
3163
|
if (e.env !== void 0) return at(e.env);
|
|
3156
3164
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: env or baseUrl is required (env: 'integration' | 'production')");
|
|
3157
3165
|
return e.baseUrl;
|
|
3158
3166
|
}
|
|
3159
|
-
async function
|
|
3167
|
+
async function Cr(e) {
|
|
3160
3168
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
3161
|
-
let t =
|
|
3169
|
+
let t = Sr(e);
|
|
3162
3170
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
3163
3171
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
3164
|
-
let r = new
|
|
3172
|
+
let r = new wr({
|
|
3165
3173
|
...e,
|
|
3166
3174
|
baseUrl: t
|
|
3167
3175
|
});
|
|
3168
3176
|
return await r.start(), r;
|
|
3169
3177
|
}
|
|
3170
|
-
var
|
|
3178
|
+
var wr = class {
|
|
3171
3179
|
opts;
|
|
3172
3180
|
abort = new AbortController();
|
|
3173
3181
|
listeners = {};
|
|
@@ -3262,7 +3270,7 @@ var Cr = class {
|
|
|
3262
3270
|
setTimeout(() => {
|
|
3263
3271
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
3264
3272
|
phase: i ? "unavailable" : "tooEarly",
|
|
3265
|
-
retryInMs:
|
|
3273
|
+
retryInMs: hr,
|
|
3266
3274
|
attempt: 1,
|
|
3267
3275
|
elapsedMs: 0,
|
|
3268
3276
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -3301,13 +3309,13 @@ var Cr = class {
|
|
|
3301
3309
|
!a && !p() && h();
|
|
3302
3310
|
}, e);
|
|
3303
3311
|
};
|
|
3304
|
-
_(
|
|
3312
|
+
_(mr), this.armingSub = E({
|
|
3305
3313
|
eventsBaseUrl: t,
|
|
3306
3314
|
matchUrn: this.opts.matchUrn,
|
|
3307
3315
|
credential: this.opts.credential,
|
|
3308
|
-
onAlive: () => _(
|
|
3316
|
+
onAlive: () => _(hr),
|
|
3309
3317
|
onState: (e) => {
|
|
3310
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
3318
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * gr);
|
|
3311
3319
|
},
|
|
3312
3320
|
onError: () => h()
|
|
3313
3321
|
});
|
|
@@ -3352,19 +3360,19 @@ var Cr = class {
|
|
|
3352
3360
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
3353
3361
|
let i = e.analytics?.sid;
|
|
3354
3362
|
if (!i) return;
|
|
3355
|
-
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } =
|
|
3363
|
+
let a = typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0, { endpoint: o, disabledReason: s } = Vn(this.opts.baseUrl, a, e.analytics?.endpoint);
|
|
3356
3364
|
if (!o) {
|
|
3357
3365
|
s && setTimeout(() => {
|
|
3358
3366
|
this.destroyed || r !== this.loadGen || this.emit("warning", new n("INTERNAL", 0, s));
|
|
3359
3367
|
}, 0);
|
|
3360
3368
|
return;
|
|
3361
3369
|
}
|
|
3362
|
-
let c = this.opts.video, l = new
|
|
3370
|
+
let c = this.opts.video, l = new Hn({
|
|
3363
3371
|
endpoint: o,
|
|
3364
3372
|
sid: i,
|
|
3365
3373
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
3366
|
-
sdkVersion:
|
|
3367
|
-
environment:
|
|
3374
|
+
sdkVersion: Jn,
|
|
3375
|
+
environment: Kn(c),
|
|
3368
3376
|
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
3369
3377
|
onIdle: () => this.onAnalyticsIdle(t),
|
|
3370
3378
|
onBlocked: (e) => setTimeout(() => {
|
|
@@ -3385,7 +3393,7 @@ var Cr = class {
|
|
|
3385
3393
|
let u = () => l.noteSeek(), d = () => l.noteVolume(c.muted, c.volume);
|
|
3386
3394
|
c.addEventListener("seeking", u), c.addEventListener("volumechange", d), this.detachMediaListeners = () => {
|
|
3387
3395
|
c.removeEventListener("seeking", u), c.removeEventListener("volumechange", d);
|
|
3388
|
-
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()),
|
|
3396
|
+
}, l.start(), l.seedVolume(c.muted, c.volume), l.notePresentation(this.currentPresentation()), qn().then((e) => l.noteEnvironment(e)), this.opts.autoplay === !1 && l.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
3389
3397
|
}
|
|
3390
3398
|
currentPresentation() {
|
|
3391
3399
|
let e = this.opts.video;
|
|
@@ -3414,9 +3422,9 @@ var Cr = class {
|
|
|
3414
3422
|
freshLicenseUrl: () => this.refreshLicense()
|
|
3415
3423
|
}, o = this.opts.engine ?? "auto";
|
|
3416
3424
|
if (o === "native") return new W(a);
|
|
3417
|
-
if (o === "hls") return new
|
|
3425
|
+
if (o === "hls") return new wn(a);
|
|
3418
3426
|
if (e.drmEnabled && e.drm?.fairplay?.licenseUrl && e.drm.fairplay.certificateUrl && H(this.opts.video) && U() || !e.drmEnabled && St() && H(this.opts.video)) return new W(a);
|
|
3419
|
-
if (It()) return new
|
|
3427
|
+
if (It()) return new wn(a);
|
|
3420
3428
|
if (H(this.opts.video)) return new W(a);
|
|
3421
3429
|
throw new n("INTERNAL", 0, "no supported HLS playback engine in this browser");
|
|
3422
3430
|
}
|
|
@@ -3479,7 +3487,7 @@ var Cr = class {
|
|
|
3479
3487
|
r = 0, i = !1;
|
|
3480
3488
|
},
|
|
3481
3489
|
onError: () => {
|
|
3482
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
3490
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= _r && (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.`))));
|
|
3483
3491
|
}
|
|
3484
3492
|
});
|
|
3485
3493
|
}
|
|
@@ -3493,7 +3501,7 @@ var Cr = class {
|
|
|
3493
3501
|
return;
|
|
3494
3502
|
}
|
|
3495
3503
|
let e = this.hiddenAtMs;
|
|
3496
|
-
this.hiddenAtMs = null, e != null && Date.now() - e >=
|
|
3504
|
+
this.hiddenAtMs = null, e != null && Date.now() - e >= vr && this.resyncLiveState();
|
|
3497
3505
|
}, this.onReturnPageShow = (e) => {
|
|
3498
3506
|
e.persisted && this.resyncLiveState();
|
|
3499
3507
|
}, document.addEventListener("visibilitychange", this.onReturnVisible), typeof window < "u" && window.addEventListener("pageshow", this.onReturnPageShow));
|
|
@@ -3525,7 +3533,7 @@ var Cr = class {
|
|
|
3525
3533
|
scheduleRejoin(e) {
|
|
3526
3534
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
3527
3535
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
3528
|
-
}, Math.random() *
|
|
3536
|
+
}, Math.random() * gr));
|
|
3529
3537
|
}
|
|
3530
3538
|
cancelRejoin() {
|
|
3531
3539
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -3549,7 +3557,7 @@ var Cr = class {
|
|
|
3549
3557
|
}
|
|
3550
3558
|
t.controls = !1;
|
|
3551
3559
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
3552
|
-
r && r.insertBefore(n, t), n.appendChild(t),
|
|
3560
|
+
r && r.insertBefore(n, t), n.appendChild(t), Zn(n, this.opts.theme), this.container = n, this.controlBar = cr({
|
|
3553
3561
|
root: n,
|
|
3554
3562
|
video: t,
|
|
3555
3563
|
player: this,
|
|
@@ -3587,7 +3595,7 @@ var Cr = class {
|
|
|
3587
3595
|
}
|
|
3588
3596
|
startStats() {
|
|
3589
3597
|
this.stopStats();
|
|
3590
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
3598
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? yr);
|
|
3591
3599
|
this.statsTimer = setInterval(() => {
|
|
3592
3600
|
if (!this.engine) return;
|
|
3593
3601
|
let e = this.engine.getStats();
|
|
@@ -3598,14 +3606,14 @@ var Cr = class {
|
|
|
3598
3606
|
this.statsTimer && clearInterval(this.statsTimer), this.statsTimer = void 0;
|
|
3599
3607
|
}
|
|
3600
3608
|
isStaleLicenseDenial(e) {
|
|
3601
|
-
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !==
|
|
3609
|
+
return this.staleLicenseReloaded || this.opts.hlsConfig?.licenseXhrSetup || this._state === "ended" || this._state === "error" || e.detail !== xr || e.error.httpStatus !== 403 || e.error.code !== "FORBIDDEN" || e.error.serverCode === "license_refused" ? !1 : K(this._descriptor?.drm?.widevine?.licenseUrl);
|
|
3602
3610
|
}
|
|
3603
3611
|
scheduleLicenseRefresh() {
|
|
3604
3612
|
if (this.stopRefresh(), !this._descriptor?.drmEnabled) return;
|
|
3605
3613
|
typeof document < "u" && this.engine?.name === "hls" && (this.onRefocus = () => {
|
|
3606
3614
|
document.visibilityState !== "visible" || this.destroyed || K(this._descriptor?.drm?.widevine?.licenseUrl) && this.refreshLicense();
|
|
3607
3615
|
}, document.addEventListener("visibilitychange", this.onRefocus));
|
|
3608
|
-
let e = this.opts.licenseRefreshMs ??
|
|
3616
|
+
let e = this.opts.licenseRefreshMs ?? br;
|
|
3609
3617
|
e && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
3610
3618
|
}
|
|
3611
3619
|
stopRefresh() {
|
|
@@ -3775,7 +3783,7 @@ function $(e) {
|
|
|
3775
3783
|
}
|
|
3776
3784
|
//#endregion
|
|
3777
3785
|
//#region src/embed/host.ts
|
|
3778
|
-
function
|
|
3786
|
+
function Tr(e) {
|
|
3779
3787
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
3780
3788
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
3781
3789
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -3834,15 +3842,15 @@ function wr(e) {
|
|
|
3834
3842
|
}
|
|
3835
3843
|
//#endregion
|
|
3836
3844
|
//#region src/embed/page.ts
|
|
3837
|
-
var
|
|
3838
|
-
function
|
|
3845
|
+
var Er = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
3846
|
+
function Dr(e) {
|
|
3839
3847
|
if (typeof e == "boolean") return e;
|
|
3840
3848
|
if (typeof e == "object" && e) {
|
|
3841
3849
|
let t = e.endpoint;
|
|
3842
3850
|
return typeof t == "string" ? { endpoint: t } : {};
|
|
3843
3851
|
}
|
|
3844
3852
|
}
|
|
3845
|
-
function
|
|
3853
|
+
function Or() {
|
|
3846
3854
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
3847
3855
|
if (e) return {
|
|
3848
3856
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -3852,7 +3860,7 @@ function Dr() {
|
|
|
3852
3860
|
autoplay: e.autoplay ?? !0,
|
|
3853
3861
|
muted: e.muted ?? !0,
|
|
3854
3862
|
waitForLive: e.waitForLive ?? !0,
|
|
3855
|
-
analytics:
|
|
3863
|
+
analytics: Dr(e.analytics)
|
|
3856
3864
|
};
|
|
3857
3865
|
let t = new URLSearchParams(location.search);
|
|
3858
3866
|
return {
|
|
@@ -3865,9 +3873,9 @@ function Dr() {
|
|
|
3865
3873
|
waitForLive: !0
|
|
3866
3874
|
};
|
|
3867
3875
|
}
|
|
3868
|
-
async function
|
|
3869
|
-
let e =
|
|
3870
|
-
|
|
3876
|
+
async function kr() {
|
|
3877
|
+
let e = Or();
|
|
3878
|
+
jr();
|
|
3871
3879
|
let t = document.createElement("video");
|
|
3872
3880
|
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);
|
|
3873
3881
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -3923,12 +3931,12 @@ async function Or() {
|
|
|
3923
3931
|
message: e.message,
|
|
3924
3932
|
...e.country === void 0 ? {} : { country: e.country }
|
|
3925
3933
|
})), e.on("autoplayblocked", () => {
|
|
3926
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
3934
|
+
i({ type: "oddin:autoplayblocked" }), Ar(t, e);
|
|
3927
3935
|
});
|
|
3928
3936
|
}, s = async (r) => {
|
|
3929
3937
|
a?.destroy(), a = null;
|
|
3930
3938
|
try {
|
|
3931
|
-
let n = await
|
|
3939
|
+
let n = await Cr({
|
|
3932
3940
|
video: t,
|
|
3933
3941
|
baseUrl: e.baseUrl,
|
|
3934
3942
|
matchUrn: r,
|
|
@@ -3991,7 +3999,7 @@ async function Or() {
|
|
|
3991
3999
|
a?.retry();
|
|
3992
4000
|
break;
|
|
3993
4001
|
case "oddin:load":
|
|
3994
|
-
typeof e.matchUrn == "string" &&
|
|
4002
|
+
typeof e.matchUrn == "string" && Er.test(e.matchUrn) && s(e.matchUrn);
|
|
3995
4003
|
break;
|
|
3996
4004
|
case "oddin:destroy": c();
|
|
3997
4005
|
}
|
|
@@ -4003,18 +4011,18 @@ async function Or() {
|
|
|
4003
4011
|
protocol: 1
|
|
4004
4012
|
});
|
|
4005
4013
|
}
|
|
4006
|
-
function
|
|
4014
|
+
function Ar(e, t) {
|
|
4007
4015
|
if (document.getElementById("havik-tap")) return;
|
|
4008
4016
|
let n = document.createElement("button");
|
|
4009
4017
|
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", () => {
|
|
4010
4018
|
n.remove(), t.play();
|
|
4011
4019
|
}), document.body.appendChild(n);
|
|
4012
4020
|
}
|
|
4013
|
-
function
|
|
4021
|
+
function jr() {
|
|
4014
4022
|
let e = document.createElement("style");
|
|
4015
4023
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
4016
4024
|
}
|
|
4017
4025
|
//#endregion
|
|
4018
|
-
export {
|
|
4026
|
+
export { Yn as ODDIN_THEME, n as PlaybackError, Zn as applyTheme, at as baseUrlForEnv, kr as bootEmbed, Ee as clearDeviceId, Re as clearRememberedBandwidth, Cr as createPlayer, D as deriveEventsBaseUrl, tt as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ve as fetchCatalog, be as fetchTournament, Se as flattenMatches, C as fullscreenSupported, A as getDeviceId, rt as isLowLatencyManifest, $ as isOddinMessage, Oe as licenseRequestHeaders, Tr as mountEmbed, fe as pollToLive, y as resolveStream, E as subscribeLiveState, S as videoFullscreenActive, we as watchStatus };
|
|
4019
4027
|
|
|
4020
4028
|
//# sourceMappingURL=index.js.map
|