@oddin-gg/havik-player 2.6.3 → 2.7.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 +9 -2
- package/dist/havik-player.global.js +2 -2
- package/dist/havik-player.global.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +197 -133
- package/dist/index.js.map +1 -1
- package/embed/index.html +1 -1
- package/examples/vanilla.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -918,17 +918,17 @@ function Fe(e, t) {
|
|
|
918
918
|
function Ie() {
|
|
919
919
|
return e.isSupported();
|
|
920
920
|
}
|
|
921
|
-
var Le = 3, Re = 5, ze = 3, Be = 3e4, Ve = 12e3, He = 3e3, H = 6e3, Ue =
|
|
922
|
-
function
|
|
921
|
+
var Le = 3, Re = 5, ze = 3, Be = 3e4, Ve = 12e3, He = 3e3, H = 6e3, Ue = 5e3, We = 4e3, Ge = 2, Ke = 5, qe = 2, Je = 2, Ye = 2e3, Xe = 3e4, Ze = 2, Qe = 9, $e = .5, et = 64;
|
|
922
|
+
function tt(e) {
|
|
923
923
|
if (e.liveSyncDurationCount != null || e.liveMaxLatencyDurationCount != null) {
|
|
924
924
|
delete e.liveSyncDuration, delete e.liveMaxLatencyDuration;
|
|
925
925
|
return;
|
|
926
926
|
}
|
|
927
|
-
e.liveSyncDuration ??=
|
|
928
|
-
let t = Math.max(12, e.liveSyncDuration +
|
|
929
|
-
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t),
|
|
927
|
+
e.liveSyncDuration ??= Ze;
|
|
928
|
+
let t = Math.max(12, e.liveSyncDuration + Qe);
|
|
929
|
+
(e.liveMaxLatencyDuration == null || e.liveMaxLatencyDuration <= e.liveSyncDuration) && (e.liveMaxLatencyDuration = t), nt(e, e.liveSyncDuration);
|
|
930
930
|
}
|
|
931
|
-
function
|
|
931
|
+
function nt(e, t) {
|
|
932
932
|
let n = (e, t, n) => Math.min(n, Math.max(t, e));
|
|
933
933
|
e.maxStarvationDelay ??= n(t / 2, .5, 4), e.maxLoadingDelay ??= n(t, 1, 4), e.abrEwmaFastLive ??= n(t / 2, 1, 3);
|
|
934
934
|
}
|
|
@@ -960,6 +960,11 @@ var U = class {
|
|
|
960
960
|
licenseRetryTimer = null;
|
|
961
961
|
onVisibility = null;
|
|
962
962
|
onSeeking = null;
|
|
963
|
+
onPause = null;
|
|
964
|
+
onPlay = null;
|
|
965
|
+
pauseSuspendTimer = null;
|
|
966
|
+
loadSuspended = !1;
|
|
967
|
+
stopped = !1;
|
|
963
968
|
sawLive = !1;
|
|
964
969
|
lastEndSN = -1;
|
|
965
970
|
lastAdvanceMs = 0;
|
|
@@ -1002,10 +1007,34 @@ var U = class {
|
|
|
1002
1007
|
if (typeof t != "number") return;
|
|
1003
1008
|
let n = typeof e.targetLatency == "number" && e.targetLatency > 0 ? e.targetLatency : 3;
|
|
1004
1009
|
t - r.currentTime > Math.max(n * 3, 8) && (r.currentTime = t);
|
|
1005
|
-
}, document.addEventListener("visibilitychange", this.onVisibility)), this.onSeeking = () =>
|
|
1010
|
+
}, document.addEventListener("visibilitychange", this.onVisibility)), this.onSeeking = () => {
|
|
1011
|
+
this.clampOverSeek(), this.loadSuspended && (this.resumeLoading(), this.schedulePauseSuspend());
|
|
1012
|
+
}, r.addEventListener("seeking", this.onSeeking), this.onPause = () => this.schedulePauseSuspend(), this.onPlay = () => this.resumeLoading(), r.addEventListener("pause", this.onPause), r.addEventListener("play", this.onPlay), this.sizeCapManaged && typeof ResizeObserver < "u" && (this.capObserver = new ResizeObserver(() => this.onMediaResize()), this.capObserver.observe(r), this.watchDprChanges());
|
|
1013
|
+
}
|
|
1014
|
+
schedulePauseSuspend() {
|
|
1015
|
+
this.pauseSuspendTimer || this.loadSuspended || this.stopped || !this.loadStarted || (this.pauseSuspendTimer = setTimeout(() => {
|
|
1016
|
+
this.pauseSuspendTimer = null;
|
|
1017
|
+
let { video: e } = this.deps;
|
|
1018
|
+
if (e.paused && !e.ended && !this.stopped && this.hls) {
|
|
1019
|
+
try {
|
|
1020
|
+
this.hls.stopLoad();
|
|
1021
|
+
} catch {
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
this.loadSuspended = !0;
|
|
1025
|
+
}
|
|
1026
|
+
}, Ue));
|
|
1027
|
+
}
|
|
1028
|
+
resumeLoading() {
|
|
1029
|
+
if (this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.loadSuspended && (this.loadSuspended = !1, !this.stopped && this.hls)) {
|
|
1030
|
+
this.lastAdvanceMs = Date.now(), this.lastFragLoadingMs = 0, this.starvedTicks = 0, this.kickPending = !1, this.kickTicks = 0;
|
|
1031
|
+
try {
|
|
1032
|
+
this.hls.startLoad(-1);
|
|
1033
|
+
} catch {}
|
|
1034
|
+
}
|
|
1006
1035
|
}
|
|
1007
1036
|
startLoad() {
|
|
1008
|
-
this.loadStarted || (this.loadStarted = !0, this.hls?.startLoad(-1));
|
|
1037
|
+
this.loadStarted || (this.loadStarted = !0, this.deps.video.paused && this.schedulePauseSuspend(), this.hls?.startLoad(-1));
|
|
1009
1038
|
}
|
|
1010
1039
|
watchDprChanges() {
|
|
1011
1040
|
if (typeof matchMedia != "function") return;
|
|
@@ -1026,7 +1055,7 @@ var U = class {
|
|
|
1026
1055
|
let t = e.liveSyncPosition;
|
|
1027
1056
|
if (typeof t != "number" || !Number.isFinite(t)) return;
|
|
1028
1057
|
let { video: n } = this.deps;
|
|
1029
|
-
n.currentTime <= t +
|
|
1058
|
+
n.currentTime <= t + $e || (n.currentTime = t);
|
|
1030
1059
|
}
|
|
1031
1060
|
startHls() {
|
|
1032
1061
|
let { video: t, descriptor: n, credential: r, deviceId: i, userId: a, lowLatency: o, debug: s, hlsConfig: c, emit: l } = this.deps;
|
|
@@ -1066,12 +1095,12 @@ var U = class {
|
|
|
1066
1095
|
} } : {},
|
|
1067
1096
|
...c
|
|
1068
1097
|
};
|
|
1069
|
-
|
|
1098
|
+
tt(d), this.sizeCapManaged = d.capLevelToPlayerSize !== !0, this.loadStarted = d.autoStartLoad !== !1;
|
|
1070
1099
|
let f = new e(d);
|
|
1071
1100
|
this.hls = f, f.on(e.Events.MANIFEST_PARSED, () => {
|
|
1072
1101
|
this.mediaRecoveries = 0, this.networkRecoveries = 0;
|
|
1073
1102
|
let e = f.levels.map((e) => e.height).filter((e) => !!e);
|
|
1074
|
-
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(), l({ type: "ready" });
|
|
1103
|
+
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" });
|
|
1075
1104
|
}), f.on(e.Events.FRAG_BUFFERED, (e, t) => {
|
|
1076
1105
|
t?.frag?.type === "main" && (this.kickPending = !1, this.kickTicks = 0, (this.mediaRecoveries > 0 || this.networkRecoveries > 0 || this.licenseRecoveries > 0 || this.starvationKicks > 0 || this.starvationRebuilds > 0) && !this.recoveryResetTimer && (this.recoveryResetTimer = setTimeout(() => {
|
|
1077
1106
|
this.mediaRecoveries = 0, this.networkRecoveries = 0, this.licenseRecoveries = 0, this.starvationKicks = 0, this.starvationRebuilds = 0, this.recoveryResetTimer = null;
|
|
@@ -1082,7 +1111,7 @@ var U = class {
|
|
|
1082
1111
|
let n = t?.frag?.stats, r = n?.loaded;
|
|
1083
1112
|
typeof r == "number" && (this.bytesLoaded += r);
|
|
1084
1113
|
let i = n?.loading;
|
|
1085
|
-
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 >
|
|
1114
|
+
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 > et && this.requestTimesMs.shift());
|
|
1086
1115
|
let a = t?.frag?.url;
|
|
1087
1116
|
if (a) {
|
|
1088
1117
|
let e = L(a);
|
|
@@ -1162,7 +1191,7 @@ var U = class {
|
|
|
1162
1191
|
return;
|
|
1163
1192
|
}
|
|
1164
1193
|
this.capTimer && clearTimeout(this.capTimer);
|
|
1165
|
-
let t = e > this.sizeCapLevel ?
|
|
1194
|
+
let t = e > this.sizeCapLevel ? Ye : Xe;
|
|
1166
1195
|
this.capTimer = setTimeout(() => {
|
|
1167
1196
|
this.capTimer = null, this.computeSizeCapTarget() === e ? this.applySizeCap() : this.onMediaResize();
|
|
1168
1197
|
}, t);
|
|
@@ -1250,27 +1279,31 @@ var U = class {
|
|
|
1250
1279
|
this.lastAdvanceMs = Date.now();
|
|
1251
1280
|
return;
|
|
1252
1281
|
}
|
|
1282
|
+
if (this.loadSuspended) {
|
|
1283
|
+
this.lastAdvanceMs = Date.now();
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1253
1286
|
let e = Date.now() - this.lastAdvanceMs;
|
|
1254
1287
|
!this.chaseSuspended && e > H && this.suspendChasing(), e > Ve && this.emitEnded("stalled");
|
|
1255
1288
|
}
|
|
1256
1289
|
checkStarvation() {
|
|
1257
1290
|
let e = this.hls, { video: t } = this.deps;
|
|
1258
1291
|
if (!e || this.endedEmitted || !this.sawLive || this.chaseSuspended) return;
|
|
1259
|
-
if (typeof document < "u" && document.hidden) {
|
|
1292
|
+
if (typeof document < "u" && document.hidden || this.loadSuspended) {
|
|
1260
1293
|
this.starvedTicks = 0;
|
|
1261
1294
|
return;
|
|
1262
1295
|
}
|
|
1263
|
-
let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < H, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs >
|
|
1296
|
+
let n = this.lastAdvanceMs !== 0 && Date.now() - this.lastAdvanceMs < H, r = this.lastFragLoadingMs !== 0 && Date.now() - this.lastFragLoadingMs > We;
|
|
1264
1297
|
if (!(t.readyState < HTMLMediaElement.HAVE_FUTURE_DATA && !t.paused && n && r)) {
|
|
1265
1298
|
this.starvedTicks = 0;
|
|
1266
1299
|
return;
|
|
1267
1300
|
}
|
|
1268
|
-
if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks <
|
|
1269
|
-
if (this.starvedTicks = 0, this.kickPending && this.kickTicks >=
|
|
1301
|
+
if (this.kickPending && (this.kickTicks += 1), !(++this.starvedTicks < Ge)) {
|
|
1302
|
+
if (this.starvedTicks = 0, this.kickPending && this.kickTicks >= qe && (this.kickPending = !1, this.kickTicks = 0, this.starvationRebuilds < Je)) {
|
|
1270
1303
|
this.starvationRebuilds += 1, 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");
|
|
1271
1304
|
return;
|
|
1272
1305
|
}
|
|
1273
|
-
if (!(this.starvationKicks >=
|
|
1306
|
+
if (!(this.starvationKicks >= Ke)) {
|
|
1274
1307
|
this.starvationKicks += 1, this.kickPending = !0, this.kickTicks = 0, console.warn("havik-player: video starved while the live playlist advances (wedged hls.js fragment pipeline) — restarting the load");
|
|
1275
1308
|
try {
|
|
1276
1309
|
e.stopLoad(), e.startLoad(-1);
|
|
@@ -1296,7 +1329,7 @@ var U = class {
|
|
|
1296
1329
|
}));
|
|
1297
1330
|
}
|
|
1298
1331
|
stop() {
|
|
1299
|
-
this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.kickPending = !1, this.kickTicks = 0;
|
|
1332
|
+
this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.kickPending = !1, this.kickTicks = 0, this.stopped = !0, this.loadSuspended = !1, this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null);
|
|
1300
1333
|
try {
|
|
1301
1334
|
this.hls?.stopLoad();
|
|
1302
1335
|
} catch {}
|
|
@@ -1305,7 +1338,7 @@ var U = class {
|
|
|
1305
1338
|
} catch {}
|
|
1306
1339
|
}
|
|
1307
1340
|
destroy() {
|
|
1308
|
-
if (this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
|
|
1341
|
+
if (this.clearRecoveryReset(), this.capTimer &&= (clearTimeout(this.capTimer), null), this.capObserver &&= (this.capObserver.disconnect(), null), this.unwatchDprChanges(), this.endWatchdog &&= (clearInterval(this.endWatchdog), null), this.onVisibility && typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), this.onVisibility = null), this.onSeeking &&= (this.deps.video.removeEventListener("seeking", this.onSeeking), null), this.onPause &&= (this.deps.video.removeEventListener("pause", this.onPause), null), this.onPlay &&= (this.deps.video.removeEventListener("play", this.onPlay), null), this.pauseSuspendTimer &&= (clearTimeout(this.pauseSuspendTimer), null), this.networkRetryTimer &&= (clearTimeout(this.networkRetryTimer), null), this.licenseRetryTimer &&= (clearTimeout(this.licenseRetryTimer), null), this.hls) {
|
|
1309
1342
|
try {
|
|
1310
1343
|
this.hls.destroy();
|
|
1311
1344
|
} catch (e) {
|
|
@@ -1393,11 +1426,11 @@ var U = class {
|
|
|
1393
1426
|
let r = e.response?.code ?? 0, a = e.details ?? e.type, o = e.reason ?? e.error?.message ?? "";
|
|
1394
1427
|
return new n(t === "DRM" ? i(r) : r === 401 ? "UNAUTHORIZED" : r === 403 ? "FORBIDDEN" : "INTERNAL", r, `${t} error: ${a}${o ? ` (${o})` : ""}`);
|
|
1395
1428
|
}
|
|
1396
|
-
},
|
|
1429
|
+
}, rt = 15e3, it = 6e5, at = 3e5, ot = 100, W = 1, st = 1e3, G = 3e4, ct = 1e3, lt = {
|
|
1397
1430
|
inline: "PRESENTATION_INLINE",
|
|
1398
1431
|
fullscreen: "PRESENTATION_FULLSCREEN",
|
|
1399
1432
|
pip: "PRESENTATION_PIP"
|
|
1400
|
-
},
|
|
1433
|
+
}, ut = {
|
|
1401
1434
|
widevine: "KEY_SYSTEM_WIDEVINE",
|
|
1402
1435
|
fairplay: "KEY_SYSTEM_FAIRPLAY",
|
|
1403
1436
|
none: "KEY_SYSTEM_NONE"
|
|
@@ -1405,7 +1438,7 @@ var U = class {
|
|
|
1405
1438
|
function K(e, t) {
|
|
1406
1439
|
return e.length === 0 ? 0 : e[Math.min(e.length, Math.max(1, Math.ceil(t / 100 * e.length))) - 1] ?? 0;
|
|
1407
1440
|
}
|
|
1408
|
-
var
|
|
1441
|
+
var dt = /* @__PURE__ */ new Set([
|
|
1409
1442
|
"INVALID_URN",
|
|
1410
1443
|
"NOT_FOUND",
|
|
1411
1444
|
"GONE",
|
|
@@ -1425,7 +1458,7 @@ var ct = /* @__PURE__ */ new Set([
|
|
|
1425
1458
|
ended: "PLAYER_STATE_ENDED",
|
|
1426
1459
|
error: "PLAYER_STATE_ERROR"
|
|
1427
1460
|
};
|
|
1428
|
-
function
|
|
1461
|
+
function ft(e) {
|
|
1429
1462
|
try {
|
|
1430
1463
|
let t = new URL(e), [n, ...r] = t.hostname.split(".");
|
|
1431
1464
|
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);
|
|
@@ -1433,7 +1466,7 @@ function lt(e) {
|
|
|
1433
1466
|
return;
|
|
1434
1467
|
}
|
|
1435
1468
|
}
|
|
1436
|
-
var
|
|
1469
|
+
var pt = class {
|
|
1437
1470
|
opts;
|
|
1438
1471
|
url;
|
|
1439
1472
|
now;
|
|
@@ -1493,19 +1526,26 @@ var ut = class {
|
|
|
1493
1526
|
lastRequestErrors = 0;
|
|
1494
1527
|
pendingStart = null;
|
|
1495
1528
|
firstFlushTimer = null;
|
|
1529
|
+
idleTimer = null;
|
|
1530
|
+
lastTickMs = 0;
|
|
1496
1531
|
bornMs;
|
|
1497
1532
|
startupAnchorMs;
|
|
1498
1533
|
startupTimeMs = 0;
|
|
1499
1534
|
manifestLoadMs = 0;
|
|
1500
1535
|
firstFragLoadMs = 0;
|
|
1501
1536
|
onPagehide = () => this.end("END_REASON_PAGEHIDE");
|
|
1537
|
+
onFreeze = () => {
|
|
1538
|
+
this.endedFlag || this.flush(!0);
|
|
1539
|
+
};
|
|
1540
|
+
onResume = () => this.checkSuspension(this.now());
|
|
1502
1541
|
onVisibility = () => {
|
|
1503
1542
|
typeof document > "u" || (document.visibilityState === "hidden" ? (this.hiddenSinceMs === null && (this.hiddenSinceMs = this.now()), this.isHidden = !0) : (this.hiddenSinceMs !== null && (this.hiddenTotalMs += this.now() - this.hiddenSinceMs, this.hiddenSinceMs = null), this.isHidden = !1), this.syncActive(), this.syncBuffering());
|
|
1504
1543
|
};
|
|
1505
1544
|
constructor(e) {
|
|
1506
1545
|
this.opts = {
|
|
1507
1546
|
...e,
|
|
1508
|
-
heartbeatMs: e.heartbeatMs ??
|
|
1547
|
+
heartbeatMs: e.heartbeatMs ?? rt,
|
|
1548
|
+
idleMs: e.idleMs ?? it
|
|
1509
1549
|
}, 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;
|
|
1510
1550
|
}
|
|
1511
1551
|
start() {
|
|
@@ -1515,7 +1555,20 @@ var ut = class {
|
|
|
1515
1555
|
sdkVersion: this.opts.sdkVersion,
|
|
1516
1556
|
...this.opts.environment
|
|
1517
1557
|
};
|
|
1518
|
-
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(),
|
|
1558
|
+
this.pendingStart = e, this.enqueue({ sessionStart: e }), this.firstFlushTimer = setTimeout(() => this.flush(), st), 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());
|
|
1559
|
+
}
|
|
1560
|
+
checkSuspension(e) {
|
|
1561
|
+
if (this.endedFlag || !this.opts.idleMs) return !1;
|
|
1562
|
+
let t = Math.max(this.opts.idleMs, at);
|
|
1563
|
+
return this.lastTickMs > 0 && e - this.lastTickMs >= t ? (this.endIdle(this.lastTickMs), !0) : (this.lastTickMs = e, !1);
|
|
1564
|
+
}
|
|
1565
|
+
syncIdle(e) {
|
|
1566
|
+
e === "paused" && this.opts.idleMs ? this.idleTimer === null && (this.idleTimer = setTimeout(() => {
|
|
1567
|
+
this.idleTimer = null, this.endIdle();
|
|
1568
|
+
}, this.opts.idleMs)) : this.idleTimer !== null && (clearTimeout(this.idleTimer), this.idleTimer = null);
|
|
1569
|
+
}
|
|
1570
|
+
endIdle(e) {
|
|
1571
|
+
this.endedFlag || (this.end("END_REASON_IDLE", e), this.opts.onIdle?.());
|
|
1519
1572
|
}
|
|
1520
1573
|
noteStateChange(e, t, n, r) {
|
|
1521
1574
|
if (this.endedFlag || e === t) return;
|
|
@@ -1525,32 +1578,32 @@ var ut = class {
|
|
|
1525
1578
|
let e = !this.isHidden && !this.stallIsSeekInduced;
|
|
1526
1579
|
e && (this.rebufferCount += 1), this.isBuffering = !0, this.lastStallMs = i, e && this.timeToFirstStallMs === 0 && (this.timeToFirstStallMs = Math.max(W, Math.round(this.playingTotalMs)));
|
|
1527
1580
|
} else e === "buffering" && (this.isBuffering = !1, this.stallIsSeekInduced = !1);
|
|
1528
|
-
this.syncBuffering(), t === "paused" && (this.pauseCount += 1);
|
|
1581
|
+
this.syncBuffering(), t === "paused" && (this.pauseCount += 1), this.syncIdle(t);
|
|
1529
1582
|
let a = {
|
|
1530
1583
|
fromState: q[e] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1531
1584
|
toState: q[t] ?? "PLAYER_STATE_UNSPECIFIED",
|
|
1532
|
-
presentation:
|
|
1585
|
+
presentation: lt[this.presentation]
|
|
1533
1586
|
}, o = this.causeOf(e, t, i);
|
|
1534
1587
|
o && (a.cause = o), n > 0 && (a.positionMs = Math.round(n)), r && (a.renditionHeight = r), this.enqueue({ stateChange: a });
|
|
1535
1588
|
}
|
|
1536
1589
|
seekInduced(e) {
|
|
1537
|
-
return this.lastSeekMs >= 0 && e - this.lastSeekMs <
|
|
1590
|
+
return this.lastSeekMs >= 0 && e - this.lastSeekMs < ct;
|
|
1538
1591
|
}
|
|
1539
1592
|
causeOf(e, t, n) {
|
|
1540
1593
|
if (t === "error") return "TRANSITION_CAUSE_ERROR";
|
|
1541
1594
|
if (t === "buffering") return this.seekInduced(n) ? "TRANSITION_CAUSE_SEEK" : "TRANSITION_CAUSE_NETWORK_STALL";
|
|
1542
1595
|
if (t === "paused" || t === "playing" && e === "paused") return "TRANSITION_CAUSE_USER";
|
|
1543
1596
|
}
|
|
1544
|
-
syncActive() {
|
|
1545
|
-
let
|
|
1546
|
-
|
|
1597
|
+
syncActive(e = this.now()) {
|
|
1598
|
+
let t = this.isPlaying && !this.isHidden && !this.isMuted;
|
|
1599
|
+
t && this.activeSinceMs === null ? this.activeSinceMs = e : !t && this.activeSinceMs !== null && (this.activeTotalMs += e - this.activeSinceMs, this.activeSinceMs = null);
|
|
1547
1600
|
}
|
|
1548
1601
|
syncBuffering() {
|
|
1549
1602
|
let e = this.isBuffering && !this.isHidden && !this.stallIsSeekInduced;
|
|
1550
1603
|
e && this.bufferingSinceMs === null ? this.bufferingSinceMs = this.now() : !e && this.bufferingSinceMs !== null && (this.rebufferTotalMs += this.now() - this.bufferingSinceMs, this.bufferingSinceMs = null);
|
|
1551
1604
|
}
|
|
1552
|
-
closePresentation() {
|
|
1553
|
-
let
|
|
1605
|
+
closePresentation(e = this.now()) {
|
|
1606
|
+
let t = e - this.presentationSinceMs;
|
|
1554
1607
|
this.presentation === "fullscreen" ? this.fullscreenTotalMs += t : this.presentation === "pip" && (this.pipTotalMs += t), this.presentationSinceMs = e;
|
|
1555
1608
|
}
|
|
1556
1609
|
noteAutoplay(e) {
|
|
@@ -1602,7 +1655,7 @@ var ut = class {
|
|
|
1602
1655
|
let r = n ?? "";
|
|
1603
1656
|
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";
|
|
1604
1657
|
if (e === "DRM_CLIENT") return "ERROR_STAGE_DRM";
|
|
1605
|
-
if (
|
|
1658
|
+
if (dt.has(e)) return "ERROR_STAGE_RESOLVE";
|
|
1606
1659
|
let i = t ?? "";
|
|
1607
1660
|
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";
|
|
1608
1661
|
}
|
|
@@ -1617,66 +1670,68 @@ var ut = class {
|
|
|
1617
1670
|
}
|
|
1618
1671
|
heartbeat() {
|
|
1619
1672
|
if (this.endedFlag) return;
|
|
1620
|
-
let e = this.
|
|
1621
|
-
|
|
1673
|
+
let e = this.now();
|
|
1674
|
+
if (this.checkSuspension(e)) return;
|
|
1675
|
+
let t = this.opts.sample(), n = this.playingTotalMs;
|
|
1676
|
+
this.playingSinceMs !== null && (n += e - this.playingSinceMs);
|
|
1622
1677
|
let r = this.hiddenTotalMs;
|
|
1623
|
-
this.hiddenSinceMs !== null && (r +=
|
|
1678
|
+
this.hiddenSinceMs !== null && (r += e - this.hiddenSinceMs);
|
|
1624
1679
|
let i = this.rebufferTotalMs;
|
|
1625
|
-
this.bufferingSinceMs !== null && (i +=
|
|
1680
|
+
this.bufferingSinceMs !== null && (i += e - this.bufferingSinceMs);
|
|
1626
1681
|
let a = this.activeTotalMs;
|
|
1627
|
-
this.activeSinceMs !== null && (a +=
|
|
1628
|
-
let o = {}, s =
|
|
1682
|
+
this.activeSinceMs !== null && (a += e - this.activeSinceMs);
|
|
1683
|
+
let o = {}, s = t.bytesLoaded ?? 0;
|
|
1629
1684
|
s > this.lastBytes && (o.bytesDownloadedDelta = s - this.lastBytes), this.lastBytes = s;
|
|
1630
|
-
let c =
|
|
1685
|
+
let c = t.playlistBytesLoaded ?? 0;
|
|
1631
1686
|
c > this.lastPlaylistBytes && (o.playlistBytesDelta = c - this.lastPlaylistBytes), this.lastPlaylistBytes = c;
|
|
1632
|
-
let l =
|
|
1687
|
+
let l = t.droppedFrames ?? 0;
|
|
1633
1688
|
l > this.lastDropped && (o.droppedFramesDelta = l - this.lastDropped), this.lastDropped = l;
|
|
1634
|
-
let u =
|
|
1635
|
-
u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof
|
|
1689
|
+
let u = t.renditionSwitches ?? 0;
|
|
1690
|
+
u > this.lastSwitches && (o.renditionSwitchesDelta = u - this.lastSwitches), this.lastSwitches = u, n > this.lastHbPlayingMs && (o.playingMsDelta = Math.round(n - this.lastHbPlayingMs)), this.lastHbPlayingMs = n, r > this.lastHbHiddenMs && (o.hiddenMsDelta = Math.round(r - this.lastHbHiddenMs)), this.lastHbHiddenMs = r, i > this.lastHbRebufferMs && (o.rebufferMsDelta = Math.round(i - this.lastHbRebufferMs)), this.lastHbRebufferMs = i, this.rebufferCount > this.lastHbRebufferCount && (o.rebufferCountDelta = this.rebufferCount - this.lastHbRebufferCount), this.lastHbRebufferCount = this.rebufferCount, a > this.lastHbActiveMs && (o.activeMsDelta = Math.round(a - this.lastHbActiveMs)), this.lastHbActiveMs = a, typeof t.latencySeconds == "number" && (o.latencyMs = Math.round(t.latencySeconds * 1e3)), typeof t.targetLatencySeconds == "number" && (o.targetLatencyMs = Math.round(t.targetLatencySeconds * 1e3)), typeof t.bandwidthKbps == "number" && (o.bandwidthEstKbps = t.bandwidthKbps), typeof t.levelHeight == "number" && (o.renditionHeight = t.levelHeight), typeof t.renditionBitrateKbps == "number" && (o.renditionBitrateKbps = t.renditionBitrateKbps), t.atLiveEdge === !0 && (o.atLiveEdge = !0), typeof t.bufferedMs == "number" && t.bufferedMs > 0 && (o.bufferedMs = Math.round(t.bufferedMs)), o.playerState = q[t.state] ?? "PLAYER_STATE_UNSPECIFIED";
|
|
1636
1691
|
let d = this.mutedTotalMs;
|
|
1637
|
-
this.mutedSinceMs !== null && (d +=
|
|
1638
|
-
let f =
|
|
1692
|
+
this.mutedSinceMs !== null && (d += e - this.mutedSinceMs), d > this.lastHbMutedMs && (o.mutedMsDelta = Math.round(d - this.lastHbMutedMs)), this.lastHbMutedMs = d;
|
|
1693
|
+
let f = t.upshifts ?? 0;
|
|
1639
1694
|
f > this.lastUpshifts && (o.upshiftsDelta = f - this.lastUpshifts), this.lastUpshifts = f;
|
|
1640
|
-
let p =
|
|
1695
|
+
let p = t.downshifts ?? 0;
|
|
1641
1696
|
p > this.lastDownshifts && (o.downshiftsDelta = p - this.lastDownshifts), this.lastDownshifts = p;
|
|
1642
|
-
let m =
|
|
1697
|
+
let m = t.decodedFrames ?? 0;
|
|
1643
1698
|
m > this.lastDecoded && (o.decodedFramesDelta = m - this.lastDecoded), this.lastDecoded = m;
|
|
1644
|
-
let h =
|
|
1699
|
+
let h = t.requestErrors ?? 0;
|
|
1645
1700
|
h > this.lastRequestErrors && (o.requestErrorsDelta = h - this.lastRequestErrors), this.lastRequestErrors = h;
|
|
1646
|
-
let g =
|
|
1701
|
+
let g = t.requestCount ?? 0, _ = g - this.lastRequestCount;
|
|
1647
1702
|
if (this.lastRequestCount = g, _ > 0) {
|
|
1648
1703
|
o.requestCountDelta = _;
|
|
1649
|
-
let
|
|
1704
|
+
let e = t.requestTimesMs ?? [], n = e.slice(Math.max(0, e.length - _)).sort((e, t) => e - t);
|
|
1650
1705
|
n.length > 0 && (o.requestTimeP50Ms = K(n, 50), o.requestTimeP95Ms = K(n, 95));
|
|
1651
1706
|
}
|
|
1652
|
-
typeof
|
|
1707
|
+
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();
|
|
1653
1708
|
}
|
|
1654
1709
|
maybeEmitMediaInfo(e) {
|
|
1655
1710
|
if (!(e.videoCodec ?? e.keySystem ?? e.ladderHeights)) return;
|
|
1656
1711
|
let t = {};
|
|
1657
|
-
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem =
|
|
1712
|
+
e.videoCodec && (t.videoCodec = e.videoCodec), e.audioCodec && (t.audioCodec = e.audioCodec), e.keySystem && (t.keySystem = ut[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);
|
|
1658
1713
|
let n = JSON.stringify(t);
|
|
1659
1714
|
n !== this.mediaInfoSignature && (this.mediaInfoSignature = n, this.enqueue({ mediaInfo: t }));
|
|
1660
1715
|
}
|
|
1661
|
-
end(e) {
|
|
1716
|
+
end(e, t) {
|
|
1662
1717
|
if (this.endedFlag) return;
|
|
1663
1718
|
this.endedFlag = !0;
|
|
1664
|
-
let
|
|
1665
|
-
this.playingSinceMs !== null && (this.playingTotalMs +=
|
|
1666
|
-
let
|
|
1667
|
-
|
|
1668
|
-
let
|
|
1669
|
-
|
|
1670
|
-
let
|
|
1671
|
-
|
|
1672
|
-
let
|
|
1673
|
-
|
|
1674
|
-
let
|
|
1675
|
-
|
|
1676
|
-
let
|
|
1677
|
-
|
|
1678
|
-
let
|
|
1679
|
-
|
|
1719
|
+
let n = t ?? this.now();
|
|
1720
|
+
this.playingSinceMs !== null && (this.playingTotalMs += n - this.playingSinceMs, this.playingSinceMs = null), this.hiddenSinceMs !== null && (this.hiddenTotalMs += n - this.hiddenSinceMs, this.hiddenSinceMs = null), this.bufferingSinceMs !== null && (this.rebufferTotalMs += n - this.bufferingSinceMs, this.bufferingSinceMs = null), this.mutedSinceMs !== null && (this.mutedTotalMs += n - this.mutedSinceMs, this.mutedSinceMs = null), this.waitingSinceMs !== null && (this.waitingTotalMs += n - this.waitingSinceMs, this.waitingSinceMs = null), this.isPlaying = !1, this.syncActive(n), this.closePresentation(n), this.firstFlushTimer &&= (clearTimeout(this.firstFlushTimer), null), this.timer &&= (clearInterval(this.timer), null), this.idleTimer &&= (clearTimeout(this.idleTimer), null), typeof window < "u" && window.removeEventListener("pagehide", this.onPagehide), typeof document < "u" && (document.removeEventListener("visibilitychange", this.onVisibility), document.removeEventListener("freeze", this.onFreeze), document.removeEventListener("resume", this.onResume));
|
|
1721
|
+
let r = this.safeSample();
|
|
1722
|
+
r && this.maybeEmitMediaInfo(r);
|
|
1723
|
+
let i = { reason: e }, a = r?.bytesLoaded ?? this.lastBytes;
|
|
1724
|
+
a > 0 && (i.bytesDownloadedTotal = a), this.playingTotalMs > 0 && (i.watchTimeMs = Math.round(this.playingTotalMs)), this.rebufferCount > 0 && (i.rebufferCount = this.rebufferCount), this.rebufferTotalMs > 0 && (i.rebufferTimeMs = Math.round(this.rebufferTotalMs)), this.startupTimeMs > 0 && (i.startupTimeMs = Math.round(this.startupTimeMs)), this.manifestLoadMs > 0 && (i.manifestLoadMs = Math.round(this.manifestLoadMs)), this.firstFragLoadMs > 0 && (i.firstFragLoadMs = Math.round(this.firstFragLoadMs));
|
|
1725
|
+
let o = r?.licenseTimeMs ?? 0;
|
|
1726
|
+
o > 0 && (i.licenseTimeMs = Math.round(o));
|
|
1727
|
+
let s = r?.droppedFrames ?? this.lastDropped;
|
|
1728
|
+
s > 0 && (i.droppedFramesTotal = s), this.errorCount > 0 && (i.errorCount = this.errorCount), this.hiddenTotalMs > 0 && (i.hiddenTimeMs = Math.round(this.hiddenTotalMs)), this.seekCount > 0 && (i.seekCount = this.seekCount), this.pauseCount > 0 && (i.pauseCount = this.pauseCount), this.firstAudioMs > 0 && (i.firstAudioMs = Math.round(this.firstAudioMs)), this.waitingTotalMs > 0 && (i.waitingForLiveMs = Math.round(this.waitingTotalMs)), this.timeToFirstStallMs > 0 && (i.timeToFirstStallMs = Math.round(this.timeToFirstStallMs));
|
|
1729
|
+
let c = r?.positionMs ?? 0;
|
|
1730
|
+
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));
|
|
1731
|
+
let l = e !== "END_REASON_ENDED";
|
|
1732
|
+
l && this.lastStallMs > 0 && n - this.lastStallMs <= G && (i.abandonAfterStallMs = Math.max(W, Math.round(n - this.lastStallMs))), l && this.lastErrorMs > 0 && n - this.lastErrorMs <= G && (i.abandonAfterErrorMs = Math.max(W, 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);
|
|
1733
|
+
let u = r?.decodedFrames ?? this.lastDecoded;
|
|
1734
|
+
u > 0 && (i.decodedFramesTotal = u), this.startupTimeMs === 0 && (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");
|
|
1680
1735
|
}
|
|
1681
1736
|
safeSample() {
|
|
1682
1737
|
try {
|
|
@@ -1694,7 +1749,7 @@ var ut = class {
|
|
|
1694
1749
|
};
|
|
1695
1750
|
}
|
|
1696
1751
|
enqueue(e) {
|
|
1697
|
-
for (this.pending.push(this.wrap(e)); this.pending.length >
|
|
1752
|
+
for (this.pending.push(this.wrap(e)); this.pending.length > ot;) {
|
|
1698
1753
|
let e = this.pending.findIndex((e) => e.heartbeat || e.stateChange);
|
|
1699
1754
|
this.pending.splice(e >= 0 ? e : 0, 1);
|
|
1700
1755
|
}
|
|
@@ -1717,7 +1772,7 @@ var ut = class {
|
|
|
1717
1772
|
};
|
|
1718
1773
|
//#endregion
|
|
1719
1774
|
//#region src/core/environment.ts
|
|
1720
|
-
function
|
|
1775
|
+
function mt() {
|
|
1721
1776
|
if (typeof window > "u") return { integration: "INTEGRATION_KIND_SDK" };
|
|
1722
1777
|
let e;
|
|
1723
1778
|
try {
|
|
@@ -1742,14 +1797,14 @@ function dt() {
|
|
|
1742
1797
|
integration: "INTEGRATION_KIND_IFRAME"
|
|
1743
1798
|
};
|
|
1744
1799
|
}
|
|
1745
|
-
function
|
|
1800
|
+
function ht() {
|
|
1746
1801
|
if (typeof navigator > "u") return "DEVICE_CLASS_OTHER";
|
|
1747
1802
|
let e = navigator.userAgentData, t = e?.platform ?? "";
|
|
1748
1803
|
if (/tv|tizen|webos/i.test(t)) return "DEVICE_CLASS_TV";
|
|
1749
1804
|
let n = typeof screen < "u" ? Math.min(screen.width, screen.height) : 0;
|
|
1750
1805
|
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";
|
|
1751
1806
|
}
|
|
1752
|
-
function
|
|
1807
|
+
function gt() {
|
|
1753
1808
|
let e = typeof navigator < "u" ? navigator.connection : void 0;
|
|
1754
1809
|
if (!e) return { connectionType: "CONNECTION_TYPE_UNKNOWN" };
|
|
1755
1810
|
let t = {
|
|
@@ -1768,17 +1823,17 @@ function pt() {
|
|
|
1768
1823
|
}
|
|
1769
1824
|
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;
|
|
1770
1825
|
}
|
|
1771
|
-
function
|
|
1772
|
-
let t =
|
|
1773
|
-
deviceClass:
|
|
1826
|
+
function _t(e) {
|
|
1827
|
+
let t = mt(), n = {
|
|
1828
|
+
deviceClass: ht(),
|
|
1774
1829
|
integration: t.integration,
|
|
1775
|
-
...
|
|
1830
|
+
...gt()
|
|
1776
1831
|
};
|
|
1777
1832
|
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);
|
|
1778
1833
|
let r = e.getBoundingClientRect?.();
|
|
1779
1834
|
return r && r.width > 0 && (n.viewportWidth = Math.round(r.width), n.viewportHeight = Math.round(r.height)), n;
|
|
1780
1835
|
}
|
|
1781
|
-
async function
|
|
1836
|
+
async function vt() {
|
|
1782
1837
|
let e = typeof navigator < "u" ? navigator.userAgentData : void 0;
|
|
1783
1838
|
if (!e?.getHighEntropyValues) return {};
|
|
1784
1839
|
try {
|
|
@@ -1790,7 +1845,7 @@ async function ht() {
|
|
|
1790
1845
|
}
|
|
1791
1846
|
//#endregion
|
|
1792
1847
|
//#region src/core/version.ts
|
|
1793
|
-
var
|
|
1848
|
+
var yt = "2.7.0", J = {
|
|
1794
1849
|
accent: "#E1B600",
|
|
1795
1850
|
accentText: "#1B1C23",
|
|
1796
1851
|
background: "#0e0f13",
|
|
@@ -1823,15 +1878,15 @@ function X(e, t) {
|
|
|
1823
1878
|
}
|
|
1824
1879
|
//#endregion
|
|
1825
1880
|
//#region src/ui/styles.ts
|
|
1826
|
-
var Z = "havik-player-styles",
|
|
1827
|
-
function
|
|
1881
|
+
var Z = "havik-player-styles", bt = "\n.havik-player{position:relative;display:block;width:100%;background:var(--havik-bg,#0e0f13);\n color:var(--havik-text,#fff);font-family:var(--havik-font,system-ui,sans-serif);\n overflow:hidden;line-height:1.4;-webkit-tap-highlight-color:transparent}\n.havik-player video{display:block;width:100%;height:auto;aspect-ratio:16/9;\n object-fit:contain;background:#000;outline:none}\n.havik-player:focus{outline:none}\n.havik-player *{box-sizing:border-box}\n\n.havik-player:fullscreen,.havik-player:-webkit-full-screen{display:flex;align-items:center;\n justify-content:center;width:100vw;height:100vh;aspect-ratio:auto}\n.havik-player:fullscreen video,.havik-player:-webkit-full-screen video{width:100%;height:100%;\n aspect-ratio:auto;object-fit:contain}\n\n.havik-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;cursor:pointer}\n.havik-gradient{position:absolute;left:0;right:0;bottom:0;height:120px;pointer-events:none;\n background:linear-gradient(to top,rgba(0,0,0,.78),transparent);\n opacity:1;transition:opacity .25s}\n.havik-player.havik-hide .havik-gradient,\n.havik-player.havik-hide .havik-bar{opacity:0;pointer-events:none}\n.havik-player.havik-hide{cursor:none}\n\n.havik-center{width:74px;height:74px;border-radius:50%;border:0;cursor:pointer;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);\n display:flex;align-items:center;justify-content:center;\n box-shadow:0 6px 24px rgba(0,0,0,.45);transition:transform .15s,opacity .15s}\n.havik-center:hover{transform:scale(1.06)}\n.havik-center svg{width:38px;height:38px;margin-left:2px}\n.havik-center.havik-gone{opacity:0;pointer-events:none;transform:scale(.8)}\n\n.havik-spinner{width:56px;height:56px;border-radius:50%;\n border:4px solid rgba(255,255,255,.2);border-top-color:var(--havik-accent,#E1B600);\n animation:havik-spin .8s linear infinite}\n@keyframes havik-spin{to{transform:rotate(360deg)}}\n\n/* Status card — branded full-bleed overlay for the stopped/pre-play states\n (ended / fatal error / pre-play / armed-waiting). */\n.havik-status{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;\n align-items:center;justify-content:center;background:rgba(14,15,19,.82);text-align:center;padding:24px}\n.havik-status__logo{width:128px;height:46px;background:var(--havik-logo) center/contain no-repeat;opacity:.95}\n.havik-status__msg{color:var(--havik-text,#fff);font-size:15px;font-weight:600;max-width:480px}\n.havik-status__btn{display:inline-flex;align-items:center;gap:8px;border:0;cursor:pointer;\n padding:10px 18px;border-radius:var(--havik-radius,8px);font-weight:700;font-size:14px;\n background:var(--havik-accent,#E1B600);color:var(--havik-accent-text,#1B1C23);transition:transform .15s}\n.havik-status__btn:hover{transform:scale(1.04)}\n.havik-status__btn svg{width:18px;height:18px}\n/* Pre-play: lighter scrim so the poster shows through, and a round play CTA. */\n.havik-status--preplay{background:rgba(14,15,19,.4)}\n.havik-status--preplay .havik-status__btn--play{width:74px;height:74px;border-radius:50%;padding:0;\n justify-content:center;box-shadow:0 6px 24px rgba(0,0,0,.45)}\n.havik-status--preplay .havik-status__btn--play svg{width:38px;height:38px;margin-left:3px}\n\n.havik-watermark{position:absolute;top:12px;right:14px;height:22px;opacity:.85;pointer-events:none;\n content:'';background:var(--havik-logo) center/contain no-repeat;width:90px}\n/* A status card carries its own logo — the corner watermark would duplicate it. */\n.havik-player.havik-has-status .havik-watermark{display:none}\n\n.havik-bar{position:absolute;left:0;right:0;bottom:0;padding:0 12px 8px;\n opacity:1;transition:opacity .25s;z-index:2}\n.havik-seek{position:relative;height:16px;display:flex;align-items:center;cursor:pointer;margin-bottom:2px}\n.havik-seek__track{position:relative;width:100%;height:4px;border-radius:3px;background:rgba(255,255,255,.25)}\n.havik-seek__buffered{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:rgba(255,255,255,.4)}\n.havik-seek__played{position:absolute;left:0;top:0;height:100%;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-seek__thumb{position:absolute;top:50%;width:13px;height:13px;border-radius:50%;\n background:var(--havik-accent,#E1B600);transform:translate(-50%,-50%) scale(0);transition:transform .1s}\n.havik-seek:hover .havik-seek__thumb{transform:translate(-50%,-50%) scale(1)}\n\n.havik-controls{display:flex;align-items:center;gap:6px;height:40px}\n.havik-spacer{flex:1}\n.havik-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;border-radius:var(--havik-radius,8px);\n padding:0;transition:background .12s,color .12s}\n.havik-btn:hover{background:rgba(255,255,255,.12)}\n.havik-btn:focus-visible{outline:2px solid var(--havik-accent,#E1B600);outline-offset:1px}\n.havik-btn svg{width:22px;height:22px}\n\n/* The volume level is filled in accent up to the thumb, like the seek bar's\n played span — a native range input paints no \"elapsed\" side, which left the\n level readable only from the dot's position. --havik-vol (0..1) is set by\n syncVolume(); the track width and thumb size live here as variables because\n the WebKit fill has to compute the thumb centre from both. */\n.havik-vol{display:flex;align-items:center}\n.havik-vol__slider{--havik-vol-w:70px;--havik-vol-thumb:12px;--havik-vol:1;\n --havik-vol-pos:calc(var(--havik-vol-thumb) / 2 + var(--havik-vol) * (var(--havik-vol-w) - var(--havik-vol-thumb)));\n width:0;opacity:0;transition:width .18s,opacity .18s;height:4px;cursor:pointer;\n appearance:none;-webkit-appearance:none;background:transparent;border-radius:3px;margin:0 4px}\n.havik-vol:hover .havik-vol__slider,.havik-vol:focus-within .havik-vol__slider{width:var(--havik-vol-w);opacity:1}\n/* WebKit/Blink have no progress pseudo-element: paint the fill as a hard-stop\n gradient that ends at the thumb centre. */\n.havik-vol__slider::-webkit-slider-runnable-track{height:4px;border-radius:3px;\n background:linear-gradient(to right,var(--havik-accent,#E1B600) var(--havik-vol-pos),\n rgba(255,255,255,.3) var(--havik-vol-pos))}\n/* Firefox fills natively, and tracks the thumb exactly. */\n.havik-vol__slider::-moz-range-track{height:4px;border-radius:3px;background:rgba(255,255,255,.3)}\n.havik-vol__slider::-moz-range-progress{height:4px;border-radius:3px;background:var(--havik-accent,#E1B600)}\n.havik-vol__slider::-webkit-slider-thumb{-webkit-appearance:none;width:var(--havik-vol-thumb);\n height:var(--havik-vol-thumb);border-radius:50%;background:var(--havik-accent,#E1B600);\n margin-top:calc((4px - var(--havik-vol-thumb)) / 2)}\n.havik-vol__slider::-moz-range-thumb{width:var(--havik-vol-thumb);height:var(--havik-vol-thumb);\n border:0;border-radius:50%;background:var(--havik-accent,#E1B600)}\n\n.havik-time{font-size:12px;color:var(--havik-text-muted,#9aa0ad);\n font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap}\n.havik-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;\n letter-spacing:.4px;padding:0 8px;color:var(--havik-text,#fff)}\n.havik-live svg{width:9px;height:9px;color:var(--havik-text-muted,#9aa0ad)}\n.havik-live.is-live svg{color:var(--havik-accent,#E1B600)}\n.havik-live__go{margin-left:2px;border:0;cursor:pointer;background:transparent;color:var(--havik-text-muted,#9aa0ad);\n font:inherit;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;padding:2px 6px;border-radius:6px}\n.havik-live.is-live .havik-live__go{display:none}\n.havik-live__go:hover{color:var(--havik-accent,#E1B600)}\n\n.havik-menu{position:absolute;bottom:54px;right:12px;min-width:170px;max-height:230px;overflow:auto;\n background:var(--havik-surface,#1B1C23);border:1px solid var(--havik-border,rgba(255,255,255,.1));\n border-radius:var(--havik-radius,8px);box-shadow:0 10px 30px rgba(0,0,0,.5);padding:6px;z-index:3}\n.havik-menu[hidden]{display:none}\n.havik-menu__title{font-size:11px;text-transform:uppercase;letter-spacing:.6px;\n color:var(--havik-text-muted,#9aa0ad);padding:6px 8px 4px}\n.havik-menu__item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;\n border:0;background:transparent;color:var(--havik-text,#fff);cursor:pointer;font:inherit;font-size:13px;\n text-align:left;padding:7px 8px;border-radius:6px}\n.havik-menu__item:hover{background:var(--havik-surface-muted,#2a2c36)}\n.havik-menu__item[aria-checked=\"true\"]{color:var(--havik-accent,#E1B600);font-weight:600}\n.havik-menu__item[aria-checked=\"true\"]::after{content:'✓'}\n";
|
|
1882
|
+
function xt(e = document) {
|
|
1828
1883
|
if (e.getElementById(Z)) return;
|
|
1829
1884
|
let t = e.createElement("style");
|
|
1830
|
-
t.id = Z, t.textContent =
|
|
1885
|
+
t.id = Z, t.textContent = bt, e.head.appendChild(t);
|
|
1831
1886
|
}
|
|
1832
1887
|
//#endregion
|
|
1833
1888
|
//#region src/ui/icons.ts
|
|
1834
|
-
var
|
|
1889
|
+
var St = {
|
|
1835
1890
|
play: "<path d=\"M8 5v14l11-7z\"/>",
|
|
1836
1891
|
pause: "<path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/>",
|
|
1837
1892
|
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\"/>",
|
|
@@ -1845,20 +1900,20 @@ var yt = {
|
|
|
1845
1900
|
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\"/>"
|
|
1846
1901
|
};
|
|
1847
1902
|
function Q(e) {
|
|
1848
|
-
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${
|
|
1903
|
+
return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="currentColor">${St[e]}</svg>`;
|
|
1849
1904
|
}
|
|
1850
1905
|
//#endregion
|
|
1851
1906
|
//#region src/ui/controls.ts
|
|
1852
|
-
var
|
|
1907
|
+
var Ct = 3e3, wt = /* @__PURE__ */ new Set([
|
|
1853
1908
|
"GONE",
|
|
1854
1909
|
"NOT_FOUND",
|
|
1855
1910
|
"INVALID_URN",
|
|
1856
1911
|
"UNAUTHORIZED"
|
|
1857
1912
|
]);
|
|
1858
|
-
function
|
|
1859
|
-
return new
|
|
1913
|
+
function Tt(e) {
|
|
1914
|
+
return new Et(e);
|
|
1860
1915
|
}
|
|
1861
|
-
var
|
|
1916
|
+
var Et = class {
|
|
1862
1917
|
root;
|
|
1863
1918
|
video;
|
|
1864
1919
|
player;
|
|
@@ -1900,7 +1955,7 @@ var Ct = class {
|
|
|
1900
1955
|
scrubbing = !1;
|
|
1901
1956
|
offFns = [];
|
|
1902
1957
|
constructor(e) {
|
|
1903
|
-
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ??
|
|
1958
|
+
this.root = e.root, this.video = e.video, this.player = e.player, this.doc = e.root.ownerDocument ?? document, this.autoHideMs = e.autoHideMs ?? Ct, 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, xt(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");
|
|
1904
1959
|
let t = (e, t, n) => {
|
|
1905
1960
|
let r = this.doc.createElement(e);
|
|
1906
1961
|
if (r.className = t, n) for (let [e, t] of Object.entries(n)) r.setAttribute(e, t);
|
|
@@ -1991,7 +2046,7 @@ var Ct = class {
|
|
|
1991
2046
|
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);
|
|
1992
2047
|
} else {
|
|
1993
2048
|
let r = this.doc.createElement("div");
|
|
1994
|
-
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !
|
|
2049
|
+
if (r.className = "havik-status__msg", r.textContent = t ?? "", n.append(r), e === "error" && this.lastError && !wt.has(this.lastError.code)) {
|
|
1995
2050
|
let e = this.doc.createElement("button");
|
|
1996
2051
|
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);
|
|
1997
2052
|
}
|
|
@@ -2032,7 +2087,7 @@ var Ct = class {
|
|
|
2032
2087
|
let n = r.end(r.length - 1), i = Math.min(1, Math.max(0, (n - e.start) / t));
|
|
2033
2088
|
this.seekBuffered.style.width = `${(i * 100).toFixed(2)}%`;
|
|
2034
2089
|
}
|
|
2035
|
-
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${
|
|
2090
|
+
!this.player.getStats().isLive && Number.isFinite(this.video.duration) && (this.time.textContent = `${Dt(this.video.currentTime)} / ${Dt(this.video.duration)}`);
|
|
2036
2091
|
}
|
|
2037
2092
|
syncLive() {
|
|
2038
2093
|
let e = this.player.getStats(), t = e.isLive !== !1;
|
|
@@ -2082,17 +2137,17 @@ var Ct = class {
|
|
|
2082
2137
|
renderQualityMenu() {
|
|
2083
2138
|
let e = this.player.getQualityLevels(), t = this.player.getCurrentQuality(), n = this.doc.createElement("div");
|
|
2084
2139
|
n.className = "havik-menu__title", n.textContent = "Quality", this.menu.replaceChildren(n, this.menuItem("Auto", t === -1, () => this.player.setQuality("auto")));
|
|
2085
|
-
for (let n of e) this.menu.append(this.menuItem(
|
|
2140
|
+
for (let n of e) this.menu.append(this.menuItem(Ot(n), t === n.index, () => this.player.setQuality(n.index)));
|
|
2086
2141
|
}
|
|
2087
2142
|
renderAudioMenu() {
|
|
2088
2143
|
let e = this.player.getAudioTracks(), t = this.doc.createElement("div");
|
|
2089
2144
|
t.className = "havik-menu__title", t.textContent = "Audio", this.menu.replaceChildren(t);
|
|
2090
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2145
|
+
for (let t of e) this.menu.append(this.menuItem(kt(t), t.default, () => this.player.setAudioTrack(t.id)));
|
|
2091
2146
|
}
|
|
2092
2147
|
renderCcMenu() {
|
|
2093
2148
|
let e = this.player.getTextTracks(), t = this.doc.createElement("div");
|
|
2094
2149
|
t.className = "havik-menu__title", t.textContent = "Subtitles", this.menu.replaceChildren(t, this.menuItem("Off", !1, () => this.player.setTextTrack(-1)));
|
|
2095
|
-
for (let t of e) this.menu.append(this.menuItem(
|
|
2150
|
+
for (let t of e) this.menu.append(this.menuItem(At(t), !1, () => this.player.setTextTrack(t.id)));
|
|
2096
2151
|
}
|
|
2097
2152
|
onTracksChanged() {
|
|
2098
2153
|
this.openMenu && this.renderMenu(this.openMenu);
|
|
@@ -2192,32 +2247,32 @@ var Ct = class {
|
|
|
2192
2247
|
this.root.classList.remove("havik-player", "havik-hide", "havik-has-status");
|
|
2193
2248
|
}
|
|
2194
2249
|
};
|
|
2195
|
-
function
|
|
2250
|
+
function Dt(e) {
|
|
2196
2251
|
(!Number.isFinite(e) || e < 0) && (e = 0);
|
|
2197
2252
|
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");
|
|
2198
2253
|
return r > 0 ? `${r}:${i}:${a}` : `${i}:${a}`;
|
|
2199
2254
|
}
|
|
2200
|
-
function
|
|
2255
|
+
function Ot(e) {
|
|
2201
2256
|
return e.height ? `${e.height}p` : `${Math.round(e.bitrate / 1e3)} kbps`;
|
|
2202
2257
|
}
|
|
2203
|
-
function
|
|
2258
|
+
function kt(e) {
|
|
2204
2259
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2205
2260
|
}
|
|
2206
|
-
function
|
|
2261
|
+
function At(e) {
|
|
2207
2262
|
return e.name || e.lang || `Track ${e.id}`;
|
|
2208
2263
|
}
|
|
2209
2264
|
//#endregion
|
|
2210
2265
|
//#region src/managed/index.ts
|
|
2211
|
-
var
|
|
2212
|
-
async function
|
|
2266
|
+
var jt = 6e3, Mt = 45e3, Nt = 2e3, Pt = 3, Ft = 2e3, It = 48e4;
|
|
2267
|
+
async function Lt(e) {
|
|
2213
2268
|
if (!e.video || typeof e.video.play != "function") throw new n("INTERNAL", 0, "createPlayer: opts.video must be an HTMLVideoElement");
|
|
2214
2269
|
if (!e.baseUrl) throw new n("INTERNAL", 0, "createPlayer: baseUrl is required");
|
|
2215
2270
|
if (!e.matchUrn) throw new n("INVALID_URN", 0, "createPlayer: matchUrn is required");
|
|
2216
2271
|
if (!e.credential) throw new n("INTERNAL", 0, "createPlayer: credential is required");
|
|
2217
|
-
let t = new
|
|
2272
|
+
let t = new Rt(e);
|
|
2218
2273
|
return await t.start(), t;
|
|
2219
2274
|
}
|
|
2220
|
-
var
|
|
2275
|
+
var Rt = class {
|
|
2221
2276
|
opts;
|
|
2222
2277
|
abort = new AbortController();
|
|
2223
2278
|
listeners = {};
|
|
@@ -2243,6 +2298,7 @@ var Ft = class {
|
|
|
2243
2298
|
analyticsSession = null;
|
|
2244
2299
|
detachMediaListeners;
|
|
2245
2300
|
playRequested = !1;
|
|
2301
|
+
idleClosed = !1;
|
|
2246
2302
|
pendingStartLoad = !1;
|
|
2247
2303
|
constructor(e) {
|
|
2248
2304
|
this.opts = e;
|
|
@@ -2304,7 +2360,7 @@ var Ft = class {
|
|
|
2304
2360
|
setTimeout(() => {
|
|
2305
2361
|
a || this.destroyed || e !== this.loadGen || this.emit("waiting", {
|
|
2306
2362
|
phase: i ? "unavailable" : "tooEarly",
|
|
2307
|
-
retryInMs:
|
|
2363
|
+
retryInMs: Mt,
|
|
2308
2364
|
attempt: 1,
|
|
2309
2365
|
elapsedMs: 0,
|
|
2310
2366
|
...!i && f !== void 0 && f > Date.now() ? { ttkMs: f - Date.now() } : {}
|
|
@@ -2343,13 +2399,13 @@ var Ft = class {
|
|
|
2343
2399
|
!a && !p() && h();
|
|
2344
2400
|
}, e);
|
|
2345
2401
|
};
|
|
2346
|
-
_(
|
|
2402
|
+
_(jt), this.armingSub = E({
|
|
2347
2403
|
eventsBaseUrl: t,
|
|
2348
2404
|
matchUrn: this.opts.matchUrn,
|
|
2349
2405
|
credential: this.opts.credential,
|
|
2350
|
-
onAlive: () => _(
|
|
2406
|
+
onAlive: () => _(Mt),
|
|
2351
2407
|
onState: (e) => {
|
|
2352
|
-
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() *
|
|
2408
|
+
a || p() || (e.state === "live" || e.state === "gone") && setTimeout(g, Math.random() * Nt);
|
|
2353
2409
|
},
|
|
2354
2410
|
onError: () => h()
|
|
2355
2411
|
});
|
|
@@ -2387,18 +2443,23 @@ var Ft = class {
|
|
|
2387
2443
|
this.destroyed || t !== this.loadGen || this.engine !== i || (this.analyticsSession?.noteReady(), this.emit("ready"));
|
|
2388
2444
|
}, 0));
|
|
2389
2445
|
}
|
|
2446
|
+
onAnalyticsIdle(e) {
|
|
2447
|
+
this.destroyed || this.engine !== e || (this.idleClosed = !0, this.pendingStartLoad = !1, e.stop());
|
|
2448
|
+
}
|
|
2390
2449
|
startAnalytics(e, t) {
|
|
2391
2450
|
if (this.analyticsSession?.noteDestroyed(), this.analyticsSession = null, this.detachMediaListeners?.(), this.opts.analytics === !1) return;
|
|
2392
2451
|
let n = e.analytics?.sid;
|
|
2393
2452
|
if (!n) return;
|
|
2394
|
-
let r = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ??
|
|
2453
|
+
let r = (typeof this.opts.analytics == "object" ? this.opts.analytics.endpoint : void 0) ?? ft(this.opts.baseUrl);
|
|
2395
2454
|
if (!r) return;
|
|
2396
|
-
let i = this.opts.video, a = new
|
|
2455
|
+
let i = this.opts.video, a = new pt({
|
|
2397
2456
|
endpoint: r,
|
|
2398
2457
|
sid: n,
|
|
2399
2458
|
player: t.name === "native" ? "PLAYER_SAFARI_NATIVE" : "PLAYER_HLSJS",
|
|
2400
|
-
sdkVersion:
|
|
2401
|
-
environment:
|
|
2459
|
+
sdkVersion: yt,
|
|
2460
|
+
environment: _t(i),
|
|
2461
|
+
idleMs: typeof this.opts.analytics == "object" ? this.opts.analytics.idleMs : void 0,
|
|
2462
|
+
onIdle: () => this.onAnalyticsIdle(t),
|
|
2402
2463
|
sample: () => {
|
|
2403
2464
|
let e = this.engine?.getStats() ?? I, t = i.buffered.length ? Math.max(0, i.buffered.end(i.buffered.length - 1) - i.currentTime) : 0;
|
|
2404
2465
|
return {
|
|
@@ -2414,7 +2475,7 @@ var Ft = class {
|
|
|
2414
2475
|
let o = () => a.noteSeek(), s = () => a.noteVolume(i.muted, i.volume);
|
|
2415
2476
|
i.addEventListener("seeking", o), i.addEventListener("volumechange", s), this.detachMediaListeners = () => {
|
|
2416
2477
|
i.removeEventListener("seeking", o), i.removeEventListener("volumechange", s);
|
|
2417
|
-
}, a.start(), a.seedVolume(i.muted, i.volume), a.notePresentation(this.currentPresentation()),
|
|
2478
|
+
}, a.start(), a.seedVolume(i.muted, i.volume), a.notePresentation(this.currentPresentation()), vt().then((e) => a.noteEnvironment(e)), this.opts.autoplay === !1 && a.noteAutoplay("AUTOPLAY_RESULT_NOT_ATTEMPTED");
|
|
2418
2479
|
}
|
|
2419
2480
|
currentPresentation() {
|
|
2420
2481
|
let e = this.opts.video;
|
|
@@ -2485,7 +2546,7 @@ var Ft = class {
|
|
|
2485
2546
|
r = 0, i = !1;
|
|
2486
2547
|
},
|
|
2487
2548
|
onError: () => {
|
|
2488
|
-
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >=
|
|
2549
|
+
this.destroyed || e !== this.loadGen || i || this.endedHandled || (r += 1, r >= Pt && (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.`))));
|
|
2489
2550
|
}
|
|
2490
2551
|
});
|
|
2491
2552
|
}
|
|
@@ -2507,7 +2568,7 @@ var Ft = class {
|
|
|
2507
2568
|
scheduleRejoin(e) {
|
|
2508
2569
|
this.rejoinEnabled() && !this.rejoinTimer && (this.rejoinTimer = setTimeout(() => {
|
|
2509
2570
|
this.rejoinTimer = null, !(this.destroyed || e !== this.loadGen || this._state !== "ended") && this.rejoin();
|
|
2510
|
-
}, Math.random() *
|
|
2571
|
+
}, Math.random() * Nt));
|
|
2511
2572
|
}
|
|
2512
2573
|
cancelRejoin() {
|
|
2513
2574
|
this.rejoinTimer &&= (clearTimeout(this.rejoinTimer), null);
|
|
@@ -2517,7 +2578,7 @@ var Ft = class {
|
|
|
2517
2578
|
this.teardownPlayback(), this.setState("waiting"), this.beginArming(e, void 0, !0);
|
|
2518
2579
|
}
|
|
2519
2580
|
teardownPlayback() {
|
|
2520
|
-
this.stopStats(), this.stopRefresh(), this.cancelRejoin(), this.closeArming(), this.closeLiveState(), this.detachMedia?.(), this.engine?.destroy(), this.engine = null, this.pendingStartLoad = !1;
|
|
2581
|
+
this.stopStats(), this.stopRefresh(), this.cancelRejoin(), this.closeArming(), this.closeLiveState(), this.detachMedia?.(), this.engine?.destroy(), this.engine = null, this.pendingStartLoad = !1, this.idleClosed = !1;
|
|
2521
2582
|
}
|
|
2522
2583
|
mountControls() {
|
|
2523
2584
|
let e = this.opts.controls ?? "custom", t = this.opts.video;
|
|
@@ -2531,7 +2592,7 @@ var Ft = class {
|
|
|
2531
2592
|
}
|
|
2532
2593
|
t.controls = !1;
|
|
2533
2594
|
let n = (t.ownerDocument ?? document).createElement("div"), r = t.parentNode;
|
|
2534
|
-
r && r.insertBefore(n, t), n.appendChild(t), X(n, this.opts.theme), this.container = n, this.controlBar =
|
|
2595
|
+
r && r.insertBefore(n, t), n.appendChild(t), X(n, this.opts.theme), this.container = n, this.controlBar = Tt({
|
|
2535
2596
|
root: n,
|
|
2536
2597
|
video: t,
|
|
2537
2598
|
player: this,
|
|
@@ -2561,7 +2622,7 @@ var Ft = class {
|
|
|
2561
2622
|
}
|
|
2562
2623
|
startStats() {
|
|
2563
2624
|
this.stopStats();
|
|
2564
|
-
let e = Math.max(500, this.opts.statsIntervalMs ??
|
|
2625
|
+
let e = Math.max(500, this.opts.statsIntervalMs ?? Ft);
|
|
2565
2626
|
this.statsTimer = setInterval(() => {
|
|
2566
2627
|
if (!this.engine) return;
|
|
2567
2628
|
let e = this.engine.getStats();
|
|
@@ -2573,7 +2634,7 @@ var Ft = class {
|
|
|
2573
2634
|
}
|
|
2574
2635
|
scheduleLicenseRefresh() {
|
|
2575
2636
|
this.stopRefresh();
|
|
2576
|
-
let e = this.opts.licenseRefreshMs ??
|
|
2637
|
+
let e = this.opts.licenseRefreshMs ?? It;
|
|
2577
2638
|
e && this._descriptor?.drmEnabled && (this.refreshTimer = setInterval(() => void this.refreshLicense(), e));
|
|
2578
2639
|
}
|
|
2579
2640
|
stopRefresh() {
|
|
@@ -2596,7 +2657,10 @@ var Ft = class {
|
|
|
2596
2657
|
async play() {
|
|
2597
2658
|
if (this.destroyed) return;
|
|
2598
2659
|
let e = !this.playRequested;
|
|
2599
|
-
this.playRequested = !0
|
|
2660
|
+
if (this.playRequested = !0, this.idleClosed && this._state !== "ended" && this._state !== "error") {
|
|
2661
|
+
this.idleClosed = !1, await this.reload();
|
|
2662
|
+
return;
|
|
2663
|
+
}
|
|
2600
2664
|
let t = this.pendingStartLoad && this._state !== "ended" && this._state !== "error";
|
|
2601
2665
|
this.opts.autoplay === !1 && this.analyticsSession?.notePlayIntent(), t && (this.pendingStartLoad = !1, this.setState("loading"), this.engine?.startLoad());
|
|
2602
2666
|
try {
|
|
@@ -2725,7 +2789,7 @@ function $(e) {
|
|
|
2725
2789
|
}
|
|
2726
2790
|
//#endregion
|
|
2727
2791
|
//#region src/embed/host.ts
|
|
2728
|
-
function
|
|
2792
|
+
function zt(e) {
|
|
2729
2793
|
if (!e.container || typeof e.container.appendChild != "function") throw Error("mountEmbed: opts.container must be a DOM element");
|
|
2730
2794
|
if (!e.src) throw Error("mountEmbed: opts.src is required");
|
|
2731
2795
|
if (!e.baseUrl || !e.matchUrn) throw Error("mountEmbed: opts.baseUrl and opts.matchUrn are required");
|
|
@@ -2784,8 +2848,8 @@ function It(e) {
|
|
|
2784
2848
|
}
|
|
2785
2849
|
//#endregion
|
|
2786
2850
|
//#region src/embed/page.ts
|
|
2787
|
-
var
|
|
2788
|
-
function
|
|
2851
|
+
var Bt = /^[A-Za-z0-9:_.-]{1,128}$/;
|
|
2852
|
+
function Vt() {
|
|
2789
2853
|
let e = window.HAVIK_EMBED_CONFIG;
|
|
2790
2854
|
if (e) return {
|
|
2791
2855
|
baseUrl: e.baseUrl ?? "",
|
|
@@ -2807,9 +2871,9 @@ function Rt() {
|
|
|
2807
2871
|
waitForLive: !0
|
|
2808
2872
|
};
|
|
2809
2873
|
}
|
|
2810
|
-
async function
|
|
2811
|
-
let e =
|
|
2812
|
-
|
|
2874
|
+
async function Ht() {
|
|
2875
|
+
let e = Vt();
|
|
2876
|
+
Wt();
|
|
2813
2877
|
let t = document.createElement("video");
|
|
2814
2878
|
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);
|
|
2815
2879
|
let r = e.parentOrigin && e.parentOrigin !== "null" ? e.parentOrigin : null;
|
|
@@ -2864,12 +2928,12 @@ async function zt() {
|
|
|
2864
2928
|
code: e.code,
|
|
2865
2929
|
message: e.message
|
|
2866
2930
|
})), e.on("autoplayblocked", () => {
|
|
2867
|
-
i({ type: "oddin:autoplayblocked" }),
|
|
2931
|
+
i({ type: "oddin:autoplayblocked" }), Ut(t, e);
|
|
2868
2932
|
});
|
|
2869
2933
|
}, s = async (r) => {
|
|
2870
2934
|
a?.destroy(), a = null;
|
|
2871
2935
|
try {
|
|
2872
|
-
let n = await
|
|
2936
|
+
let n = await Lt({
|
|
2873
2937
|
video: t,
|
|
2874
2938
|
baseUrl: e.baseUrl,
|
|
2875
2939
|
matchUrn: r,
|
|
@@ -2930,7 +2994,7 @@ async function zt() {
|
|
|
2930
2994
|
a?.retry();
|
|
2931
2995
|
break;
|
|
2932
2996
|
case "oddin:load":
|
|
2933
|
-
typeof e.matchUrn == "string" &&
|
|
2997
|
+
typeof e.matchUrn == "string" && Bt.test(e.matchUrn) && s(e.matchUrn);
|
|
2934
2998
|
break;
|
|
2935
2999
|
case "oddin:destroy": c();
|
|
2936
3000
|
}
|
|
@@ -2942,18 +3006,18 @@ async function zt() {
|
|
|
2942
3006
|
protocol: 1
|
|
2943
3007
|
});
|
|
2944
3008
|
}
|
|
2945
|
-
function
|
|
3009
|
+
function Ut(e, t) {
|
|
2946
3010
|
if (document.getElementById("havik-tap")) return;
|
|
2947
3011
|
let n = document.createElement("button");
|
|
2948
3012
|
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", () => {
|
|
2949
3013
|
n.remove(), t.play();
|
|
2950
3014
|
}), document.body.appendChild(n);
|
|
2951
3015
|
}
|
|
2952
|
-
function
|
|
3016
|
+
function Wt() {
|
|
2953
3017
|
let e = document.createElement("style");
|
|
2954
3018
|
e.textContent = "html,body{margin:0;height:100%;background:#000;overflow:hidden}body{display:flex}", document.head.appendChild(e);
|
|
2955
3019
|
}
|
|
2956
3020
|
//#endregion
|
|
2957
|
-
export { J as ODDIN_THEME, n as PlaybackError, X as applyTheme,
|
|
3021
|
+
export { J as ODDIN_THEME, n as PlaybackError, X as applyTheme, Ht as bootEmbed, _e as clearDeviceId, Lt as createPlayer, D as deriveEventsBaseUrl, Oe as detectDrmSupport, w as enterVideoFullscreen, T as exitVideoFullscreen, ue as fetchCatalog, fe as fetchTournament, me as flattenMatches, A as getDeviceId, Ae as isLowLatencyManifest, $ as isOddinMessage, ye as licenseRequestHeaders, zt as mountEmbed, oe as pollToLive, y as resolveStream, E as subscribeLiveState, C as videoFullscreenActive, he as watchStatus };
|
|
2958
3022
|
|
|
2959
3023
|
//# sourceMappingURL=index.js.map
|